diff options
Diffstat (limited to 'snd-alpx-dkms')
110 files changed, 48289 insertions, 0 deletions
diff --git a/snd-alpx-dkms/.gitignore b/snd-alpx-dkms/.gitignore new file mode 100644 index 0000000..8696913 --- /dev/null +++ b/snd-alpx-dkms/.gitignore @@ -0,0 +1,10 @@ +*.o +*.o.d +*.ko +*.cmd +*.mod +*.mod.c +Module.symvers +modules.order +load_alp_driver.sh +*.orig diff --git a/snd-alpx-dkms/Controls/Alp222e-MIC_Contents.txt b/snd-alpx-dkms/Controls/Alp222e-MIC_Contents.txt new file mode 100644 index 0000000..37ae035 --- /dev/null +++ b/snd-alpx-dkms/Controls/Alp222e-MIC_Contents.txt @@ -0,0 +1,412 @@ +numid=3,iface=MIXER,name='AES Capture Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=4,iface=MIXER,name='AES Capture Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=11,iface=MIXER,name='AES Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=12,iface=MIXER,name='AES Playback Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=86,iface=MIXER,name='AES SRC' + ; type=BOOLEAN,access=rw------,values=1 + : values=off +numid=1,iface=MIXER,name='Ana Capture Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=2,iface=MIXER,name='Ana Capture Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=9,iface=MIXER,name='Ana Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=10,iface=MIXER,name='Ana Playback Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=88,iface=MIXER,name='CkSc Down' + ; type=BOOLEAN,access=rw------,values=1 + : values=on +numid=87,iface=MIXER,name='CkSc Up' + ; type=BOOLEAN,access=rw------,values=1 + : values=on +numid=84,iface=MIXER,name='Clk Eff' + ; type=ENUMERATED,access=r--v----,values=1,items=14 + ; Item #0 '8kHz' + ; Item #1 '11.025kHz' + ; Item #2 '16kHz' + ; Item #3 '22.05kHz' + ; Item #4 '24kHz' + ; Item #5 '32kHz' + ; Item #6 '44.1kHz' + ; Item #7 '48kHz' + ; Item #8 '64kHz' + ; Item #9 '88.2kHz' + ; Item #10 '96kHz' + ; Item #11 '128kHz' + ; Item #12 '176,4kHz' + ; Item #13 '192kHz' + : values=7 +numid=89,iface=MIXER,name='Clk P0' + ; type=ENUMERATED,access=rw------,values=1,items=5 + ; Item #0 'Internal' + ; Item #1 'SIC' + ; Item #2 'Word Clk' + ; Item #3 'AES Syn' + ; Item #4 'AES Aud' + : values=0 +numid=90,iface=MIXER,name='Clk P1' + ; type=ENUMERATED,access=rw------,values=1,items=5 + ; Item #0 'Internal' + ; Item #1 'SIC' + ; Item #2 'Word Clk' + ; Item #3 'AES Syn' + ; Item #4 'AES Aud' + : values=0 +numid=91,iface=MIXER,name='Clk P2' + ; type=ENUMERATED,access=rw------,values=1,items=5 + ; Item #0 'Internal' + ; Item #1 'SIC' + ; Item #2 'Word Clk' + ; Item #3 'AES Syn' + ; Item #4 'AES Aud' + : values=0 +numid=92,iface=MIXER,name='Clk P3' + ; type=ENUMERATED,access=rw------,values=1,items=5 + ; Item #0 'Internal' + ; Item #1 'SIC' + ; Item #2 'Word Clk' + ; Item #3 'AES Syn' + ; Item #4 'AES Aud' + : values=0 +numid=83,iface=MIXER,name='Clk Src' + ; type=ENUMERATED,access=r-------,values=1,items=5 + ; Item #0 'Internal' + ; Item #1 'SIC' + ; Item #2 'Word Clk' + ; Item #3 'AES Syn' + ; Item #4 'AES Aud' + : values=0 +numid=17,iface=MIXER,name='Codec Analog Capture Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=255,step=0 + : values=174 + | dBminmaxmute-min=-88.00dB,max=39.00dB +numid=18,iface=MIXER,name='Codec Analog Capture Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=255,step=0 + : values=174 + | dBminmaxmute-min=-88.00dB,max=39.00dB +numid=13,iface=MIXER,name='DAW Capture Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=14,iface=MIXER,name='DAW Capture Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=15,iface=MIXER,name='DAW Capture Volume',index=2 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=16,iface=MIXER,name='DAW Capture Volume',index=3 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=5,iface=MIXER,name='DAW Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=6,iface=MIXER,name='DAW Playback Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=7,iface=MIXER,name='DAW Playback Volume',index=2 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=8,iface=MIXER,name='DAW Playback Volume',index=3 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=97,iface=MIXER,name='McEnL' + ; type=BOOLEAN,access=rw------,values=1 + : values=off +numid=98,iface=MIXER,name='McEnR' + ; type=BOOLEAN,access=rw------,values=1 + : values=off +numid=93,iface=MIXER,name='McGaL' + ; type=INTEGER,access=rw------,values=1,min=10,max=65,step=0 + : values=10 +numid=94,iface=MIXER,name='McGaR' + ; type=INTEGER,access=rw------,values=1,min=10,max=65,step=0 + : values=10 +numid=95,iface=MIXER,name='McPhL' + ; type=BOOLEAN,access=rw------,values=1 + : values=off +numid=96,iface=MIXER,name='McPhR' + ; type=BOOLEAN,access=rw------,values=1 + : values=off +numid=19,iface=MIXER,name='Mxr 0/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=27,iface=MIXER,name='Mxr 0/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=35,iface=MIXER,name='Mxr 0/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=43,iface=MIXER,name='Mxr 0/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=51,iface=MIXER,name='Mxr 0/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=59,iface=MIXER,name='Mxr 0/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=67,iface=MIXER,name='Mxr 0/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=75,iface=MIXER,name='Mxr 0/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=20,iface=MIXER,name='Mxr 1/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=28,iface=MIXER,name='Mxr 1/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=36,iface=MIXER,name='Mxr 1/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=44,iface=MIXER,name='Mxr 1/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=52,iface=MIXER,name='Mxr 1/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=60,iface=MIXER,name='Mxr 1/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=68,iface=MIXER,name='Mxr 1/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=76,iface=MIXER,name='Mxr 1/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=21,iface=MIXER,name='Mxr 2/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=29,iface=MIXER,name='Mxr 2/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=37,iface=MIXER,name='Mxr 2/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=45,iface=MIXER,name='Mxr 2/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=53,iface=MIXER,name='Mxr 2/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=61,iface=MIXER,name='Mxr 2/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=69,iface=MIXER,name='Mxr 2/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=77,iface=MIXER,name='Mxr 2/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=22,iface=MIXER,name='Mxr 3/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=30,iface=MIXER,name='Mxr 3/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=38,iface=MIXER,name='Mxr 3/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=46,iface=MIXER,name='Mxr 3/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=54,iface=MIXER,name='Mxr 3/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=62,iface=MIXER,name='Mxr 3/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=70,iface=MIXER,name='Mxr 3/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=78,iface=MIXER,name='Mxr 3/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=23,iface=MIXER,name='Mxr 4/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=31,iface=MIXER,name='Mxr 4/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=39,iface=MIXER,name='Mxr 4/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=47,iface=MIXER,name='Mxr 4/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=55,iface=MIXER,name='Mxr 4/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=63,iface=MIXER,name='Mxr 4/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=71,iface=MIXER,name='Mxr 4/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=79,iface=MIXER,name='Mxr 4/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=24,iface=MIXER,name='Mxr 5/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=32,iface=MIXER,name='Mxr 5/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=40,iface=MIXER,name='Mxr 5/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=48,iface=MIXER,name='Mxr 5/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=56,iface=MIXER,name='Mxr 5/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=64,iface=MIXER,name='Mxr 5/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=72,iface=MIXER,name='Mxr 5/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=80,iface=MIXER,name='Mxr 5/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=25,iface=MIXER,name='Mxr 6/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=33,iface=MIXER,name='Mxr 6/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=41,iface=MIXER,name='Mxr 6/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=49,iface=MIXER,name='Mxr 6/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=57,iface=MIXER,name='Mxr 6/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=65,iface=MIXER,name='Mxr 6/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=73,iface=MIXER,name='Mxr 6/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=81,iface=MIXER,name='Mxr 6/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=26,iface=MIXER,name='Mxr 7/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=34,iface=MIXER,name='Mxr 7/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=42,iface=MIXER,name='Mxr 7/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=50,iface=MIXER,name='Mxr 7/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=58,iface=MIXER,name='Mxr 7/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=66,iface=MIXER,name='Mxr 7/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=74,iface=MIXER,name='Mxr 7/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=82,iface=MIXER,name='Mxr 7/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB diff --git a/snd-alpx-dkms/Controls/Alp222e-MIC_Controls.txt b/snd-alpx-dkms/Controls/Alp222e-MIC_Controls.txt new file mode 100644 index 0000000..6b84ff6 --- /dev/null +++ b/snd-alpx-dkms/Controls/Alp222e-MIC_Controls.txt @@ -0,0 +1,97 @@ +numid=3,iface=MIXER,name='AES Capture Volume' +numid=4,iface=MIXER,name='AES Capture Volume',index=1 +numid=11,iface=MIXER,name='AES Playback Volume' +numid=12,iface=MIXER,name='AES Playback Volume',index=1 +numid=86,iface=MIXER,name='AES SRC' +numid=1,iface=MIXER,name='Ana Capture Volume' +numid=2,iface=MIXER,name='Ana Capture Volume',index=1 +numid=9,iface=MIXER,name='Ana Playback Volume' +numid=10,iface=MIXER,name='Ana Playback Volume',index=1 +numid=88,iface=MIXER,name='CkSc Down' +numid=87,iface=MIXER,name='CkSc Up' +numid=84,iface=MIXER,name='Clk Eff' +numid=89,iface=MIXER,name='Clk P0' +numid=90,iface=MIXER,name='Clk P1' +numid=91,iface=MIXER,name='Clk P2' +numid=92,iface=MIXER,name='Clk P3' +numid=83,iface=MIXER,name='Clk Src' +numid=17,iface=MIXER,name='Codec Analog Capture Volume' +numid=18,iface=MIXER,name='Codec Analog Capture Volume',index=1 +numid=13,iface=MIXER,name='DAW Capture Volume' +numid=14,iface=MIXER,name='DAW Capture Volume',index=1 +numid=15,iface=MIXER,name='DAW Capture Volume',index=2 +numid=16,iface=MIXER,name='DAW Capture Volume',index=3 +numid=5,iface=MIXER,name='DAW Playback Volume' +numid=6,iface=MIXER,name='DAW Playback Volume',index=1 +numid=7,iface=MIXER,name='DAW Playback Volume',index=2 +numid=8,iface=MIXER,name='DAW Playback Volume',index=3 +numid=97,iface=MIXER,name='McEnL' +numid=98,iface=MIXER,name='McEnR' +numid=93,iface=MIXER,name='McGaL' +numid=94,iface=MIXER,name='McGaR' +numid=95,iface=MIXER,name='McPhL' +numid=96,iface=MIXER,name='McPhR' +numid=19,iface=MIXER,name='Mxr 0/0 Playback Volume' +numid=27,iface=MIXER,name='Mxr 0/1 Playback Volume' +numid=35,iface=MIXER,name='Mxr 0/2 Playback Volume' +numid=43,iface=MIXER,name='Mxr 0/3 Playback Volume' +numid=51,iface=MIXER,name='Mxr 0/4 Playback Volume' +numid=59,iface=MIXER,name='Mxr 0/5 Playback Volume' +numid=67,iface=MIXER,name='Mxr 0/6 Playback Volume' +numid=75,iface=MIXER,name='Mxr 0/7 Playback Volume' +numid=20,iface=MIXER,name='Mxr 1/0 Playback Volume' +numid=28,iface=MIXER,name='Mxr 1/1 Playback Volume' +numid=36,iface=MIXER,name='Mxr 1/2 Playback Volume' +numid=44,iface=MIXER,name='Mxr 1/3 Playback Volume' +numid=52,iface=MIXER,name='Mxr 1/4 Playback Volume' +numid=60,iface=MIXER,name='Mxr 1/5 Playback Volume' +numid=68,iface=MIXER,name='Mxr 1/6 Playback Volume' +numid=76,iface=MIXER,name='Mxr 1/7 Playback Volume' +numid=21,iface=MIXER,name='Mxr 2/0 Playback Volume' +numid=29,iface=MIXER,name='Mxr 2/1 Playback Volume' +numid=37,iface=MIXER,name='Mxr 2/2 Playback Volume' +numid=45,iface=MIXER,name='Mxr 2/3 Playback Volume' +numid=53,iface=MIXER,name='Mxr 2/4 Playback Volume' +numid=61,iface=MIXER,name='Mxr 2/5 Playback Volume' +numid=69,iface=MIXER,name='Mxr 2/6 Playback Volume' +numid=77,iface=MIXER,name='Mxr 2/7 Playback Volume' +numid=22,iface=MIXER,name='Mxr 3/0 Playback Volume' +numid=30,iface=MIXER,name='Mxr 3/1 Playback Volume' +numid=38,iface=MIXER,name='Mxr 3/2 Playback Volume' +numid=46,iface=MIXER,name='Mxr 3/3 Playback Volume' +numid=54,iface=MIXER,name='Mxr 3/4 Playback Volume' +numid=62,iface=MIXER,name='Mxr 3/5 Playback Volume' +numid=70,iface=MIXER,name='Mxr 3/6 Playback Volume' +numid=78,iface=MIXER,name='Mxr 3/7 Playback Volume' +numid=23,iface=MIXER,name='Mxr 4/0 Playback Volume' +numid=31,iface=MIXER,name='Mxr 4/1 Playback Volume' +numid=39,iface=MIXER,name='Mxr 4/2 Playback Volume' +numid=47,iface=MIXER,name='Mxr 4/3 Playback Volume' +numid=55,iface=MIXER,name='Mxr 4/4 Playback Volume' +numid=63,iface=MIXER,name='Mxr 4/5 Playback Volume' +numid=71,iface=MIXER,name='Mxr 4/6 Playback Volume' +numid=79,iface=MIXER,name='Mxr 4/7 Playback Volume' +numid=24,iface=MIXER,name='Mxr 5/0 Playback Volume' +numid=32,iface=MIXER,name='Mxr 5/1 Playback Volume' +numid=40,iface=MIXER,name='Mxr 5/2 Playback Volume' +numid=48,iface=MIXER,name='Mxr 5/3 Playback Volume' +numid=56,iface=MIXER,name='Mxr 5/4 Playback Volume' +numid=64,iface=MIXER,name='Mxr 5/5 Playback Volume' +numid=72,iface=MIXER,name='Mxr 5/6 Playback Volume' +numid=80,iface=MIXER,name='Mxr 5/7 Playback Volume' +numid=25,iface=MIXER,name='Mxr 6/0 Playback Volume' +numid=33,iface=MIXER,name='Mxr 6/1 Playback Volume' +numid=41,iface=MIXER,name='Mxr 6/2 Playback Volume' +numid=49,iface=MIXER,name='Mxr 6/3 Playback Volume' +numid=57,iface=MIXER,name='Mxr 6/4 Playback Volume' +numid=65,iface=MIXER,name='Mxr 6/5 Playback Volume' +numid=73,iface=MIXER,name='Mxr 6/6 Playback Volume' +numid=81,iface=MIXER,name='Mxr 6/7 Playback Volume' +numid=26,iface=MIXER,name='Mxr 7/0 Playback Volume' +numid=34,iface=MIXER,name='Mxr 7/1 Playback Volume' +numid=42,iface=MIXER,name='Mxr 7/2 Playback Volume' +numid=50,iface=MIXER,name='Mxr 7/3 Playback Volume' +numid=58,iface=MIXER,name='Mxr 7/4 Playback Volume' +numid=66,iface=MIXER,name='Mxr 7/5 Playback Volume' +numid=74,iface=MIXER,name='Mxr 7/6 Playback Volume' +numid=82,iface=MIXER,name='Mxr 7/7 Playback Volume' diff --git a/snd-alpx-dkms/Controls/Alp222e_Contents.txt b/snd-alpx-dkms/Controls/Alp222e_Contents.txt new file mode 100644 index 0000000..9f87602 --- /dev/null +++ b/snd-alpx-dkms/Controls/Alp222e_Contents.txt @@ -0,0 +1,394 @@ +numid=3,iface=MIXER,name='AES Capture Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=4,iface=MIXER,name='AES Capture Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=11,iface=MIXER,name='AES Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=12,iface=MIXER,name='AES Playback Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=86,iface=MIXER,name='AES SRC Disable' + ; type=BOOLEAN,access=rw------,values=1 + : values=off +numid=1,iface=MIXER,name='Ana Capture Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=2,iface=MIXER,name='Ana Capture Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=9,iface=MIXER,name='Ana Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=1021 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=10,iface=MIXER,name='Ana Playback Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=88,iface=MIXER,name='CkSc Down' + ; type=BOOLEAN,access=rw------,values=1 + : values=on +numid=87,iface=MIXER,name='CkSc Up' + ; type=BOOLEAN,access=rw------,values=1 + : values=on +numid=84,iface=MIXER,name='Clk Eff' + ; type=ENUMERATED,access=r--v----,values=1,items=14 + ; Item #0 '8kHz' + ; Item #1 '11.025kHz' + ; Item #2 '16kHz' + ; Item #3 '22.05kHz' + ; Item #4 '24kHz' + ; Item #5 '32kHz' + ; Item #6 '44.1kHz' + ; Item #7 '48kHz' + ; Item #8 '64kHz' + ; Item #9 '88.2kHz' + ; Item #10 '96kHz' + ; Item #11 '128kHz' + ; Item #12 '176,4kHz' + ; Item #13 '192kHz' + : values=7 +numid=89,iface=MIXER,name='Clk P0' + ; type=ENUMERATED,access=rw------,values=1,items=5 + ; Item #0 'Internal' + ; Item #1 'SIC' + ; Item #2 'Word Clk' + ; Item #3 'AES Syn' + ; Item #4 'AES Aud' + : values=0 +numid=90,iface=MIXER,name='Clk P1' + ; type=ENUMERATED,access=rw------,values=1,items=5 + ; Item #0 'Internal' + ; Item #1 'SIC' + ; Item #2 'Word Clk' + ; Item #3 'AES Syn' + ; Item #4 'AES Aud' + : values=0 +numid=91,iface=MIXER,name='Clk P2' + ; type=ENUMERATED,access=rw------,values=1,items=5 + ; Item #0 'Internal' + ; Item #1 'SIC' + ; Item #2 'Word Clk' + ; Item #3 'AES Syn' + ; Item #4 'AES Aud' + : values=0 +numid=92,iface=MIXER,name='Clk P3' + ; type=ENUMERATED,access=rw------,values=1,items=5 + ; Item #0 'Internal' + ; Item #1 'SIC' + ; Item #2 'Word Clk' + ; Item #3 'AES Syn' + ; Item #4 'AES Aud' + : values=0 +numid=83,iface=MIXER,name='Clk Src' + ; type=ENUMERATED,access=r-------,values=1,items=5 + ; Item #0 'Internal' + ; Item #1 'SIC' + ; Item #2 'Word Clk' + ; Item #3 'AES Syn' + ; Item #4 'AES Aud' + : values=0 +numid=17,iface=MIXER,name='Codec Analog Capture Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=255,step=0 + : values=174 + | dBminmaxmute-min=-88.00dB,max=39.00dB +numid=18,iface=MIXER,name='Codec Analog Capture Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=255,step=0 + : values=174 + | dBminmaxmute-min=-88.00dB,max=39.00dB +numid=13,iface=MIXER,name='DAW Capture Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=14,iface=MIXER,name='DAW Capture Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=15,iface=MIXER,name='DAW Capture Volume',index=2 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=16,iface=MIXER,name='DAW Capture Volume',index=3 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=5,iface=MIXER,name='DAW Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=6,iface=MIXER,name='DAW Playback Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=7,iface=MIXER,name='DAW Playback Volume',index=2 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=8,iface=MIXER,name='DAW Playback Volume',index=3 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=19,iface=MIXER,name='Mxr 0/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=27,iface=MIXER,name='Mxr 0/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=35,iface=MIXER,name='Mxr 0/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=43,iface=MIXER,name='Mxr 0/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=51,iface=MIXER,name='Mxr 0/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=59,iface=MIXER,name='Mxr 0/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=67,iface=MIXER,name='Mxr 0/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=75,iface=MIXER,name='Mxr 0/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=20,iface=MIXER,name='Mxr 1/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=28,iface=MIXER,name='Mxr 1/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=36,iface=MIXER,name='Mxr 1/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=44,iface=MIXER,name='Mxr 1/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=52,iface=MIXER,name='Mxr 1/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=60,iface=MIXER,name='Mxr 1/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=68,iface=MIXER,name='Mxr 1/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=76,iface=MIXER,name='Mxr 1/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=21,iface=MIXER,name='Mxr 2/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=29,iface=MIXER,name='Mxr 2/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=37,iface=MIXER,name='Mxr 2/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=45,iface=MIXER,name='Mxr 2/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=53,iface=MIXER,name='Mxr 2/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=61,iface=MIXER,name='Mxr 2/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=69,iface=MIXER,name='Mxr 2/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=77,iface=MIXER,name='Mxr 2/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=22,iface=MIXER,name='Mxr 3/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=30,iface=MIXER,name='Mxr 3/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=38,iface=MIXER,name='Mxr 3/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=46,iface=MIXER,name='Mxr 3/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=54,iface=MIXER,name='Mxr 3/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=62,iface=MIXER,name='Mxr 3/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=70,iface=MIXER,name='Mxr 3/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=78,iface=MIXER,name='Mxr 3/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=23,iface=MIXER,name='Mxr 4/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=31,iface=MIXER,name='Mxr 4/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=39,iface=MIXER,name='Mxr 4/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=47,iface=MIXER,name='Mxr 4/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=55,iface=MIXER,name='Mxr 4/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=63,iface=MIXER,name='Mxr 4/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=71,iface=MIXER,name='Mxr 4/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=79,iface=MIXER,name='Mxr 4/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=24,iface=MIXER,name='Mxr 5/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=32,iface=MIXER,name='Mxr 5/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=40,iface=MIXER,name='Mxr 5/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=48,iface=MIXER,name='Mxr 5/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=56,iface=MIXER,name='Mxr 5/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=64,iface=MIXER,name='Mxr 5/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=72,iface=MIXER,name='Mxr 5/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=80,iface=MIXER,name='Mxr 5/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=25,iface=MIXER,name='Mxr 6/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=33,iface=MIXER,name='Mxr 6/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=41,iface=MIXER,name='Mxr 6/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=49,iface=MIXER,name='Mxr 6/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=57,iface=MIXER,name='Mxr 6/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=65,iface=MIXER,name='Mxr 6/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=73,iface=MIXER,name='Mxr 6/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=81,iface=MIXER,name='Mxr 6/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=26,iface=MIXER,name='Mxr 7/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=34,iface=MIXER,name='Mxr 7/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=42,iface=MIXER,name='Mxr 7/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=50,iface=MIXER,name='Mxr 7/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=58,iface=MIXER,name='Mxr 7/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=66,iface=MIXER,name='Mxr 7/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=74,iface=MIXER,name='Mxr 7/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=82,iface=MIXER,name='Mxr 7/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB diff --git a/snd-alpx-dkms/Controls/Alp222e_Controls.txt b/snd-alpx-dkms/Controls/Alp222e_Controls.txt new file mode 100644 index 0000000..37345f0 --- /dev/null +++ b/snd-alpx-dkms/Controls/Alp222e_Controls.txt @@ -0,0 +1,91 @@ +numid=3,iface=MIXER,name='AES Capture Volume' +numid=4,iface=MIXER,name='AES Capture Volume',index=1 +numid=11,iface=MIXER,name='AES Playback Volume' +numid=12,iface=MIXER,name='AES Playback Volume',index=1 +numid=86,iface=MIXER,name='AES SRC Disable' +numid=1,iface=MIXER,name='Ana Capture Volume' +numid=2,iface=MIXER,name='Ana Capture Volume',index=1 +numid=9,iface=MIXER,name='Ana Playback Volume' +numid=10,iface=MIXER,name='Ana Playback Volume',index=1 +numid=88,iface=MIXER,name='CkSc Down' +numid=87,iface=MIXER,name='CkSc Up' +numid=84,iface=MIXER,name='Clk Eff' +numid=89,iface=MIXER,name='Clk P0' +numid=90,iface=MIXER,name='Clk P1' +numid=91,iface=MIXER,name='Clk P2' +numid=92,iface=MIXER,name='Clk P3' +numid=83,iface=MIXER,name='Clk Src' +numid=17,iface=MIXER,name='Codec Analog Capture Volume' +numid=18,iface=MIXER,name='Codec Analog Capture Volume',index=1 +numid=13,iface=MIXER,name='DAW Capture Volume' +numid=14,iface=MIXER,name='DAW Capture Volume',index=1 +numid=15,iface=MIXER,name='DAW Capture Volume',index=2 +numid=16,iface=MIXER,name='DAW Capture Volume',index=3 +numid=5,iface=MIXER,name='DAW Playback Volume' +numid=6,iface=MIXER,name='DAW Playback Volume',index=1 +numid=7,iface=MIXER,name='DAW Playback Volume',index=2 +numid=8,iface=MIXER,name='DAW Playback Volume',index=3 +numid=19,iface=MIXER,name='Mxr 0/0 Playback Volume' +numid=27,iface=MIXER,name='Mxr 0/1 Playback Volume' +numid=35,iface=MIXER,name='Mxr 0/2 Playback Volume' +numid=43,iface=MIXER,name='Mxr 0/3 Playback Volume' +numid=51,iface=MIXER,name='Mxr 0/4 Playback Volume' +numid=59,iface=MIXER,name='Mxr 0/5 Playback Volume' +numid=67,iface=MIXER,name='Mxr 0/6 Playback Volume' +numid=75,iface=MIXER,name='Mxr 0/7 Playback Volume' +numid=20,iface=MIXER,name='Mxr 1/0 Playback Volume' +numid=28,iface=MIXER,name='Mxr 1/1 Playback Volume' +numid=36,iface=MIXER,name='Mxr 1/2 Playback Volume' +numid=44,iface=MIXER,name='Mxr 1/3 Playback Volume' +numid=52,iface=MIXER,name='Mxr 1/4 Playback Volume' +numid=60,iface=MIXER,name='Mxr 1/5 Playback Volume' +numid=68,iface=MIXER,name='Mxr 1/6 Playback Volume' +numid=76,iface=MIXER,name='Mxr 1/7 Playback Volume' +numid=21,iface=MIXER,name='Mxr 2/0 Playback Volume' +numid=29,iface=MIXER,name='Mxr 2/1 Playback Volume' +numid=37,iface=MIXER,name='Mxr 2/2 Playback Volume' +numid=45,iface=MIXER,name='Mxr 2/3 Playback Volume' +numid=53,iface=MIXER,name='Mxr 2/4 Playback Volume' +numid=61,iface=MIXER,name='Mxr 2/5 Playback Volume' +numid=69,iface=MIXER,name='Mxr 2/6 Playback Volume' +numid=77,iface=MIXER,name='Mxr 2/7 Playback Volume' +numid=22,iface=MIXER,name='Mxr 3/0 Playback Volume' +numid=30,iface=MIXER,name='Mxr 3/1 Playback Volume' +numid=38,iface=MIXER,name='Mxr 3/2 Playback Volume' +numid=46,iface=MIXER,name='Mxr 3/3 Playback Volume' +numid=54,iface=MIXER,name='Mxr 3/4 Playback Volume' +numid=62,iface=MIXER,name='Mxr 3/5 Playback Volume' +numid=70,iface=MIXER,name='Mxr 3/6 Playback Volume' +numid=78,iface=MIXER,name='Mxr 3/7 Playback Volume' +numid=23,iface=MIXER,name='Mxr 4/0 Playback Volume' +numid=31,iface=MIXER,name='Mxr 4/1 Playback Volume' +numid=39,iface=MIXER,name='Mxr 4/2 Playback Volume' +numid=47,iface=MIXER,name='Mxr 4/3 Playback Volume' +numid=55,iface=MIXER,name='Mxr 4/4 Playback Volume' +numid=63,iface=MIXER,name='Mxr 4/5 Playback Volume' +numid=71,iface=MIXER,name='Mxr 4/6 Playback Volume' +numid=79,iface=MIXER,name='Mxr 4/7 Playback Volume' +numid=24,iface=MIXER,name='Mxr 5/0 Playback Volume' +numid=32,iface=MIXER,name='Mxr 5/1 Playback Volume' +numid=40,iface=MIXER,name='Mxr 5/2 Playback Volume' +numid=48,iface=MIXER,name='Mxr 5/3 Playback Volume' +numid=56,iface=MIXER,name='Mxr 5/4 Playback Volume' +numid=64,iface=MIXER,name='Mxr 5/5 Playback Volume' +numid=72,iface=MIXER,name='Mxr 5/6 Playback Volume' +numid=80,iface=MIXER,name='Mxr 5/7 Playback Volume' +numid=25,iface=MIXER,name='Mxr 6/0 Playback Volume' +numid=33,iface=MIXER,name='Mxr 6/1 Playback Volume' +numid=41,iface=MIXER,name='Mxr 6/2 Playback Volume' +numid=49,iface=MIXER,name='Mxr 6/3 Playback Volume' +numid=57,iface=MIXER,name='Mxr 6/4 Playback Volume' +numid=65,iface=MIXER,name='Mxr 6/5 Playback Volume' +numid=73,iface=MIXER,name='Mxr 6/6 Playback Volume' +numid=81,iface=MIXER,name='Mxr 6/7 Playback Volume' +numid=26,iface=MIXER,name='Mxr 7/0 Playback Volume' +numid=34,iface=MIXER,name='Mxr 7/1 Playback Volume' +numid=42,iface=MIXER,name='Mxr 7/2 Playback Volume' +numid=50,iface=MIXER,name='Mxr 7/3 Playback Volume' +numid=58,iface=MIXER,name='Mxr 7/4 Playback Volume' +numid=66,iface=MIXER,name='Mxr 7/5 Playback Volume' +numid=74,iface=MIXER,name='Mxr 7/6 Playback Volume' +numid=82,iface=MIXER,name='Mxr 7/7 Playback Volume' diff --git a/snd-alpx-dkms/Controls/Alp442e-MIC_contents.txt b/snd-alpx-dkms/Controls/Alp442e-MIC_contents.txt new file mode 100644 index 0000000..3b1f592 --- /dev/null +++ b/snd-alpx-dkms/Controls/Alp442e-MIC_contents.txt @@ -0,0 +1,1254 @@ +numid=13,iface=MIXER,name='AES Capture Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=14,iface=MIXER,name='AES Capture Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=15,iface=MIXER,name='AES Capture Volume',index=2 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=16,iface=MIXER,name='AES Capture Volume',index=3 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=21,iface=MIXER,name='AES Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=22,iface=MIXER,name='AES Playback Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=23,iface=MIXER,name='AES Playback Volume',index=2 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=24,iface=MIXER,name='AES Playback Volume',index=3 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=298,iface=MIXER,name='AES SRC 1/2 Disable' + ; type=BOOLEAN,access=rw------,values=1 + : values=off +numid=299,iface=MIXER,name='AES SRC 3/4 Disable' + ; type=BOOLEAN,access=rw------,values=1 + : values=off +numid=9,iface=MIXER,name='Ana Capture Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=10,iface=MIXER,name='Ana Capture Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=11,iface=MIXER,name='Ana Capture Volume',index=2 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=12,iface=MIXER,name='Ana Capture Volume',index=3 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=17,iface=MIXER,name='Ana Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=18,iface=MIXER,name='Ana Playback Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=19,iface=MIXER,name='Ana Playback Volume',index=2 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=20,iface=MIXER,name='Ana Playback Volume',index=3 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=290,iface=MIXER,name='Clk Eff' + ; type=ENUMERATED,access=r--v----,values=1,items=14 + ; Item #0 '8kHz' + ; Item #1 '11.025kHz' + ; Item #2 '16kHz' + ; Item #3 '22.05kHz' + ; Item #4 '24kHz' + ; Item #5 '32kHz' + ; Item #6 '44.1kHz' + ; Item #7 '48kHz' + ; Item #8 '64kHz' + ; Item #9 '88.2kHz' + ; Item #10 '96kHz' + ; Item #11 '128kHz' + ; Item #12 '176,4kHz' + ; Item #13 '192kHz' + : values=7 +numid=289,iface=MIXER,name='Clk Eff Src' + ; type=ENUMERATED,access=r-------,values=1,items=6 + ; Item #0 'Internal' + ; Item #1 'SIC' + ; Item #2 'Word Clk' + ; Item #3 'AES Syn' + ; Item #4 'AES Aud 1/2' + ; Item #5 'AES Aud 3/4' + : values=0 +numid=294,iface=MIXER,name='Clk P0' + ; type=ENUMERATED,access=rw------,values=1,items=6 + ; Item #0 'Internal' + ; Item #1 'SIC' + ; Item #2 'Word Clk' + ; Item #3 'AES Syn' + ; Item #4 'AES Aud 1/2' + ; Item #5 'AES Aud 3/4' + : values=0 +numid=295,iface=MIXER,name='Clk P1' + ; type=ENUMERATED,access=rw------,values=1,items=6 + ; Item #0 'Internal' + ; Item #1 'SIC' + ; Item #2 'Word Clk' + ; Item #3 'AES Syn' + ; Item #4 'AES Aud 1/2' + ; Item #5 'AES Aud 3/4' + : values=0 +numid=296,iface=MIXER,name='Clk P2' + ; type=ENUMERATED,access=rw------,values=1,items=6 + ; Item #0 'Internal' + ; Item #1 'SIC' + ; Item #2 'Word Clk' + ; Item #3 'AES Syn' + ; Item #4 'AES Aud 1/2' + ; Item #5 'AES Aud 3/4' + : values=0 +numid=297,iface=MIXER,name='Clk P3' + ; type=ENUMERATED,access=rw------,values=1,items=6 + ; Item #0 'Internal' + ; Item #1 'SIC' + ; Item #2 'Word Clk' + ; Item #3 'AES Syn' + ; Item #4 'AES Aud 1/2' + ; Item #5 'AES Aud 3/4' + : values=0 +numid=293,iface=MIXER,name='Clk Src Down' + ; type=BOOLEAN,access=rw------,values=1 + : values=on +numid=292,iface=MIXER,name='Clk Src Up' + ; type=BOOLEAN,access=rw------,values=1 + : values=on +numid=300,iface=MIXER,name='Codec MIC Analog Capture Volume' + ; type=INTEGER,access=rw---R--,values=1,min=49,max=162,step=0 + : values=50 + | dBminmaxmute-min=0.00dB,max=56.00dB +numid=301,iface=MIXER,name='Codec MIC Analog Capture Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=49,max=162,step=0 + : values=50 + | dBminmaxmute-min=0.00dB,max=56.00dB +numid=302,iface=MIXER,name='Codec MIC Analog Capture Volume',index=2 + ; type=INTEGER,access=rw---R--,values=1,min=49,max=162,step=0 + : values=50 + | dBminmaxmute-min=0.00dB,max=56.00dB +numid=303,iface=MIXER,name='Codec MIC Analog Capture Volume',index=3 + ; type=INTEGER,access=rw---R--,values=1,min=49,max=162,step=0 + : values=50 + | dBminmaxmute-min=0.00dB,max=56.00dB +numid=1,iface=MIXER,name='DAW Capture Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=2,iface=MIXER,name='DAW Capture Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=3,iface=MIXER,name='DAW Capture Volume',index=2 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=4,iface=MIXER,name='DAW Capture Volume',index=3 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=5,iface=MIXER,name='DAW Capture Volume',index=4 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=6,iface=MIXER,name='DAW Capture Volume',index=5 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=7,iface=MIXER,name='DAW Capture Volume',index=6 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=8,iface=MIXER,name='DAW Capture Volume',index=7 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=25,iface=MIXER,name='DAW Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=26,iface=MIXER,name='DAW Playback Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=27,iface=MIXER,name='DAW Playback Volume',index=2 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=28,iface=MIXER,name='DAW Playback Volume',index=3 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=29,iface=MIXER,name='DAW Playback Volume',index=4 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=30,iface=MIXER,name='DAW Playback Volume',index=5 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=31,iface=MIXER,name='DAW Playback Volume',index=6 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=32,iface=MIXER,name='DAW Playback Volume',index=7 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=304,iface=MIXER,name='McPh1' + ; type=BOOLEAN,access=rw------,values=1 + : values=off +numid=305,iface=MIXER,name='McPh2' + ; type=BOOLEAN,access=rw------,values=1 + : values=off +numid=306,iface=MIXER,name='McPh3' + ; type=BOOLEAN,access=rw------,values=1 + : values=off +numid=307,iface=MIXER,name='McPh4' + ; type=BOOLEAN,access=rw------,values=1 + : values=off +numid=33,iface=MIXER,name='Mxr 0/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=49,iface=MIXER,name='Mxr 0/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=193,iface=MIXER,name='Mxr 0/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=209,iface=MIXER,name='Mxr 0/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=225,iface=MIXER,name='Mxr 0/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=241,iface=MIXER,name='Mxr 0/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=257,iface=MIXER,name='Mxr 0/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=273,iface=MIXER,name='Mxr 0/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=65,iface=MIXER,name='Mxr 0/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=81,iface=MIXER,name='Mxr 0/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=97,iface=MIXER,name='Mxr 0/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=113,iface=MIXER,name='Mxr 0/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=129,iface=MIXER,name='Mxr 0/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=145,iface=MIXER,name='Mxr 0/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=161,iface=MIXER,name='Mxr 0/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=177,iface=MIXER,name='Mxr 0/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=34,iface=MIXER,name='Mxr 1/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=50,iface=MIXER,name='Mxr 1/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=194,iface=MIXER,name='Mxr 1/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=210,iface=MIXER,name='Mxr 1/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=226,iface=MIXER,name='Mxr 1/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=242,iface=MIXER,name='Mxr 1/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=258,iface=MIXER,name='Mxr 1/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=274,iface=MIXER,name='Mxr 1/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=66,iface=MIXER,name='Mxr 1/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=82,iface=MIXER,name='Mxr 1/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=98,iface=MIXER,name='Mxr 1/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=114,iface=MIXER,name='Mxr 1/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=130,iface=MIXER,name='Mxr 1/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=146,iface=MIXER,name='Mxr 1/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=162,iface=MIXER,name='Mxr 1/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=178,iface=MIXER,name='Mxr 1/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=43,iface=MIXER,name='Mxr 10/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=59,iface=MIXER,name='Mxr 10/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=203,iface=MIXER,name='Mxr 10/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=219,iface=MIXER,name='Mxr 10/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=235,iface=MIXER,name='Mxr 10/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=251,iface=MIXER,name='Mxr 10/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=267,iface=MIXER,name='Mxr 10/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=283,iface=MIXER,name='Mxr 10/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=75,iface=MIXER,name='Mxr 10/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=91,iface=MIXER,name='Mxr 10/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=107,iface=MIXER,name='Mxr 10/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=123,iface=MIXER,name='Mxr 10/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=139,iface=MIXER,name='Mxr 10/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=155,iface=MIXER,name='Mxr 10/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=171,iface=MIXER,name='Mxr 10/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=187,iface=MIXER,name='Mxr 10/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=44,iface=MIXER,name='Mxr 11/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=60,iface=MIXER,name='Mxr 11/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=204,iface=MIXER,name='Mxr 11/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=220,iface=MIXER,name='Mxr 11/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=236,iface=MIXER,name='Mxr 11/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=252,iface=MIXER,name='Mxr 11/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=268,iface=MIXER,name='Mxr 11/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=284,iface=MIXER,name='Mxr 11/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=76,iface=MIXER,name='Mxr 11/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=92,iface=MIXER,name='Mxr 11/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=108,iface=MIXER,name='Mxr 11/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=124,iface=MIXER,name='Mxr 11/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=140,iface=MIXER,name='Mxr 11/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=156,iface=MIXER,name='Mxr 11/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=172,iface=MIXER,name='Mxr 11/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=188,iface=MIXER,name='Mxr 11/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=45,iface=MIXER,name='Mxr 12/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=61,iface=MIXER,name='Mxr 12/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=205,iface=MIXER,name='Mxr 12/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=221,iface=MIXER,name='Mxr 12/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=237,iface=MIXER,name='Mxr 12/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=253,iface=MIXER,name='Mxr 12/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=269,iface=MIXER,name='Mxr 12/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=285,iface=MIXER,name='Mxr 12/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=77,iface=MIXER,name='Mxr 12/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=93,iface=MIXER,name='Mxr 12/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=109,iface=MIXER,name='Mxr 12/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=125,iface=MIXER,name='Mxr 12/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=141,iface=MIXER,name='Mxr 12/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=157,iface=MIXER,name='Mxr 12/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=173,iface=MIXER,name='Mxr 12/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=189,iface=MIXER,name='Mxr 12/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=46,iface=MIXER,name='Mxr 13/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=62,iface=MIXER,name='Mxr 13/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=206,iface=MIXER,name='Mxr 13/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=222,iface=MIXER,name='Mxr 13/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=238,iface=MIXER,name='Mxr 13/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=254,iface=MIXER,name='Mxr 13/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=270,iface=MIXER,name='Mxr 13/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=286,iface=MIXER,name='Mxr 13/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=78,iface=MIXER,name='Mxr 13/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=94,iface=MIXER,name='Mxr 13/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=110,iface=MIXER,name='Mxr 13/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=126,iface=MIXER,name='Mxr 13/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=142,iface=MIXER,name='Mxr 13/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=158,iface=MIXER,name='Mxr 13/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=174,iface=MIXER,name='Mxr 13/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=190,iface=MIXER,name='Mxr 13/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=47,iface=MIXER,name='Mxr 14/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=63,iface=MIXER,name='Mxr 14/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=207,iface=MIXER,name='Mxr 14/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=223,iface=MIXER,name='Mxr 14/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=239,iface=MIXER,name='Mxr 14/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=255,iface=MIXER,name='Mxr 14/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=271,iface=MIXER,name='Mxr 14/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=287,iface=MIXER,name='Mxr 14/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=79,iface=MIXER,name='Mxr 14/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=95,iface=MIXER,name='Mxr 14/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=111,iface=MIXER,name='Mxr 14/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=127,iface=MIXER,name='Mxr 14/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=143,iface=MIXER,name='Mxr 14/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=159,iface=MIXER,name='Mxr 14/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=175,iface=MIXER,name='Mxr 14/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=191,iface=MIXER,name='Mxr 14/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=48,iface=MIXER,name='Mxr 15/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=64,iface=MIXER,name='Mxr 15/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=208,iface=MIXER,name='Mxr 15/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=224,iface=MIXER,name='Mxr 15/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=240,iface=MIXER,name='Mxr 15/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=256,iface=MIXER,name='Mxr 15/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=272,iface=MIXER,name='Mxr 15/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=288,iface=MIXER,name='Mxr 15/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=80,iface=MIXER,name='Mxr 15/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=96,iface=MIXER,name='Mxr 15/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=112,iface=MIXER,name='Mxr 15/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=128,iface=MIXER,name='Mxr 15/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=144,iface=MIXER,name='Mxr 15/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=160,iface=MIXER,name='Mxr 15/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=176,iface=MIXER,name='Mxr 15/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=192,iface=MIXER,name='Mxr 15/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=35,iface=MIXER,name='Mxr 2/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=51,iface=MIXER,name='Mxr 2/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=195,iface=MIXER,name='Mxr 2/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=211,iface=MIXER,name='Mxr 2/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=227,iface=MIXER,name='Mxr 2/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=243,iface=MIXER,name='Mxr 2/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=259,iface=MIXER,name='Mxr 2/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=275,iface=MIXER,name='Mxr 2/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=67,iface=MIXER,name='Mxr 2/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=83,iface=MIXER,name='Mxr 2/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=99,iface=MIXER,name='Mxr 2/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=115,iface=MIXER,name='Mxr 2/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=131,iface=MIXER,name='Mxr 2/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=147,iface=MIXER,name='Mxr 2/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=163,iface=MIXER,name='Mxr 2/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=179,iface=MIXER,name='Mxr 2/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=36,iface=MIXER,name='Mxr 3/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=52,iface=MIXER,name='Mxr 3/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=196,iface=MIXER,name='Mxr 3/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=212,iface=MIXER,name='Mxr 3/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=228,iface=MIXER,name='Mxr 3/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=244,iface=MIXER,name='Mxr 3/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=260,iface=MIXER,name='Mxr 3/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=276,iface=MIXER,name='Mxr 3/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=68,iface=MIXER,name='Mxr 3/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=84,iface=MIXER,name='Mxr 3/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=100,iface=MIXER,name='Mxr 3/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=116,iface=MIXER,name='Mxr 3/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=132,iface=MIXER,name='Mxr 3/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=148,iface=MIXER,name='Mxr 3/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=164,iface=MIXER,name='Mxr 3/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=180,iface=MIXER,name='Mxr 3/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=37,iface=MIXER,name='Mxr 4/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=53,iface=MIXER,name='Mxr 4/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=197,iface=MIXER,name='Mxr 4/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=213,iface=MIXER,name='Mxr 4/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=229,iface=MIXER,name='Mxr 4/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=245,iface=MIXER,name='Mxr 4/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=261,iface=MIXER,name='Mxr 4/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=277,iface=MIXER,name='Mxr 4/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=69,iface=MIXER,name='Mxr 4/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=85,iface=MIXER,name='Mxr 4/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=101,iface=MIXER,name='Mxr 4/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=117,iface=MIXER,name='Mxr 4/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=133,iface=MIXER,name='Mxr 4/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=149,iface=MIXER,name='Mxr 4/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=165,iface=MIXER,name='Mxr 4/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=181,iface=MIXER,name='Mxr 4/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=38,iface=MIXER,name='Mxr 5/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=54,iface=MIXER,name='Mxr 5/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=198,iface=MIXER,name='Mxr 5/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=214,iface=MIXER,name='Mxr 5/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=230,iface=MIXER,name='Mxr 5/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=246,iface=MIXER,name='Mxr 5/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=262,iface=MIXER,name='Mxr 5/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=278,iface=MIXER,name='Mxr 5/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=70,iface=MIXER,name='Mxr 5/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=86,iface=MIXER,name='Mxr 5/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=102,iface=MIXER,name='Mxr 5/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=118,iface=MIXER,name='Mxr 5/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=134,iface=MIXER,name='Mxr 5/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=150,iface=MIXER,name='Mxr 5/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=166,iface=MIXER,name='Mxr 5/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=182,iface=MIXER,name='Mxr 5/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=39,iface=MIXER,name='Mxr 6/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=55,iface=MIXER,name='Mxr 6/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=199,iface=MIXER,name='Mxr 6/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=215,iface=MIXER,name='Mxr 6/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=231,iface=MIXER,name='Mxr 6/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=247,iface=MIXER,name='Mxr 6/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=263,iface=MIXER,name='Mxr 6/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=279,iface=MIXER,name='Mxr 6/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=71,iface=MIXER,name='Mxr 6/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=87,iface=MIXER,name='Mxr 6/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=103,iface=MIXER,name='Mxr 6/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=119,iface=MIXER,name='Mxr 6/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=135,iface=MIXER,name='Mxr 6/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=151,iface=MIXER,name='Mxr 6/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=167,iface=MIXER,name='Mxr 6/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=183,iface=MIXER,name='Mxr 6/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=40,iface=MIXER,name='Mxr 7/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=56,iface=MIXER,name='Mxr 7/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=200,iface=MIXER,name='Mxr 7/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=216,iface=MIXER,name='Mxr 7/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=232,iface=MIXER,name='Mxr 7/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=248,iface=MIXER,name='Mxr 7/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=264,iface=MIXER,name='Mxr 7/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=280,iface=MIXER,name='Mxr 7/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=72,iface=MIXER,name='Mxr 7/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=88,iface=MIXER,name='Mxr 7/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=104,iface=MIXER,name='Mxr 7/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=120,iface=MIXER,name='Mxr 7/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=136,iface=MIXER,name='Mxr 7/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=152,iface=MIXER,name='Mxr 7/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=168,iface=MIXER,name='Mxr 7/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=184,iface=MIXER,name='Mxr 7/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=41,iface=MIXER,name='Mxr 8/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=57,iface=MIXER,name='Mxr 8/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=201,iface=MIXER,name='Mxr 8/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=217,iface=MIXER,name='Mxr 8/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=233,iface=MIXER,name='Mxr 8/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=249,iface=MIXER,name='Mxr 8/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=265,iface=MIXER,name='Mxr 8/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=281,iface=MIXER,name='Mxr 8/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=73,iface=MIXER,name='Mxr 8/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=89,iface=MIXER,name='Mxr 8/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=105,iface=MIXER,name='Mxr 8/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=121,iface=MIXER,name='Mxr 8/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=137,iface=MIXER,name='Mxr 8/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=153,iface=MIXER,name='Mxr 8/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=169,iface=MIXER,name='Mxr 8/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=185,iface=MIXER,name='Mxr 8/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=42,iface=MIXER,name='Mxr 9/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=58,iface=MIXER,name='Mxr 9/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=202,iface=MIXER,name='Mxr 9/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=218,iface=MIXER,name='Mxr 9/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=234,iface=MIXER,name='Mxr 9/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=250,iface=MIXER,name='Mxr 9/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=266,iface=MIXER,name='Mxr 9/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=282,iface=MIXER,name='Mxr 9/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=74,iface=MIXER,name='Mxr 9/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=90,iface=MIXER,name='Mxr 9/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=106,iface=MIXER,name='Mxr 9/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=122,iface=MIXER,name='Mxr 9/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=138,iface=MIXER,name='Mxr 9/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=154,iface=MIXER,name='Mxr 9/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=170,iface=MIXER,name='Mxr 9/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=186,iface=MIXER,name='Mxr 9/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB diff --git a/snd-alpx-dkms/Controls/Alp442e-MIC_controls.txt b/snd-alpx-dkms/Controls/Alp442e-MIC_controls.txt new file mode 100644 index 0000000..96c41f6 --- /dev/null +++ b/snd-alpx-dkms/Controls/Alp442e-MIC_controls.txt @@ -0,0 +1,306 @@ +numid=13,iface=MIXER,name='AES Capture Volume' +numid=14,iface=MIXER,name='AES Capture Volume',index=1 +numid=15,iface=MIXER,name='AES Capture Volume',index=2 +numid=16,iface=MIXER,name='AES Capture Volume',index=3 +numid=21,iface=MIXER,name='AES Playback Volume' +numid=22,iface=MIXER,name='AES Playback Volume',index=1 +numid=23,iface=MIXER,name='AES Playback Volume',index=2 +numid=24,iface=MIXER,name='AES Playback Volume',index=3 +numid=298,iface=MIXER,name='AES SRC 1/2 Disable' +numid=299,iface=MIXER,name='AES SRC 3/4 Disable' +numid=9,iface=MIXER,name='Ana Capture Volume' +numid=10,iface=MIXER,name='Ana Capture Volume',index=1 +numid=11,iface=MIXER,name='Ana Capture Volume',index=2 +numid=12,iface=MIXER,name='Ana Capture Volume',index=3 +numid=17,iface=MIXER,name='Ana Playback Volume' +numid=18,iface=MIXER,name='Ana Playback Volume',index=1 +numid=19,iface=MIXER,name='Ana Playback Volume',index=2 +numid=20,iface=MIXER,name='Ana Playback Volume',index=3 +numid=290,iface=MIXER,name='Clk Eff' +numid=289,iface=MIXER,name='Clk Eff Src' +numid=294,iface=MIXER,name='Clk P0' +numid=295,iface=MIXER,name='Clk P1' +numid=296,iface=MIXER,name='Clk P2' +numid=297,iface=MIXER,name='Clk P3' +numid=293,iface=MIXER,name='Clk Src Down' +numid=292,iface=MIXER,name='Clk Src Up' +numid=300,iface=MIXER,name='Codec MIC Analog Capture Volume' +numid=301,iface=MIXER,name='Codec MIC Analog Capture Volume',index=1 +numid=302,iface=MIXER,name='Codec MIC Analog Capture Volume',index=2 +numid=303,iface=MIXER,name='Codec MIC Analog Capture Volume',index=3 +numid=1,iface=MIXER,name='DAW Capture Volume' +numid=2,iface=MIXER,name='DAW Capture Volume',index=1 +numid=3,iface=MIXER,name='DAW Capture Volume',index=2 +numid=4,iface=MIXER,name='DAW Capture Volume',index=3 +numid=5,iface=MIXER,name='DAW Capture Volume',index=4 +numid=6,iface=MIXER,name='DAW Capture Volume',index=5 +numid=7,iface=MIXER,name='DAW Capture Volume',index=6 +numid=8,iface=MIXER,name='DAW Capture Volume',index=7 +numid=25,iface=MIXER,name='DAW Playback Volume' +numid=26,iface=MIXER,name='DAW Playback Volume',index=1 +numid=27,iface=MIXER,name='DAW Playback Volume',index=2 +numid=28,iface=MIXER,name='DAW Playback Volume',index=3 +numid=29,iface=MIXER,name='DAW Playback Volume',index=4 +numid=30,iface=MIXER,name='DAW Playback Volume',index=5 +numid=31,iface=MIXER,name='DAW Playback Volume',index=6 +numid=32,iface=MIXER,name='DAW Playback Volume',index=7 +numid=304,iface=MIXER,name='McPh1' +numid=305,iface=MIXER,name='McPh2' +numid=306,iface=MIXER,name='McPh3' +numid=307,iface=MIXER,name='McPh4' +numid=33,iface=MIXER,name='Mxr 0/0 Playback Volume' +numid=49,iface=MIXER,name='Mxr 0/1 Playback Volume' +numid=193,iface=MIXER,name='Mxr 0/10 Playback Volume' +numid=209,iface=MIXER,name='Mxr 0/11 Playback Volume' +numid=225,iface=MIXER,name='Mxr 0/12 Playback Volume' +numid=241,iface=MIXER,name='Mxr 0/13 Playback Volume' +numid=257,iface=MIXER,name='Mxr 0/14 Playback Volume' +numid=273,iface=MIXER,name='Mxr 0/15 Playback Volume' +numid=65,iface=MIXER,name='Mxr 0/2 Playback Volume' +numid=81,iface=MIXER,name='Mxr 0/3 Playback Volume' +numid=97,iface=MIXER,name='Mxr 0/4 Playback Volume' +numid=113,iface=MIXER,name='Mxr 0/5 Playback Volume' +numid=129,iface=MIXER,name='Mxr 0/6 Playback Volume' +numid=145,iface=MIXER,name='Mxr 0/7 Playback Volume' +numid=161,iface=MIXER,name='Mxr 0/8 Playback Volume' +numid=177,iface=MIXER,name='Mxr 0/9 Playback Volume' +numid=34,iface=MIXER,name='Mxr 1/0 Playback Volume' +numid=50,iface=MIXER,name='Mxr 1/1 Playback Volume' +numid=194,iface=MIXER,name='Mxr 1/10 Playback Volume' +numid=210,iface=MIXER,name='Mxr 1/11 Playback Volume' +numid=226,iface=MIXER,name='Mxr 1/12 Playback Volume' +numid=242,iface=MIXER,name='Mxr 1/13 Playback Volume' +numid=258,iface=MIXER,name='Mxr 1/14 Playback Volume' +numid=274,iface=MIXER,name='Mxr 1/15 Playback Volume' +numid=66,iface=MIXER,name='Mxr 1/2 Playback Volume' +numid=82,iface=MIXER,name='Mxr 1/3 Playback Volume' +numid=98,iface=MIXER,name='Mxr 1/4 Playback Volume' +numid=114,iface=MIXER,name='Mxr 1/5 Playback Volume' +numid=130,iface=MIXER,name='Mxr 1/6 Playback Volume' +numid=146,iface=MIXER,name='Mxr 1/7 Playback Volume' +numid=162,iface=MIXER,name='Mxr 1/8 Playback Volume' +numid=178,iface=MIXER,name='Mxr 1/9 Playback Volume' +numid=43,iface=MIXER,name='Mxr 10/0 Playback Volume' +numid=59,iface=MIXER,name='Mxr 10/1 Playback Volume' +numid=203,iface=MIXER,name='Mxr 10/10 Playback Volume' +numid=219,iface=MIXER,name='Mxr 10/11 Playback Volume' +numid=235,iface=MIXER,name='Mxr 10/12 Playback Volume' +numid=251,iface=MIXER,name='Mxr 10/13 Playback Volume' +numid=267,iface=MIXER,name='Mxr 10/14 Playback Volume' +numid=283,iface=MIXER,name='Mxr 10/15 Playback Volume' +numid=75,iface=MIXER,name='Mxr 10/2 Playback Volume' +numid=91,iface=MIXER,name='Mxr 10/3 Playback Volume' +numid=107,iface=MIXER,name='Mxr 10/4 Playback Volume' +numid=123,iface=MIXER,name='Mxr 10/5 Playback Volume' +numid=139,iface=MIXER,name='Mxr 10/6 Playback Volume' +numid=155,iface=MIXER,name='Mxr 10/7 Playback Volume' +numid=171,iface=MIXER,name='Mxr 10/8 Playback Volume' +numid=187,iface=MIXER,name='Mxr 10/9 Playback Volume' +numid=44,iface=MIXER,name='Mxr 11/0 Playback Volume' +numid=60,iface=MIXER,name='Mxr 11/1 Playback Volume' +numid=204,iface=MIXER,name='Mxr 11/10 Playback Volume' +numid=220,iface=MIXER,name='Mxr 11/11 Playback Volume' +numid=236,iface=MIXER,name='Mxr 11/12 Playback Volume' +numid=252,iface=MIXER,name='Mxr 11/13 Playback Volume' +numid=268,iface=MIXER,name='Mxr 11/14 Playback Volume' +numid=284,iface=MIXER,name='Mxr 11/15 Playback Volume' +numid=76,iface=MIXER,name='Mxr 11/2 Playback Volume' +numid=92,iface=MIXER,name='Mxr 11/3 Playback Volume' +numid=108,iface=MIXER,name='Mxr 11/4 Playback Volume' +numid=124,iface=MIXER,name='Mxr 11/5 Playback Volume' +numid=140,iface=MIXER,name='Mxr 11/6 Playback Volume' +numid=156,iface=MIXER,name='Mxr 11/7 Playback Volume' +numid=172,iface=MIXER,name='Mxr 11/8 Playback Volume' +numid=188,iface=MIXER,name='Mxr 11/9 Playback Volume' +numid=45,iface=MIXER,name='Mxr 12/0 Playback Volume' +numid=61,iface=MIXER,name='Mxr 12/1 Playback Volume' +numid=205,iface=MIXER,name='Mxr 12/10 Playback Volume' +numid=221,iface=MIXER,name='Mxr 12/11 Playback Volume' +numid=237,iface=MIXER,name='Mxr 12/12 Playback Volume' +numid=253,iface=MIXER,name='Mxr 12/13 Playback Volume' +numid=269,iface=MIXER,name='Mxr 12/14 Playback Volume' +numid=285,iface=MIXER,name='Mxr 12/15 Playback Volume' +numid=77,iface=MIXER,name='Mxr 12/2 Playback Volume' +numid=93,iface=MIXER,name='Mxr 12/3 Playback Volume' +numid=109,iface=MIXER,name='Mxr 12/4 Playback Volume' +numid=125,iface=MIXER,name='Mxr 12/5 Playback Volume' +numid=141,iface=MIXER,name='Mxr 12/6 Playback Volume' +numid=157,iface=MIXER,name='Mxr 12/7 Playback Volume' +numid=173,iface=MIXER,name='Mxr 12/8 Playback Volume' +numid=189,iface=MIXER,name='Mxr 12/9 Playback Volume' +numid=46,iface=MIXER,name='Mxr 13/0 Playback Volume' +numid=62,iface=MIXER,name='Mxr 13/1 Playback Volume' +numid=206,iface=MIXER,name='Mxr 13/10 Playback Volume' +numid=222,iface=MIXER,name='Mxr 13/11 Playback Volume' +numid=238,iface=MIXER,name='Mxr 13/12 Playback Volume' +numid=254,iface=MIXER,name='Mxr 13/13 Playback Volume' +numid=270,iface=MIXER,name='Mxr 13/14 Playback Volume' +numid=286,iface=MIXER,name='Mxr 13/15 Playback Volume' +numid=78,iface=MIXER,name='Mxr 13/2 Playback Volume' +numid=94,iface=MIXER,name='Mxr 13/3 Playback Volume' +numid=110,iface=MIXER,name='Mxr 13/4 Playback Volume' +numid=126,iface=MIXER,name='Mxr 13/5 Playback Volume' +numid=142,iface=MIXER,name='Mxr 13/6 Playback Volume' +numid=158,iface=MIXER,name='Mxr 13/7 Playback Volume' +numid=174,iface=MIXER,name='Mxr 13/8 Playback Volume' +numid=190,iface=MIXER,name='Mxr 13/9 Playback Volume' +numid=47,iface=MIXER,name='Mxr 14/0 Playback Volume' +numid=63,iface=MIXER,name='Mxr 14/1 Playback Volume' +numid=207,iface=MIXER,name='Mxr 14/10 Playback Volume' +numid=223,iface=MIXER,name='Mxr 14/11 Playback Volume' +numid=239,iface=MIXER,name='Mxr 14/12 Playback Volume' +numid=255,iface=MIXER,name='Mxr 14/13 Playback Volume' +numid=271,iface=MIXER,name='Mxr 14/14 Playback Volume' +numid=287,iface=MIXER,name='Mxr 14/15 Playback Volume' +numid=79,iface=MIXER,name='Mxr 14/2 Playback Volume' +numid=95,iface=MIXER,name='Mxr 14/3 Playback Volume' +numid=111,iface=MIXER,name='Mxr 14/4 Playback Volume' +numid=127,iface=MIXER,name='Mxr 14/5 Playback Volume' +numid=143,iface=MIXER,name='Mxr 14/6 Playback Volume' +numid=159,iface=MIXER,name='Mxr 14/7 Playback Volume' +numid=175,iface=MIXER,name='Mxr 14/8 Playback Volume' +numid=191,iface=MIXER,name='Mxr 14/9 Playback Volume' +numid=48,iface=MIXER,name='Mxr 15/0 Playback Volume' +numid=64,iface=MIXER,name='Mxr 15/1 Playback Volume' +numid=208,iface=MIXER,name='Mxr 15/10 Playback Volume' +numid=224,iface=MIXER,name='Mxr 15/11 Playback Volume' +numid=240,iface=MIXER,name='Mxr 15/12 Playback Volume' +numid=256,iface=MIXER,name='Mxr 15/13 Playback Volume' +numid=272,iface=MIXER,name='Mxr 15/14 Playback Volume' +numid=288,iface=MIXER,name='Mxr 15/15 Playback Volume' +numid=80,iface=MIXER,name='Mxr 15/2 Playback Volume' +numid=96,iface=MIXER,name='Mxr 15/3 Playback Volume' +numid=112,iface=MIXER,name='Mxr 15/4 Playback Volume' +numid=128,iface=MIXER,name='Mxr 15/5 Playback Volume' +numid=144,iface=MIXER,name='Mxr 15/6 Playback Volume' +numid=160,iface=MIXER,name='Mxr 15/7 Playback Volume' +numid=176,iface=MIXER,name='Mxr 15/8 Playback Volume' +numid=192,iface=MIXER,name='Mxr 15/9 Playback Volume' +numid=35,iface=MIXER,name='Mxr 2/0 Playback Volume' +numid=51,iface=MIXER,name='Mxr 2/1 Playback Volume' +numid=195,iface=MIXER,name='Mxr 2/10 Playback Volume' +numid=211,iface=MIXER,name='Mxr 2/11 Playback Volume' +numid=227,iface=MIXER,name='Mxr 2/12 Playback Volume' +numid=243,iface=MIXER,name='Mxr 2/13 Playback Volume' +numid=259,iface=MIXER,name='Mxr 2/14 Playback Volume' +numid=275,iface=MIXER,name='Mxr 2/15 Playback Volume' +numid=67,iface=MIXER,name='Mxr 2/2 Playback Volume' +numid=83,iface=MIXER,name='Mxr 2/3 Playback Volume' +numid=99,iface=MIXER,name='Mxr 2/4 Playback Volume' +numid=115,iface=MIXER,name='Mxr 2/5 Playback Volume' +numid=131,iface=MIXER,name='Mxr 2/6 Playback Volume' +numid=147,iface=MIXER,name='Mxr 2/7 Playback Volume' +numid=163,iface=MIXER,name='Mxr 2/8 Playback Volume' +numid=179,iface=MIXER,name='Mxr 2/9 Playback Volume' +numid=36,iface=MIXER,name='Mxr 3/0 Playback Volume' +numid=52,iface=MIXER,name='Mxr 3/1 Playback Volume' +numid=196,iface=MIXER,name='Mxr 3/10 Playback Volume' +numid=212,iface=MIXER,name='Mxr 3/11 Playback Volume' +numid=228,iface=MIXER,name='Mxr 3/12 Playback Volume' +numid=244,iface=MIXER,name='Mxr 3/13 Playback Volume' +numid=260,iface=MIXER,name='Mxr 3/14 Playback Volume' +numid=276,iface=MIXER,name='Mxr 3/15 Playback Volume' +numid=68,iface=MIXER,name='Mxr 3/2 Playback Volume' +numid=84,iface=MIXER,name='Mxr 3/3 Playback Volume' +numid=100,iface=MIXER,name='Mxr 3/4 Playback Volume' +numid=116,iface=MIXER,name='Mxr 3/5 Playback Volume' +numid=132,iface=MIXER,name='Mxr 3/6 Playback Volume' +numid=148,iface=MIXER,name='Mxr 3/7 Playback Volume' +numid=164,iface=MIXER,name='Mxr 3/8 Playback Volume' +numid=180,iface=MIXER,name='Mxr 3/9 Playback Volume' +numid=37,iface=MIXER,name='Mxr 4/0 Playback Volume' +numid=53,iface=MIXER,name='Mxr 4/1 Playback Volume' +numid=197,iface=MIXER,name='Mxr 4/10 Playback Volume' +numid=213,iface=MIXER,name='Mxr 4/11 Playback Volume' +numid=229,iface=MIXER,name='Mxr 4/12 Playback Volume' +numid=245,iface=MIXER,name='Mxr 4/13 Playback Volume' +numid=261,iface=MIXER,name='Mxr 4/14 Playback Volume' +numid=277,iface=MIXER,name='Mxr 4/15 Playback Volume' +numid=69,iface=MIXER,name='Mxr 4/2 Playback Volume' +numid=85,iface=MIXER,name='Mxr 4/3 Playback Volume' +numid=101,iface=MIXER,name='Mxr 4/4 Playback Volume' +numid=117,iface=MIXER,name='Mxr 4/5 Playback Volume' +numid=133,iface=MIXER,name='Mxr 4/6 Playback Volume' +numid=149,iface=MIXER,name='Mxr 4/7 Playback Volume' +numid=165,iface=MIXER,name='Mxr 4/8 Playback Volume' +numid=181,iface=MIXER,name='Mxr 4/9 Playback Volume' +numid=38,iface=MIXER,name='Mxr 5/0 Playback Volume' +numid=54,iface=MIXER,name='Mxr 5/1 Playback Volume' +numid=198,iface=MIXER,name='Mxr 5/10 Playback Volume' +numid=214,iface=MIXER,name='Mxr 5/11 Playback Volume' +numid=230,iface=MIXER,name='Mxr 5/12 Playback Volume' +numid=246,iface=MIXER,name='Mxr 5/13 Playback Volume' +numid=262,iface=MIXER,name='Mxr 5/14 Playback Volume' +numid=278,iface=MIXER,name='Mxr 5/15 Playback Volume' +numid=70,iface=MIXER,name='Mxr 5/2 Playback Volume' +numid=86,iface=MIXER,name='Mxr 5/3 Playback Volume' +numid=102,iface=MIXER,name='Mxr 5/4 Playback Volume' +numid=118,iface=MIXER,name='Mxr 5/5 Playback Volume' +numid=134,iface=MIXER,name='Mxr 5/6 Playback Volume' +numid=150,iface=MIXER,name='Mxr 5/7 Playback Volume' +numid=166,iface=MIXER,name='Mxr 5/8 Playback Volume' +numid=182,iface=MIXER,name='Mxr 5/9 Playback Volume' +numid=39,iface=MIXER,name='Mxr 6/0 Playback Volume' +numid=55,iface=MIXER,name='Mxr 6/1 Playback Volume' +numid=199,iface=MIXER,name='Mxr 6/10 Playback Volume' +numid=215,iface=MIXER,name='Mxr 6/11 Playback Volume' +numid=231,iface=MIXER,name='Mxr 6/12 Playback Volume' +numid=247,iface=MIXER,name='Mxr 6/13 Playback Volume' +numid=263,iface=MIXER,name='Mxr 6/14 Playback Volume' +numid=279,iface=MIXER,name='Mxr 6/15 Playback Volume' +numid=71,iface=MIXER,name='Mxr 6/2 Playback Volume' +numid=87,iface=MIXER,name='Mxr 6/3 Playback Volume' +numid=103,iface=MIXER,name='Mxr 6/4 Playback Volume' +numid=119,iface=MIXER,name='Mxr 6/5 Playback Volume' +numid=135,iface=MIXER,name='Mxr 6/6 Playback Volume' +numid=151,iface=MIXER,name='Mxr 6/7 Playback Volume' +numid=167,iface=MIXER,name='Mxr 6/8 Playback Volume' +numid=183,iface=MIXER,name='Mxr 6/9 Playback Volume' +numid=40,iface=MIXER,name='Mxr 7/0 Playback Volume' +numid=56,iface=MIXER,name='Mxr 7/1 Playback Volume' +numid=200,iface=MIXER,name='Mxr 7/10 Playback Volume' +numid=216,iface=MIXER,name='Mxr 7/11 Playback Volume' +numid=232,iface=MIXER,name='Mxr 7/12 Playback Volume' +numid=248,iface=MIXER,name='Mxr 7/13 Playback Volume' +numid=264,iface=MIXER,name='Mxr 7/14 Playback Volume' +numid=280,iface=MIXER,name='Mxr 7/15 Playback Volume' +numid=72,iface=MIXER,name='Mxr 7/2 Playback Volume' +numid=88,iface=MIXER,name='Mxr 7/3 Playback Volume' +numid=104,iface=MIXER,name='Mxr 7/4 Playback Volume' +numid=120,iface=MIXER,name='Mxr 7/5 Playback Volume' +numid=136,iface=MIXER,name='Mxr 7/6 Playback Volume' +numid=152,iface=MIXER,name='Mxr 7/7 Playback Volume' +numid=168,iface=MIXER,name='Mxr 7/8 Playback Volume' +numid=184,iface=MIXER,name='Mxr 7/9 Playback Volume' +numid=41,iface=MIXER,name='Mxr 8/0 Playback Volume' +numid=57,iface=MIXER,name='Mxr 8/1 Playback Volume' +numid=201,iface=MIXER,name='Mxr 8/10 Playback Volume' +numid=217,iface=MIXER,name='Mxr 8/11 Playback Volume' +numid=233,iface=MIXER,name='Mxr 8/12 Playback Volume' +numid=249,iface=MIXER,name='Mxr 8/13 Playback Volume' +numid=265,iface=MIXER,name='Mxr 8/14 Playback Volume' +numid=281,iface=MIXER,name='Mxr 8/15 Playback Volume' +numid=73,iface=MIXER,name='Mxr 8/2 Playback Volume' +numid=89,iface=MIXER,name='Mxr 8/3 Playback Volume' +numid=105,iface=MIXER,name='Mxr 8/4 Playback Volume' +numid=121,iface=MIXER,name='Mxr 8/5 Playback Volume' +numid=137,iface=MIXER,name='Mxr 8/6 Playback Volume' +numid=153,iface=MIXER,name='Mxr 8/7 Playback Volume' +numid=169,iface=MIXER,name='Mxr 8/8 Playback Volume' +numid=185,iface=MIXER,name='Mxr 8/9 Playback Volume' +numid=42,iface=MIXER,name='Mxr 9/0 Playback Volume' +numid=58,iface=MIXER,name='Mxr 9/1 Playback Volume' +numid=202,iface=MIXER,name='Mxr 9/10 Playback Volume' +numid=218,iface=MIXER,name='Mxr 9/11 Playback Volume' +numid=234,iface=MIXER,name='Mxr 9/12 Playback Volume' +numid=250,iface=MIXER,name='Mxr 9/13 Playback Volume' +numid=266,iface=MIXER,name='Mxr 9/14 Playback Volume' +numid=282,iface=MIXER,name='Mxr 9/15 Playback Volume' +numid=74,iface=MIXER,name='Mxr 9/2 Playback Volume' +numid=90,iface=MIXER,name='Mxr 9/3 Playback Volume' +numid=106,iface=MIXER,name='Mxr 9/4 Playback Volume' +numid=122,iface=MIXER,name='Mxr 9/5 Playback Volume' +numid=138,iface=MIXER,name='Mxr 9/6 Playback Volume' +numid=154,iface=MIXER,name='Mxr 9/7 Playback Volume' +numid=170,iface=MIXER,name='Mxr 9/8 Playback Volume' +numid=186,iface=MIXER,name='Mxr 9/9 Playback Volume' diff --git a/snd-alpx-dkms/Controls/Alp442e_contents.txt b/snd-alpx-dkms/Controls/Alp442e_contents.txt new file mode 100644 index 0000000..e352005 --- /dev/null +++ b/snd-alpx-dkms/Controls/Alp442e_contents.txt @@ -0,0 +1,1242 @@ +numid=13,iface=MIXER,name='AES Capture Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=14,iface=MIXER,name='AES Capture Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=15,iface=MIXER,name='AES Capture Volume',index=2 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=16,iface=MIXER,name='AES Capture Volume',index=3 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=21,iface=MIXER,name='AES Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=22,iface=MIXER,name='AES Playback Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=23,iface=MIXER,name='AES Playback Volume',index=2 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=24,iface=MIXER,name='AES Playback Volume',index=3 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=298,iface=MIXER,name='AES SRC 1/2 Disable' + ; type=BOOLEAN,access=rw------,values=1 + : values=off +numid=299,iface=MIXER,name='AES SRC 3/4 Disable' + ; type=BOOLEAN,access=rw------,values=1 + : values=off +numid=9,iface=MIXER,name='Ana Capture Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=10,iface=MIXER,name='Ana Capture Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=11,iface=MIXER,name='Ana Capture Volume',index=2 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=12,iface=MIXER,name='Ana Capture Volume',index=3 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=17,iface=MIXER,name='Ana Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=18,iface=MIXER,name='Ana Playback Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=19,iface=MIXER,name='Ana Playback Volume',index=2 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=20,iface=MIXER,name='Ana Playback Volume',index=3 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=290,iface=MIXER,name='Clk Eff' + ; type=ENUMERATED,access=r--v----,values=1,items=14 + ; Item #0 '8kHz' + ; Item #1 '11.025kHz' + ; Item #2 '16kHz' + ; Item #3 '22.05kHz' + ; Item #4 '24kHz' + ; Item #5 '32kHz' + ; Item #6 '44.1kHz' + ; Item #7 '48kHz' + ; Item #8 '64kHz' + ; Item #9 '88.2kHz' + ; Item #10 '96kHz' + ; Item #11 '128kHz' + ; Item #12 '176,4kHz' + ; Item #13 '192kHz' + : values=7 +numid=289,iface=MIXER,name='Clk Eff Src' + ; type=ENUMERATED,access=r-------,values=1,items=6 + ; Item #0 'Internal' + ; Item #1 'SIC' + ; Item #2 'Word Clk' + ; Item #3 'AES Syn' + ; Item #4 'AES Aud 1/2' + ; Item #5 'AES Aud 3/4' + : values=0 +numid=294,iface=MIXER,name='Clk P0' + ; type=ENUMERATED,access=rw------,values=1,items=6 + ; Item #0 'Internal' + ; Item #1 'SIC' + ; Item #2 'Word Clk' + ; Item #3 'AES Syn' + ; Item #4 'AES Aud 1/2' + ; Item #5 'AES Aud 3/4' + : values=0 +numid=295,iface=MIXER,name='Clk P1' + ; type=ENUMERATED,access=rw------,values=1,items=6 + ; Item #0 'Internal' + ; Item #1 'SIC' + ; Item #2 'Word Clk' + ; Item #3 'AES Syn' + ; Item #4 'AES Aud 1/2' + ; Item #5 'AES Aud 3/4' + : values=0 +numid=296,iface=MIXER,name='Clk P2' + ; type=ENUMERATED,access=rw------,values=1,items=6 + ; Item #0 'Internal' + ; Item #1 'SIC' + ; Item #2 'Word Clk' + ; Item #3 'AES Syn' + ; Item #4 'AES Aud 1/2' + ; Item #5 'AES Aud 3/4' + : values=0 +numid=297,iface=MIXER,name='Clk P3' + ; type=ENUMERATED,access=rw------,values=1,items=6 + ; Item #0 'Internal' + ; Item #1 'SIC' + ; Item #2 'Word Clk' + ; Item #3 'AES Syn' + ; Item #4 'AES Aud 1/2' + ; Item #5 'AES Aud 3/4' + : values=0 +numid=293,iface=MIXER,name='Clk Src Down' + ; type=BOOLEAN,access=rw------,values=1 + : values=on +numid=292,iface=MIXER,name='Clk Src Up' + ; type=BOOLEAN,access=rw------,values=1 + : values=on +numid=300,iface=MIXER,name='Codec Analog Capture Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=82,step=0 + : values=1 + | dBminmaxmute-min=-24.00dB,max=16.00dB +numid=301,iface=MIXER,name='Codec Analog Capture Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=82,step=0 + : values=1 + | dBminmaxmute-min=-24.00dB,max=16.00dB +numid=302,iface=MIXER,name='Codec Analog Capture Volume',index=2 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=82,step=0 + : values=1 + | dBminmaxmute-min=-24.00dB,max=16.00dB +numid=303,iface=MIXER,name='Codec Analog Capture Volume',index=3 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=82,step=0 + : values=1 + | dBminmaxmute-min=-24.00dB,max=16.00dB +numid=1,iface=MIXER,name='DAW Capture Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=2,iface=MIXER,name='DAW Capture Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=3,iface=MIXER,name='DAW Capture Volume',index=2 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=4,iface=MIXER,name='DAW Capture Volume',index=3 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=5,iface=MIXER,name='DAW Capture Volume',index=4 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=6,iface=MIXER,name='DAW Capture Volume',index=5 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=7,iface=MIXER,name='DAW Capture Volume',index=6 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=8,iface=MIXER,name='DAW Capture Volume',index=7 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=25,iface=MIXER,name='DAW Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=26,iface=MIXER,name='DAW Playback Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=27,iface=MIXER,name='DAW Playback Volume',index=2 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=28,iface=MIXER,name='DAW Playback Volume',index=3 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=29,iface=MIXER,name='DAW Playback Volume',index=4 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=30,iface=MIXER,name='DAW Playback Volume',index=5 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=31,iface=MIXER,name='DAW Playback Volume',index=6 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=32,iface=MIXER,name='DAW Playback Volume',index=7 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=33,iface=MIXER,name='Mxr 0/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=49,iface=MIXER,name='Mxr 0/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=193,iface=MIXER,name='Mxr 0/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=209,iface=MIXER,name='Mxr 0/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=225,iface=MIXER,name='Mxr 0/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=241,iface=MIXER,name='Mxr 0/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=257,iface=MIXER,name='Mxr 0/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=273,iface=MIXER,name='Mxr 0/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=65,iface=MIXER,name='Mxr 0/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=81,iface=MIXER,name='Mxr 0/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=97,iface=MIXER,name='Mxr 0/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=113,iface=MIXER,name='Mxr 0/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=129,iface=MIXER,name='Mxr 0/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=145,iface=MIXER,name='Mxr 0/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=161,iface=MIXER,name='Mxr 0/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=177,iface=MIXER,name='Mxr 0/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=34,iface=MIXER,name='Mxr 1/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=50,iface=MIXER,name='Mxr 1/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=194,iface=MIXER,name='Mxr 1/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=210,iface=MIXER,name='Mxr 1/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=226,iface=MIXER,name='Mxr 1/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=242,iface=MIXER,name='Mxr 1/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=258,iface=MIXER,name='Mxr 1/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=274,iface=MIXER,name='Mxr 1/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=66,iface=MIXER,name='Mxr 1/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=82,iface=MIXER,name='Mxr 1/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=98,iface=MIXER,name='Mxr 1/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=114,iface=MIXER,name='Mxr 1/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=130,iface=MIXER,name='Mxr 1/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=146,iface=MIXER,name='Mxr 1/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=162,iface=MIXER,name='Mxr 1/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=178,iface=MIXER,name='Mxr 1/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=43,iface=MIXER,name='Mxr 10/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=59,iface=MIXER,name='Mxr 10/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=203,iface=MIXER,name='Mxr 10/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=219,iface=MIXER,name='Mxr 10/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=235,iface=MIXER,name='Mxr 10/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=251,iface=MIXER,name='Mxr 10/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=267,iface=MIXER,name='Mxr 10/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=283,iface=MIXER,name='Mxr 10/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=75,iface=MIXER,name='Mxr 10/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=91,iface=MIXER,name='Mxr 10/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=107,iface=MIXER,name='Mxr 10/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=123,iface=MIXER,name='Mxr 10/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=139,iface=MIXER,name='Mxr 10/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=155,iface=MIXER,name='Mxr 10/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=171,iface=MIXER,name='Mxr 10/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=187,iface=MIXER,name='Mxr 10/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=44,iface=MIXER,name='Mxr 11/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=60,iface=MIXER,name='Mxr 11/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=204,iface=MIXER,name='Mxr 11/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=220,iface=MIXER,name='Mxr 11/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=236,iface=MIXER,name='Mxr 11/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=252,iface=MIXER,name='Mxr 11/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=268,iface=MIXER,name='Mxr 11/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=284,iface=MIXER,name='Mxr 11/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=76,iface=MIXER,name='Mxr 11/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=92,iface=MIXER,name='Mxr 11/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=108,iface=MIXER,name='Mxr 11/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=124,iface=MIXER,name='Mxr 11/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=140,iface=MIXER,name='Mxr 11/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=156,iface=MIXER,name='Mxr 11/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=172,iface=MIXER,name='Mxr 11/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=188,iface=MIXER,name='Mxr 11/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=45,iface=MIXER,name='Mxr 12/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=61,iface=MIXER,name='Mxr 12/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=205,iface=MIXER,name='Mxr 12/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=221,iface=MIXER,name='Mxr 12/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=237,iface=MIXER,name='Mxr 12/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=253,iface=MIXER,name='Mxr 12/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=269,iface=MIXER,name='Mxr 12/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=285,iface=MIXER,name='Mxr 12/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=77,iface=MIXER,name='Mxr 12/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=93,iface=MIXER,name='Mxr 12/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=109,iface=MIXER,name='Mxr 12/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=125,iface=MIXER,name='Mxr 12/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=141,iface=MIXER,name='Mxr 12/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=157,iface=MIXER,name='Mxr 12/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=173,iface=MIXER,name='Mxr 12/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=189,iface=MIXER,name='Mxr 12/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=46,iface=MIXER,name='Mxr 13/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=62,iface=MIXER,name='Mxr 13/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=206,iface=MIXER,name='Mxr 13/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=222,iface=MIXER,name='Mxr 13/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=238,iface=MIXER,name='Mxr 13/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=254,iface=MIXER,name='Mxr 13/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=270,iface=MIXER,name='Mxr 13/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=286,iface=MIXER,name='Mxr 13/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=78,iface=MIXER,name='Mxr 13/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=94,iface=MIXER,name='Mxr 13/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=110,iface=MIXER,name='Mxr 13/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=126,iface=MIXER,name='Mxr 13/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=142,iface=MIXER,name='Mxr 13/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=158,iface=MIXER,name='Mxr 13/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=174,iface=MIXER,name='Mxr 13/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=190,iface=MIXER,name='Mxr 13/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=47,iface=MIXER,name='Mxr 14/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=63,iface=MIXER,name='Mxr 14/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=207,iface=MIXER,name='Mxr 14/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=223,iface=MIXER,name='Mxr 14/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=239,iface=MIXER,name='Mxr 14/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=255,iface=MIXER,name='Mxr 14/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=271,iface=MIXER,name='Mxr 14/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=287,iface=MIXER,name='Mxr 14/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=79,iface=MIXER,name='Mxr 14/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=95,iface=MIXER,name='Mxr 14/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=111,iface=MIXER,name='Mxr 14/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=127,iface=MIXER,name='Mxr 14/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=143,iface=MIXER,name='Mxr 14/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=159,iface=MIXER,name='Mxr 14/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=175,iface=MIXER,name='Mxr 14/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=191,iface=MIXER,name='Mxr 14/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=48,iface=MIXER,name='Mxr 15/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=64,iface=MIXER,name='Mxr 15/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=208,iface=MIXER,name='Mxr 15/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=224,iface=MIXER,name='Mxr 15/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=240,iface=MIXER,name='Mxr 15/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=256,iface=MIXER,name='Mxr 15/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=272,iface=MIXER,name='Mxr 15/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=288,iface=MIXER,name='Mxr 15/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=80,iface=MIXER,name='Mxr 15/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=96,iface=MIXER,name='Mxr 15/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=112,iface=MIXER,name='Mxr 15/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=128,iface=MIXER,name='Mxr 15/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=144,iface=MIXER,name='Mxr 15/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=160,iface=MIXER,name='Mxr 15/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=176,iface=MIXER,name='Mxr 15/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=192,iface=MIXER,name='Mxr 15/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=35,iface=MIXER,name='Mxr 2/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=51,iface=MIXER,name='Mxr 2/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=195,iface=MIXER,name='Mxr 2/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=211,iface=MIXER,name='Mxr 2/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=227,iface=MIXER,name='Mxr 2/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=243,iface=MIXER,name='Mxr 2/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=259,iface=MIXER,name='Mxr 2/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=275,iface=MIXER,name='Mxr 2/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=67,iface=MIXER,name='Mxr 2/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=83,iface=MIXER,name='Mxr 2/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=99,iface=MIXER,name='Mxr 2/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=115,iface=MIXER,name='Mxr 2/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=131,iface=MIXER,name='Mxr 2/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=147,iface=MIXER,name='Mxr 2/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=163,iface=MIXER,name='Mxr 2/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=179,iface=MIXER,name='Mxr 2/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=36,iface=MIXER,name='Mxr 3/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=52,iface=MIXER,name='Mxr 3/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=196,iface=MIXER,name='Mxr 3/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=212,iface=MIXER,name='Mxr 3/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=228,iface=MIXER,name='Mxr 3/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=244,iface=MIXER,name='Mxr 3/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=260,iface=MIXER,name='Mxr 3/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=276,iface=MIXER,name='Mxr 3/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=68,iface=MIXER,name='Mxr 3/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=84,iface=MIXER,name='Mxr 3/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=100,iface=MIXER,name='Mxr 3/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=116,iface=MIXER,name='Mxr 3/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=132,iface=MIXER,name='Mxr 3/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=148,iface=MIXER,name='Mxr 3/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=164,iface=MIXER,name='Mxr 3/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=180,iface=MIXER,name='Mxr 3/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=37,iface=MIXER,name='Mxr 4/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=53,iface=MIXER,name='Mxr 4/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=197,iface=MIXER,name='Mxr 4/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=213,iface=MIXER,name='Mxr 4/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=229,iface=MIXER,name='Mxr 4/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=245,iface=MIXER,name='Mxr 4/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=261,iface=MIXER,name='Mxr 4/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=277,iface=MIXER,name='Mxr 4/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=69,iface=MIXER,name='Mxr 4/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=85,iface=MIXER,name='Mxr 4/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=101,iface=MIXER,name='Mxr 4/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=117,iface=MIXER,name='Mxr 4/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=133,iface=MIXER,name='Mxr 4/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=149,iface=MIXER,name='Mxr 4/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=165,iface=MIXER,name='Mxr 4/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=181,iface=MIXER,name='Mxr 4/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=38,iface=MIXER,name='Mxr 5/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=54,iface=MIXER,name='Mxr 5/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=198,iface=MIXER,name='Mxr 5/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=214,iface=MIXER,name='Mxr 5/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=230,iface=MIXER,name='Mxr 5/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=246,iface=MIXER,name='Mxr 5/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=262,iface=MIXER,name='Mxr 5/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=278,iface=MIXER,name='Mxr 5/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=70,iface=MIXER,name='Mxr 5/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=86,iface=MIXER,name='Mxr 5/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=102,iface=MIXER,name='Mxr 5/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=118,iface=MIXER,name='Mxr 5/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=134,iface=MIXER,name='Mxr 5/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=150,iface=MIXER,name='Mxr 5/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=166,iface=MIXER,name='Mxr 5/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=182,iface=MIXER,name='Mxr 5/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=39,iface=MIXER,name='Mxr 6/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=55,iface=MIXER,name='Mxr 6/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=199,iface=MIXER,name='Mxr 6/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=215,iface=MIXER,name='Mxr 6/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=231,iface=MIXER,name='Mxr 6/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=247,iface=MIXER,name='Mxr 6/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=263,iface=MIXER,name='Mxr 6/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=279,iface=MIXER,name='Mxr 6/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=71,iface=MIXER,name='Mxr 6/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=87,iface=MIXER,name='Mxr 6/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=103,iface=MIXER,name='Mxr 6/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=119,iface=MIXER,name='Mxr 6/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=135,iface=MIXER,name='Mxr 6/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=151,iface=MIXER,name='Mxr 6/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=167,iface=MIXER,name='Mxr 6/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=183,iface=MIXER,name='Mxr 6/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=40,iface=MIXER,name='Mxr 7/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=56,iface=MIXER,name='Mxr 7/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=200,iface=MIXER,name='Mxr 7/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=216,iface=MIXER,name='Mxr 7/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=232,iface=MIXER,name='Mxr 7/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=248,iface=MIXER,name='Mxr 7/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=264,iface=MIXER,name='Mxr 7/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=280,iface=MIXER,name='Mxr 7/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=72,iface=MIXER,name='Mxr 7/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=88,iface=MIXER,name='Mxr 7/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=104,iface=MIXER,name='Mxr 7/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=120,iface=MIXER,name='Mxr 7/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=136,iface=MIXER,name='Mxr 7/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=152,iface=MIXER,name='Mxr 7/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=168,iface=MIXER,name='Mxr 7/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=184,iface=MIXER,name='Mxr 7/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=41,iface=MIXER,name='Mxr 8/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=57,iface=MIXER,name='Mxr 8/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=201,iface=MIXER,name='Mxr 8/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=217,iface=MIXER,name='Mxr 8/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=233,iface=MIXER,name='Mxr 8/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=249,iface=MIXER,name='Mxr 8/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=265,iface=MIXER,name='Mxr 8/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=281,iface=MIXER,name='Mxr 8/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=73,iface=MIXER,name='Mxr 8/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=89,iface=MIXER,name='Mxr 8/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=105,iface=MIXER,name='Mxr 8/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=121,iface=MIXER,name='Mxr 8/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=137,iface=MIXER,name='Mxr 8/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=153,iface=MIXER,name='Mxr 8/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=169,iface=MIXER,name='Mxr 8/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=185,iface=MIXER,name='Mxr 8/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=42,iface=MIXER,name='Mxr 9/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=58,iface=MIXER,name='Mxr 9/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=202,iface=MIXER,name='Mxr 9/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=218,iface=MIXER,name='Mxr 9/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=234,iface=MIXER,name='Mxr 9/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=250,iface=MIXER,name='Mxr 9/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=266,iface=MIXER,name='Mxr 9/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=282,iface=MIXER,name='Mxr 9/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=74,iface=MIXER,name='Mxr 9/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=90,iface=MIXER,name='Mxr 9/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=106,iface=MIXER,name='Mxr 9/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=122,iface=MIXER,name='Mxr 9/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=138,iface=MIXER,name='Mxr 9/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=154,iface=MIXER,name='Mxr 9/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=170,iface=MIXER,name='Mxr 9/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=186,iface=MIXER,name='Mxr 9/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB diff --git a/snd-alpx-dkms/Controls/Alp442e_controls.txt b/snd-alpx-dkms/Controls/Alp442e_controls.txt new file mode 100644 index 0000000..4606999 --- /dev/null +++ b/snd-alpx-dkms/Controls/Alp442e_controls.txt @@ -0,0 +1,302 @@ +numid=13,iface=MIXER,name='AES Capture Volume' +numid=14,iface=MIXER,name='AES Capture Volume',index=1 +numid=15,iface=MIXER,name='AES Capture Volume',index=2 +numid=16,iface=MIXER,name='AES Capture Volume',index=3 +numid=21,iface=MIXER,name='AES Playback Volume' +numid=22,iface=MIXER,name='AES Playback Volume',index=1 +numid=23,iface=MIXER,name='AES Playback Volume',index=2 +numid=24,iface=MIXER,name='AES Playback Volume',index=3 +numid=298,iface=MIXER,name='AES SRC 1/2 Disable' +numid=299,iface=MIXER,name='AES SRC 3/4 Disable' +numid=9,iface=MIXER,name='Ana Capture Volume' +numid=10,iface=MIXER,name='Ana Capture Volume',index=1 +numid=11,iface=MIXER,name='Ana Capture Volume',index=2 +numid=12,iface=MIXER,name='Ana Capture Volume',index=3 +numid=17,iface=MIXER,name='Ana Playback Volume' +numid=18,iface=MIXER,name='Ana Playback Volume',index=1 +numid=19,iface=MIXER,name='Ana Playback Volume',index=2 +numid=20,iface=MIXER,name='Ana Playback Volume',index=3 +numid=290,iface=MIXER,name='Clk Eff' +numid=289,iface=MIXER,name='Clk Eff Src' +numid=294,iface=MIXER,name='Clk P0' +numid=295,iface=MIXER,name='Clk P1' +numid=296,iface=MIXER,name='Clk P2' +numid=297,iface=MIXER,name='Clk P3' +numid=293,iface=MIXER,name='Clk Src Down' +numid=292,iface=MIXER,name='Clk Src Up' +numid=300,iface=MIXER,name='Codec Analog Capture Volume' +numid=301,iface=MIXER,name='Codec Analog Capture Volume',index=1 +numid=302,iface=MIXER,name='Codec Analog Capture Volume',index=2 +numid=303,iface=MIXER,name='Codec Analog Capture Volume',index=3 +numid=1,iface=MIXER,name='DAW Capture Volume' +numid=2,iface=MIXER,name='DAW Capture Volume',index=1 +numid=3,iface=MIXER,name='DAW Capture Volume',index=2 +numid=4,iface=MIXER,name='DAW Capture Volume',index=3 +numid=5,iface=MIXER,name='DAW Capture Volume',index=4 +numid=6,iface=MIXER,name='DAW Capture Volume',index=5 +numid=7,iface=MIXER,name='DAW Capture Volume',index=6 +numid=8,iface=MIXER,name='DAW Capture Volume',index=7 +numid=25,iface=MIXER,name='DAW Playback Volume' +numid=26,iface=MIXER,name='DAW Playback Volume',index=1 +numid=27,iface=MIXER,name='DAW Playback Volume',index=2 +numid=28,iface=MIXER,name='DAW Playback Volume',index=3 +numid=29,iface=MIXER,name='DAW Playback Volume',index=4 +numid=30,iface=MIXER,name='DAW Playback Volume',index=5 +numid=31,iface=MIXER,name='DAW Playback Volume',index=6 +numid=32,iface=MIXER,name='DAW Playback Volume',index=7 +numid=33,iface=MIXER,name='Mxr 0/0 Playback Volume' +numid=49,iface=MIXER,name='Mxr 0/1 Playback Volume' +numid=193,iface=MIXER,name='Mxr 0/10 Playback Volume' +numid=209,iface=MIXER,name='Mxr 0/11 Playback Volume' +numid=225,iface=MIXER,name='Mxr 0/12 Playback Volume' +numid=241,iface=MIXER,name='Mxr 0/13 Playback Volume' +numid=257,iface=MIXER,name='Mxr 0/14 Playback Volume' +numid=273,iface=MIXER,name='Mxr 0/15 Playback Volume' +numid=65,iface=MIXER,name='Mxr 0/2 Playback Volume' +numid=81,iface=MIXER,name='Mxr 0/3 Playback Volume' +numid=97,iface=MIXER,name='Mxr 0/4 Playback Volume' +numid=113,iface=MIXER,name='Mxr 0/5 Playback Volume' +numid=129,iface=MIXER,name='Mxr 0/6 Playback Volume' +numid=145,iface=MIXER,name='Mxr 0/7 Playback Volume' +numid=161,iface=MIXER,name='Mxr 0/8 Playback Volume' +numid=177,iface=MIXER,name='Mxr 0/9 Playback Volume' +numid=34,iface=MIXER,name='Mxr 1/0 Playback Volume' +numid=50,iface=MIXER,name='Mxr 1/1 Playback Volume' +numid=194,iface=MIXER,name='Mxr 1/10 Playback Volume' +numid=210,iface=MIXER,name='Mxr 1/11 Playback Volume' +numid=226,iface=MIXER,name='Mxr 1/12 Playback Volume' +numid=242,iface=MIXER,name='Mxr 1/13 Playback Volume' +numid=258,iface=MIXER,name='Mxr 1/14 Playback Volume' +numid=274,iface=MIXER,name='Mxr 1/15 Playback Volume' +numid=66,iface=MIXER,name='Mxr 1/2 Playback Volume' +numid=82,iface=MIXER,name='Mxr 1/3 Playback Volume' +numid=98,iface=MIXER,name='Mxr 1/4 Playback Volume' +numid=114,iface=MIXER,name='Mxr 1/5 Playback Volume' +numid=130,iface=MIXER,name='Mxr 1/6 Playback Volume' +numid=146,iface=MIXER,name='Mxr 1/7 Playback Volume' +numid=162,iface=MIXER,name='Mxr 1/8 Playback Volume' +numid=178,iface=MIXER,name='Mxr 1/9 Playback Volume' +numid=43,iface=MIXER,name='Mxr 10/0 Playback Volume' +numid=59,iface=MIXER,name='Mxr 10/1 Playback Volume' +numid=203,iface=MIXER,name='Mxr 10/10 Playback Volume' +numid=219,iface=MIXER,name='Mxr 10/11 Playback Volume' +numid=235,iface=MIXER,name='Mxr 10/12 Playback Volume' +numid=251,iface=MIXER,name='Mxr 10/13 Playback Volume' +numid=267,iface=MIXER,name='Mxr 10/14 Playback Volume' +numid=283,iface=MIXER,name='Mxr 10/15 Playback Volume' +numid=75,iface=MIXER,name='Mxr 10/2 Playback Volume' +numid=91,iface=MIXER,name='Mxr 10/3 Playback Volume' +numid=107,iface=MIXER,name='Mxr 10/4 Playback Volume' +numid=123,iface=MIXER,name='Mxr 10/5 Playback Volume' +numid=139,iface=MIXER,name='Mxr 10/6 Playback Volume' +numid=155,iface=MIXER,name='Mxr 10/7 Playback Volume' +numid=171,iface=MIXER,name='Mxr 10/8 Playback Volume' +numid=187,iface=MIXER,name='Mxr 10/9 Playback Volume' +numid=44,iface=MIXER,name='Mxr 11/0 Playback Volume' +numid=60,iface=MIXER,name='Mxr 11/1 Playback Volume' +numid=204,iface=MIXER,name='Mxr 11/10 Playback Volume' +numid=220,iface=MIXER,name='Mxr 11/11 Playback Volume' +numid=236,iface=MIXER,name='Mxr 11/12 Playback Volume' +numid=252,iface=MIXER,name='Mxr 11/13 Playback Volume' +numid=268,iface=MIXER,name='Mxr 11/14 Playback Volume' +numid=284,iface=MIXER,name='Mxr 11/15 Playback Volume' +numid=76,iface=MIXER,name='Mxr 11/2 Playback Volume' +numid=92,iface=MIXER,name='Mxr 11/3 Playback Volume' +numid=108,iface=MIXER,name='Mxr 11/4 Playback Volume' +numid=124,iface=MIXER,name='Mxr 11/5 Playback Volume' +numid=140,iface=MIXER,name='Mxr 11/6 Playback Volume' +numid=156,iface=MIXER,name='Mxr 11/7 Playback Volume' +numid=172,iface=MIXER,name='Mxr 11/8 Playback Volume' +numid=188,iface=MIXER,name='Mxr 11/9 Playback Volume' +numid=45,iface=MIXER,name='Mxr 12/0 Playback Volume' +numid=61,iface=MIXER,name='Mxr 12/1 Playback Volume' +numid=205,iface=MIXER,name='Mxr 12/10 Playback Volume' +numid=221,iface=MIXER,name='Mxr 12/11 Playback Volume' +numid=237,iface=MIXER,name='Mxr 12/12 Playback Volume' +numid=253,iface=MIXER,name='Mxr 12/13 Playback Volume' +numid=269,iface=MIXER,name='Mxr 12/14 Playback Volume' +numid=285,iface=MIXER,name='Mxr 12/15 Playback Volume' +numid=77,iface=MIXER,name='Mxr 12/2 Playback Volume' +numid=93,iface=MIXER,name='Mxr 12/3 Playback Volume' +numid=109,iface=MIXER,name='Mxr 12/4 Playback Volume' +numid=125,iface=MIXER,name='Mxr 12/5 Playback Volume' +numid=141,iface=MIXER,name='Mxr 12/6 Playback Volume' +numid=157,iface=MIXER,name='Mxr 12/7 Playback Volume' +numid=173,iface=MIXER,name='Mxr 12/8 Playback Volume' +numid=189,iface=MIXER,name='Mxr 12/9 Playback Volume' +numid=46,iface=MIXER,name='Mxr 13/0 Playback Volume' +numid=62,iface=MIXER,name='Mxr 13/1 Playback Volume' +numid=206,iface=MIXER,name='Mxr 13/10 Playback Volume' +numid=222,iface=MIXER,name='Mxr 13/11 Playback Volume' +numid=238,iface=MIXER,name='Mxr 13/12 Playback Volume' +numid=254,iface=MIXER,name='Mxr 13/13 Playback Volume' +numid=270,iface=MIXER,name='Mxr 13/14 Playback Volume' +numid=286,iface=MIXER,name='Mxr 13/15 Playback Volume' +numid=78,iface=MIXER,name='Mxr 13/2 Playback Volume' +numid=94,iface=MIXER,name='Mxr 13/3 Playback Volume' +numid=110,iface=MIXER,name='Mxr 13/4 Playback Volume' +numid=126,iface=MIXER,name='Mxr 13/5 Playback Volume' +numid=142,iface=MIXER,name='Mxr 13/6 Playback Volume' +numid=158,iface=MIXER,name='Mxr 13/7 Playback Volume' +numid=174,iface=MIXER,name='Mxr 13/8 Playback Volume' +numid=190,iface=MIXER,name='Mxr 13/9 Playback Volume' +numid=47,iface=MIXER,name='Mxr 14/0 Playback Volume' +numid=63,iface=MIXER,name='Mxr 14/1 Playback Volume' +numid=207,iface=MIXER,name='Mxr 14/10 Playback Volume' +numid=223,iface=MIXER,name='Mxr 14/11 Playback Volume' +numid=239,iface=MIXER,name='Mxr 14/12 Playback Volume' +numid=255,iface=MIXER,name='Mxr 14/13 Playback Volume' +numid=271,iface=MIXER,name='Mxr 14/14 Playback Volume' +numid=287,iface=MIXER,name='Mxr 14/15 Playback Volume' +numid=79,iface=MIXER,name='Mxr 14/2 Playback Volume' +numid=95,iface=MIXER,name='Mxr 14/3 Playback Volume' +numid=111,iface=MIXER,name='Mxr 14/4 Playback Volume' +numid=127,iface=MIXER,name='Mxr 14/5 Playback Volume' +numid=143,iface=MIXER,name='Mxr 14/6 Playback Volume' +numid=159,iface=MIXER,name='Mxr 14/7 Playback Volume' +numid=175,iface=MIXER,name='Mxr 14/8 Playback Volume' +numid=191,iface=MIXER,name='Mxr 14/9 Playback Volume' +numid=48,iface=MIXER,name='Mxr 15/0 Playback Volume' +numid=64,iface=MIXER,name='Mxr 15/1 Playback Volume' +numid=208,iface=MIXER,name='Mxr 15/10 Playback Volume' +numid=224,iface=MIXER,name='Mxr 15/11 Playback Volume' +numid=240,iface=MIXER,name='Mxr 15/12 Playback Volume' +numid=256,iface=MIXER,name='Mxr 15/13 Playback Volume' +numid=272,iface=MIXER,name='Mxr 15/14 Playback Volume' +numid=288,iface=MIXER,name='Mxr 15/15 Playback Volume' +numid=80,iface=MIXER,name='Mxr 15/2 Playback Volume' +numid=96,iface=MIXER,name='Mxr 15/3 Playback Volume' +numid=112,iface=MIXER,name='Mxr 15/4 Playback Volume' +numid=128,iface=MIXER,name='Mxr 15/5 Playback Volume' +numid=144,iface=MIXER,name='Mxr 15/6 Playback Volume' +numid=160,iface=MIXER,name='Mxr 15/7 Playback Volume' +numid=176,iface=MIXER,name='Mxr 15/8 Playback Volume' +numid=192,iface=MIXER,name='Mxr 15/9 Playback Volume' +numid=35,iface=MIXER,name='Mxr 2/0 Playback Volume' +numid=51,iface=MIXER,name='Mxr 2/1 Playback Volume' +numid=195,iface=MIXER,name='Mxr 2/10 Playback Volume' +numid=211,iface=MIXER,name='Mxr 2/11 Playback Volume' +numid=227,iface=MIXER,name='Mxr 2/12 Playback Volume' +numid=243,iface=MIXER,name='Mxr 2/13 Playback Volume' +numid=259,iface=MIXER,name='Mxr 2/14 Playback Volume' +numid=275,iface=MIXER,name='Mxr 2/15 Playback Volume' +numid=67,iface=MIXER,name='Mxr 2/2 Playback Volume' +numid=83,iface=MIXER,name='Mxr 2/3 Playback Volume' +numid=99,iface=MIXER,name='Mxr 2/4 Playback Volume' +numid=115,iface=MIXER,name='Mxr 2/5 Playback Volume' +numid=131,iface=MIXER,name='Mxr 2/6 Playback Volume' +numid=147,iface=MIXER,name='Mxr 2/7 Playback Volume' +numid=163,iface=MIXER,name='Mxr 2/8 Playback Volume' +numid=179,iface=MIXER,name='Mxr 2/9 Playback Volume' +numid=36,iface=MIXER,name='Mxr 3/0 Playback Volume' +numid=52,iface=MIXER,name='Mxr 3/1 Playback Volume' +numid=196,iface=MIXER,name='Mxr 3/10 Playback Volume' +numid=212,iface=MIXER,name='Mxr 3/11 Playback Volume' +numid=228,iface=MIXER,name='Mxr 3/12 Playback Volume' +numid=244,iface=MIXER,name='Mxr 3/13 Playback Volume' +numid=260,iface=MIXER,name='Mxr 3/14 Playback Volume' +numid=276,iface=MIXER,name='Mxr 3/15 Playback Volume' +numid=68,iface=MIXER,name='Mxr 3/2 Playback Volume' +numid=84,iface=MIXER,name='Mxr 3/3 Playback Volume' +numid=100,iface=MIXER,name='Mxr 3/4 Playback Volume' +numid=116,iface=MIXER,name='Mxr 3/5 Playback Volume' +numid=132,iface=MIXER,name='Mxr 3/6 Playback Volume' +numid=148,iface=MIXER,name='Mxr 3/7 Playback Volume' +numid=164,iface=MIXER,name='Mxr 3/8 Playback Volume' +numid=180,iface=MIXER,name='Mxr 3/9 Playback Volume' +numid=37,iface=MIXER,name='Mxr 4/0 Playback Volume' +numid=53,iface=MIXER,name='Mxr 4/1 Playback Volume' +numid=197,iface=MIXER,name='Mxr 4/10 Playback Volume' +numid=213,iface=MIXER,name='Mxr 4/11 Playback Volume' +numid=229,iface=MIXER,name='Mxr 4/12 Playback Volume' +numid=245,iface=MIXER,name='Mxr 4/13 Playback Volume' +numid=261,iface=MIXER,name='Mxr 4/14 Playback Volume' +numid=277,iface=MIXER,name='Mxr 4/15 Playback Volume' +numid=69,iface=MIXER,name='Mxr 4/2 Playback Volume' +numid=85,iface=MIXER,name='Mxr 4/3 Playback Volume' +numid=101,iface=MIXER,name='Mxr 4/4 Playback Volume' +numid=117,iface=MIXER,name='Mxr 4/5 Playback Volume' +numid=133,iface=MIXER,name='Mxr 4/6 Playback Volume' +numid=149,iface=MIXER,name='Mxr 4/7 Playback Volume' +numid=165,iface=MIXER,name='Mxr 4/8 Playback Volume' +numid=181,iface=MIXER,name='Mxr 4/9 Playback Volume' +numid=38,iface=MIXER,name='Mxr 5/0 Playback Volume' +numid=54,iface=MIXER,name='Mxr 5/1 Playback Volume' +numid=198,iface=MIXER,name='Mxr 5/10 Playback Volume' +numid=214,iface=MIXER,name='Mxr 5/11 Playback Volume' +numid=230,iface=MIXER,name='Mxr 5/12 Playback Volume' +numid=246,iface=MIXER,name='Mxr 5/13 Playback Volume' +numid=262,iface=MIXER,name='Mxr 5/14 Playback Volume' +numid=278,iface=MIXER,name='Mxr 5/15 Playback Volume' +numid=70,iface=MIXER,name='Mxr 5/2 Playback Volume' +numid=86,iface=MIXER,name='Mxr 5/3 Playback Volume' +numid=102,iface=MIXER,name='Mxr 5/4 Playback Volume' +numid=118,iface=MIXER,name='Mxr 5/5 Playback Volume' +numid=134,iface=MIXER,name='Mxr 5/6 Playback Volume' +numid=150,iface=MIXER,name='Mxr 5/7 Playback Volume' +numid=166,iface=MIXER,name='Mxr 5/8 Playback Volume' +numid=182,iface=MIXER,name='Mxr 5/9 Playback Volume' +numid=39,iface=MIXER,name='Mxr 6/0 Playback Volume' +numid=55,iface=MIXER,name='Mxr 6/1 Playback Volume' +numid=199,iface=MIXER,name='Mxr 6/10 Playback Volume' +numid=215,iface=MIXER,name='Mxr 6/11 Playback Volume' +numid=231,iface=MIXER,name='Mxr 6/12 Playback Volume' +numid=247,iface=MIXER,name='Mxr 6/13 Playback Volume' +numid=263,iface=MIXER,name='Mxr 6/14 Playback Volume' +numid=279,iface=MIXER,name='Mxr 6/15 Playback Volume' +numid=71,iface=MIXER,name='Mxr 6/2 Playback Volume' +numid=87,iface=MIXER,name='Mxr 6/3 Playback Volume' +numid=103,iface=MIXER,name='Mxr 6/4 Playback Volume' +numid=119,iface=MIXER,name='Mxr 6/5 Playback Volume' +numid=135,iface=MIXER,name='Mxr 6/6 Playback Volume' +numid=151,iface=MIXER,name='Mxr 6/7 Playback Volume' +numid=167,iface=MIXER,name='Mxr 6/8 Playback Volume' +numid=183,iface=MIXER,name='Mxr 6/9 Playback Volume' +numid=40,iface=MIXER,name='Mxr 7/0 Playback Volume' +numid=56,iface=MIXER,name='Mxr 7/1 Playback Volume' +numid=200,iface=MIXER,name='Mxr 7/10 Playback Volume' +numid=216,iface=MIXER,name='Mxr 7/11 Playback Volume' +numid=232,iface=MIXER,name='Mxr 7/12 Playback Volume' +numid=248,iface=MIXER,name='Mxr 7/13 Playback Volume' +numid=264,iface=MIXER,name='Mxr 7/14 Playback Volume' +numid=280,iface=MIXER,name='Mxr 7/15 Playback Volume' +numid=72,iface=MIXER,name='Mxr 7/2 Playback Volume' +numid=88,iface=MIXER,name='Mxr 7/3 Playback Volume' +numid=104,iface=MIXER,name='Mxr 7/4 Playback Volume' +numid=120,iface=MIXER,name='Mxr 7/5 Playback Volume' +numid=136,iface=MIXER,name='Mxr 7/6 Playback Volume' +numid=152,iface=MIXER,name='Mxr 7/7 Playback Volume' +numid=168,iface=MIXER,name='Mxr 7/8 Playback Volume' +numid=184,iface=MIXER,name='Mxr 7/9 Playback Volume' +numid=41,iface=MIXER,name='Mxr 8/0 Playback Volume' +numid=57,iface=MIXER,name='Mxr 8/1 Playback Volume' +numid=201,iface=MIXER,name='Mxr 8/10 Playback Volume' +numid=217,iface=MIXER,name='Mxr 8/11 Playback Volume' +numid=233,iface=MIXER,name='Mxr 8/12 Playback Volume' +numid=249,iface=MIXER,name='Mxr 8/13 Playback Volume' +numid=265,iface=MIXER,name='Mxr 8/14 Playback Volume' +numid=281,iface=MIXER,name='Mxr 8/15 Playback Volume' +numid=73,iface=MIXER,name='Mxr 8/2 Playback Volume' +numid=89,iface=MIXER,name='Mxr 8/3 Playback Volume' +numid=105,iface=MIXER,name='Mxr 8/4 Playback Volume' +numid=121,iface=MIXER,name='Mxr 8/5 Playback Volume' +numid=137,iface=MIXER,name='Mxr 8/6 Playback Volume' +numid=153,iface=MIXER,name='Mxr 8/7 Playback Volume' +numid=169,iface=MIXER,name='Mxr 8/8 Playback Volume' +numid=185,iface=MIXER,name='Mxr 8/9 Playback Volume' +numid=42,iface=MIXER,name='Mxr 9/0 Playback Volume' +numid=58,iface=MIXER,name='Mxr 9/1 Playback Volume' +numid=202,iface=MIXER,name='Mxr 9/10 Playback Volume' +numid=218,iface=MIXER,name='Mxr 9/11 Playback Volume' +numid=234,iface=MIXER,name='Mxr 9/12 Playback Volume' +numid=250,iface=MIXER,name='Mxr 9/13 Playback Volume' +numid=266,iface=MIXER,name='Mxr 9/14 Playback Volume' +numid=282,iface=MIXER,name='Mxr 9/15 Playback Volume' +numid=74,iface=MIXER,name='Mxr 9/2 Playback Volume' +numid=90,iface=MIXER,name='Mxr 9/3 Playback Volume' +numid=106,iface=MIXER,name='Mxr 9/4 Playback Volume' +numid=122,iface=MIXER,name='Mxr 9/5 Playback Volume' +numid=138,iface=MIXER,name='Mxr 9/6 Playback Volume' +numid=154,iface=MIXER,name='Mxr 9/7 Playback Volume' +numid=170,iface=MIXER,name='Mxr 9/8 Playback Volume' +numid=186,iface=MIXER,name='Mxr 9/9 Playback Volume' diff --git a/snd-alpx-dkms/Controls/Alp882e-MIC_Contents.txt b/snd-alpx-dkms/Controls/Alp882e-MIC_Contents.txt new file mode 100644 index 0000000..7178a57 --- /dev/null +++ b/snd-alpx-dkms/Controls/Alp882e-MIC_Contents.txt @@ -0,0 +1,4498 @@ +numid=25,iface=MIXER,name='AES Capture Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=26,iface=MIXER,name='AES Capture Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=27,iface=MIXER,name='AES Capture Volume',index=2 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=28,iface=MIXER,name='AES Capture Volume',index=3 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=29,iface=MIXER,name='AES Capture Volume',index=4 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=30,iface=MIXER,name='AES Capture Volume',index=5 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=31,iface=MIXER,name='AES Capture Volume',index=6 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=32,iface=MIXER,name='AES Capture Volume',index=7 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=41,iface=MIXER,name='AES Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=42,iface=MIXER,name='AES Playback Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=43,iface=MIXER,name='AES Playback Volume',index=2 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=44,iface=MIXER,name='AES Playback Volume',index=3 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=45,iface=MIXER,name='AES Playback Volume',index=4 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=46,iface=MIXER,name='AES Playback Volume',index=5 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=47,iface=MIXER,name='AES Playback Volume',index=6 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=48,iface=MIXER,name='AES Playback Volume',index=7 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1098,iface=MIXER,name='AES SRC 1/2 Disable' + ; type=BOOLEAN,access=rw------,values=1 + : values=off +numid=1099,iface=MIXER,name='AES SRC 3/4 Disable' + ; type=BOOLEAN,access=rw------,values=1 + : values=off +numid=1100,iface=MIXER,name='AES SRC 5/6 Disable' + ; type=BOOLEAN,access=rw------,values=1 + : values=off +numid=1101,iface=MIXER,name='AES SRC 7/8 Disable' + ; type=BOOLEAN,access=rw------,values=1 + : values=off +numid=17,iface=MIXER,name='Ana Capture Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=18,iface=MIXER,name='Ana Capture Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=19,iface=MIXER,name='Ana Capture Volume',index=2 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=20,iface=MIXER,name='Ana Capture Volume',index=3 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=21,iface=MIXER,name='Ana Capture Volume',index=4 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=22,iface=MIXER,name='Ana Capture Volume',index=5 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=23,iface=MIXER,name='Ana Capture Volume',index=6 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=24,iface=MIXER,name='Ana Capture Volume',index=7 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=33,iface=MIXER,name='Ana Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=34,iface=MIXER,name='Ana Playback Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=35,iface=MIXER,name='Ana Playback Volume',index=2 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=36,iface=MIXER,name='Ana Playback Volume',index=3 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=37,iface=MIXER,name='Ana Playback Volume',index=4 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=38,iface=MIXER,name='Ana Playback Volume',index=5 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=39,iface=MIXER,name='Ana Playback Volume',index=6 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=40,iface=MIXER,name='Ana Playback Volume',index=7 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1090,iface=MIXER,name='Clk Eff' + ; type=ENUMERATED,access=r--v----,values=1,items=14 + ; Item #0 '8kHz' + ; Item #1 '11.025kHz' + ; Item #2 '16kHz' + ; Item #3 '22.05kHz' + ; Item #4 '24kHz' + ; Item #5 '32kHz' + ; Item #6 '44.1kHz' + ; Item #7 '48kHz' + ; Item #8 '64kHz' + ; Item #9 '88.2kHz' + ; Item #10 '96kHz' + ; Item #11 '128kHz' + ; Item #12 '176,4kHz' + ; Item #13 '192kHz' + : values=7 +numid=1089,iface=MIXER,name='Clk Eff Src' + ; type=ENUMERATED,access=r-------,values=1,items=8 + ; Item #0 'Internal' + ; Item #1 'SIC' + ; Item #2 'Word Clk' + ; Item #3 'AES Syn' + ; Item #4 'AES Aud 1/2' + ; Item #5 'AES Aud 3/4' + ; Item #6 'AES Aud 5/6' + ; Item #7 'AES Aud 7/8' + : values=0 +numid=1094,iface=MIXER,name='Clk P0' + ; type=ENUMERATED,access=rw------,values=1,items=8 + ; Item #0 'Internal' + ; Item #1 'SIC' + ; Item #2 'Word Clk' + ; Item #3 'AES Syn' + ; Item #4 'AES Aud 1/2' + ; Item #5 'AES Aud 3/4' + ; Item #6 'AES Aud 5/6' + ; Item #7 'AES Aud 7/8' + : values=0 +numid=1095,iface=MIXER,name='Clk P1' + ; type=ENUMERATED,access=rw------,values=1,items=8 + ; Item #0 'Internal' + ; Item #1 'SIC' + ; Item #2 'Word Clk' + ; Item #3 'AES Syn' + ; Item #4 'AES Aud 1/2' + ; Item #5 'AES Aud 3/4' + ; Item #6 'AES Aud 5/6' + ; Item #7 'AES Aud 7/8' + : values=0 +numid=1096,iface=MIXER,name='Clk P2' + ; type=ENUMERATED,access=rw------,values=1,items=8 + ; Item #0 'Internal' + ; Item #1 'SIC' + ; Item #2 'Word Clk' + ; Item #3 'AES Syn' + ; Item #4 'AES Aud 1/2' + ; Item #5 'AES Aud 3/4' + ; Item #6 'AES Aud 5/6' + ; Item #7 'AES Aud 7/8' + : values=0 +numid=1097,iface=MIXER,name='Clk P3' + ; type=ENUMERATED,access=rw------,values=1,items=8 + ; Item #0 'Internal' + ; Item #1 'SIC' + ; Item #2 'Word Clk' + ; Item #3 'AES Syn' + ; Item #4 'AES Aud 1/2' + ; Item #5 'AES Aud 3/4' + ; Item #6 'AES Aud 5/6' + ; Item #7 'AES Aud 7/8' + : values=0 +numid=1093,iface=MIXER,name='Clk Src Down' + ; type=BOOLEAN,access=rw------,values=1 + : values=on +numid=1092,iface=MIXER,name='Clk Src Up' + ; type=BOOLEAN,access=rw------,values=1 + : values=on +numid=1102,iface=MIXER,name='Codec MIC Analog Capture Volume' + ; type=INTEGER,access=rw---R--,values=1,min=49,max=162,step=0 + : values=49 + | dBminmaxmute-min=0.00dB,max=56.00dB +numid=1103,iface=MIXER,name='Codec MIC Analog Capture Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=49,max=162,step=0 + : values=49 + | dBminmaxmute-min=0.00dB,max=56.00dB +numid=1104,iface=MIXER,name='Codec MIC Analog Capture Volume',index=2 + ; type=INTEGER,access=rw---R--,values=1,min=49,max=162,step=0 + : values=49 + | dBminmaxmute-min=0.00dB,max=56.00dB +numid=1105,iface=MIXER,name='Codec MIC Analog Capture Volume',index=3 + ; type=INTEGER,access=rw---R--,values=1,min=49,max=162,step=0 + : values=49 + | dBminmaxmute-min=0.00dB,max=56.00dB +numid=1106,iface=MIXER,name='Codec MIC Analog Capture Volume',index=4 + ; type=INTEGER,access=rw---R--,values=1,min=49,max=162,step=0 + : values=49 + | dBminmaxmute-min=0.00dB,max=56.00dB +numid=1107,iface=MIXER,name='Codec MIC Analog Capture Volume',index=5 + ; type=INTEGER,access=rw---R--,values=1,min=49,max=162,step=0 + : values=49 + | dBminmaxmute-min=0.00dB,max=56.00dB +numid=1108,iface=MIXER,name='Codec MIC Analog Capture Volume',index=6 + ; type=INTEGER,access=rw---R--,values=1,min=49,max=162,step=0 + : values=49 + | dBminmaxmute-min=0.00dB,max=56.00dB +numid=1109,iface=MIXER,name='Codec MIC Analog Capture Volume',index=7 + ; type=INTEGER,access=rw---R--,values=1,min=49,max=162,step=0 + : values=49 + | dBminmaxmute-min=0.00dB,max=56.00dB +numid=1,iface=MIXER,name='DAW Capture Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=2,iface=MIXER,name='DAW Capture Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=3,iface=MIXER,name='DAW Capture Volume',index=2 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=4,iface=MIXER,name='DAW Capture Volume',index=3 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=5,iface=MIXER,name='DAW Capture Volume',index=4 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=6,iface=MIXER,name='DAW Capture Volume',index=5 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=7,iface=MIXER,name='DAW Capture Volume',index=6 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=8,iface=MIXER,name='DAW Capture Volume',index=7 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=9,iface=MIXER,name='DAW Capture Volume',index=8 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=10,iface=MIXER,name='DAW Capture Volume',index=9 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=11,iface=MIXER,name='DAW Capture Volume',index=10 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=12,iface=MIXER,name='DAW Capture Volume',index=11 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=13,iface=MIXER,name='DAW Capture Volume',index=12 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=14,iface=MIXER,name='DAW Capture Volume',index=13 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=15,iface=MIXER,name='DAW Capture Volume',index=14 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=16,iface=MIXER,name='DAW Capture Volume',index=15 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=49,iface=MIXER,name='DAW Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=50,iface=MIXER,name='DAW Playback Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=51,iface=MIXER,name='DAW Playback Volume',index=2 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=52,iface=MIXER,name='DAW Playback Volume',index=3 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=53,iface=MIXER,name='DAW Playback Volume',index=4 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=54,iface=MIXER,name='DAW Playback Volume',index=5 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=55,iface=MIXER,name='DAW Playback Volume',index=6 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=56,iface=MIXER,name='DAW Playback Volume',index=7 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=57,iface=MIXER,name='DAW Playback Volume',index=8 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=58,iface=MIXER,name='DAW Playback Volume',index=9 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=59,iface=MIXER,name='DAW Playback Volume',index=10 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=60,iface=MIXER,name='DAW Playback Volume',index=11 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=61,iface=MIXER,name='DAW Playback Volume',index=12 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=62,iface=MIXER,name='DAW Playback Volume',index=13 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=63,iface=MIXER,name='DAW Playback Volume',index=14 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=64,iface=MIXER,name='DAW Playback Volume',index=15 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1110,iface=MIXER,name='McPh1' + ; type=BOOLEAN,access=rw------,values=1 + : values=off +numid=1111,iface=MIXER,name='McPh2' + ; type=BOOLEAN,access=rw------,values=1 + : values=off +numid=1112,iface=MIXER,name='McPh3' + ; type=BOOLEAN,access=rw------,values=1 + : values=off +numid=1113,iface=MIXER,name='McPh4' + ; type=BOOLEAN,access=rw------,values=1 + : values=off +numid=1114,iface=MIXER,name='McPh5' + ; type=BOOLEAN,access=rw------,values=1 + : values=off +numid=1115,iface=MIXER,name='McPh6' + ; type=BOOLEAN,access=rw------,values=1 + : values=off +numid=1116,iface=MIXER,name='McPh7' + ; type=BOOLEAN,access=rw------,values=1 + : values=off +numid=1117,iface=MIXER,name='McPh8' + ; type=BOOLEAN,access=rw------,values=1 + : values=off +numid=65,iface=MIXER,name='Mxr 0/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=97,iface=MIXER,name='Mxr 0/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=385,iface=MIXER,name='Mxr 0/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=417,iface=MIXER,name='Mxr 0/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=449,iface=MIXER,name='Mxr 0/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=481,iface=MIXER,name='Mxr 0/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=513,iface=MIXER,name='Mxr 0/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=545,iface=MIXER,name='Mxr 0/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=577,iface=MIXER,name='Mxr 0/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=609,iface=MIXER,name='Mxr 0/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=641,iface=MIXER,name='Mxr 0/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=673,iface=MIXER,name='Mxr 0/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=129,iface=MIXER,name='Mxr 0/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=705,iface=MIXER,name='Mxr 0/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=737,iface=MIXER,name='Mxr 0/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=769,iface=MIXER,name='Mxr 0/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=801,iface=MIXER,name='Mxr 0/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=833,iface=MIXER,name='Mxr 0/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=865,iface=MIXER,name='Mxr 0/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=897,iface=MIXER,name='Mxr 0/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=929,iface=MIXER,name='Mxr 0/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=961,iface=MIXER,name='Mxr 0/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=993,iface=MIXER,name='Mxr 0/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=161,iface=MIXER,name='Mxr 0/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1025,iface=MIXER,name='Mxr 0/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1057,iface=MIXER,name='Mxr 0/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=193,iface=MIXER,name='Mxr 0/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=225,iface=MIXER,name='Mxr 0/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=257,iface=MIXER,name='Mxr 0/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=289,iface=MIXER,name='Mxr 0/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=321,iface=MIXER,name='Mxr 0/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=353,iface=MIXER,name='Mxr 0/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=66,iface=MIXER,name='Mxr 1/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=98,iface=MIXER,name='Mxr 1/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=386,iface=MIXER,name='Mxr 1/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=418,iface=MIXER,name='Mxr 1/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=450,iface=MIXER,name='Mxr 1/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=482,iface=MIXER,name='Mxr 1/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=514,iface=MIXER,name='Mxr 1/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=546,iface=MIXER,name='Mxr 1/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=578,iface=MIXER,name='Mxr 1/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=610,iface=MIXER,name='Mxr 1/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=642,iface=MIXER,name='Mxr 1/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=674,iface=MIXER,name='Mxr 1/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=130,iface=MIXER,name='Mxr 1/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=706,iface=MIXER,name='Mxr 1/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=738,iface=MIXER,name='Mxr 1/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=770,iface=MIXER,name='Mxr 1/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=802,iface=MIXER,name='Mxr 1/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=834,iface=MIXER,name='Mxr 1/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=866,iface=MIXER,name='Mxr 1/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=898,iface=MIXER,name='Mxr 1/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=930,iface=MIXER,name='Mxr 1/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=962,iface=MIXER,name='Mxr 1/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=994,iface=MIXER,name='Mxr 1/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=162,iface=MIXER,name='Mxr 1/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1026,iface=MIXER,name='Mxr 1/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1058,iface=MIXER,name='Mxr 1/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=194,iface=MIXER,name='Mxr 1/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=226,iface=MIXER,name='Mxr 1/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=258,iface=MIXER,name='Mxr 1/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=290,iface=MIXER,name='Mxr 1/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=322,iface=MIXER,name='Mxr 1/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=354,iface=MIXER,name='Mxr 1/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=75,iface=MIXER,name='Mxr 10/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=107,iface=MIXER,name='Mxr 10/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=395,iface=MIXER,name='Mxr 10/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=427,iface=MIXER,name='Mxr 10/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=459,iface=MIXER,name='Mxr 10/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=491,iface=MIXER,name='Mxr 10/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=523,iface=MIXER,name='Mxr 10/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=555,iface=MIXER,name='Mxr 10/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=587,iface=MIXER,name='Mxr 10/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=619,iface=MIXER,name='Mxr 10/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=651,iface=MIXER,name='Mxr 10/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=683,iface=MIXER,name='Mxr 10/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=139,iface=MIXER,name='Mxr 10/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=715,iface=MIXER,name='Mxr 10/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=747,iface=MIXER,name='Mxr 10/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=779,iface=MIXER,name='Mxr 10/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=811,iface=MIXER,name='Mxr 10/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=843,iface=MIXER,name='Mxr 10/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=875,iface=MIXER,name='Mxr 10/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=907,iface=MIXER,name='Mxr 10/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=939,iface=MIXER,name='Mxr 10/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=971,iface=MIXER,name='Mxr 10/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1003,iface=MIXER,name='Mxr 10/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=171,iface=MIXER,name='Mxr 10/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1035,iface=MIXER,name='Mxr 10/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1067,iface=MIXER,name='Mxr 10/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=203,iface=MIXER,name='Mxr 10/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=235,iface=MIXER,name='Mxr 10/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=267,iface=MIXER,name='Mxr 10/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=299,iface=MIXER,name='Mxr 10/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=331,iface=MIXER,name='Mxr 10/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=363,iface=MIXER,name='Mxr 10/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=76,iface=MIXER,name='Mxr 11/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=108,iface=MIXER,name='Mxr 11/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=396,iface=MIXER,name='Mxr 11/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=428,iface=MIXER,name='Mxr 11/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=460,iface=MIXER,name='Mxr 11/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=492,iface=MIXER,name='Mxr 11/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=524,iface=MIXER,name='Mxr 11/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=556,iface=MIXER,name='Mxr 11/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=588,iface=MIXER,name='Mxr 11/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=620,iface=MIXER,name='Mxr 11/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=652,iface=MIXER,name='Mxr 11/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=684,iface=MIXER,name='Mxr 11/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=140,iface=MIXER,name='Mxr 11/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=716,iface=MIXER,name='Mxr 11/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=748,iface=MIXER,name='Mxr 11/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=780,iface=MIXER,name='Mxr 11/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=812,iface=MIXER,name='Mxr 11/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=844,iface=MIXER,name='Mxr 11/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=876,iface=MIXER,name='Mxr 11/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=908,iface=MIXER,name='Mxr 11/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=940,iface=MIXER,name='Mxr 11/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=972,iface=MIXER,name='Mxr 11/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1004,iface=MIXER,name='Mxr 11/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=172,iface=MIXER,name='Mxr 11/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1036,iface=MIXER,name='Mxr 11/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1068,iface=MIXER,name='Mxr 11/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=204,iface=MIXER,name='Mxr 11/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=236,iface=MIXER,name='Mxr 11/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=268,iface=MIXER,name='Mxr 11/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=300,iface=MIXER,name='Mxr 11/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=332,iface=MIXER,name='Mxr 11/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=364,iface=MIXER,name='Mxr 11/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=77,iface=MIXER,name='Mxr 12/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=109,iface=MIXER,name='Mxr 12/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=397,iface=MIXER,name='Mxr 12/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=429,iface=MIXER,name='Mxr 12/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=461,iface=MIXER,name='Mxr 12/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=493,iface=MIXER,name='Mxr 12/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=525,iface=MIXER,name='Mxr 12/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=557,iface=MIXER,name='Mxr 12/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=589,iface=MIXER,name='Mxr 12/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=621,iface=MIXER,name='Mxr 12/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=653,iface=MIXER,name='Mxr 12/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=685,iface=MIXER,name='Mxr 12/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=141,iface=MIXER,name='Mxr 12/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=717,iface=MIXER,name='Mxr 12/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=749,iface=MIXER,name='Mxr 12/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=781,iface=MIXER,name='Mxr 12/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=813,iface=MIXER,name='Mxr 12/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=845,iface=MIXER,name='Mxr 12/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=877,iface=MIXER,name='Mxr 12/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=909,iface=MIXER,name='Mxr 12/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=941,iface=MIXER,name='Mxr 12/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=973,iface=MIXER,name='Mxr 12/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1005,iface=MIXER,name='Mxr 12/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=173,iface=MIXER,name='Mxr 12/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1037,iface=MIXER,name='Mxr 12/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1069,iface=MIXER,name='Mxr 12/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=205,iface=MIXER,name='Mxr 12/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=237,iface=MIXER,name='Mxr 12/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=269,iface=MIXER,name='Mxr 12/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=301,iface=MIXER,name='Mxr 12/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=333,iface=MIXER,name='Mxr 12/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=365,iface=MIXER,name='Mxr 12/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=78,iface=MIXER,name='Mxr 13/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=110,iface=MIXER,name='Mxr 13/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=398,iface=MIXER,name='Mxr 13/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=430,iface=MIXER,name='Mxr 13/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=462,iface=MIXER,name='Mxr 13/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=494,iface=MIXER,name='Mxr 13/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=526,iface=MIXER,name='Mxr 13/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=558,iface=MIXER,name='Mxr 13/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=590,iface=MIXER,name='Mxr 13/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=622,iface=MIXER,name='Mxr 13/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=654,iface=MIXER,name='Mxr 13/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=686,iface=MIXER,name='Mxr 13/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=142,iface=MIXER,name='Mxr 13/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=718,iface=MIXER,name='Mxr 13/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=750,iface=MIXER,name='Mxr 13/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=782,iface=MIXER,name='Mxr 13/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=814,iface=MIXER,name='Mxr 13/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=846,iface=MIXER,name='Mxr 13/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=878,iface=MIXER,name='Mxr 13/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=910,iface=MIXER,name='Mxr 13/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=942,iface=MIXER,name='Mxr 13/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=974,iface=MIXER,name='Mxr 13/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1006,iface=MIXER,name='Mxr 13/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=174,iface=MIXER,name='Mxr 13/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1038,iface=MIXER,name='Mxr 13/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1070,iface=MIXER,name='Mxr 13/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=206,iface=MIXER,name='Mxr 13/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=238,iface=MIXER,name='Mxr 13/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=270,iface=MIXER,name='Mxr 13/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=302,iface=MIXER,name='Mxr 13/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=334,iface=MIXER,name='Mxr 13/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=366,iface=MIXER,name='Mxr 13/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=79,iface=MIXER,name='Mxr 14/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=111,iface=MIXER,name='Mxr 14/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=399,iface=MIXER,name='Mxr 14/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=431,iface=MIXER,name='Mxr 14/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=463,iface=MIXER,name='Mxr 14/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=495,iface=MIXER,name='Mxr 14/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=527,iface=MIXER,name='Mxr 14/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=559,iface=MIXER,name='Mxr 14/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=591,iface=MIXER,name='Mxr 14/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=623,iface=MIXER,name='Mxr 14/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=655,iface=MIXER,name='Mxr 14/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=687,iface=MIXER,name='Mxr 14/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=143,iface=MIXER,name='Mxr 14/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=719,iface=MIXER,name='Mxr 14/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=751,iface=MIXER,name='Mxr 14/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=783,iface=MIXER,name='Mxr 14/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=815,iface=MIXER,name='Mxr 14/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=847,iface=MIXER,name='Mxr 14/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=879,iface=MIXER,name='Mxr 14/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=911,iface=MIXER,name='Mxr 14/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=943,iface=MIXER,name='Mxr 14/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=975,iface=MIXER,name='Mxr 14/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1007,iface=MIXER,name='Mxr 14/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=175,iface=MIXER,name='Mxr 14/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1039,iface=MIXER,name='Mxr 14/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1071,iface=MIXER,name='Mxr 14/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=207,iface=MIXER,name='Mxr 14/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=239,iface=MIXER,name='Mxr 14/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=271,iface=MIXER,name='Mxr 14/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=303,iface=MIXER,name='Mxr 14/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=335,iface=MIXER,name='Mxr 14/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=367,iface=MIXER,name='Mxr 14/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=80,iface=MIXER,name='Mxr 15/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=112,iface=MIXER,name='Mxr 15/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=400,iface=MIXER,name='Mxr 15/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=432,iface=MIXER,name='Mxr 15/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=464,iface=MIXER,name='Mxr 15/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=496,iface=MIXER,name='Mxr 15/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=528,iface=MIXER,name='Mxr 15/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=560,iface=MIXER,name='Mxr 15/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=592,iface=MIXER,name='Mxr 15/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=624,iface=MIXER,name='Mxr 15/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=656,iface=MIXER,name='Mxr 15/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=688,iface=MIXER,name='Mxr 15/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=144,iface=MIXER,name='Mxr 15/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=720,iface=MIXER,name='Mxr 15/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=752,iface=MIXER,name='Mxr 15/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=784,iface=MIXER,name='Mxr 15/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=816,iface=MIXER,name='Mxr 15/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=848,iface=MIXER,name='Mxr 15/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=880,iface=MIXER,name='Mxr 15/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=912,iface=MIXER,name='Mxr 15/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=944,iface=MIXER,name='Mxr 15/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=976,iface=MIXER,name='Mxr 15/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1008,iface=MIXER,name='Mxr 15/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=176,iface=MIXER,name='Mxr 15/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1040,iface=MIXER,name='Mxr 15/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1072,iface=MIXER,name='Mxr 15/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=208,iface=MIXER,name='Mxr 15/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=240,iface=MIXER,name='Mxr 15/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=272,iface=MIXER,name='Mxr 15/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=304,iface=MIXER,name='Mxr 15/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=336,iface=MIXER,name='Mxr 15/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=368,iface=MIXER,name='Mxr 15/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=81,iface=MIXER,name='Mxr 16/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=113,iface=MIXER,name='Mxr 16/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=401,iface=MIXER,name='Mxr 16/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=433,iface=MIXER,name='Mxr 16/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=465,iface=MIXER,name='Mxr 16/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=497,iface=MIXER,name='Mxr 16/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=529,iface=MIXER,name='Mxr 16/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=561,iface=MIXER,name='Mxr 16/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=593,iface=MIXER,name='Mxr 16/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=625,iface=MIXER,name='Mxr 16/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=657,iface=MIXER,name='Mxr 16/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=689,iface=MIXER,name='Mxr 16/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=145,iface=MIXER,name='Mxr 16/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=721,iface=MIXER,name='Mxr 16/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=753,iface=MIXER,name='Mxr 16/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=785,iface=MIXER,name='Mxr 16/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=817,iface=MIXER,name='Mxr 16/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=849,iface=MIXER,name='Mxr 16/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=881,iface=MIXER,name='Mxr 16/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=913,iface=MIXER,name='Mxr 16/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=945,iface=MIXER,name='Mxr 16/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=977,iface=MIXER,name='Mxr 16/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1009,iface=MIXER,name='Mxr 16/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=177,iface=MIXER,name='Mxr 16/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1041,iface=MIXER,name='Mxr 16/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1073,iface=MIXER,name='Mxr 16/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=209,iface=MIXER,name='Mxr 16/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=241,iface=MIXER,name='Mxr 16/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=273,iface=MIXER,name='Mxr 16/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=305,iface=MIXER,name='Mxr 16/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=337,iface=MIXER,name='Mxr 16/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=369,iface=MIXER,name='Mxr 16/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=82,iface=MIXER,name='Mxr 17/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=114,iface=MIXER,name='Mxr 17/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=402,iface=MIXER,name='Mxr 17/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=434,iface=MIXER,name='Mxr 17/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=466,iface=MIXER,name='Mxr 17/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=498,iface=MIXER,name='Mxr 17/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=530,iface=MIXER,name='Mxr 17/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=562,iface=MIXER,name='Mxr 17/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=594,iface=MIXER,name='Mxr 17/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=626,iface=MIXER,name='Mxr 17/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=658,iface=MIXER,name='Mxr 17/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=690,iface=MIXER,name='Mxr 17/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=146,iface=MIXER,name='Mxr 17/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=722,iface=MIXER,name='Mxr 17/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=754,iface=MIXER,name='Mxr 17/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=786,iface=MIXER,name='Mxr 17/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=818,iface=MIXER,name='Mxr 17/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=850,iface=MIXER,name='Mxr 17/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=882,iface=MIXER,name='Mxr 17/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=914,iface=MIXER,name='Mxr 17/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=946,iface=MIXER,name='Mxr 17/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=978,iface=MIXER,name='Mxr 17/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1010,iface=MIXER,name='Mxr 17/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=178,iface=MIXER,name='Mxr 17/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1042,iface=MIXER,name='Mxr 17/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1074,iface=MIXER,name='Mxr 17/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=210,iface=MIXER,name='Mxr 17/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=242,iface=MIXER,name='Mxr 17/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=274,iface=MIXER,name='Mxr 17/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=306,iface=MIXER,name='Mxr 17/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=338,iface=MIXER,name='Mxr 17/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=370,iface=MIXER,name='Mxr 17/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=83,iface=MIXER,name='Mxr 18/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=115,iface=MIXER,name='Mxr 18/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=403,iface=MIXER,name='Mxr 18/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=435,iface=MIXER,name='Mxr 18/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=467,iface=MIXER,name='Mxr 18/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=499,iface=MIXER,name='Mxr 18/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=531,iface=MIXER,name='Mxr 18/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=563,iface=MIXER,name='Mxr 18/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=595,iface=MIXER,name='Mxr 18/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=627,iface=MIXER,name='Mxr 18/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=659,iface=MIXER,name='Mxr 18/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=691,iface=MIXER,name='Mxr 18/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=147,iface=MIXER,name='Mxr 18/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=723,iface=MIXER,name='Mxr 18/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=755,iface=MIXER,name='Mxr 18/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=787,iface=MIXER,name='Mxr 18/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=819,iface=MIXER,name='Mxr 18/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=851,iface=MIXER,name='Mxr 18/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=883,iface=MIXER,name='Mxr 18/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=915,iface=MIXER,name='Mxr 18/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=947,iface=MIXER,name='Mxr 18/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=979,iface=MIXER,name='Mxr 18/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1011,iface=MIXER,name='Mxr 18/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=179,iface=MIXER,name='Mxr 18/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1043,iface=MIXER,name='Mxr 18/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1075,iface=MIXER,name='Mxr 18/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=211,iface=MIXER,name='Mxr 18/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=243,iface=MIXER,name='Mxr 18/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=275,iface=MIXER,name='Mxr 18/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=307,iface=MIXER,name='Mxr 18/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=339,iface=MIXER,name='Mxr 18/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=371,iface=MIXER,name='Mxr 18/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=84,iface=MIXER,name='Mxr 19/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=116,iface=MIXER,name='Mxr 19/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=404,iface=MIXER,name='Mxr 19/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=436,iface=MIXER,name='Mxr 19/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=468,iface=MIXER,name='Mxr 19/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=500,iface=MIXER,name='Mxr 19/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=532,iface=MIXER,name='Mxr 19/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=564,iface=MIXER,name='Mxr 19/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=596,iface=MIXER,name='Mxr 19/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=628,iface=MIXER,name='Mxr 19/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=660,iface=MIXER,name='Mxr 19/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=692,iface=MIXER,name='Mxr 19/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=148,iface=MIXER,name='Mxr 19/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=724,iface=MIXER,name='Mxr 19/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=756,iface=MIXER,name='Mxr 19/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=788,iface=MIXER,name='Mxr 19/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=820,iface=MIXER,name='Mxr 19/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=852,iface=MIXER,name='Mxr 19/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=884,iface=MIXER,name='Mxr 19/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=916,iface=MIXER,name='Mxr 19/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=948,iface=MIXER,name='Mxr 19/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=980,iface=MIXER,name='Mxr 19/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1012,iface=MIXER,name='Mxr 19/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=180,iface=MIXER,name='Mxr 19/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1044,iface=MIXER,name='Mxr 19/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1076,iface=MIXER,name='Mxr 19/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=212,iface=MIXER,name='Mxr 19/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=244,iface=MIXER,name='Mxr 19/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=276,iface=MIXER,name='Mxr 19/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=308,iface=MIXER,name='Mxr 19/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=340,iface=MIXER,name='Mxr 19/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=372,iface=MIXER,name='Mxr 19/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=67,iface=MIXER,name='Mxr 2/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=99,iface=MIXER,name='Mxr 2/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=387,iface=MIXER,name='Mxr 2/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=419,iface=MIXER,name='Mxr 2/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=451,iface=MIXER,name='Mxr 2/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=483,iface=MIXER,name='Mxr 2/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=515,iface=MIXER,name='Mxr 2/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=547,iface=MIXER,name='Mxr 2/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=579,iface=MIXER,name='Mxr 2/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=611,iface=MIXER,name='Mxr 2/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=643,iface=MIXER,name='Mxr 2/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=675,iface=MIXER,name='Mxr 2/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=131,iface=MIXER,name='Mxr 2/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=707,iface=MIXER,name='Mxr 2/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=739,iface=MIXER,name='Mxr 2/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=771,iface=MIXER,name='Mxr 2/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=803,iface=MIXER,name='Mxr 2/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=835,iface=MIXER,name='Mxr 2/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=867,iface=MIXER,name='Mxr 2/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=899,iface=MIXER,name='Mxr 2/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=931,iface=MIXER,name='Mxr 2/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=963,iface=MIXER,name='Mxr 2/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=995,iface=MIXER,name='Mxr 2/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=163,iface=MIXER,name='Mxr 2/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1027,iface=MIXER,name='Mxr 2/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1059,iface=MIXER,name='Mxr 2/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=195,iface=MIXER,name='Mxr 2/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=227,iface=MIXER,name='Mxr 2/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=259,iface=MIXER,name='Mxr 2/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=291,iface=MIXER,name='Mxr 2/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=323,iface=MIXER,name='Mxr 2/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=355,iface=MIXER,name='Mxr 2/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=85,iface=MIXER,name='Mxr 20/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=117,iface=MIXER,name='Mxr 20/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=405,iface=MIXER,name='Mxr 20/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=437,iface=MIXER,name='Mxr 20/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=469,iface=MIXER,name='Mxr 20/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=501,iface=MIXER,name='Mxr 20/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=533,iface=MIXER,name='Mxr 20/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=565,iface=MIXER,name='Mxr 20/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=597,iface=MIXER,name='Mxr 20/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=629,iface=MIXER,name='Mxr 20/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=661,iface=MIXER,name='Mxr 20/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=693,iface=MIXER,name='Mxr 20/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=149,iface=MIXER,name='Mxr 20/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=725,iface=MIXER,name='Mxr 20/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=757,iface=MIXER,name='Mxr 20/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=789,iface=MIXER,name='Mxr 20/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=821,iface=MIXER,name='Mxr 20/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=853,iface=MIXER,name='Mxr 20/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=885,iface=MIXER,name='Mxr 20/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=917,iface=MIXER,name='Mxr 20/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=949,iface=MIXER,name='Mxr 20/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=981,iface=MIXER,name='Mxr 20/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1013,iface=MIXER,name='Mxr 20/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=181,iface=MIXER,name='Mxr 20/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1045,iface=MIXER,name='Mxr 20/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1077,iface=MIXER,name='Mxr 20/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=213,iface=MIXER,name='Mxr 20/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=245,iface=MIXER,name='Mxr 20/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=277,iface=MIXER,name='Mxr 20/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=309,iface=MIXER,name='Mxr 20/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=341,iface=MIXER,name='Mxr 20/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=373,iface=MIXER,name='Mxr 20/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=86,iface=MIXER,name='Mxr 21/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=118,iface=MIXER,name='Mxr 21/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=406,iface=MIXER,name='Mxr 21/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=438,iface=MIXER,name='Mxr 21/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=470,iface=MIXER,name='Mxr 21/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=502,iface=MIXER,name='Mxr 21/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=534,iface=MIXER,name='Mxr 21/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=566,iface=MIXER,name='Mxr 21/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=598,iface=MIXER,name='Mxr 21/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=630,iface=MIXER,name='Mxr 21/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=662,iface=MIXER,name='Mxr 21/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=694,iface=MIXER,name='Mxr 21/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=150,iface=MIXER,name='Mxr 21/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=726,iface=MIXER,name='Mxr 21/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=758,iface=MIXER,name='Mxr 21/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=790,iface=MIXER,name='Mxr 21/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=822,iface=MIXER,name='Mxr 21/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=854,iface=MIXER,name='Mxr 21/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=886,iface=MIXER,name='Mxr 21/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=918,iface=MIXER,name='Mxr 21/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=950,iface=MIXER,name='Mxr 21/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=982,iface=MIXER,name='Mxr 21/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1014,iface=MIXER,name='Mxr 21/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=182,iface=MIXER,name='Mxr 21/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1046,iface=MIXER,name='Mxr 21/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1078,iface=MIXER,name='Mxr 21/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=214,iface=MIXER,name='Mxr 21/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=246,iface=MIXER,name='Mxr 21/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=278,iface=MIXER,name='Mxr 21/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=310,iface=MIXER,name='Mxr 21/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=342,iface=MIXER,name='Mxr 21/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=374,iface=MIXER,name='Mxr 21/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=87,iface=MIXER,name='Mxr 22/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=119,iface=MIXER,name='Mxr 22/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=407,iface=MIXER,name='Mxr 22/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=439,iface=MIXER,name='Mxr 22/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=471,iface=MIXER,name='Mxr 22/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=503,iface=MIXER,name='Mxr 22/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=535,iface=MIXER,name='Mxr 22/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=567,iface=MIXER,name='Mxr 22/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=599,iface=MIXER,name='Mxr 22/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=631,iface=MIXER,name='Mxr 22/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=663,iface=MIXER,name='Mxr 22/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=695,iface=MIXER,name='Mxr 22/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=151,iface=MIXER,name='Mxr 22/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=727,iface=MIXER,name='Mxr 22/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=759,iface=MIXER,name='Mxr 22/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=791,iface=MIXER,name='Mxr 22/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=823,iface=MIXER,name='Mxr 22/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=855,iface=MIXER,name='Mxr 22/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=887,iface=MIXER,name='Mxr 22/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=919,iface=MIXER,name='Mxr 22/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=951,iface=MIXER,name='Mxr 22/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=983,iface=MIXER,name='Mxr 22/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1015,iface=MIXER,name='Mxr 22/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=183,iface=MIXER,name='Mxr 22/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1047,iface=MIXER,name='Mxr 22/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1079,iface=MIXER,name='Mxr 22/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=215,iface=MIXER,name='Mxr 22/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=247,iface=MIXER,name='Mxr 22/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=279,iface=MIXER,name='Mxr 22/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=311,iface=MIXER,name='Mxr 22/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=343,iface=MIXER,name='Mxr 22/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=375,iface=MIXER,name='Mxr 22/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=88,iface=MIXER,name='Mxr 23/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=120,iface=MIXER,name='Mxr 23/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=408,iface=MIXER,name='Mxr 23/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=440,iface=MIXER,name='Mxr 23/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=472,iface=MIXER,name='Mxr 23/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=504,iface=MIXER,name='Mxr 23/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=536,iface=MIXER,name='Mxr 23/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=568,iface=MIXER,name='Mxr 23/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=600,iface=MIXER,name='Mxr 23/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=632,iface=MIXER,name='Mxr 23/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=664,iface=MIXER,name='Mxr 23/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=696,iface=MIXER,name='Mxr 23/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=152,iface=MIXER,name='Mxr 23/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=728,iface=MIXER,name='Mxr 23/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=760,iface=MIXER,name='Mxr 23/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=792,iface=MIXER,name='Mxr 23/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=824,iface=MIXER,name='Mxr 23/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=856,iface=MIXER,name='Mxr 23/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=888,iface=MIXER,name='Mxr 23/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=920,iface=MIXER,name='Mxr 23/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=952,iface=MIXER,name='Mxr 23/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=984,iface=MIXER,name='Mxr 23/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1016,iface=MIXER,name='Mxr 23/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=184,iface=MIXER,name='Mxr 23/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1048,iface=MIXER,name='Mxr 23/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1080,iface=MIXER,name='Mxr 23/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=216,iface=MIXER,name='Mxr 23/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=248,iface=MIXER,name='Mxr 23/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=280,iface=MIXER,name='Mxr 23/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=312,iface=MIXER,name='Mxr 23/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=344,iface=MIXER,name='Mxr 23/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=376,iface=MIXER,name='Mxr 23/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=89,iface=MIXER,name='Mxr 24/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=121,iface=MIXER,name='Mxr 24/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=409,iface=MIXER,name='Mxr 24/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=441,iface=MIXER,name='Mxr 24/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=473,iface=MIXER,name='Mxr 24/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=505,iface=MIXER,name='Mxr 24/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=537,iface=MIXER,name='Mxr 24/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=569,iface=MIXER,name='Mxr 24/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=601,iface=MIXER,name='Mxr 24/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=633,iface=MIXER,name='Mxr 24/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=665,iface=MIXER,name='Mxr 24/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=697,iface=MIXER,name='Mxr 24/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=153,iface=MIXER,name='Mxr 24/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=729,iface=MIXER,name='Mxr 24/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=761,iface=MIXER,name='Mxr 24/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=793,iface=MIXER,name='Mxr 24/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=825,iface=MIXER,name='Mxr 24/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=857,iface=MIXER,name='Mxr 24/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=889,iface=MIXER,name='Mxr 24/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=921,iface=MIXER,name='Mxr 24/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=953,iface=MIXER,name='Mxr 24/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=985,iface=MIXER,name='Mxr 24/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1017,iface=MIXER,name='Mxr 24/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=185,iface=MIXER,name='Mxr 24/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1049,iface=MIXER,name='Mxr 24/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1081,iface=MIXER,name='Mxr 24/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=217,iface=MIXER,name='Mxr 24/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=249,iface=MIXER,name='Mxr 24/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=281,iface=MIXER,name='Mxr 24/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=313,iface=MIXER,name='Mxr 24/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=345,iface=MIXER,name='Mxr 24/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=377,iface=MIXER,name='Mxr 24/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=90,iface=MIXER,name='Mxr 25/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=122,iface=MIXER,name='Mxr 25/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=410,iface=MIXER,name='Mxr 25/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=442,iface=MIXER,name='Mxr 25/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=474,iface=MIXER,name='Mxr 25/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=506,iface=MIXER,name='Mxr 25/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=538,iface=MIXER,name='Mxr 25/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=570,iface=MIXER,name='Mxr 25/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=602,iface=MIXER,name='Mxr 25/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=634,iface=MIXER,name='Mxr 25/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=666,iface=MIXER,name='Mxr 25/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=698,iface=MIXER,name='Mxr 25/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=154,iface=MIXER,name='Mxr 25/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=730,iface=MIXER,name='Mxr 25/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=762,iface=MIXER,name='Mxr 25/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=794,iface=MIXER,name='Mxr 25/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=826,iface=MIXER,name='Mxr 25/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=858,iface=MIXER,name='Mxr 25/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=890,iface=MIXER,name='Mxr 25/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=922,iface=MIXER,name='Mxr 25/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=954,iface=MIXER,name='Mxr 25/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=986,iface=MIXER,name='Mxr 25/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1018,iface=MIXER,name='Mxr 25/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=186,iface=MIXER,name='Mxr 25/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1050,iface=MIXER,name='Mxr 25/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1082,iface=MIXER,name='Mxr 25/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=218,iface=MIXER,name='Mxr 25/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=250,iface=MIXER,name='Mxr 25/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=282,iface=MIXER,name='Mxr 25/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=314,iface=MIXER,name='Mxr 25/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=346,iface=MIXER,name='Mxr 25/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=378,iface=MIXER,name='Mxr 25/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=91,iface=MIXER,name='Mxr 26/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=123,iface=MIXER,name='Mxr 26/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=411,iface=MIXER,name='Mxr 26/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=443,iface=MIXER,name='Mxr 26/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=475,iface=MIXER,name='Mxr 26/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=507,iface=MIXER,name='Mxr 26/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=539,iface=MIXER,name='Mxr 26/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=571,iface=MIXER,name='Mxr 26/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=603,iface=MIXER,name='Mxr 26/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=635,iface=MIXER,name='Mxr 26/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=667,iface=MIXER,name='Mxr 26/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=699,iface=MIXER,name='Mxr 26/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=155,iface=MIXER,name='Mxr 26/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=731,iface=MIXER,name='Mxr 26/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=763,iface=MIXER,name='Mxr 26/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=795,iface=MIXER,name='Mxr 26/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=827,iface=MIXER,name='Mxr 26/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=859,iface=MIXER,name='Mxr 26/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=891,iface=MIXER,name='Mxr 26/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=923,iface=MIXER,name='Mxr 26/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=955,iface=MIXER,name='Mxr 26/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=987,iface=MIXER,name='Mxr 26/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1019,iface=MIXER,name='Mxr 26/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=187,iface=MIXER,name='Mxr 26/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1051,iface=MIXER,name='Mxr 26/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1083,iface=MIXER,name='Mxr 26/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=219,iface=MIXER,name='Mxr 26/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=251,iface=MIXER,name='Mxr 26/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=283,iface=MIXER,name='Mxr 26/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=315,iface=MIXER,name='Mxr 26/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=347,iface=MIXER,name='Mxr 26/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=379,iface=MIXER,name='Mxr 26/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=92,iface=MIXER,name='Mxr 27/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=124,iface=MIXER,name='Mxr 27/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=412,iface=MIXER,name='Mxr 27/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=444,iface=MIXER,name='Mxr 27/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=476,iface=MIXER,name='Mxr 27/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=508,iface=MIXER,name='Mxr 27/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=540,iface=MIXER,name='Mxr 27/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=572,iface=MIXER,name='Mxr 27/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=604,iface=MIXER,name='Mxr 27/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=636,iface=MIXER,name='Mxr 27/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=668,iface=MIXER,name='Mxr 27/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=700,iface=MIXER,name='Mxr 27/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=156,iface=MIXER,name='Mxr 27/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=732,iface=MIXER,name='Mxr 27/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=764,iface=MIXER,name='Mxr 27/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=796,iface=MIXER,name='Mxr 27/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=828,iface=MIXER,name='Mxr 27/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=860,iface=MIXER,name='Mxr 27/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=892,iface=MIXER,name='Mxr 27/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=924,iface=MIXER,name='Mxr 27/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=956,iface=MIXER,name='Mxr 27/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=988,iface=MIXER,name='Mxr 27/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1020,iface=MIXER,name='Mxr 27/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=188,iface=MIXER,name='Mxr 27/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1052,iface=MIXER,name='Mxr 27/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1084,iface=MIXER,name='Mxr 27/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=220,iface=MIXER,name='Mxr 27/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=252,iface=MIXER,name='Mxr 27/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=284,iface=MIXER,name='Mxr 27/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=316,iface=MIXER,name='Mxr 27/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=348,iface=MIXER,name='Mxr 27/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=380,iface=MIXER,name='Mxr 27/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=93,iface=MIXER,name='Mxr 28/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=125,iface=MIXER,name='Mxr 28/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=413,iface=MIXER,name='Mxr 28/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=445,iface=MIXER,name='Mxr 28/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=477,iface=MIXER,name='Mxr 28/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=509,iface=MIXER,name='Mxr 28/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=541,iface=MIXER,name='Mxr 28/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=573,iface=MIXER,name='Mxr 28/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=605,iface=MIXER,name='Mxr 28/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=637,iface=MIXER,name='Mxr 28/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=669,iface=MIXER,name='Mxr 28/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=701,iface=MIXER,name='Mxr 28/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=157,iface=MIXER,name='Mxr 28/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=733,iface=MIXER,name='Mxr 28/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=765,iface=MIXER,name='Mxr 28/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=797,iface=MIXER,name='Mxr 28/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=829,iface=MIXER,name='Mxr 28/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=861,iface=MIXER,name='Mxr 28/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=893,iface=MIXER,name='Mxr 28/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=925,iface=MIXER,name='Mxr 28/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=957,iface=MIXER,name='Mxr 28/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=989,iface=MIXER,name='Mxr 28/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1021,iface=MIXER,name='Mxr 28/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=189,iface=MIXER,name='Mxr 28/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1053,iface=MIXER,name='Mxr 28/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1085,iface=MIXER,name='Mxr 28/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=221,iface=MIXER,name='Mxr 28/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=253,iface=MIXER,name='Mxr 28/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=285,iface=MIXER,name='Mxr 28/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=317,iface=MIXER,name='Mxr 28/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=349,iface=MIXER,name='Mxr 28/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=381,iface=MIXER,name='Mxr 28/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=94,iface=MIXER,name='Mxr 29/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=126,iface=MIXER,name='Mxr 29/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=414,iface=MIXER,name='Mxr 29/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=446,iface=MIXER,name='Mxr 29/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=478,iface=MIXER,name='Mxr 29/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=510,iface=MIXER,name='Mxr 29/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=542,iface=MIXER,name='Mxr 29/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=574,iface=MIXER,name='Mxr 29/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=606,iface=MIXER,name='Mxr 29/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=638,iface=MIXER,name='Mxr 29/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=670,iface=MIXER,name='Mxr 29/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=702,iface=MIXER,name='Mxr 29/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=158,iface=MIXER,name='Mxr 29/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=734,iface=MIXER,name='Mxr 29/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=766,iface=MIXER,name='Mxr 29/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=798,iface=MIXER,name='Mxr 29/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=830,iface=MIXER,name='Mxr 29/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=862,iface=MIXER,name='Mxr 29/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=894,iface=MIXER,name='Mxr 29/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=926,iface=MIXER,name='Mxr 29/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=958,iface=MIXER,name='Mxr 29/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=990,iface=MIXER,name='Mxr 29/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1022,iface=MIXER,name='Mxr 29/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=190,iface=MIXER,name='Mxr 29/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1054,iface=MIXER,name='Mxr 29/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1086,iface=MIXER,name='Mxr 29/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=222,iface=MIXER,name='Mxr 29/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=254,iface=MIXER,name='Mxr 29/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=286,iface=MIXER,name='Mxr 29/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=318,iface=MIXER,name='Mxr 29/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=350,iface=MIXER,name='Mxr 29/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=382,iface=MIXER,name='Mxr 29/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=68,iface=MIXER,name='Mxr 3/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=100,iface=MIXER,name='Mxr 3/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=388,iface=MIXER,name='Mxr 3/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=420,iface=MIXER,name='Mxr 3/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=452,iface=MIXER,name='Mxr 3/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=484,iface=MIXER,name='Mxr 3/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=516,iface=MIXER,name='Mxr 3/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=548,iface=MIXER,name='Mxr 3/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=580,iface=MIXER,name='Mxr 3/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=612,iface=MIXER,name='Mxr 3/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=644,iface=MIXER,name='Mxr 3/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=676,iface=MIXER,name='Mxr 3/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=132,iface=MIXER,name='Mxr 3/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=708,iface=MIXER,name='Mxr 3/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=740,iface=MIXER,name='Mxr 3/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=772,iface=MIXER,name='Mxr 3/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=804,iface=MIXER,name='Mxr 3/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=836,iface=MIXER,name='Mxr 3/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=868,iface=MIXER,name='Mxr 3/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=900,iface=MIXER,name='Mxr 3/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=932,iface=MIXER,name='Mxr 3/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=964,iface=MIXER,name='Mxr 3/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=996,iface=MIXER,name='Mxr 3/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=164,iface=MIXER,name='Mxr 3/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1028,iface=MIXER,name='Mxr 3/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1060,iface=MIXER,name='Mxr 3/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=196,iface=MIXER,name='Mxr 3/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=228,iface=MIXER,name='Mxr 3/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=260,iface=MIXER,name='Mxr 3/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=292,iface=MIXER,name='Mxr 3/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=324,iface=MIXER,name='Mxr 3/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=356,iface=MIXER,name='Mxr 3/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=95,iface=MIXER,name='Mxr 30/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=127,iface=MIXER,name='Mxr 30/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=415,iface=MIXER,name='Mxr 30/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=447,iface=MIXER,name='Mxr 30/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=479,iface=MIXER,name='Mxr 30/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=511,iface=MIXER,name='Mxr 30/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=543,iface=MIXER,name='Mxr 30/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=575,iface=MIXER,name='Mxr 30/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=607,iface=MIXER,name='Mxr 30/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=639,iface=MIXER,name='Mxr 30/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=671,iface=MIXER,name='Mxr 30/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=703,iface=MIXER,name='Mxr 30/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=159,iface=MIXER,name='Mxr 30/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=735,iface=MIXER,name='Mxr 30/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=767,iface=MIXER,name='Mxr 30/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=799,iface=MIXER,name='Mxr 30/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=831,iface=MIXER,name='Mxr 30/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=863,iface=MIXER,name='Mxr 30/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=895,iface=MIXER,name='Mxr 30/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=927,iface=MIXER,name='Mxr 30/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=959,iface=MIXER,name='Mxr 30/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=991,iface=MIXER,name='Mxr 30/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1023,iface=MIXER,name='Mxr 30/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=191,iface=MIXER,name='Mxr 30/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1055,iface=MIXER,name='Mxr 30/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1087,iface=MIXER,name='Mxr 30/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=223,iface=MIXER,name='Mxr 30/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=255,iface=MIXER,name='Mxr 30/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=287,iface=MIXER,name='Mxr 30/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=319,iface=MIXER,name='Mxr 30/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=351,iface=MIXER,name='Mxr 30/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=383,iface=MIXER,name='Mxr 30/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=96,iface=MIXER,name='Mxr 31/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=128,iface=MIXER,name='Mxr 31/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=416,iface=MIXER,name='Mxr 31/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=448,iface=MIXER,name='Mxr 31/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=480,iface=MIXER,name='Mxr 31/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=512,iface=MIXER,name='Mxr 31/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=544,iface=MIXER,name='Mxr 31/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=576,iface=MIXER,name='Mxr 31/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=608,iface=MIXER,name='Mxr 31/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=640,iface=MIXER,name='Mxr 31/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=672,iface=MIXER,name='Mxr 31/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=704,iface=MIXER,name='Mxr 31/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=160,iface=MIXER,name='Mxr 31/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=736,iface=MIXER,name='Mxr 31/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=768,iface=MIXER,name='Mxr 31/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=800,iface=MIXER,name='Mxr 31/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=832,iface=MIXER,name='Mxr 31/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=864,iface=MIXER,name='Mxr 31/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=896,iface=MIXER,name='Mxr 31/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=928,iface=MIXER,name='Mxr 31/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=960,iface=MIXER,name='Mxr 31/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=992,iface=MIXER,name='Mxr 31/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1024,iface=MIXER,name='Mxr 31/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=192,iface=MIXER,name='Mxr 31/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1056,iface=MIXER,name='Mxr 31/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1088,iface=MIXER,name='Mxr 31/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=224,iface=MIXER,name='Mxr 31/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=256,iface=MIXER,name='Mxr 31/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=288,iface=MIXER,name='Mxr 31/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=320,iface=MIXER,name='Mxr 31/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=352,iface=MIXER,name='Mxr 31/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=384,iface=MIXER,name='Mxr 31/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=69,iface=MIXER,name='Mxr 4/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=101,iface=MIXER,name='Mxr 4/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=389,iface=MIXER,name='Mxr 4/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=421,iface=MIXER,name='Mxr 4/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=453,iface=MIXER,name='Mxr 4/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=485,iface=MIXER,name='Mxr 4/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=517,iface=MIXER,name='Mxr 4/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=549,iface=MIXER,name='Mxr 4/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=581,iface=MIXER,name='Mxr 4/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=613,iface=MIXER,name='Mxr 4/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=645,iface=MIXER,name='Mxr 4/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=677,iface=MIXER,name='Mxr 4/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=133,iface=MIXER,name='Mxr 4/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=709,iface=MIXER,name='Mxr 4/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=741,iface=MIXER,name='Mxr 4/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=773,iface=MIXER,name='Mxr 4/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=805,iface=MIXER,name='Mxr 4/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=837,iface=MIXER,name='Mxr 4/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=869,iface=MIXER,name='Mxr 4/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=901,iface=MIXER,name='Mxr 4/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=933,iface=MIXER,name='Mxr 4/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=965,iface=MIXER,name='Mxr 4/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=997,iface=MIXER,name='Mxr 4/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=165,iface=MIXER,name='Mxr 4/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1029,iface=MIXER,name='Mxr 4/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1061,iface=MIXER,name='Mxr 4/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=197,iface=MIXER,name='Mxr 4/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=229,iface=MIXER,name='Mxr 4/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=261,iface=MIXER,name='Mxr 4/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=293,iface=MIXER,name='Mxr 4/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=325,iface=MIXER,name='Mxr 4/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=357,iface=MIXER,name='Mxr 4/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=70,iface=MIXER,name='Mxr 5/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=102,iface=MIXER,name='Mxr 5/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=390,iface=MIXER,name='Mxr 5/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=422,iface=MIXER,name='Mxr 5/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=454,iface=MIXER,name='Mxr 5/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=486,iface=MIXER,name='Mxr 5/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=518,iface=MIXER,name='Mxr 5/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=550,iface=MIXER,name='Mxr 5/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=582,iface=MIXER,name='Mxr 5/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=614,iface=MIXER,name='Mxr 5/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=646,iface=MIXER,name='Mxr 5/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=678,iface=MIXER,name='Mxr 5/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=134,iface=MIXER,name='Mxr 5/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=710,iface=MIXER,name='Mxr 5/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=742,iface=MIXER,name='Mxr 5/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=774,iface=MIXER,name='Mxr 5/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=806,iface=MIXER,name='Mxr 5/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=838,iface=MIXER,name='Mxr 5/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=870,iface=MIXER,name='Mxr 5/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=902,iface=MIXER,name='Mxr 5/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=934,iface=MIXER,name='Mxr 5/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=966,iface=MIXER,name='Mxr 5/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=998,iface=MIXER,name='Mxr 5/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=166,iface=MIXER,name='Mxr 5/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1030,iface=MIXER,name='Mxr 5/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1062,iface=MIXER,name='Mxr 5/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=198,iface=MIXER,name='Mxr 5/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=230,iface=MIXER,name='Mxr 5/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=262,iface=MIXER,name='Mxr 5/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=294,iface=MIXER,name='Mxr 5/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=326,iface=MIXER,name='Mxr 5/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=358,iface=MIXER,name='Mxr 5/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=71,iface=MIXER,name='Mxr 6/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=103,iface=MIXER,name='Mxr 6/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=391,iface=MIXER,name='Mxr 6/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=423,iface=MIXER,name='Mxr 6/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=455,iface=MIXER,name='Mxr 6/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=487,iface=MIXER,name='Mxr 6/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=519,iface=MIXER,name='Mxr 6/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=551,iface=MIXER,name='Mxr 6/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=583,iface=MIXER,name='Mxr 6/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=615,iface=MIXER,name='Mxr 6/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=647,iface=MIXER,name='Mxr 6/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=679,iface=MIXER,name='Mxr 6/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=135,iface=MIXER,name='Mxr 6/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=711,iface=MIXER,name='Mxr 6/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=743,iface=MIXER,name='Mxr 6/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=775,iface=MIXER,name='Mxr 6/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=807,iface=MIXER,name='Mxr 6/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=839,iface=MIXER,name='Mxr 6/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=871,iface=MIXER,name='Mxr 6/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=903,iface=MIXER,name='Mxr 6/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=935,iface=MIXER,name='Mxr 6/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=967,iface=MIXER,name='Mxr 6/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=999,iface=MIXER,name='Mxr 6/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=167,iface=MIXER,name='Mxr 6/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1031,iface=MIXER,name='Mxr 6/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1063,iface=MIXER,name='Mxr 6/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=199,iface=MIXER,name='Mxr 6/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=231,iface=MIXER,name='Mxr 6/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=263,iface=MIXER,name='Mxr 6/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=295,iface=MIXER,name='Mxr 6/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=327,iface=MIXER,name='Mxr 6/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=359,iface=MIXER,name='Mxr 6/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=72,iface=MIXER,name='Mxr 7/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=104,iface=MIXER,name='Mxr 7/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=392,iface=MIXER,name='Mxr 7/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=424,iface=MIXER,name='Mxr 7/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=456,iface=MIXER,name='Mxr 7/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=488,iface=MIXER,name='Mxr 7/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=520,iface=MIXER,name='Mxr 7/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=552,iface=MIXER,name='Mxr 7/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=584,iface=MIXER,name='Mxr 7/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=616,iface=MIXER,name='Mxr 7/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=648,iface=MIXER,name='Mxr 7/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=680,iface=MIXER,name='Mxr 7/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=136,iface=MIXER,name='Mxr 7/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=712,iface=MIXER,name='Mxr 7/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=744,iface=MIXER,name='Mxr 7/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=776,iface=MIXER,name='Mxr 7/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=808,iface=MIXER,name='Mxr 7/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=840,iface=MIXER,name='Mxr 7/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=872,iface=MIXER,name='Mxr 7/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=904,iface=MIXER,name='Mxr 7/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=936,iface=MIXER,name='Mxr 7/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=968,iface=MIXER,name='Mxr 7/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1000,iface=MIXER,name='Mxr 7/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=168,iface=MIXER,name='Mxr 7/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1032,iface=MIXER,name='Mxr 7/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1064,iface=MIXER,name='Mxr 7/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=200,iface=MIXER,name='Mxr 7/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=232,iface=MIXER,name='Mxr 7/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=264,iface=MIXER,name='Mxr 7/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=296,iface=MIXER,name='Mxr 7/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=328,iface=MIXER,name='Mxr 7/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=360,iface=MIXER,name='Mxr 7/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=73,iface=MIXER,name='Mxr 8/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=105,iface=MIXER,name='Mxr 8/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=393,iface=MIXER,name='Mxr 8/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=425,iface=MIXER,name='Mxr 8/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=457,iface=MIXER,name='Mxr 8/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=489,iface=MIXER,name='Mxr 8/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=521,iface=MIXER,name='Mxr 8/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=553,iface=MIXER,name='Mxr 8/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=585,iface=MIXER,name='Mxr 8/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=617,iface=MIXER,name='Mxr 8/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=649,iface=MIXER,name='Mxr 8/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=681,iface=MIXER,name='Mxr 8/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=137,iface=MIXER,name='Mxr 8/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=713,iface=MIXER,name='Mxr 8/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=745,iface=MIXER,name='Mxr 8/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=777,iface=MIXER,name='Mxr 8/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=809,iface=MIXER,name='Mxr 8/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=841,iface=MIXER,name='Mxr 8/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=873,iface=MIXER,name='Mxr 8/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=905,iface=MIXER,name='Mxr 8/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=937,iface=MIXER,name='Mxr 8/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=969,iface=MIXER,name='Mxr 8/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1001,iface=MIXER,name='Mxr 8/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=169,iface=MIXER,name='Mxr 8/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1033,iface=MIXER,name='Mxr 8/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1065,iface=MIXER,name='Mxr 8/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=201,iface=MIXER,name='Mxr 8/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=233,iface=MIXER,name='Mxr 8/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=265,iface=MIXER,name='Mxr 8/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=297,iface=MIXER,name='Mxr 8/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=329,iface=MIXER,name='Mxr 8/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=361,iface=MIXER,name='Mxr 8/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=74,iface=MIXER,name='Mxr 9/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=106,iface=MIXER,name='Mxr 9/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=394,iface=MIXER,name='Mxr 9/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=426,iface=MIXER,name='Mxr 9/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=458,iface=MIXER,name='Mxr 9/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=490,iface=MIXER,name='Mxr 9/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=522,iface=MIXER,name='Mxr 9/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=554,iface=MIXER,name='Mxr 9/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=586,iface=MIXER,name='Mxr 9/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=618,iface=MIXER,name='Mxr 9/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=650,iface=MIXER,name='Mxr 9/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=682,iface=MIXER,name='Mxr 9/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=138,iface=MIXER,name='Mxr 9/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=714,iface=MIXER,name='Mxr 9/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=746,iface=MIXER,name='Mxr 9/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=778,iface=MIXER,name='Mxr 9/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=810,iface=MIXER,name='Mxr 9/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=842,iface=MIXER,name='Mxr 9/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=874,iface=MIXER,name='Mxr 9/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=906,iface=MIXER,name='Mxr 9/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=938,iface=MIXER,name='Mxr 9/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=970,iface=MIXER,name='Mxr 9/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1002,iface=MIXER,name='Mxr 9/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=170,iface=MIXER,name='Mxr 9/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1034,iface=MIXER,name='Mxr 9/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1066,iface=MIXER,name='Mxr 9/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=202,iface=MIXER,name='Mxr 9/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=234,iface=MIXER,name='Mxr 9/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=266,iface=MIXER,name='Mxr 9/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=298,iface=MIXER,name='Mxr 9/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=330,iface=MIXER,name='Mxr 9/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=362,iface=MIXER,name='Mxr 9/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB diff --git a/snd-alpx-dkms/Controls/Alp882e-MIC_Controls.txt b/snd-alpx-dkms/Controls/Alp882e-MIC_Controls.txt new file mode 100644 index 0000000..2e9eee2 --- /dev/null +++ b/snd-alpx-dkms/Controls/Alp882e-MIC_Controls.txt @@ -0,0 +1,1116 @@ +numid=25,iface=MIXER,name='AES Capture Volume' +numid=26,iface=MIXER,name='AES Capture Volume',index=1 +numid=27,iface=MIXER,name='AES Capture Volume',index=2 +numid=28,iface=MIXER,name='AES Capture Volume',index=3 +numid=29,iface=MIXER,name='AES Capture Volume',index=4 +numid=30,iface=MIXER,name='AES Capture Volume',index=5 +numid=31,iface=MIXER,name='AES Capture Volume',index=6 +numid=32,iface=MIXER,name='AES Capture Volume',index=7 +numid=41,iface=MIXER,name='AES Playback Volume' +numid=42,iface=MIXER,name='AES Playback Volume',index=1 +numid=43,iface=MIXER,name='AES Playback Volume',index=2 +numid=44,iface=MIXER,name='AES Playback Volume',index=3 +numid=45,iface=MIXER,name='AES Playback Volume',index=4 +numid=46,iface=MIXER,name='AES Playback Volume',index=5 +numid=47,iface=MIXER,name='AES Playback Volume',index=6 +numid=48,iface=MIXER,name='AES Playback Volume',index=7 +numid=1098,iface=MIXER,name='AES SRC 1/2 Disable' +numid=1099,iface=MIXER,name='AES SRC 3/4 Disable' +numid=1100,iface=MIXER,name='AES SRC 5/6 Disable' +numid=1101,iface=MIXER,name='AES SRC 7/8 Disable' +numid=17,iface=MIXER,name='Ana Capture Volume' +numid=18,iface=MIXER,name='Ana Capture Volume',index=1 +numid=19,iface=MIXER,name='Ana Capture Volume',index=2 +numid=20,iface=MIXER,name='Ana Capture Volume',index=3 +numid=21,iface=MIXER,name='Ana Capture Volume',index=4 +numid=22,iface=MIXER,name='Ana Capture Volume',index=5 +numid=23,iface=MIXER,name='Ana Capture Volume',index=6 +numid=24,iface=MIXER,name='Ana Capture Volume',index=7 +numid=33,iface=MIXER,name='Ana Playback Volume' +numid=34,iface=MIXER,name='Ana Playback Volume',index=1 +numid=35,iface=MIXER,name='Ana Playback Volume',index=2 +numid=36,iface=MIXER,name='Ana Playback Volume',index=3 +numid=37,iface=MIXER,name='Ana Playback Volume',index=4 +numid=38,iface=MIXER,name='Ana Playback Volume',index=5 +numid=39,iface=MIXER,name='Ana Playback Volume',index=6 +numid=40,iface=MIXER,name='Ana Playback Volume',index=7 +numid=1090,iface=MIXER,name='Clk Eff' +numid=1089,iface=MIXER,name='Clk Eff Src' +numid=1094,iface=MIXER,name='Clk P0' +numid=1095,iface=MIXER,name='Clk P1' +numid=1096,iface=MIXER,name='Clk P2' +numid=1097,iface=MIXER,name='Clk P3' +numid=1093,iface=MIXER,name='Clk Src Down' +numid=1092,iface=MIXER,name='Clk Src Up' +numid=1102,iface=MIXER,name='Codec MIC Analog Capture Volume' +numid=1103,iface=MIXER,name='Codec MIC Analog Capture Volume',index=1 +numid=1104,iface=MIXER,name='Codec MIC Analog Capture Volume',index=2 +numid=1105,iface=MIXER,name='Codec MIC Analog Capture Volume',index=3 +numid=1106,iface=MIXER,name='Codec MIC Analog Capture Volume',index=4 +numid=1107,iface=MIXER,name='Codec MIC Analog Capture Volume',index=5 +numid=1108,iface=MIXER,name='Codec MIC Analog Capture Volume',index=6 +numid=1109,iface=MIXER,name='Codec MIC Analog Capture Volume',index=7 +numid=1,iface=MIXER,name='DAW Capture Volume' +numid=2,iface=MIXER,name='DAW Capture Volume',index=1 +numid=3,iface=MIXER,name='DAW Capture Volume',index=2 +numid=4,iface=MIXER,name='DAW Capture Volume',index=3 +numid=5,iface=MIXER,name='DAW Capture Volume',index=4 +numid=6,iface=MIXER,name='DAW Capture Volume',index=5 +numid=7,iface=MIXER,name='DAW Capture Volume',index=6 +numid=8,iface=MIXER,name='DAW Capture Volume',index=7 +numid=9,iface=MIXER,name='DAW Capture Volume',index=8 +numid=10,iface=MIXER,name='DAW Capture Volume',index=9 +numid=11,iface=MIXER,name='DAW Capture Volume',index=10 +numid=12,iface=MIXER,name='DAW Capture Volume',index=11 +numid=13,iface=MIXER,name='DAW Capture Volume',index=12 +numid=14,iface=MIXER,name='DAW Capture Volume',index=13 +numid=15,iface=MIXER,name='DAW Capture Volume',index=14 +numid=16,iface=MIXER,name='DAW Capture Volume',index=15 +numid=49,iface=MIXER,name='DAW Playback Volume' +numid=50,iface=MIXER,name='DAW Playback Volume',index=1 +numid=51,iface=MIXER,name='DAW Playback Volume',index=2 +numid=52,iface=MIXER,name='DAW Playback Volume',index=3 +numid=53,iface=MIXER,name='DAW Playback Volume',index=4 +numid=54,iface=MIXER,name='DAW Playback Volume',index=5 +numid=55,iface=MIXER,name='DAW Playback Volume',index=6 +numid=56,iface=MIXER,name='DAW Playback Volume',index=7 +numid=57,iface=MIXER,name='DAW Playback Volume',index=8 +numid=58,iface=MIXER,name='DAW Playback Volume',index=9 +numid=59,iface=MIXER,name='DAW Playback Volume',index=10 +numid=60,iface=MIXER,name='DAW Playback Volume',index=11 +numid=61,iface=MIXER,name='DAW Playback Volume',index=12 +numid=62,iface=MIXER,name='DAW Playback Volume',index=13 +numid=63,iface=MIXER,name='DAW Playback Volume',index=14 +numid=64,iface=MIXER,name='DAW Playback Volume',index=15 +numid=1110,iface=MIXER,name='McPh1' +numid=1111,iface=MIXER,name='McPh2' +numid=1112,iface=MIXER,name='McPh3' +numid=1113,iface=MIXER,name='McPh4' +numid=1114,iface=MIXER,name='McPh5' +numid=1115,iface=MIXER,name='McPh6' +numid=1116,iface=MIXER,name='McPh7' +numid=1117,iface=MIXER,name='McPh8' +numid=65,iface=MIXER,name='Mxr 0/0 Playback Volume' +numid=97,iface=MIXER,name='Mxr 0/1 Playback Volume' +numid=385,iface=MIXER,name='Mxr 0/10 Playback Volume' +numid=417,iface=MIXER,name='Mxr 0/11 Playback Volume' +numid=449,iface=MIXER,name='Mxr 0/12 Playback Volume' +numid=481,iface=MIXER,name='Mxr 0/13 Playback Volume' +numid=513,iface=MIXER,name='Mxr 0/14 Playback Volume' +numid=545,iface=MIXER,name='Mxr 0/15 Playback Volume' +numid=577,iface=MIXER,name='Mxr 0/16 Playback Volume' +numid=609,iface=MIXER,name='Mxr 0/17 Playback Volume' +numid=641,iface=MIXER,name='Mxr 0/18 Playback Volume' +numid=673,iface=MIXER,name='Mxr 0/19 Playback Volume' +numid=129,iface=MIXER,name='Mxr 0/2 Playback Volume' +numid=705,iface=MIXER,name='Mxr 0/20 Playback Volume' +numid=737,iface=MIXER,name='Mxr 0/21 Playback Volume' +numid=769,iface=MIXER,name='Mxr 0/22 Playback Volume' +numid=801,iface=MIXER,name='Mxr 0/23 Playback Volume' +numid=833,iface=MIXER,name='Mxr 0/24 Playback Volume' +numid=865,iface=MIXER,name='Mxr 0/25 Playback Volume' +numid=897,iface=MIXER,name='Mxr 0/26 Playback Volume' +numid=929,iface=MIXER,name='Mxr 0/27 Playback Volume' +numid=961,iface=MIXER,name='Mxr 0/28 Playback Volume' +numid=993,iface=MIXER,name='Mxr 0/29 Playback Volume' +numid=161,iface=MIXER,name='Mxr 0/3 Playback Volume' +numid=1025,iface=MIXER,name='Mxr 0/30 Playback Volume' +numid=1057,iface=MIXER,name='Mxr 0/31 Playback Volume' +numid=193,iface=MIXER,name='Mxr 0/4 Playback Volume' +numid=225,iface=MIXER,name='Mxr 0/5 Playback Volume' +numid=257,iface=MIXER,name='Mxr 0/6 Playback Volume' +numid=289,iface=MIXER,name='Mxr 0/7 Playback Volume' +numid=321,iface=MIXER,name='Mxr 0/8 Playback Volume' +numid=353,iface=MIXER,name='Mxr 0/9 Playback Volume' +numid=66,iface=MIXER,name='Mxr 1/0 Playback Volume' +numid=98,iface=MIXER,name='Mxr 1/1 Playback Volume' +numid=386,iface=MIXER,name='Mxr 1/10 Playback Volume' +numid=418,iface=MIXER,name='Mxr 1/11 Playback Volume' +numid=450,iface=MIXER,name='Mxr 1/12 Playback Volume' +numid=482,iface=MIXER,name='Mxr 1/13 Playback Volume' +numid=514,iface=MIXER,name='Mxr 1/14 Playback Volume' +numid=546,iface=MIXER,name='Mxr 1/15 Playback Volume' +numid=578,iface=MIXER,name='Mxr 1/16 Playback Volume' +numid=610,iface=MIXER,name='Mxr 1/17 Playback Volume' +numid=642,iface=MIXER,name='Mxr 1/18 Playback Volume' +numid=674,iface=MIXER,name='Mxr 1/19 Playback Volume' +numid=130,iface=MIXER,name='Mxr 1/2 Playback Volume' +numid=706,iface=MIXER,name='Mxr 1/20 Playback Volume' +numid=738,iface=MIXER,name='Mxr 1/21 Playback Volume' +numid=770,iface=MIXER,name='Mxr 1/22 Playback Volume' +numid=802,iface=MIXER,name='Mxr 1/23 Playback Volume' +numid=834,iface=MIXER,name='Mxr 1/24 Playback Volume' +numid=866,iface=MIXER,name='Mxr 1/25 Playback Volume' +numid=898,iface=MIXER,name='Mxr 1/26 Playback Volume' +numid=930,iface=MIXER,name='Mxr 1/27 Playback Volume' +numid=962,iface=MIXER,name='Mxr 1/28 Playback Volume' +numid=994,iface=MIXER,name='Mxr 1/29 Playback Volume' +numid=162,iface=MIXER,name='Mxr 1/3 Playback Volume' +numid=1026,iface=MIXER,name='Mxr 1/30 Playback Volume' +numid=1058,iface=MIXER,name='Mxr 1/31 Playback Volume' +numid=194,iface=MIXER,name='Mxr 1/4 Playback Volume' +numid=226,iface=MIXER,name='Mxr 1/5 Playback Volume' +numid=258,iface=MIXER,name='Mxr 1/6 Playback Volume' +numid=290,iface=MIXER,name='Mxr 1/7 Playback Volume' +numid=322,iface=MIXER,name='Mxr 1/8 Playback Volume' +numid=354,iface=MIXER,name='Mxr 1/9 Playback Volume' +numid=75,iface=MIXER,name='Mxr 10/0 Playback Volume' +numid=107,iface=MIXER,name='Mxr 10/1 Playback Volume' +numid=395,iface=MIXER,name='Mxr 10/10 Playback Volume' +numid=427,iface=MIXER,name='Mxr 10/11 Playback Volume' +numid=459,iface=MIXER,name='Mxr 10/12 Playback Volume' +numid=491,iface=MIXER,name='Mxr 10/13 Playback Volume' +numid=523,iface=MIXER,name='Mxr 10/14 Playback Volume' +numid=555,iface=MIXER,name='Mxr 10/15 Playback Volume' +numid=587,iface=MIXER,name='Mxr 10/16 Playback Volume' +numid=619,iface=MIXER,name='Mxr 10/17 Playback Volume' +numid=651,iface=MIXER,name='Mxr 10/18 Playback Volume' +numid=683,iface=MIXER,name='Mxr 10/19 Playback Volume' +numid=139,iface=MIXER,name='Mxr 10/2 Playback Volume' +numid=715,iface=MIXER,name='Mxr 10/20 Playback Volume' +numid=747,iface=MIXER,name='Mxr 10/21 Playback Volume' +numid=779,iface=MIXER,name='Mxr 10/22 Playback Volume' +numid=811,iface=MIXER,name='Mxr 10/23 Playback Volume' +numid=843,iface=MIXER,name='Mxr 10/24 Playback Volume' +numid=875,iface=MIXER,name='Mxr 10/25 Playback Volume' +numid=907,iface=MIXER,name='Mxr 10/26 Playback Volume' +numid=939,iface=MIXER,name='Mxr 10/27 Playback Volume' +numid=971,iface=MIXER,name='Mxr 10/28 Playback Volume' +numid=1003,iface=MIXER,name='Mxr 10/29 Playback Volume' +numid=171,iface=MIXER,name='Mxr 10/3 Playback Volume' +numid=1035,iface=MIXER,name='Mxr 10/30 Playback Volume' +numid=1067,iface=MIXER,name='Mxr 10/31 Playback Volume' +numid=203,iface=MIXER,name='Mxr 10/4 Playback Volume' +numid=235,iface=MIXER,name='Mxr 10/5 Playback Volume' +numid=267,iface=MIXER,name='Mxr 10/6 Playback Volume' +numid=299,iface=MIXER,name='Mxr 10/7 Playback Volume' +numid=331,iface=MIXER,name='Mxr 10/8 Playback Volume' +numid=363,iface=MIXER,name='Mxr 10/9 Playback Volume' +numid=76,iface=MIXER,name='Mxr 11/0 Playback Volume' +numid=108,iface=MIXER,name='Mxr 11/1 Playback Volume' +numid=396,iface=MIXER,name='Mxr 11/10 Playback Volume' +numid=428,iface=MIXER,name='Mxr 11/11 Playback Volume' +numid=460,iface=MIXER,name='Mxr 11/12 Playback Volume' +numid=492,iface=MIXER,name='Mxr 11/13 Playback Volume' +numid=524,iface=MIXER,name='Mxr 11/14 Playback Volume' +numid=556,iface=MIXER,name='Mxr 11/15 Playback Volume' +numid=588,iface=MIXER,name='Mxr 11/16 Playback Volume' +numid=620,iface=MIXER,name='Mxr 11/17 Playback Volume' +numid=652,iface=MIXER,name='Mxr 11/18 Playback Volume' +numid=684,iface=MIXER,name='Mxr 11/19 Playback Volume' +numid=140,iface=MIXER,name='Mxr 11/2 Playback Volume' +numid=716,iface=MIXER,name='Mxr 11/20 Playback Volume' +numid=748,iface=MIXER,name='Mxr 11/21 Playback Volume' +numid=780,iface=MIXER,name='Mxr 11/22 Playback Volume' +numid=812,iface=MIXER,name='Mxr 11/23 Playback Volume' +numid=844,iface=MIXER,name='Mxr 11/24 Playback Volume' +numid=876,iface=MIXER,name='Mxr 11/25 Playback Volume' +numid=908,iface=MIXER,name='Mxr 11/26 Playback Volume' +numid=940,iface=MIXER,name='Mxr 11/27 Playback Volume' +numid=972,iface=MIXER,name='Mxr 11/28 Playback Volume' +numid=1004,iface=MIXER,name='Mxr 11/29 Playback Volume' +numid=172,iface=MIXER,name='Mxr 11/3 Playback Volume' +numid=1036,iface=MIXER,name='Mxr 11/30 Playback Volume' +numid=1068,iface=MIXER,name='Mxr 11/31 Playback Volume' +numid=204,iface=MIXER,name='Mxr 11/4 Playback Volume' +numid=236,iface=MIXER,name='Mxr 11/5 Playback Volume' +numid=268,iface=MIXER,name='Mxr 11/6 Playback Volume' +numid=300,iface=MIXER,name='Mxr 11/7 Playback Volume' +numid=332,iface=MIXER,name='Mxr 11/8 Playback Volume' +numid=364,iface=MIXER,name='Mxr 11/9 Playback Volume' +numid=77,iface=MIXER,name='Mxr 12/0 Playback Volume' +numid=109,iface=MIXER,name='Mxr 12/1 Playback Volume' +numid=397,iface=MIXER,name='Mxr 12/10 Playback Volume' +numid=429,iface=MIXER,name='Mxr 12/11 Playback Volume' +numid=461,iface=MIXER,name='Mxr 12/12 Playback Volume' +numid=493,iface=MIXER,name='Mxr 12/13 Playback Volume' +numid=525,iface=MIXER,name='Mxr 12/14 Playback Volume' +numid=557,iface=MIXER,name='Mxr 12/15 Playback Volume' +numid=589,iface=MIXER,name='Mxr 12/16 Playback Volume' +numid=621,iface=MIXER,name='Mxr 12/17 Playback Volume' +numid=653,iface=MIXER,name='Mxr 12/18 Playback Volume' +numid=685,iface=MIXER,name='Mxr 12/19 Playback Volume' +numid=141,iface=MIXER,name='Mxr 12/2 Playback Volume' +numid=717,iface=MIXER,name='Mxr 12/20 Playback Volume' +numid=749,iface=MIXER,name='Mxr 12/21 Playback Volume' +numid=781,iface=MIXER,name='Mxr 12/22 Playback Volume' +numid=813,iface=MIXER,name='Mxr 12/23 Playback Volume' +numid=845,iface=MIXER,name='Mxr 12/24 Playback Volume' +numid=877,iface=MIXER,name='Mxr 12/25 Playback Volume' +numid=909,iface=MIXER,name='Mxr 12/26 Playback Volume' +numid=941,iface=MIXER,name='Mxr 12/27 Playback Volume' +numid=973,iface=MIXER,name='Mxr 12/28 Playback Volume' +numid=1005,iface=MIXER,name='Mxr 12/29 Playback Volume' +numid=173,iface=MIXER,name='Mxr 12/3 Playback Volume' +numid=1037,iface=MIXER,name='Mxr 12/30 Playback Volume' +numid=1069,iface=MIXER,name='Mxr 12/31 Playback Volume' +numid=205,iface=MIXER,name='Mxr 12/4 Playback Volume' +numid=237,iface=MIXER,name='Mxr 12/5 Playback Volume' +numid=269,iface=MIXER,name='Mxr 12/6 Playback Volume' +numid=301,iface=MIXER,name='Mxr 12/7 Playback Volume' +numid=333,iface=MIXER,name='Mxr 12/8 Playback Volume' +numid=365,iface=MIXER,name='Mxr 12/9 Playback Volume' +numid=78,iface=MIXER,name='Mxr 13/0 Playback Volume' +numid=110,iface=MIXER,name='Mxr 13/1 Playback Volume' +numid=398,iface=MIXER,name='Mxr 13/10 Playback Volume' +numid=430,iface=MIXER,name='Mxr 13/11 Playback Volume' +numid=462,iface=MIXER,name='Mxr 13/12 Playback Volume' +numid=494,iface=MIXER,name='Mxr 13/13 Playback Volume' +numid=526,iface=MIXER,name='Mxr 13/14 Playback Volume' +numid=558,iface=MIXER,name='Mxr 13/15 Playback Volume' +numid=590,iface=MIXER,name='Mxr 13/16 Playback Volume' +numid=622,iface=MIXER,name='Mxr 13/17 Playback Volume' +numid=654,iface=MIXER,name='Mxr 13/18 Playback Volume' +numid=686,iface=MIXER,name='Mxr 13/19 Playback Volume' +numid=142,iface=MIXER,name='Mxr 13/2 Playback Volume' +numid=718,iface=MIXER,name='Mxr 13/20 Playback Volume' +numid=750,iface=MIXER,name='Mxr 13/21 Playback Volume' +numid=782,iface=MIXER,name='Mxr 13/22 Playback Volume' +numid=814,iface=MIXER,name='Mxr 13/23 Playback Volume' +numid=846,iface=MIXER,name='Mxr 13/24 Playback Volume' +numid=878,iface=MIXER,name='Mxr 13/25 Playback Volume' +numid=910,iface=MIXER,name='Mxr 13/26 Playback Volume' +numid=942,iface=MIXER,name='Mxr 13/27 Playback Volume' +numid=974,iface=MIXER,name='Mxr 13/28 Playback Volume' +numid=1006,iface=MIXER,name='Mxr 13/29 Playback Volume' +numid=174,iface=MIXER,name='Mxr 13/3 Playback Volume' +numid=1038,iface=MIXER,name='Mxr 13/30 Playback Volume' +numid=1070,iface=MIXER,name='Mxr 13/31 Playback Volume' +numid=206,iface=MIXER,name='Mxr 13/4 Playback Volume' +numid=238,iface=MIXER,name='Mxr 13/5 Playback Volume' +numid=270,iface=MIXER,name='Mxr 13/6 Playback Volume' +numid=302,iface=MIXER,name='Mxr 13/7 Playback Volume' +numid=334,iface=MIXER,name='Mxr 13/8 Playback Volume' +numid=366,iface=MIXER,name='Mxr 13/9 Playback Volume' +numid=79,iface=MIXER,name='Mxr 14/0 Playback Volume' +numid=111,iface=MIXER,name='Mxr 14/1 Playback Volume' +numid=399,iface=MIXER,name='Mxr 14/10 Playback Volume' +numid=431,iface=MIXER,name='Mxr 14/11 Playback Volume' +numid=463,iface=MIXER,name='Mxr 14/12 Playback Volume' +numid=495,iface=MIXER,name='Mxr 14/13 Playback Volume' +numid=527,iface=MIXER,name='Mxr 14/14 Playback Volume' +numid=559,iface=MIXER,name='Mxr 14/15 Playback Volume' +numid=591,iface=MIXER,name='Mxr 14/16 Playback Volume' +numid=623,iface=MIXER,name='Mxr 14/17 Playback Volume' +numid=655,iface=MIXER,name='Mxr 14/18 Playback Volume' +numid=687,iface=MIXER,name='Mxr 14/19 Playback Volume' +numid=143,iface=MIXER,name='Mxr 14/2 Playback Volume' +numid=719,iface=MIXER,name='Mxr 14/20 Playback Volume' +numid=751,iface=MIXER,name='Mxr 14/21 Playback Volume' +numid=783,iface=MIXER,name='Mxr 14/22 Playback Volume' +numid=815,iface=MIXER,name='Mxr 14/23 Playback Volume' +numid=847,iface=MIXER,name='Mxr 14/24 Playback Volume' +numid=879,iface=MIXER,name='Mxr 14/25 Playback Volume' +numid=911,iface=MIXER,name='Mxr 14/26 Playback Volume' +numid=943,iface=MIXER,name='Mxr 14/27 Playback Volume' +numid=975,iface=MIXER,name='Mxr 14/28 Playback Volume' +numid=1007,iface=MIXER,name='Mxr 14/29 Playback Volume' +numid=175,iface=MIXER,name='Mxr 14/3 Playback Volume' +numid=1039,iface=MIXER,name='Mxr 14/30 Playback Volume' +numid=1071,iface=MIXER,name='Mxr 14/31 Playback Volume' +numid=207,iface=MIXER,name='Mxr 14/4 Playback Volume' +numid=239,iface=MIXER,name='Mxr 14/5 Playback Volume' +numid=271,iface=MIXER,name='Mxr 14/6 Playback Volume' +numid=303,iface=MIXER,name='Mxr 14/7 Playback Volume' +numid=335,iface=MIXER,name='Mxr 14/8 Playback Volume' +numid=367,iface=MIXER,name='Mxr 14/9 Playback Volume' +numid=80,iface=MIXER,name='Mxr 15/0 Playback Volume' +numid=112,iface=MIXER,name='Mxr 15/1 Playback Volume' +numid=400,iface=MIXER,name='Mxr 15/10 Playback Volume' +numid=432,iface=MIXER,name='Mxr 15/11 Playback Volume' +numid=464,iface=MIXER,name='Mxr 15/12 Playback Volume' +numid=496,iface=MIXER,name='Mxr 15/13 Playback Volume' +numid=528,iface=MIXER,name='Mxr 15/14 Playback Volume' +numid=560,iface=MIXER,name='Mxr 15/15 Playback Volume' +numid=592,iface=MIXER,name='Mxr 15/16 Playback Volume' +numid=624,iface=MIXER,name='Mxr 15/17 Playback Volume' +numid=656,iface=MIXER,name='Mxr 15/18 Playback Volume' +numid=688,iface=MIXER,name='Mxr 15/19 Playback Volume' +numid=144,iface=MIXER,name='Mxr 15/2 Playback Volume' +numid=720,iface=MIXER,name='Mxr 15/20 Playback Volume' +numid=752,iface=MIXER,name='Mxr 15/21 Playback Volume' +numid=784,iface=MIXER,name='Mxr 15/22 Playback Volume' +numid=816,iface=MIXER,name='Mxr 15/23 Playback Volume' +numid=848,iface=MIXER,name='Mxr 15/24 Playback Volume' +numid=880,iface=MIXER,name='Mxr 15/25 Playback Volume' +numid=912,iface=MIXER,name='Mxr 15/26 Playback Volume' +numid=944,iface=MIXER,name='Mxr 15/27 Playback Volume' +numid=976,iface=MIXER,name='Mxr 15/28 Playback Volume' +numid=1008,iface=MIXER,name='Mxr 15/29 Playback Volume' +numid=176,iface=MIXER,name='Mxr 15/3 Playback Volume' +numid=1040,iface=MIXER,name='Mxr 15/30 Playback Volume' +numid=1072,iface=MIXER,name='Mxr 15/31 Playback Volume' +numid=208,iface=MIXER,name='Mxr 15/4 Playback Volume' +numid=240,iface=MIXER,name='Mxr 15/5 Playback Volume' +numid=272,iface=MIXER,name='Mxr 15/6 Playback Volume' +numid=304,iface=MIXER,name='Mxr 15/7 Playback Volume' +numid=336,iface=MIXER,name='Mxr 15/8 Playback Volume' +numid=368,iface=MIXER,name='Mxr 15/9 Playback Volume' +numid=81,iface=MIXER,name='Mxr 16/0 Playback Volume' +numid=113,iface=MIXER,name='Mxr 16/1 Playback Volume' +numid=401,iface=MIXER,name='Mxr 16/10 Playback Volume' +numid=433,iface=MIXER,name='Mxr 16/11 Playback Volume' +numid=465,iface=MIXER,name='Mxr 16/12 Playback Volume' +numid=497,iface=MIXER,name='Mxr 16/13 Playback Volume' +numid=529,iface=MIXER,name='Mxr 16/14 Playback Volume' +numid=561,iface=MIXER,name='Mxr 16/15 Playback Volume' +numid=593,iface=MIXER,name='Mxr 16/16 Playback Volume' +numid=625,iface=MIXER,name='Mxr 16/17 Playback Volume' +numid=657,iface=MIXER,name='Mxr 16/18 Playback Volume' +numid=689,iface=MIXER,name='Mxr 16/19 Playback Volume' +numid=145,iface=MIXER,name='Mxr 16/2 Playback Volume' +numid=721,iface=MIXER,name='Mxr 16/20 Playback Volume' +numid=753,iface=MIXER,name='Mxr 16/21 Playback Volume' +numid=785,iface=MIXER,name='Mxr 16/22 Playback Volume' +numid=817,iface=MIXER,name='Mxr 16/23 Playback Volume' +numid=849,iface=MIXER,name='Mxr 16/24 Playback Volume' +numid=881,iface=MIXER,name='Mxr 16/25 Playback Volume' +numid=913,iface=MIXER,name='Mxr 16/26 Playback Volume' +numid=945,iface=MIXER,name='Mxr 16/27 Playback Volume' +numid=977,iface=MIXER,name='Mxr 16/28 Playback Volume' +numid=1009,iface=MIXER,name='Mxr 16/29 Playback Volume' +numid=177,iface=MIXER,name='Mxr 16/3 Playback Volume' +numid=1041,iface=MIXER,name='Mxr 16/30 Playback Volume' +numid=1073,iface=MIXER,name='Mxr 16/31 Playback Volume' +numid=209,iface=MIXER,name='Mxr 16/4 Playback Volume' +numid=241,iface=MIXER,name='Mxr 16/5 Playback Volume' +numid=273,iface=MIXER,name='Mxr 16/6 Playback Volume' +numid=305,iface=MIXER,name='Mxr 16/7 Playback Volume' +numid=337,iface=MIXER,name='Mxr 16/8 Playback Volume' +numid=369,iface=MIXER,name='Mxr 16/9 Playback Volume' +numid=82,iface=MIXER,name='Mxr 17/0 Playback Volume' +numid=114,iface=MIXER,name='Mxr 17/1 Playback Volume' +numid=402,iface=MIXER,name='Mxr 17/10 Playback Volume' +numid=434,iface=MIXER,name='Mxr 17/11 Playback Volume' +numid=466,iface=MIXER,name='Mxr 17/12 Playback Volume' +numid=498,iface=MIXER,name='Mxr 17/13 Playback Volume' +numid=530,iface=MIXER,name='Mxr 17/14 Playback Volume' +numid=562,iface=MIXER,name='Mxr 17/15 Playback Volume' +numid=594,iface=MIXER,name='Mxr 17/16 Playback Volume' +numid=626,iface=MIXER,name='Mxr 17/17 Playback Volume' +numid=658,iface=MIXER,name='Mxr 17/18 Playback Volume' +numid=690,iface=MIXER,name='Mxr 17/19 Playback Volume' +numid=146,iface=MIXER,name='Mxr 17/2 Playback Volume' +numid=722,iface=MIXER,name='Mxr 17/20 Playback Volume' +numid=754,iface=MIXER,name='Mxr 17/21 Playback Volume' +numid=786,iface=MIXER,name='Mxr 17/22 Playback Volume' +numid=818,iface=MIXER,name='Mxr 17/23 Playback Volume' +numid=850,iface=MIXER,name='Mxr 17/24 Playback Volume' +numid=882,iface=MIXER,name='Mxr 17/25 Playback Volume' +numid=914,iface=MIXER,name='Mxr 17/26 Playback Volume' +numid=946,iface=MIXER,name='Mxr 17/27 Playback Volume' +numid=978,iface=MIXER,name='Mxr 17/28 Playback Volume' +numid=1010,iface=MIXER,name='Mxr 17/29 Playback Volume' +numid=178,iface=MIXER,name='Mxr 17/3 Playback Volume' +numid=1042,iface=MIXER,name='Mxr 17/30 Playback Volume' +numid=1074,iface=MIXER,name='Mxr 17/31 Playback Volume' +numid=210,iface=MIXER,name='Mxr 17/4 Playback Volume' +numid=242,iface=MIXER,name='Mxr 17/5 Playback Volume' +numid=274,iface=MIXER,name='Mxr 17/6 Playback Volume' +numid=306,iface=MIXER,name='Mxr 17/7 Playback Volume' +numid=338,iface=MIXER,name='Mxr 17/8 Playback Volume' +numid=370,iface=MIXER,name='Mxr 17/9 Playback Volume' +numid=83,iface=MIXER,name='Mxr 18/0 Playback Volume' +numid=115,iface=MIXER,name='Mxr 18/1 Playback Volume' +numid=403,iface=MIXER,name='Mxr 18/10 Playback Volume' +numid=435,iface=MIXER,name='Mxr 18/11 Playback Volume' +numid=467,iface=MIXER,name='Mxr 18/12 Playback Volume' +numid=499,iface=MIXER,name='Mxr 18/13 Playback Volume' +numid=531,iface=MIXER,name='Mxr 18/14 Playback Volume' +numid=563,iface=MIXER,name='Mxr 18/15 Playback Volume' +numid=595,iface=MIXER,name='Mxr 18/16 Playback Volume' +numid=627,iface=MIXER,name='Mxr 18/17 Playback Volume' +numid=659,iface=MIXER,name='Mxr 18/18 Playback Volume' +numid=691,iface=MIXER,name='Mxr 18/19 Playback Volume' +numid=147,iface=MIXER,name='Mxr 18/2 Playback Volume' +numid=723,iface=MIXER,name='Mxr 18/20 Playback Volume' +numid=755,iface=MIXER,name='Mxr 18/21 Playback Volume' +numid=787,iface=MIXER,name='Mxr 18/22 Playback Volume' +numid=819,iface=MIXER,name='Mxr 18/23 Playback Volume' +numid=851,iface=MIXER,name='Mxr 18/24 Playback Volume' +numid=883,iface=MIXER,name='Mxr 18/25 Playback Volume' +numid=915,iface=MIXER,name='Mxr 18/26 Playback Volume' +numid=947,iface=MIXER,name='Mxr 18/27 Playback Volume' +numid=979,iface=MIXER,name='Mxr 18/28 Playback Volume' +numid=1011,iface=MIXER,name='Mxr 18/29 Playback Volume' +numid=179,iface=MIXER,name='Mxr 18/3 Playback Volume' +numid=1043,iface=MIXER,name='Mxr 18/30 Playback Volume' +numid=1075,iface=MIXER,name='Mxr 18/31 Playback Volume' +numid=211,iface=MIXER,name='Mxr 18/4 Playback Volume' +numid=243,iface=MIXER,name='Mxr 18/5 Playback Volume' +numid=275,iface=MIXER,name='Mxr 18/6 Playback Volume' +numid=307,iface=MIXER,name='Mxr 18/7 Playback Volume' +numid=339,iface=MIXER,name='Mxr 18/8 Playback Volume' +numid=371,iface=MIXER,name='Mxr 18/9 Playback Volume' +numid=84,iface=MIXER,name='Mxr 19/0 Playback Volume' +numid=116,iface=MIXER,name='Mxr 19/1 Playback Volume' +numid=404,iface=MIXER,name='Mxr 19/10 Playback Volume' +numid=436,iface=MIXER,name='Mxr 19/11 Playback Volume' +numid=468,iface=MIXER,name='Mxr 19/12 Playback Volume' +numid=500,iface=MIXER,name='Mxr 19/13 Playback Volume' +numid=532,iface=MIXER,name='Mxr 19/14 Playback Volume' +numid=564,iface=MIXER,name='Mxr 19/15 Playback Volume' +numid=596,iface=MIXER,name='Mxr 19/16 Playback Volume' +numid=628,iface=MIXER,name='Mxr 19/17 Playback Volume' +numid=660,iface=MIXER,name='Mxr 19/18 Playback Volume' +numid=692,iface=MIXER,name='Mxr 19/19 Playback Volume' +numid=148,iface=MIXER,name='Mxr 19/2 Playback Volume' +numid=724,iface=MIXER,name='Mxr 19/20 Playback Volume' +numid=756,iface=MIXER,name='Mxr 19/21 Playback Volume' +numid=788,iface=MIXER,name='Mxr 19/22 Playback Volume' +numid=820,iface=MIXER,name='Mxr 19/23 Playback Volume' +numid=852,iface=MIXER,name='Mxr 19/24 Playback Volume' +numid=884,iface=MIXER,name='Mxr 19/25 Playback Volume' +numid=916,iface=MIXER,name='Mxr 19/26 Playback Volume' +numid=948,iface=MIXER,name='Mxr 19/27 Playback Volume' +numid=980,iface=MIXER,name='Mxr 19/28 Playback Volume' +numid=1012,iface=MIXER,name='Mxr 19/29 Playback Volume' +numid=180,iface=MIXER,name='Mxr 19/3 Playback Volume' +numid=1044,iface=MIXER,name='Mxr 19/30 Playback Volume' +numid=1076,iface=MIXER,name='Mxr 19/31 Playback Volume' +numid=212,iface=MIXER,name='Mxr 19/4 Playback Volume' +numid=244,iface=MIXER,name='Mxr 19/5 Playback Volume' +numid=276,iface=MIXER,name='Mxr 19/6 Playback Volume' +numid=308,iface=MIXER,name='Mxr 19/7 Playback Volume' +numid=340,iface=MIXER,name='Mxr 19/8 Playback Volume' +numid=372,iface=MIXER,name='Mxr 19/9 Playback Volume' +numid=67,iface=MIXER,name='Mxr 2/0 Playback Volume' +numid=99,iface=MIXER,name='Mxr 2/1 Playback Volume' +numid=387,iface=MIXER,name='Mxr 2/10 Playback Volume' +numid=419,iface=MIXER,name='Mxr 2/11 Playback Volume' +numid=451,iface=MIXER,name='Mxr 2/12 Playback Volume' +numid=483,iface=MIXER,name='Mxr 2/13 Playback Volume' +numid=515,iface=MIXER,name='Mxr 2/14 Playback Volume' +numid=547,iface=MIXER,name='Mxr 2/15 Playback Volume' +numid=579,iface=MIXER,name='Mxr 2/16 Playback Volume' +numid=611,iface=MIXER,name='Mxr 2/17 Playback Volume' +numid=643,iface=MIXER,name='Mxr 2/18 Playback Volume' +numid=675,iface=MIXER,name='Mxr 2/19 Playback Volume' +numid=131,iface=MIXER,name='Mxr 2/2 Playback Volume' +numid=707,iface=MIXER,name='Mxr 2/20 Playback Volume' +numid=739,iface=MIXER,name='Mxr 2/21 Playback Volume' +numid=771,iface=MIXER,name='Mxr 2/22 Playback Volume' +numid=803,iface=MIXER,name='Mxr 2/23 Playback Volume' +numid=835,iface=MIXER,name='Mxr 2/24 Playback Volume' +numid=867,iface=MIXER,name='Mxr 2/25 Playback Volume' +numid=899,iface=MIXER,name='Mxr 2/26 Playback Volume' +numid=931,iface=MIXER,name='Mxr 2/27 Playback Volume' +numid=963,iface=MIXER,name='Mxr 2/28 Playback Volume' +numid=995,iface=MIXER,name='Mxr 2/29 Playback Volume' +numid=163,iface=MIXER,name='Mxr 2/3 Playback Volume' +numid=1027,iface=MIXER,name='Mxr 2/30 Playback Volume' +numid=1059,iface=MIXER,name='Mxr 2/31 Playback Volume' +numid=195,iface=MIXER,name='Mxr 2/4 Playback Volume' +numid=227,iface=MIXER,name='Mxr 2/5 Playback Volume' +numid=259,iface=MIXER,name='Mxr 2/6 Playback Volume' +numid=291,iface=MIXER,name='Mxr 2/7 Playback Volume' +numid=323,iface=MIXER,name='Mxr 2/8 Playback Volume' +numid=355,iface=MIXER,name='Mxr 2/9 Playback Volume' +numid=85,iface=MIXER,name='Mxr 20/0 Playback Volume' +numid=117,iface=MIXER,name='Mxr 20/1 Playback Volume' +numid=405,iface=MIXER,name='Mxr 20/10 Playback Volume' +numid=437,iface=MIXER,name='Mxr 20/11 Playback Volume' +numid=469,iface=MIXER,name='Mxr 20/12 Playback Volume' +numid=501,iface=MIXER,name='Mxr 20/13 Playback Volume' +numid=533,iface=MIXER,name='Mxr 20/14 Playback Volume' +numid=565,iface=MIXER,name='Mxr 20/15 Playback Volume' +numid=597,iface=MIXER,name='Mxr 20/16 Playback Volume' +numid=629,iface=MIXER,name='Mxr 20/17 Playback Volume' +numid=661,iface=MIXER,name='Mxr 20/18 Playback Volume' +numid=693,iface=MIXER,name='Mxr 20/19 Playback Volume' +numid=149,iface=MIXER,name='Mxr 20/2 Playback Volume' +numid=725,iface=MIXER,name='Mxr 20/20 Playback Volume' +numid=757,iface=MIXER,name='Mxr 20/21 Playback Volume' +numid=789,iface=MIXER,name='Mxr 20/22 Playback Volume' +numid=821,iface=MIXER,name='Mxr 20/23 Playback Volume' +numid=853,iface=MIXER,name='Mxr 20/24 Playback Volume' +numid=885,iface=MIXER,name='Mxr 20/25 Playback Volume' +numid=917,iface=MIXER,name='Mxr 20/26 Playback Volume' +numid=949,iface=MIXER,name='Mxr 20/27 Playback Volume' +numid=981,iface=MIXER,name='Mxr 20/28 Playback Volume' +numid=1013,iface=MIXER,name='Mxr 20/29 Playback Volume' +numid=181,iface=MIXER,name='Mxr 20/3 Playback Volume' +numid=1045,iface=MIXER,name='Mxr 20/30 Playback Volume' +numid=1077,iface=MIXER,name='Mxr 20/31 Playback Volume' +numid=213,iface=MIXER,name='Mxr 20/4 Playback Volume' +numid=245,iface=MIXER,name='Mxr 20/5 Playback Volume' +numid=277,iface=MIXER,name='Mxr 20/6 Playback Volume' +numid=309,iface=MIXER,name='Mxr 20/7 Playback Volume' +numid=341,iface=MIXER,name='Mxr 20/8 Playback Volume' +numid=373,iface=MIXER,name='Mxr 20/9 Playback Volume' +numid=86,iface=MIXER,name='Mxr 21/0 Playback Volume' +numid=118,iface=MIXER,name='Mxr 21/1 Playback Volume' +numid=406,iface=MIXER,name='Mxr 21/10 Playback Volume' +numid=438,iface=MIXER,name='Mxr 21/11 Playback Volume' +numid=470,iface=MIXER,name='Mxr 21/12 Playback Volume' +numid=502,iface=MIXER,name='Mxr 21/13 Playback Volume' +numid=534,iface=MIXER,name='Mxr 21/14 Playback Volume' +numid=566,iface=MIXER,name='Mxr 21/15 Playback Volume' +numid=598,iface=MIXER,name='Mxr 21/16 Playback Volume' +numid=630,iface=MIXER,name='Mxr 21/17 Playback Volume' +numid=662,iface=MIXER,name='Mxr 21/18 Playback Volume' +numid=694,iface=MIXER,name='Mxr 21/19 Playback Volume' +numid=150,iface=MIXER,name='Mxr 21/2 Playback Volume' +numid=726,iface=MIXER,name='Mxr 21/20 Playback Volume' +numid=758,iface=MIXER,name='Mxr 21/21 Playback Volume' +numid=790,iface=MIXER,name='Mxr 21/22 Playback Volume' +numid=822,iface=MIXER,name='Mxr 21/23 Playback Volume' +numid=854,iface=MIXER,name='Mxr 21/24 Playback Volume' +numid=886,iface=MIXER,name='Mxr 21/25 Playback Volume' +numid=918,iface=MIXER,name='Mxr 21/26 Playback Volume' +numid=950,iface=MIXER,name='Mxr 21/27 Playback Volume' +numid=982,iface=MIXER,name='Mxr 21/28 Playback Volume' +numid=1014,iface=MIXER,name='Mxr 21/29 Playback Volume' +numid=182,iface=MIXER,name='Mxr 21/3 Playback Volume' +numid=1046,iface=MIXER,name='Mxr 21/30 Playback Volume' +numid=1078,iface=MIXER,name='Mxr 21/31 Playback Volume' +numid=214,iface=MIXER,name='Mxr 21/4 Playback Volume' +numid=246,iface=MIXER,name='Mxr 21/5 Playback Volume' +numid=278,iface=MIXER,name='Mxr 21/6 Playback Volume' +numid=310,iface=MIXER,name='Mxr 21/7 Playback Volume' +numid=342,iface=MIXER,name='Mxr 21/8 Playback Volume' +numid=374,iface=MIXER,name='Mxr 21/9 Playback Volume' +numid=87,iface=MIXER,name='Mxr 22/0 Playback Volume' +numid=119,iface=MIXER,name='Mxr 22/1 Playback Volume' +numid=407,iface=MIXER,name='Mxr 22/10 Playback Volume' +numid=439,iface=MIXER,name='Mxr 22/11 Playback Volume' +numid=471,iface=MIXER,name='Mxr 22/12 Playback Volume' +numid=503,iface=MIXER,name='Mxr 22/13 Playback Volume' +numid=535,iface=MIXER,name='Mxr 22/14 Playback Volume' +numid=567,iface=MIXER,name='Mxr 22/15 Playback Volume' +numid=599,iface=MIXER,name='Mxr 22/16 Playback Volume' +numid=631,iface=MIXER,name='Mxr 22/17 Playback Volume' +numid=663,iface=MIXER,name='Mxr 22/18 Playback Volume' +numid=695,iface=MIXER,name='Mxr 22/19 Playback Volume' +numid=151,iface=MIXER,name='Mxr 22/2 Playback Volume' +numid=727,iface=MIXER,name='Mxr 22/20 Playback Volume' +numid=759,iface=MIXER,name='Mxr 22/21 Playback Volume' +numid=791,iface=MIXER,name='Mxr 22/22 Playback Volume' +numid=823,iface=MIXER,name='Mxr 22/23 Playback Volume' +numid=855,iface=MIXER,name='Mxr 22/24 Playback Volume' +numid=887,iface=MIXER,name='Mxr 22/25 Playback Volume' +numid=919,iface=MIXER,name='Mxr 22/26 Playback Volume' +numid=951,iface=MIXER,name='Mxr 22/27 Playback Volume' +numid=983,iface=MIXER,name='Mxr 22/28 Playback Volume' +numid=1015,iface=MIXER,name='Mxr 22/29 Playback Volume' +numid=183,iface=MIXER,name='Mxr 22/3 Playback Volume' +numid=1047,iface=MIXER,name='Mxr 22/30 Playback Volume' +numid=1079,iface=MIXER,name='Mxr 22/31 Playback Volume' +numid=215,iface=MIXER,name='Mxr 22/4 Playback Volume' +numid=247,iface=MIXER,name='Mxr 22/5 Playback Volume' +numid=279,iface=MIXER,name='Mxr 22/6 Playback Volume' +numid=311,iface=MIXER,name='Mxr 22/7 Playback Volume' +numid=343,iface=MIXER,name='Mxr 22/8 Playback Volume' +numid=375,iface=MIXER,name='Mxr 22/9 Playback Volume' +numid=88,iface=MIXER,name='Mxr 23/0 Playback Volume' +numid=120,iface=MIXER,name='Mxr 23/1 Playback Volume' +numid=408,iface=MIXER,name='Mxr 23/10 Playback Volume' +numid=440,iface=MIXER,name='Mxr 23/11 Playback Volume' +numid=472,iface=MIXER,name='Mxr 23/12 Playback Volume' +numid=504,iface=MIXER,name='Mxr 23/13 Playback Volume' +numid=536,iface=MIXER,name='Mxr 23/14 Playback Volume' +numid=568,iface=MIXER,name='Mxr 23/15 Playback Volume' +numid=600,iface=MIXER,name='Mxr 23/16 Playback Volume' +numid=632,iface=MIXER,name='Mxr 23/17 Playback Volume' +numid=664,iface=MIXER,name='Mxr 23/18 Playback Volume' +numid=696,iface=MIXER,name='Mxr 23/19 Playback Volume' +numid=152,iface=MIXER,name='Mxr 23/2 Playback Volume' +numid=728,iface=MIXER,name='Mxr 23/20 Playback Volume' +numid=760,iface=MIXER,name='Mxr 23/21 Playback Volume' +numid=792,iface=MIXER,name='Mxr 23/22 Playback Volume' +numid=824,iface=MIXER,name='Mxr 23/23 Playback Volume' +numid=856,iface=MIXER,name='Mxr 23/24 Playback Volume' +numid=888,iface=MIXER,name='Mxr 23/25 Playback Volume' +numid=920,iface=MIXER,name='Mxr 23/26 Playback Volume' +numid=952,iface=MIXER,name='Mxr 23/27 Playback Volume' +numid=984,iface=MIXER,name='Mxr 23/28 Playback Volume' +numid=1016,iface=MIXER,name='Mxr 23/29 Playback Volume' +numid=184,iface=MIXER,name='Mxr 23/3 Playback Volume' +numid=1048,iface=MIXER,name='Mxr 23/30 Playback Volume' +numid=1080,iface=MIXER,name='Mxr 23/31 Playback Volume' +numid=216,iface=MIXER,name='Mxr 23/4 Playback Volume' +numid=248,iface=MIXER,name='Mxr 23/5 Playback Volume' +numid=280,iface=MIXER,name='Mxr 23/6 Playback Volume' +numid=312,iface=MIXER,name='Mxr 23/7 Playback Volume' +numid=344,iface=MIXER,name='Mxr 23/8 Playback Volume' +numid=376,iface=MIXER,name='Mxr 23/9 Playback Volume' +numid=89,iface=MIXER,name='Mxr 24/0 Playback Volume' +numid=121,iface=MIXER,name='Mxr 24/1 Playback Volume' +numid=409,iface=MIXER,name='Mxr 24/10 Playback Volume' +numid=441,iface=MIXER,name='Mxr 24/11 Playback Volume' +numid=473,iface=MIXER,name='Mxr 24/12 Playback Volume' +numid=505,iface=MIXER,name='Mxr 24/13 Playback Volume' +numid=537,iface=MIXER,name='Mxr 24/14 Playback Volume' +numid=569,iface=MIXER,name='Mxr 24/15 Playback Volume' +numid=601,iface=MIXER,name='Mxr 24/16 Playback Volume' +numid=633,iface=MIXER,name='Mxr 24/17 Playback Volume' +numid=665,iface=MIXER,name='Mxr 24/18 Playback Volume' +numid=697,iface=MIXER,name='Mxr 24/19 Playback Volume' +numid=153,iface=MIXER,name='Mxr 24/2 Playback Volume' +numid=729,iface=MIXER,name='Mxr 24/20 Playback Volume' +numid=761,iface=MIXER,name='Mxr 24/21 Playback Volume' +numid=793,iface=MIXER,name='Mxr 24/22 Playback Volume' +numid=825,iface=MIXER,name='Mxr 24/23 Playback Volume' +numid=857,iface=MIXER,name='Mxr 24/24 Playback Volume' +numid=889,iface=MIXER,name='Mxr 24/25 Playback Volume' +numid=921,iface=MIXER,name='Mxr 24/26 Playback Volume' +numid=953,iface=MIXER,name='Mxr 24/27 Playback Volume' +numid=985,iface=MIXER,name='Mxr 24/28 Playback Volume' +numid=1017,iface=MIXER,name='Mxr 24/29 Playback Volume' +numid=185,iface=MIXER,name='Mxr 24/3 Playback Volume' +numid=1049,iface=MIXER,name='Mxr 24/30 Playback Volume' +numid=1081,iface=MIXER,name='Mxr 24/31 Playback Volume' +numid=217,iface=MIXER,name='Mxr 24/4 Playback Volume' +numid=249,iface=MIXER,name='Mxr 24/5 Playback Volume' +numid=281,iface=MIXER,name='Mxr 24/6 Playback Volume' +numid=313,iface=MIXER,name='Mxr 24/7 Playback Volume' +numid=345,iface=MIXER,name='Mxr 24/8 Playback Volume' +numid=377,iface=MIXER,name='Mxr 24/9 Playback Volume' +numid=90,iface=MIXER,name='Mxr 25/0 Playback Volume' +numid=122,iface=MIXER,name='Mxr 25/1 Playback Volume' +numid=410,iface=MIXER,name='Mxr 25/10 Playback Volume' +numid=442,iface=MIXER,name='Mxr 25/11 Playback Volume' +numid=474,iface=MIXER,name='Mxr 25/12 Playback Volume' +numid=506,iface=MIXER,name='Mxr 25/13 Playback Volume' +numid=538,iface=MIXER,name='Mxr 25/14 Playback Volume' +numid=570,iface=MIXER,name='Mxr 25/15 Playback Volume' +numid=602,iface=MIXER,name='Mxr 25/16 Playback Volume' +numid=634,iface=MIXER,name='Mxr 25/17 Playback Volume' +numid=666,iface=MIXER,name='Mxr 25/18 Playback Volume' +numid=698,iface=MIXER,name='Mxr 25/19 Playback Volume' +numid=154,iface=MIXER,name='Mxr 25/2 Playback Volume' +numid=730,iface=MIXER,name='Mxr 25/20 Playback Volume' +numid=762,iface=MIXER,name='Mxr 25/21 Playback Volume' +numid=794,iface=MIXER,name='Mxr 25/22 Playback Volume' +numid=826,iface=MIXER,name='Mxr 25/23 Playback Volume' +numid=858,iface=MIXER,name='Mxr 25/24 Playback Volume' +numid=890,iface=MIXER,name='Mxr 25/25 Playback Volume' +numid=922,iface=MIXER,name='Mxr 25/26 Playback Volume' +numid=954,iface=MIXER,name='Mxr 25/27 Playback Volume' +numid=986,iface=MIXER,name='Mxr 25/28 Playback Volume' +numid=1018,iface=MIXER,name='Mxr 25/29 Playback Volume' +numid=186,iface=MIXER,name='Mxr 25/3 Playback Volume' +numid=1050,iface=MIXER,name='Mxr 25/30 Playback Volume' +numid=1082,iface=MIXER,name='Mxr 25/31 Playback Volume' +numid=218,iface=MIXER,name='Mxr 25/4 Playback Volume' +numid=250,iface=MIXER,name='Mxr 25/5 Playback Volume' +numid=282,iface=MIXER,name='Mxr 25/6 Playback Volume' +numid=314,iface=MIXER,name='Mxr 25/7 Playback Volume' +numid=346,iface=MIXER,name='Mxr 25/8 Playback Volume' +numid=378,iface=MIXER,name='Mxr 25/9 Playback Volume' +numid=91,iface=MIXER,name='Mxr 26/0 Playback Volume' +numid=123,iface=MIXER,name='Mxr 26/1 Playback Volume' +numid=411,iface=MIXER,name='Mxr 26/10 Playback Volume' +numid=443,iface=MIXER,name='Mxr 26/11 Playback Volume' +numid=475,iface=MIXER,name='Mxr 26/12 Playback Volume' +numid=507,iface=MIXER,name='Mxr 26/13 Playback Volume' +numid=539,iface=MIXER,name='Mxr 26/14 Playback Volume' +numid=571,iface=MIXER,name='Mxr 26/15 Playback Volume' +numid=603,iface=MIXER,name='Mxr 26/16 Playback Volume' +numid=635,iface=MIXER,name='Mxr 26/17 Playback Volume' +numid=667,iface=MIXER,name='Mxr 26/18 Playback Volume' +numid=699,iface=MIXER,name='Mxr 26/19 Playback Volume' +numid=155,iface=MIXER,name='Mxr 26/2 Playback Volume' +numid=731,iface=MIXER,name='Mxr 26/20 Playback Volume' +numid=763,iface=MIXER,name='Mxr 26/21 Playback Volume' +numid=795,iface=MIXER,name='Mxr 26/22 Playback Volume' +numid=827,iface=MIXER,name='Mxr 26/23 Playback Volume' +numid=859,iface=MIXER,name='Mxr 26/24 Playback Volume' +numid=891,iface=MIXER,name='Mxr 26/25 Playback Volume' +numid=923,iface=MIXER,name='Mxr 26/26 Playback Volume' +numid=955,iface=MIXER,name='Mxr 26/27 Playback Volume' +numid=987,iface=MIXER,name='Mxr 26/28 Playback Volume' +numid=1019,iface=MIXER,name='Mxr 26/29 Playback Volume' +numid=187,iface=MIXER,name='Mxr 26/3 Playback Volume' +numid=1051,iface=MIXER,name='Mxr 26/30 Playback Volume' +numid=1083,iface=MIXER,name='Mxr 26/31 Playback Volume' +numid=219,iface=MIXER,name='Mxr 26/4 Playback Volume' +numid=251,iface=MIXER,name='Mxr 26/5 Playback Volume' +numid=283,iface=MIXER,name='Mxr 26/6 Playback Volume' +numid=315,iface=MIXER,name='Mxr 26/7 Playback Volume' +numid=347,iface=MIXER,name='Mxr 26/8 Playback Volume' +numid=379,iface=MIXER,name='Mxr 26/9 Playback Volume' +numid=92,iface=MIXER,name='Mxr 27/0 Playback Volume' +numid=124,iface=MIXER,name='Mxr 27/1 Playback Volume' +numid=412,iface=MIXER,name='Mxr 27/10 Playback Volume' +numid=444,iface=MIXER,name='Mxr 27/11 Playback Volume' +numid=476,iface=MIXER,name='Mxr 27/12 Playback Volume' +numid=508,iface=MIXER,name='Mxr 27/13 Playback Volume' +numid=540,iface=MIXER,name='Mxr 27/14 Playback Volume' +numid=572,iface=MIXER,name='Mxr 27/15 Playback Volume' +numid=604,iface=MIXER,name='Mxr 27/16 Playback Volume' +numid=636,iface=MIXER,name='Mxr 27/17 Playback Volume' +numid=668,iface=MIXER,name='Mxr 27/18 Playback Volume' +numid=700,iface=MIXER,name='Mxr 27/19 Playback Volume' +numid=156,iface=MIXER,name='Mxr 27/2 Playback Volume' +numid=732,iface=MIXER,name='Mxr 27/20 Playback Volume' +numid=764,iface=MIXER,name='Mxr 27/21 Playback Volume' +numid=796,iface=MIXER,name='Mxr 27/22 Playback Volume' +numid=828,iface=MIXER,name='Mxr 27/23 Playback Volume' +numid=860,iface=MIXER,name='Mxr 27/24 Playback Volume' +numid=892,iface=MIXER,name='Mxr 27/25 Playback Volume' +numid=924,iface=MIXER,name='Mxr 27/26 Playback Volume' +numid=956,iface=MIXER,name='Mxr 27/27 Playback Volume' +numid=988,iface=MIXER,name='Mxr 27/28 Playback Volume' +numid=1020,iface=MIXER,name='Mxr 27/29 Playback Volume' +numid=188,iface=MIXER,name='Mxr 27/3 Playback Volume' +numid=1052,iface=MIXER,name='Mxr 27/30 Playback Volume' +numid=1084,iface=MIXER,name='Mxr 27/31 Playback Volume' +numid=220,iface=MIXER,name='Mxr 27/4 Playback Volume' +numid=252,iface=MIXER,name='Mxr 27/5 Playback Volume' +numid=284,iface=MIXER,name='Mxr 27/6 Playback Volume' +numid=316,iface=MIXER,name='Mxr 27/7 Playback Volume' +numid=348,iface=MIXER,name='Mxr 27/8 Playback Volume' +numid=380,iface=MIXER,name='Mxr 27/9 Playback Volume' +numid=93,iface=MIXER,name='Mxr 28/0 Playback Volume' +numid=125,iface=MIXER,name='Mxr 28/1 Playback Volume' +numid=413,iface=MIXER,name='Mxr 28/10 Playback Volume' +numid=445,iface=MIXER,name='Mxr 28/11 Playback Volume' +numid=477,iface=MIXER,name='Mxr 28/12 Playback Volume' +numid=509,iface=MIXER,name='Mxr 28/13 Playback Volume' +numid=541,iface=MIXER,name='Mxr 28/14 Playback Volume' +numid=573,iface=MIXER,name='Mxr 28/15 Playback Volume' +numid=605,iface=MIXER,name='Mxr 28/16 Playback Volume' +numid=637,iface=MIXER,name='Mxr 28/17 Playback Volume' +numid=669,iface=MIXER,name='Mxr 28/18 Playback Volume' +numid=701,iface=MIXER,name='Mxr 28/19 Playback Volume' +numid=157,iface=MIXER,name='Mxr 28/2 Playback Volume' +numid=733,iface=MIXER,name='Mxr 28/20 Playback Volume' +numid=765,iface=MIXER,name='Mxr 28/21 Playback Volume' +numid=797,iface=MIXER,name='Mxr 28/22 Playback Volume' +numid=829,iface=MIXER,name='Mxr 28/23 Playback Volume' +numid=861,iface=MIXER,name='Mxr 28/24 Playback Volume' +numid=893,iface=MIXER,name='Mxr 28/25 Playback Volume' +numid=925,iface=MIXER,name='Mxr 28/26 Playback Volume' +numid=957,iface=MIXER,name='Mxr 28/27 Playback Volume' +numid=989,iface=MIXER,name='Mxr 28/28 Playback Volume' +numid=1021,iface=MIXER,name='Mxr 28/29 Playback Volume' +numid=189,iface=MIXER,name='Mxr 28/3 Playback Volume' +numid=1053,iface=MIXER,name='Mxr 28/30 Playback Volume' +numid=1085,iface=MIXER,name='Mxr 28/31 Playback Volume' +numid=221,iface=MIXER,name='Mxr 28/4 Playback Volume' +numid=253,iface=MIXER,name='Mxr 28/5 Playback Volume' +numid=285,iface=MIXER,name='Mxr 28/6 Playback Volume' +numid=317,iface=MIXER,name='Mxr 28/7 Playback Volume' +numid=349,iface=MIXER,name='Mxr 28/8 Playback Volume' +numid=381,iface=MIXER,name='Mxr 28/9 Playback Volume' +numid=94,iface=MIXER,name='Mxr 29/0 Playback Volume' +numid=126,iface=MIXER,name='Mxr 29/1 Playback Volume' +numid=414,iface=MIXER,name='Mxr 29/10 Playback Volume' +numid=446,iface=MIXER,name='Mxr 29/11 Playback Volume' +numid=478,iface=MIXER,name='Mxr 29/12 Playback Volume' +numid=510,iface=MIXER,name='Mxr 29/13 Playback Volume' +numid=542,iface=MIXER,name='Mxr 29/14 Playback Volume' +numid=574,iface=MIXER,name='Mxr 29/15 Playback Volume' +numid=606,iface=MIXER,name='Mxr 29/16 Playback Volume' +numid=638,iface=MIXER,name='Mxr 29/17 Playback Volume' +numid=670,iface=MIXER,name='Mxr 29/18 Playback Volume' +numid=702,iface=MIXER,name='Mxr 29/19 Playback Volume' +numid=158,iface=MIXER,name='Mxr 29/2 Playback Volume' +numid=734,iface=MIXER,name='Mxr 29/20 Playback Volume' +numid=766,iface=MIXER,name='Mxr 29/21 Playback Volume' +numid=798,iface=MIXER,name='Mxr 29/22 Playback Volume' +numid=830,iface=MIXER,name='Mxr 29/23 Playback Volume' +numid=862,iface=MIXER,name='Mxr 29/24 Playback Volume' +numid=894,iface=MIXER,name='Mxr 29/25 Playback Volume' +numid=926,iface=MIXER,name='Mxr 29/26 Playback Volume' +numid=958,iface=MIXER,name='Mxr 29/27 Playback Volume' +numid=990,iface=MIXER,name='Mxr 29/28 Playback Volume' +numid=1022,iface=MIXER,name='Mxr 29/29 Playback Volume' +numid=190,iface=MIXER,name='Mxr 29/3 Playback Volume' +numid=1054,iface=MIXER,name='Mxr 29/30 Playback Volume' +numid=1086,iface=MIXER,name='Mxr 29/31 Playback Volume' +numid=222,iface=MIXER,name='Mxr 29/4 Playback Volume' +numid=254,iface=MIXER,name='Mxr 29/5 Playback Volume' +numid=286,iface=MIXER,name='Mxr 29/6 Playback Volume' +numid=318,iface=MIXER,name='Mxr 29/7 Playback Volume' +numid=350,iface=MIXER,name='Mxr 29/8 Playback Volume' +numid=382,iface=MIXER,name='Mxr 29/9 Playback Volume' +numid=68,iface=MIXER,name='Mxr 3/0 Playback Volume' +numid=100,iface=MIXER,name='Mxr 3/1 Playback Volume' +numid=388,iface=MIXER,name='Mxr 3/10 Playback Volume' +numid=420,iface=MIXER,name='Mxr 3/11 Playback Volume' +numid=452,iface=MIXER,name='Mxr 3/12 Playback Volume' +numid=484,iface=MIXER,name='Mxr 3/13 Playback Volume' +numid=516,iface=MIXER,name='Mxr 3/14 Playback Volume' +numid=548,iface=MIXER,name='Mxr 3/15 Playback Volume' +numid=580,iface=MIXER,name='Mxr 3/16 Playback Volume' +numid=612,iface=MIXER,name='Mxr 3/17 Playback Volume' +numid=644,iface=MIXER,name='Mxr 3/18 Playback Volume' +numid=676,iface=MIXER,name='Mxr 3/19 Playback Volume' +numid=132,iface=MIXER,name='Mxr 3/2 Playback Volume' +numid=708,iface=MIXER,name='Mxr 3/20 Playback Volume' +numid=740,iface=MIXER,name='Mxr 3/21 Playback Volume' +numid=772,iface=MIXER,name='Mxr 3/22 Playback Volume' +numid=804,iface=MIXER,name='Mxr 3/23 Playback Volume' +numid=836,iface=MIXER,name='Mxr 3/24 Playback Volume' +numid=868,iface=MIXER,name='Mxr 3/25 Playback Volume' +numid=900,iface=MIXER,name='Mxr 3/26 Playback Volume' +numid=932,iface=MIXER,name='Mxr 3/27 Playback Volume' +numid=964,iface=MIXER,name='Mxr 3/28 Playback Volume' +numid=996,iface=MIXER,name='Mxr 3/29 Playback Volume' +numid=164,iface=MIXER,name='Mxr 3/3 Playback Volume' +numid=1028,iface=MIXER,name='Mxr 3/30 Playback Volume' +numid=1060,iface=MIXER,name='Mxr 3/31 Playback Volume' +numid=196,iface=MIXER,name='Mxr 3/4 Playback Volume' +numid=228,iface=MIXER,name='Mxr 3/5 Playback Volume' +numid=260,iface=MIXER,name='Mxr 3/6 Playback Volume' +numid=292,iface=MIXER,name='Mxr 3/7 Playback Volume' +numid=324,iface=MIXER,name='Mxr 3/8 Playback Volume' +numid=356,iface=MIXER,name='Mxr 3/9 Playback Volume' +numid=95,iface=MIXER,name='Mxr 30/0 Playback Volume' +numid=127,iface=MIXER,name='Mxr 30/1 Playback Volume' +numid=415,iface=MIXER,name='Mxr 30/10 Playback Volume' +numid=447,iface=MIXER,name='Mxr 30/11 Playback Volume' +numid=479,iface=MIXER,name='Mxr 30/12 Playback Volume' +numid=511,iface=MIXER,name='Mxr 30/13 Playback Volume' +numid=543,iface=MIXER,name='Mxr 30/14 Playback Volume' +numid=575,iface=MIXER,name='Mxr 30/15 Playback Volume' +numid=607,iface=MIXER,name='Mxr 30/16 Playback Volume' +numid=639,iface=MIXER,name='Mxr 30/17 Playback Volume' +numid=671,iface=MIXER,name='Mxr 30/18 Playback Volume' +numid=703,iface=MIXER,name='Mxr 30/19 Playback Volume' +numid=159,iface=MIXER,name='Mxr 30/2 Playback Volume' +numid=735,iface=MIXER,name='Mxr 30/20 Playback Volume' +numid=767,iface=MIXER,name='Mxr 30/21 Playback Volume' +numid=799,iface=MIXER,name='Mxr 30/22 Playback Volume' +numid=831,iface=MIXER,name='Mxr 30/23 Playback Volume' +numid=863,iface=MIXER,name='Mxr 30/24 Playback Volume' +numid=895,iface=MIXER,name='Mxr 30/25 Playback Volume' +numid=927,iface=MIXER,name='Mxr 30/26 Playback Volume' +numid=959,iface=MIXER,name='Mxr 30/27 Playback Volume' +numid=991,iface=MIXER,name='Mxr 30/28 Playback Volume' +numid=1023,iface=MIXER,name='Mxr 30/29 Playback Volume' +numid=191,iface=MIXER,name='Mxr 30/3 Playback Volume' +numid=1055,iface=MIXER,name='Mxr 30/30 Playback Volume' +numid=1087,iface=MIXER,name='Mxr 30/31 Playback Volume' +numid=223,iface=MIXER,name='Mxr 30/4 Playback Volume' +numid=255,iface=MIXER,name='Mxr 30/5 Playback Volume' +numid=287,iface=MIXER,name='Mxr 30/6 Playback Volume' +numid=319,iface=MIXER,name='Mxr 30/7 Playback Volume' +numid=351,iface=MIXER,name='Mxr 30/8 Playback Volume' +numid=383,iface=MIXER,name='Mxr 30/9 Playback Volume' +numid=96,iface=MIXER,name='Mxr 31/0 Playback Volume' +numid=128,iface=MIXER,name='Mxr 31/1 Playback Volume' +numid=416,iface=MIXER,name='Mxr 31/10 Playback Volume' +numid=448,iface=MIXER,name='Mxr 31/11 Playback Volume' +numid=480,iface=MIXER,name='Mxr 31/12 Playback Volume' +numid=512,iface=MIXER,name='Mxr 31/13 Playback Volume' +numid=544,iface=MIXER,name='Mxr 31/14 Playback Volume' +numid=576,iface=MIXER,name='Mxr 31/15 Playback Volume' +numid=608,iface=MIXER,name='Mxr 31/16 Playback Volume' +numid=640,iface=MIXER,name='Mxr 31/17 Playback Volume' +numid=672,iface=MIXER,name='Mxr 31/18 Playback Volume' +numid=704,iface=MIXER,name='Mxr 31/19 Playback Volume' +numid=160,iface=MIXER,name='Mxr 31/2 Playback Volume' +numid=736,iface=MIXER,name='Mxr 31/20 Playback Volume' +numid=768,iface=MIXER,name='Mxr 31/21 Playback Volume' +numid=800,iface=MIXER,name='Mxr 31/22 Playback Volume' +numid=832,iface=MIXER,name='Mxr 31/23 Playback Volume' +numid=864,iface=MIXER,name='Mxr 31/24 Playback Volume' +numid=896,iface=MIXER,name='Mxr 31/25 Playback Volume' +numid=928,iface=MIXER,name='Mxr 31/26 Playback Volume' +numid=960,iface=MIXER,name='Mxr 31/27 Playback Volume' +numid=992,iface=MIXER,name='Mxr 31/28 Playback Volume' +numid=1024,iface=MIXER,name='Mxr 31/29 Playback Volume' +numid=192,iface=MIXER,name='Mxr 31/3 Playback Volume' +numid=1056,iface=MIXER,name='Mxr 31/30 Playback Volume' +numid=1088,iface=MIXER,name='Mxr 31/31 Playback Volume' +numid=224,iface=MIXER,name='Mxr 31/4 Playback Volume' +numid=256,iface=MIXER,name='Mxr 31/5 Playback Volume' +numid=288,iface=MIXER,name='Mxr 31/6 Playback Volume' +numid=320,iface=MIXER,name='Mxr 31/7 Playback Volume' +numid=352,iface=MIXER,name='Mxr 31/8 Playback Volume' +numid=384,iface=MIXER,name='Mxr 31/9 Playback Volume' +numid=69,iface=MIXER,name='Mxr 4/0 Playback Volume' +numid=101,iface=MIXER,name='Mxr 4/1 Playback Volume' +numid=389,iface=MIXER,name='Mxr 4/10 Playback Volume' +numid=421,iface=MIXER,name='Mxr 4/11 Playback Volume' +numid=453,iface=MIXER,name='Mxr 4/12 Playback Volume' +numid=485,iface=MIXER,name='Mxr 4/13 Playback Volume' +numid=517,iface=MIXER,name='Mxr 4/14 Playback Volume' +numid=549,iface=MIXER,name='Mxr 4/15 Playback Volume' +numid=581,iface=MIXER,name='Mxr 4/16 Playback Volume' +numid=613,iface=MIXER,name='Mxr 4/17 Playback Volume' +numid=645,iface=MIXER,name='Mxr 4/18 Playback Volume' +numid=677,iface=MIXER,name='Mxr 4/19 Playback Volume' +numid=133,iface=MIXER,name='Mxr 4/2 Playback Volume' +numid=709,iface=MIXER,name='Mxr 4/20 Playback Volume' +numid=741,iface=MIXER,name='Mxr 4/21 Playback Volume' +numid=773,iface=MIXER,name='Mxr 4/22 Playback Volume' +numid=805,iface=MIXER,name='Mxr 4/23 Playback Volume' +numid=837,iface=MIXER,name='Mxr 4/24 Playback Volume' +numid=869,iface=MIXER,name='Mxr 4/25 Playback Volume' +numid=901,iface=MIXER,name='Mxr 4/26 Playback Volume' +numid=933,iface=MIXER,name='Mxr 4/27 Playback Volume' +numid=965,iface=MIXER,name='Mxr 4/28 Playback Volume' +numid=997,iface=MIXER,name='Mxr 4/29 Playback Volume' +numid=165,iface=MIXER,name='Mxr 4/3 Playback Volume' +numid=1029,iface=MIXER,name='Mxr 4/30 Playback Volume' +numid=1061,iface=MIXER,name='Mxr 4/31 Playback Volume' +numid=197,iface=MIXER,name='Mxr 4/4 Playback Volume' +numid=229,iface=MIXER,name='Mxr 4/5 Playback Volume' +numid=261,iface=MIXER,name='Mxr 4/6 Playback Volume' +numid=293,iface=MIXER,name='Mxr 4/7 Playback Volume' +numid=325,iface=MIXER,name='Mxr 4/8 Playback Volume' +numid=357,iface=MIXER,name='Mxr 4/9 Playback Volume' +numid=70,iface=MIXER,name='Mxr 5/0 Playback Volume' +numid=102,iface=MIXER,name='Mxr 5/1 Playback Volume' +numid=390,iface=MIXER,name='Mxr 5/10 Playback Volume' +numid=422,iface=MIXER,name='Mxr 5/11 Playback Volume' +numid=454,iface=MIXER,name='Mxr 5/12 Playback Volume' +numid=486,iface=MIXER,name='Mxr 5/13 Playback Volume' +numid=518,iface=MIXER,name='Mxr 5/14 Playback Volume' +numid=550,iface=MIXER,name='Mxr 5/15 Playback Volume' +numid=582,iface=MIXER,name='Mxr 5/16 Playback Volume' +numid=614,iface=MIXER,name='Mxr 5/17 Playback Volume' +numid=646,iface=MIXER,name='Mxr 5/18 Playback Volume' +numid=678,iface=MIXER,name='Mxr 5/19 Playback Volume' +numid=134,iface=MIXER,name='Mxr 5/2 Playback Volume' +numid=710,iface=MIXER,name='Mxr 5/20 Playback Volume' +numid=742,iface=MIXER,name='Mxr 5/21 Playback Volume' +numid=774,iface=MIXER,name='Mxr 5/22 Playback Volume' +numid=806,iface=MIXER,name='Mxr 5/23 Playback Volume' +numid=838,iface=MIXER,name='Mxr 5/24 Playback Volume' +numid=870,iface=MIXER,name='Mxr 5/25 Playback Volume' +numid=902,iface=MIXER,name='Mxr 5/26 Playback Volume' +numid=934,iface=MIXER,name='Mxr 5/27 Playback Volume' +numid=966,iface=MIXER,name='Mxr 5/28 Playback Volume' +numid=998,iface=MIXER,name='Mxr 5/29 Playback Volume' +numid=166,iface=MIXER,name='Mxr 5/3 Playback Volume' +numid=1030,iface=MIXER,name='Mxr 5/30 Playback Volume' +numid=1062,iface=MIXER,name='Mxr 5/31 Playback Volume' +numid=198,iface=MIXER,name='Mxr 5/4 Playback Volume' +numid=230,iface=MIXER,name='Mxr 5/5 Playback Volume' +numid=262,iface=MIXER,name='Mxr 5/6 Playback Volume' +numid=294,iface=MIXER,name='Mxr 5/7 Playback Volume' +numid=326,iface=MIXER,name='Mxr 5/8 Playback Volume' +numid=358,iface=MIXER,name='Mxr 5/9 Playback Volume' +numid=71,iface=MIXER,name='Mxr 6/0 Playback Volume' +numid=103,iface=MIXER,name='Mxr 6/1 Playback Volume' +numid=391,iface=MIXER,name='Mxr 6/10 Playback Volume' +numid=423,iface=MIXER,name='Mxr 6/11 Playback Volume' +numid=455,iface=MIXER,name='Mxr 6/12 Playback Volume' +numid=487,iface=MIXER,name='Mxr 6/13 Playback Volume' +numid=519,iface=MIXER,name='Mxr 6/14 Playback Volume' +numid=551,iface=MIXER,name='Mxr 6/15 Playback Volume' +numid=583,iface=MIXER,name='Mxr 6/16 Playback Volume' +numid=615,iface=MIXER,name='Mxr 6/17 Playback Volume' +numid=647,iface=MIXER,name='Mxr 6/18 Playback Volume' +numid=679,iface=MIXER,name='Mxr 6/19 Playback Volume' +numid=135,iface=MIXER,name='Mxr 6/2 Playback Volume' +numid=711,iface=MIXER,name='Mxr 6/20 Playback Volume' +numid=743,iface=MIXER,name='Mxr 6/21 Playback Volume' +numid=775,iface=MIXER,name='Mxr 6/22 Playback Volume' +numid=807,iface=MIXER,name='Mxr 6/23 Playback Volume' +numid=839,iface=MIXER,name='Mxr 6/24 Playback Volume' +numid=871,iface=MIXER,name='Mxr 6/25 Playback Volume' +numid=903,iface=MIXER,name='Mxr 6/26 Playback Volume' +numid=935,iface=MIXER,name='Mxr 6/27 Playback Volume' +numid=967,iface=MIXER,name='Mxr 6/28 Playback Volume' +numid=999,iface=MIXER,name='Mxr 6/29 Playback Volume' +numid=167,iface=MIXER,name='Mxr 6/3 Playback Volume' +numid=1031,iface=MIXER,name='Mxr 6/30 Playback Volume' +numid=1063,iface=MIXER,name='Mxr 6/31 Playback Volume' +numid=199,iface=MIXER,name='Mxr 6/4 Playback Volume' +numid=231,iface=MIXER,name='Mxr 6/5 Playback Volume' +numid=263,iface=MIXER,name='Mxr 6/6 Playback Volume' +numid=295,iface=MIXER,name='Mxr 6/7 Playback Volume' +numid=327,iface=MIXER,name='Mxr 6/8 Playback Volume' +numid=359,iface=MIXER,name='Mxr 6/9 Playback Volume' +numid=72,iface=MIXER,name='Mxr 7/0 Playback Volume' +numid=104,iface=MIXER,name='Mxr 7/1 Playback Volume' +numid=392,iface=MIXER,name='Mxr 7/10 Playback Volume' +numid=424,iface=MIXER,name='Mxr 7/11 Playback Volume' +numid=456,iface=MIXER,name='Mxr 7/12 Playback Volume' +numid=488,iface=MIXER,name='Mxr 7/13 Playback Volume' +numid=520,iface=MIXER,name='Mxr 7/14 Playback Volume' +numid=552,iface=MIXER,name='Mxr 7/15 Playback Volume' +numid=584,iface=MIXER,name='Mxr 7/16 Playback Volume' +numid=616,iface=MIXER,name='Mxr 7/17 Playback Volume' +numid=648,iface=MIXER,name='Mxr 7/18 Playback Volume' +numid=680,iface=MIXER,name='Mxr 7/19 Playback Volume' +numid=136,iface=MIXER,name='Mxr 7/2 Playback Volume' +numid=712,iface=MIXER,name='Mxr 7/20 Playback Volume' +numid=744,iface=MIXER,name='Mxr 7/21 Playback Volume' +numid=776,iface=MIXER,name='Mxr 7/22 Playback Volume' +numid=808,iface=MIXER,name='Mxr 7/23 Playback Volume' +numid=840,iface=MIXER,name='Mxr 7/24 Playback Volume' +numid=872,iface=MIXER,name='Mxr 7/25 Playback Volume' +numid=904,iface=MIXER,name='Mxr 7/26 Playback Volume' +numid=936,iface=MIXER,name='Mxr 7/27 Playback Volume' +numid=968,iface=MIXER,name='Mxr 7/28 Playback Volume' +numid=1000,iface=MIXER,name='Mxr 7/29 Playback Volume' +numid=168,iface=MIXER,name='Mxr 7/3 Playback Volume' +numid=1032,iface=MIXER,name='Mxr 7/30 Playback Volume' +numid=1064,iface=MIXER,name='Mxr 7/31 Playback Volume' +numid=200,iface=MIXER,name='Mxr 7/4 Playback Volume' +numid=232,iface=MIXER,name='Mxr 7/5 Playback Volume' +numid=264,iface=MIXER,name='Mxr 7/6 Playback Volume' +numid=296,iface=MIXER,name='Mxr 7/7 Playback Volume' +numid=328,iface=MIXER,name='Mxr 7/8 Playback Volume' +numid=360,iface=MIXER,name='Mxr 7/9 Playback Volume' +numid=73,iface=MIXER,name='Mxr 8/0 Playback Volume' +numid=105,iface=MIXER,name='Mxr 8/1 Playback Volume' +numid=393,iface=MIXER,name='Mxr 8/10 Playback Volume' +numid=425,iface=MIXER,name='Mxr 8/11 Playback Volume' +numid=457,iface=MIXER,name='Mxr 8/12 Playback Volume' +numid=489,iface=MIXER,name='Mxr 8/13 Playback Volume' +numid=521,iface=MIXER,name='Mxr 8/14 Playback Volume' +numid=553,iface=MIXER,name='Mxr 8/15 Playback Volume' +numid=585,iface=MIXER,name='Mxr 8/16 Playback Volume' +numid=617,iface=MIXER,name='Mxr 8/17 Playback Volume' +numid=649,iface=MIXER,name='Mxr 8/18 Playback Volume' +numid=681,iface=MIXER,name='Mxr 8/19 Playback Volume' +numid=137,iface=MIXER,name='Mxr 8/2 Playback Volume' +numid=713,iface=MIXER,name='Mxr 8/20 Playback Volume' +numid=745,iface=MIXER,name='Mxr 8/21 Playback Volume' +numid=777,iface=MIXER,name='Mxr 8/22 Playback Volume' +numid=809,iface=MIXER,name='Mxr 8/23 Playback Volume' +numid=841,iface=MIXER,name='Mxr 8/24 Playback Volume' +numid=873,iface=MIXER,name='Mxr 8/25 Playback Volume' +numid=905,iface=MIXER,name='Mxr 8/26 Playback Volume' +numid=937,iface=MIXER,name='Mxr 8/27 Playback Volume' +numid=969,iface=MIXER,name='Mxr 8/28 Playback Volume' +numid=1001,iface=MIXER,name='Mxr 8/29 Playback Volume' +numid=169,iface=MIXER,name='Mxr 8/3 Playback Volume' +numid=1033,iface=MIXER,name='Mxr 8/30 Playback Volume' +numid=1065,iface=MIXER,name='Mxr 8/31 Playback Volume' +numid=201,iface=MIXER,name='Mxr 8/4 Playback Volume' +numid=233,iface=MIXER,name='Mxr 8/5 Playback Volume' +numid=265,iface=MIXER,name='Mxr 8/6 Playback Volume' +numid=297,iface=MIXER,name='Mxr 8/7 Playback Volume' +numid=329,iface=MIXER,name='Mxr 8/8 Playback Volume' +numid=361,iface=MIXER,name='Mxr 8/9 Playback Volume' +numid=74,iface=MIXER,name='Mxr 9/0 Playback Volume' +numid=106,iface=MIXER,name='Mxr 9/1 Playback Volume' +numid=394,iface=MIXER,name='Mxr 9/10 Playback Volume' +numid=426,iface=MIXER,name='Mxr 9/11 Playback Volume' +numid=458,iface=MIXER,name='Mxr 9/12 Playback Volume' +numid=490,iface=MIXER,name='Mxr 9/13 Playback Volume' +numid=522,iface=MIXER,name='Mxr 9/14 Playback Volume' +numid=554,iface=MIXER,name='Mxr 9/15 Playback Volume' +numid=586,iface=MIXER,name='Mxr 9/16 Playback Volume' +numid=618,iface=MIXER,name='Mxr 9/17 Playback Volume' +numid=650,iface=MIXER,name='Mxr 9/18 Playback Volume' +numid=682,iface=MIXER,name='Mxr 9/19 Playback Volume' +numid=138,iface=MIXER,name='Mxr 9/2 Playback Volume' +numid=714,iface=MIXER,name='Mxr 9/20 Playback Volume' +numid=746,iface=MIXER,name='Mxr 9/21 Playback Volume' +numid=778,iface=MIXER,name='Mxr 9/22 Playback Volume' +numid=810,iface=MIXER,name='Mxr 9/23 Playback Volume' +numid=842,iface=MIXER,name='Mxr 9/24 Playback Volume' +numid=874,iface=MIXER,name='Mxr 9/25 Playback Volume' +numid=906,iface=MIXER,name='Mxr 9/26 Playback Volume' +numid=938,iface=MIXER,name='Mxr 9/27 Playback Volume' +numid=970,iface=MIXER,name='Mxr 9/28 Playback Volume' +numid=1002,iface=MIXER,name='Mxr 9/29 Playback Volume' +numid=170,iface=MIXER,name='Mxr 9/3 Playback Volume' +numid=1034,iface=MIXER,name='Mxr 9/30 Playback Volume' +numid=1066,iface=MIXER,name='Mxr 9/31 Playback Volume' +numid=202,iface=MIXER,name='Mxr 9/4 Playback Volume' +numid=234,iface=MIXER,name='Mxr 9/5 Playback Volume' +numid=266,iface=MIXER,name='Mxr 9/6 Playback Volume' +numid=298,iface=MIXER,name='Mxr 9/7 Playback Volume' +numid=330,iface=MIXER,name='Mxr 9/8 Playback Volume' +numid=362,iface=MIXER,name='Mxr 9/9 Playback Volume' diff --git a/snd-alpx-dkms/Controls/Alp882e_Contents.txt b/snd-alpx-dkms/Controls/Alp882e_Contents.txt new file mode 100644 index 0000000..d8f897d --- /dev/null +++ b/snd-alpx-dkms/Controls/Alp882e_Contents.txt @@ -0,0 +1,4469 @@ +numid=25,iface=MIXER,name='AES Capture Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=26,iface=MIXER,name='AES Capture Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=27,iface=MIXER,name='AES Capture Volume',index=2 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=28,iface=MIXER,name='AES Capture Volume',index=3 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=29,iface=MIXER,name='AES Capture Volume',index=4 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=30,iface=MIXER,name='AES Capture Volume',index=5 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=31,iface=MIXER,name='AES Capture Volume',index=6 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=32,iface=MIXER,name='AES Capture Volume',index=7 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=41,iface=MIXER,name='AES Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=915 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=42,iface=MIXER,name='AES Playback Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=43,iface=MIXER,name='AES Playback Volume',index=2 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=44,iface=MIXER,name='AES Playback Volume',index=3 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=45,iface=MIXER,name='AES Playback Volume',index=4 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=46,iface=MIXER,name='AES Playback Volume',index=5 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=47,iface=MIXER,name='AES Playback Volume',index=6 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=48,iface=MIXER,name='AES Playback Volume',index=7 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1098,iface=MIXER,name='AES SRC 1/2 Disable' + ; type=BOOLEAN,access=rw------,values=1 + : values=off +numid=1099,iface=MIXER,name='AES SRC 3/4 Disable' + ; type=BOOLEAN,access=rw------,values=1 + : values=off +numid=1100,iface=MIXER,name='AES SRC 5/6 Disable' + ; type=BOOLEAN,access=rw------,values=1 + : values=off +numid=1101,iface=MIXER,name='AES SRC 7/8 Disable' + ; type=BOOLEAN,access=rw------,values=1 + : values=off +numid=17,iface=MIXER,name='Ana Capture Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=18,iface=MIXER,name='Ana Capture Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=19,iface=MIXER,name='Ana Capture Volume',index=2 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=20,iface=MIXER,name='Ana Capture Volume',index=3 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=21,iface=MIXER,name='Ana Capture Volume',index=4 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=22,iface=MIXER,name='Ana Capture Volume',index=5 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=23,iface=MIXER,name='Ana Capture Volume',index=6 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=24,iface=MIXER,name='Ana Capture Volume',index=7 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=33,iface=MIXER,name='Ana Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=890 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=34,iface=MIXER,name='Ana Playback Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=35,iface=MIXER,name='Ana Playback Volume',index=2 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=36,iface=MIXER,name='Ana Playback Volume',index=3 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=37,iface=MIXER,name='Ana Playback Volume',index=4 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=38,iface=MIXER,name='Ana Playback Volume',index=5 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=39,iface=MIXER,name='Ana Playback Volume',index=6 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=40,iface=MIXER,name='Ana Playback Volume',index=7 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1090,iface=MIXER,name='Clk Eff' + ; type=ENUMERATED,access=r--v----,values=1,items=14 + ; Item #0 '8kHz' + ; Item #1 '11.025kHz' + ; Item #2 '16kHz' + ; Item #3 '22.05kHz' + ; Item #4 '24kHz' + ; Item #5 '32kHz' + ; Item #6 '44.1kHz' + ; Item #7 '48kHz' + ; Item #8 '64kHz' + ; Item #9 '88.2kHz' + ; Item #10 '96kHz' + ; Item #11 '128kHz' + ; Item #12 '176,4kHz' + ; Item #13 '192kHz' + : values=1 +numid=1089,iface=MIXER,name='Clk Eff Src' + ; type=ENUMERATED,access=r-------,values=1,items=7 + ; Item #0 'Word Clk' + ; Item #1 'AES Syn' + ; Item #2 'AES Aud 1/2' + ; Item #3 'AES Aud 3/4' + ; Item #4 'AES Aud 5/6' + ; Item #5 'AES Aud 7/8' + ; Item #6 'Internal' + : values=6 +numid=1094,iface=MIXER,name='Clk P0' + ; type=ENUMERATED,access=rw------,values=1,items=7 + ; Item #0 'Word Clk' + ; Item #1 'AES Syn' + ; Item #2 'AES Aud 1/2' + ; Item #3 'AES Aud 3/4' + ; Item #4 'AES Aud 5/6' + ; Item #5 'AES Aud 7/8' + ; Item #6 'Internal' + : values=6 +numid=1095,iface=MIXER,name='Clk P1' + ; type=ENUMERATED,access=rw------,values=1,items=7 + ; Item #0 'Word Clk' + ; Item #1 'AES Syn' + ; Item #2 'AES Aud 1/2' + ; Item #3 'AES Aud 3/4' + ; Item #4 'AES Aud 5/6' + ; Item #5 'AES Aud 7/8' + ; Item #6 'Internal' + : values=6 +numid=1096,iface=MIXER,name='Clk P2' + ; type=ENUMERATED,access=rw------,values=1,items=7 + ; Item #0 'Word Clk' + ; Item #1 'AES Syn' + ; Item #2 'AES Aud 1/2' + ; Item #3 'AES Aud 3/4' + ; Item #4 'AES Aud 5/6' + ; Item #5 'AES Aud 7/8' + ; Item #6 'Internal' + : values=6 +numid=1097,iface=MIXER,name='Clk P3' + ; type=ENUMERATED,access=rw------,values=1,items=7 + ; Item #0 'Word Clk' + ; Item #1 'AES Syn' + ; Item #2 'AES Aud 1/2' + ; Item #3 'AES Aud 3/4' + ; Item #4 'AES Aud 5/6' + ; Item #5 'AES Aud 7/8' + ; Item #6 'Internal' + : values=6 +numid=1093,iface=MIXER,name='Clk Src Down' + ; type=BOOLEAN,access=rw------,values=1 + : values=on +numid=1092,iface=MIXER,name='Clk Src Up' + ; type=BOOLEAN,access=rw------,values=1 + : values=on +numid=1102,iface=MIXER,name='Codec Analog Capture Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=82,step=0 + : values=4 + | dBminmaxmute-min=-24.00dB,max=16.00dB +numid=1103,iface=MIXER,name='Codec Analog Capture Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=82,step=0 + : values=1 + | dBminmaxmute-min=-24.00dB,max=16.00dB +numid=1104,iface=MIXER,name='Codec Analog Capture Volume',index=2 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=82,step=0 + : values=1 + | dBminmaxmute-min=-24.00dB,max=16.00dB +numid=1105,iface=MIXER,name='Codec Analog Capture Volume',index=3 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=82,step=0 + : values=0 + | dBminmaxmute-min=-24.00dB,max=16.00dB +numid=1106,iface=MIXER,name='Codec Analog Capture Volume',index=4 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=82,step=0 + : values=1 + | dBminmaxmute-min=-24.00dB,max=16.00dB +numid=1107,iface=MIXER,name='Codec Analog Capture Volume',index=5 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=82,step=0 + : values=0 + | dBminmaxmute-min=-24.00dB,max=16.00dB +numid=1108,iface=MIXER,name='Codec Analog Capture Volume',index=6 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=82,step=0 + : values=1 + | dBminmaxmute-min=-24.00dB,max=16.00dB +numid=1109,iface=MIXER,name='Codec Analog Capture Volume',index=7 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=82,step=0 + : values=1 + | dBminmaxmute-min=-24.00dB,max=16.00dB +numid=1,iface=MIXER,name='DAW Capture Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=2,iface=MIXER,name='DAW Capture Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=3,iface=MIXER,name='DAW Capture Volume',index=2 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=4,iface=MIXER,name='DAW Capture Volume',index=3 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=5,iface=MIXER,name='DAW Capture Volume',index=4 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=6,iface=MIXER,name='DAW Capture Volume',index=5 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=7,iface=MIXER,name='DAW Capture Volume',index=6 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=8,iface=MIXER,name='DAW Capture Volume',index=7 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=9,iface=MIXER,name='DAW Capture Volume',index=8 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=10,iface=MIXER,name='DAW Capture Volume',index=9 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=11,iface=MIXER,name='DAW Capture Volume',index=10 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=12,iface=MIXER,name='DAW Capture Volume',index=11 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=13,iface=MIXER,name='DAW Capture Volume',index=12 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=14,iface=MIXER,name='DAW Capture Volume',index=13 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=15,iface=MIXER,name='DAW Capture Volume',index=14 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=16,iface=MIXER,name='DAW Capture Volume',index=15 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=49,iface=MIXER,name='DAW Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=50,iface=MIXER,name='DAW Playback Volume',index=1 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=51,iface=MIXER,name='DAW Playback Volume',index=2 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=52,iface=MIXER,name='DAW Playback Volume',index=3 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=53,iface=MIXER,name='DAW Playback Volume',index=4 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=54,iface=MIXER,name='DAW Playback Volume',index=5 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=55,iface=MIXER,name='DAW Playback Volume',index=6 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=56,iface=MIXER,name='DAW Playback Volume',index=7 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=57,iface=MIXER,name='DAW Playback Volume',index=8 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=58,iface=MIXER,name='DAW Playback Volume',index=9 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=59,iface=MIXER,name='DAW Playback Volume',index=10 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=60,iface=MIXER,name='DAW Playback Volume',index=11 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=61,iface=MIXER,name='DAW Playback Volume',index=12 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=62,iface=MIXER,name='DAW Playback Volume',index=13 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=63,iface=MIXER,name='DAW Playback Volume',index=14 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=64,iface=MIXER,name='DAW Playback Volume',index=15 + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=65,iface=MIXER,name='Mxr 0/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=97,iface=MIXER,name='Mxr 0/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=385,iface=MIXER,name='Mxr 0/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=417,iface=MIXER,name='Mxr 0/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=449,iface=MIXER,name='Mxr 0/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=481,iface=MIXER,name='Mxr 0/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=513,iface=MIXER,name='Mxr 0/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=545,iface=MIXER,name='Mxr 0/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=577,iface=MIXER,name='Mxr 0/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=609,iface=MIXER,name='Mxr 0/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=641,iface=MIXER,name='Mxr 0/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=673,iface=MIXER,name='Mxr 0/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=129,iface=MIXER,name='Mxr 0/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=705,iface=MIXER,name='Mxr 0/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=737,iface=MIXER,name='Mxr 0/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=769,iface=MIXER,name='Mxr 0/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=801,iface=MIXER,name='Mxr 0/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=833,iface=MIXER,name='Mxr 0/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=865,iface=MIXER,name='Mxr 0/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=897,iface=MIXER,name='Mxr 0/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=929,iface=MIXER,name='Mxr 0/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=961,iface=MIXER,name='Mxr 0/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=993,iface=MIXER,name='Mxr 0/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=161,iface=MIXER,name='Mxr 0/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1025,iface=MIXER,name='Mxr 0/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1057,iface=MIXER,name='Mxr 0/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=193,iface=MIXER,name='Mxr 0/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=225,iface=MIXER,name='Mxr 0/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=257,iface=MIXER,name='Mxr 0/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=289,iface=MIXER,name='Mxr 0/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=321,iface=MIXER,name='Mxr 0/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=353,iface=MIXER,name='Mxr 0/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=66,iface=MIXER,name='Mxr 1/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=98,iface=MIXER,name='Mxr 1/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=386,iface=MIXER,name='Mxr 1/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=418,iface=MIXER,name='Mxr 1/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=450,iface=MIXER,name='Mxr 1/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=482,iface=MIXER,name='Mxr 1/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=514,iface=MIXER,name='Mxr 1/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=546,iface=MIXER,name='Mxr 1/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=578,iface=MIXER,name='Mxr 1/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=610,iface=MIXER,name='Mxr 1/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=642,iface=MIXER,name='Mxr 1/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=674,iface=MIXER,name='Mxr 1/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=130,iface=MIXER,name='Mxr 1/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=706,iface=MIXER,name='Mxr 1/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=738,iface=MIXER,name='Mxr 1/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=770,iface=MIXER,name='Mxr 1/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=802,iface=MIXER,name='Mxr 1/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=834,iface=MIXER,name='Mxr 1/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=866,iface=MIXER,name='Mxr 1/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=898,iface=MIXER,name='Mxr 1/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=930,iface=MIXER,name='Mxr 1/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=962,iface=MIXER,name='Mxr 1/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=994,iface=MIXER,name='Mxr 1/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=162,iface=MIXER,name='Mxr 1/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1026,iface=MIXER,name='Mxr 1/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1058,iface=MIXER,name='Mxr 1/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=194,iface=MIXER,name='Mxr 1/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=226,iface=MIXER,name='Mxr 1/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=258,iface=MIXER,name='Mxr 1/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=290,iface=MIXER,name='Mxr 1/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=322,iface=MIXER,name='Mxr 1/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=354,iface=MIXER,name='Mxr 1/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=75,iface=MIXER,name='Mxr 10/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=107,iface=MIXER,name='Mxr 10/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=395,iface=MIXER,name='Mxr 10/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=427,iface=MIXER,name='Mxr 10/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=459,iface=MIXER,name='Mxr 10/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=491,iface=MIXER,name='Mxr 10/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=523,iface=MIXER,name='Mxr 10/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=555,iface=MIXER,name='Mxr 10/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=587,iface=MIXER,name='Mxr 10/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=619,iface=MIXER,name='Mxr 10/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=651,iface=MIXER,name='Mxr 10/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=683,iface=MIXER,name='Mxr 10/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=139,iface=MIXER,name='Mxr 10/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=715,iface=MIXER,name='Mxr 10/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=747,iface=MIXER,name='Mxr 10/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=779,iface=MIXER,name='Mxr 10/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=811,iface=MIXER,name='Mxr 10/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=843,iface=MIXER,name='Mxr 10/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=875,iface=MIXER,name='Mxr 10/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=907,iface=MIXER,name='Mxr 10/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=939,iface=MIXER,name='Mxr 10/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=971,iface=MIXER,name='Mxr 10/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1003,iface=MIXER,name='Mxr 10/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=171,iface=MIXER,name='Mxr 10/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1035,iface=MIXER,name='Mxr 10/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1067,iface=MIXER,name='Mxr 10/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=203,iface=MIXER,name='Mxr 10/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=235,iface=MIXER,name='Mxr 10/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=267,iface=MIXER,name='Mxr 10/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=299,iface=MIXER,name='Mxr 10/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=331,iface=MIXER,name='Mxr 10/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=363,iface=MIXER,name='Mxr 10/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=76,iface=MIXER,name='Mxr 11/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=108,iface=MIXER,name='Mxr 11/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=396,iface=MIXER,name='Mxr 11/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=428,iface=MIXER,name='Mxr 11/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=460,iface=MIXER,name='Mxr 11/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=492,iface=MIXER,name='Mxr 11/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=524,iface=MIXER,name='Mxr 11/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=556,iface=MIXER,name='Mxr 11/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=588,iface=MIXER,name='Mxr 11/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=620,iface=MIXER,name='Mxr 11/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=652,iface=MIXER,name='Mxr 11/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=684,iface=MIXER,name='Mxr 11/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=140,iface=MIXER,name='Mxr 11/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=716,iface=MIXER,name='Mxr 11/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=748,iface=MIXER,name='Mxr 11/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=780,iface=MIXER,name='Mxr 11/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=812,iface=MIXER,name='Mxr 11/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=844,iface=MIXER,name='Mxr 11/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=876,iface=MIXER,name='Mxr 11/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=908,iface=MIXER,name='Mxr 11/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=940,iface=MIXER,name='Mxr 11/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=972,iface=MIXER,name='Mxr 11/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1004,iface=MIXER,name='Mxr 11/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=172,iface=MIXER,name='Mxr 11/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1036,iface=MIXER,name='Mxr 11/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1068,iface=MIXER,name='Mxr 11/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=204,iface=MIXER,name='Mxr 11/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=236,iface=MIXER,name='Mxr 11/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=268,iface=MIXER,name='Mxr 11/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=300,iface=MIXER,name='Mxr 11/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=332,iface=MIXER,name='Mxr 11/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=364,iface=MIXER,name='Mxr 11/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=77,iface=MIXER,name='Mxr 12/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=109,iface=MIXER,name='Mxr 12/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=397,iface=MIXER,name='Mxr 12/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=429,iface=MIXER,name='Mxr 12/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=461,iface=MIXER,name='Mxr 12/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=493,iface=MIXER,name='Mxr 12/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=525,iface=MIXER,name='Mxr 12/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=557,iface=MIXER,name='Mxr 12/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=589,iface=MIXER,name='Mxr 12/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=621,iface=MIXER,name='Mxr 12/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=653,iface=MIXER,name='Mxr 12/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=685,iface=MIXER,name='Mxr 12/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=141,iface=MIXER,name='Mxr 12/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=717,iface=MIXER,name='Mxr 12/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=749,iface=MIXER,name='Mxr 12/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=781,iface=MIXER,name='Mxr 12/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=813,iface=MIXER,name='Mxr 12/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=845,iface=MIXER,name='Mxr 12/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=877,iface=MIXER,name='Mxr 12/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=909,iface=MIXER,name='Mxr 12/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=941,iface=MIXER,name='Mxr 12/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=973,iface=MIXER,name='Mxr 12/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1005,iface=MIXER,name='Mxr 12/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=173,iface=MIXER,name='Mxr 12/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1037,iface=MIXER,name='Mxr 12/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1069,iface=MIXER,name='Mxr 12/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=205,iface=MIXER,name='Mxr 12/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=237,iface=MIXER,name='Mxr 12/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=269,iface=MIXER,name='Mxr 12/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=301,iface=MIXER,name='Mxr 12/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=333,iface=MIXER,name='Mxr 12/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=365,iface=MIXER,name='Mxr 12/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=78,iface=MIXER,name='Mxr 13/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=110,iface=MIXER,name='Mxr 13/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=398,iface=MIXER,name='Mxr 13/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=430,iface=MIXER,name='Mxr 13/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=462,iface=MIXER,name='Mxr 13/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=494,iface=MIXER,name='Mxr 13/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=526,iface=MIXER,name='Mxr 13/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=558,iface=MIXER,name='Mxr 13/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=590,iface=MIXER,name='Mxr 13/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=622,iface=MIXER,name='Mxr 13/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=654,iface=MIXER,name='Mxr 13/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=686,iface=MIXER,name='Mxr 13/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=142,iface=MIXER,name='Mxr 13/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=718,iface=MIXER,name='Mxr 13/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=750,iface=MIXER,name='Mxr 13/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=782,iface=MIXER,name='Mxr 13/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=814,iface=MIXER,name='Mxr 13/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=846,iface=MIXER,name='Mxr 13/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=878,iface=MIXER,name='Mxr 13/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=910,iface=MIXER,name='Mxr 13/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=942,iface=MIXER,name='Mxr 13/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=974,iface=MIXER,name='Mxr 13/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1006,iface=MIXER,name='Mxr 13/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=174,iface=MIXER,name='Mxr 13/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1038,iface=MIXER,name='Mxr 13/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1070,iface=MIXER,name='Mxr 13/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=206,iface=MIXER,name='Mxr 13/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=238,iface=MIXER,name='Mxr 13/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=270,iface=MIXER,name='Mxr 13/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=302,iface=MIXER,name='Mxr 13/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=334,iface=MIXER,name='Mxr 13/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=366,iface=MIXER,name='Mxr 13/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=79,iface=MIXER,name='Mxr 14/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=111,iface=MIXER,name='Mxr 14/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=399,iface=MIXER,name='Mxr 14/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=431,iface=MIXER,name='Mxr 14/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=463,iface=MIXER,name='Mxr 14/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=495,iface=MIXER,name='Mxr 14/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=527,iface=MIXER,name='Mxr 14/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=559,iface=MIXER,name='Mxr 14/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=591,iface=MIXER,name='Mxr 14/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=623,iface=MIXER,name='Mxr 14/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=655,iface=MIXER,name='Mxr 14/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=687,iface=MIXER,name='Mxr 14/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=143,iface=MIXER,name='Mxr 14/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=719,iface=MIXER,name='Mxr 14/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=751,iface=MIXER,name='Mxr 14/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=783,iface=MIXER,name='Mxr 14/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=815,iface=MIXER,name='Mxr 14/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=847,iface=MIXER,name='Mxr 14/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=879,iface=MIXER,name='Mxr 14/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=911,iface=MIXER,name='Mxr 14/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=943,iface=MIXER,name='Mxr 14/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=975,iface=MIXER,name='Mxr 14/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1007,iface=MIXER,name='Mxr 14/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=175,iface=MIXER,name='Mxr 14/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1039,iface=MIXER,name='Mxr 14/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1071,iface=MIXER,name='Mxr 14/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=207,iface=MIXER,name='Mxr 14/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=239,iface=MIXER,name='Mxr 14/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=271,iface=MIXER,name='Mxr 14/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=303,iface=MIXER,name='Mxr 14/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=335,iface=MIXER,name='Mxr 14/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=367,iface=MIXER,name='Mxr 14/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=80,iface=MIXER,name='Mxr 15/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=112,iface=MIXER,name='Mxr 15/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=400,iface=MIXER,name='Mxr 15/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=432,iface=MIXER,name='Mxr 15/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=464,iface=MIXER,name='Mxr 15/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=496,iface=MIXER,name='Mxr 15/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=528,iface=MIXER,name='Mxr 15/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=560,iface=MIXER,name='Mxr 15/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=592,iface=MIXER,name='Mxr 15/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=624,iface=MIXER,name='Mxr 15/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=656,iface=MIXER,name='Mxr 15/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=688,iface=MIXER,name='Mxr 15/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=144,iface=MIXER,name='Mxr 15/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=720,iface=MIXER,name='Mxr 15/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=752,iface=MIXER,name='Mxr 15/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=784,iface=MIXER,name='Mxr 15/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=816,iface=MIXER,name='Mxr 15/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=848,iface=MIXER,name='Mxr 15/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=880,iface=MIXER,name='Mxr 15/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=912,iface=MIXER,name='Mxr 15/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=944,iface=MIXER,name='Mxr 15/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=976,iface=MIXER,name='Mxr 15/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1008,iface=MIXER,name='Mxr 15/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=176,iface=MIXER,name='Mxr 15/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1040,iface=MIXER,name='Mxr 15/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1072,iface=MIXER,name='Mxr 15/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=208,iface=MIXER,name='Mxr 15/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=240,iface=MIXER,name='Mxr 15/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=272,iface=MIXER,name='Mxr 15/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=304,iface=MIXER,name='Mxr 15/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=336,iface=MIXER,name='Mxr 15/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=368,iface=MIXER,name='Mxr 15/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=81,iface=MIXER,name='Mxr 16/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=113,iface=MIXER,name='Mxr 16/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=401,iface=MIXER,name='Mxr 16/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=433,iface=MIXER,name='Mxr 16/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=465,iface=MIXER,name='Mxr 16/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=497,iface=MIXER,name='Mxr 16/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=529,iface=MIXER,name='Mxr 16/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=561,iface=MIXER,name='Mxr 16/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=593,iface=MIXER,name='Mxr 16/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=625,iface=MIXER,name='Mxr 16/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=657,iface=MIXER,name='Mxr 16/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=689,iface=MIXER,name='Mxr 16/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=145,iface=MIXER,name='Mxr 16/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=721,iface=MIXER,name='Mxr 16/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=753,iface=MIXER,name='Mxr 16/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=785,iface=MIXER,name='Mxr 16/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=817,iface=MIXER,name='Mxr 16/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=849,iface=MIXER,name='Mxr 16/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=881,iface=MIXER,name='Mxr 16/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=913,iface=MIXER,name='Mxr 16/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=945,iface=MIXER,name='Mxr 16/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=977,iface=MIXER,name='Mxr 16/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1009,iface=MIXER,name='Mxr 16/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=177,iface=MIXER,name='Mxr 16/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1041,iface=MIXER,name='Mxr 16/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1073,iface=MIXER,name='Mxr 16/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=209,iface=MIXER,name='Mxr 16/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=241,iface=MIXER,name='Mxr 16/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=273,iface=MIXER,name='Mxr 16/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=305,iface=MIXER,name='Mxr 16/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=337,iface=MIXER,name='Mxr 16/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=369,iface=MIXER,name='Mxr 16/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=82,iface=MIXER,name='Mxr 17/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=114,iface=MIXER,name='Mxr 17/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=402,iface=MIXER,name='Mxr 17/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=434,iface=MIXER,name='Mxr 17/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=466,iface=MIXER,name='Mxr 17/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=498,iface=MIXER,name='Mxr 17/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=530,iface=MIXER,name='Mxr 17/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=562,iface=MIXER,name='Mxr 17/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=594,iface=MIXER,name='Mxr 17/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=626,iface=MIXER,name='Mxr 17/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=658,iface=MIXER,name='Mxr 17/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=690,iface=MIXER,name='Mxr 17/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=146,iface=MIXER,name='Mxr 17/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=722,iface=MIXER,name='Mxr 17/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=754,iface=MIXER,name='Mxr 17/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=786,iface=MIXER,name='Mxr 17/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=818,iface=MIXER,name='Mxr 17/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=850,iface=MIXER,name='Mxr 17/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=882,iface=MIXER,name='Mxr 17/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=914,iface=MIXER,name='Mxr 17/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=946,iface=MIXER,name='Mxr 17/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=978,iface=MIXER,name='Mxr 17/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1010,iface=MIXER,name='Mxr 17/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=178,iface=MIXER,name='Mxr 17/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1042,iface=MIXER,name='Mxr 17/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1074,iface=MIXER,name='Mxr 17/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=210,iface=MIXER,name='Mxr 17/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=242,iface=MIXER,name='Mxr 17/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=274,iface=MIXER,name='Mxr 17/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=306,iface=MIXER,name='Mxr 17/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=338,iface=MIXER,name='Mxr 17/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=370,iface=MIXER,name='Mxr 17/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=83,iface=MIXER,name='Mxr 18/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=115,iface=MIXER,name='Mxr 18/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=403,iface=MIXER,name='Mxr 18/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=435,iface=MIXER,name='Mxr 18/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=467,iface=MIXER,name='Mxr 18/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=499,iface=MIXER,name='Mxr 18/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=531,iface=MIXER,name='Mxr 18/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=563,iface=MIXER,name='Mxr 18/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=595,iface=MIXER,name='Mxr 18/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=627,iface=MIXER,name='Mxr 18/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=659,iface=MIXER,name='Mxr 18/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=691,iface=MIXER,name='Mxr 18/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=147,iface=MIXER,name='Mxr 18/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=723,iface=MIXER,name='Mxr 18/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=755,iface=MIXER,name='Mxr 18/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=787,iface=MIXER,name='Mxr 18/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=819,iface=MIXER,name='Mxr 18/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=851,iface=MIXER,name='Mxr 18/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=883,iface=MIXER,name='Mxr 18/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=915,iface=MIXER,name='Mxr 18/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=947,iface=MIXER,name='Mxr 18/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=979,iface=MIXER,name='Mxr 18/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1011,iface=MIXER,name='Mxr 18/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=179,iface=MIXER,name='Mxr 18/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1043,iface=MIXER,name='Mxr 18/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1075,iface=MIXER,name='Mxr 18/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=211,iface=MIXER,name='Mxr 18/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=243,iface=MIXER,name='Mxr 18/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=275,iface=MIXER,name='Mxr 18/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=307,iface=MIXER,name='Mxr 18/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=339,iface=MIXER,name='Mxr 18/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=371,iface=MIXER,name='Mxr 18/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=84,iface=MIXER,name='Mxr 19/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=116,iface=MIXER,name='Mxr 19/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=404,iface=MIXER,name='Mxr 19/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=436,iface=MIXER,name='Mxr 19/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=468,iface=MIXER,name='Mxr 19/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=500,iface=MIXER,name='Mxr 19/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=532,iface=MIXER,name='Mxr 19/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=564,iface=MIXER,name='Mxr 19/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=596,iface=MIXER,name='Mxr 19/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=628,iface=MIXER,name='Mxr 19/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=660,iface=MIXER,name='Mxr 19/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=692,iface=MIXER,name='Mxr 19/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=148,iface=MIXER,name='Mxr 19/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=724,iface=MIXER,name='Mxr 19/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=756,iface=MIXER,name='Mxr 19/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=788,iface=MIXER,name='Mxr 19/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=820,iface=MIXER,name='Mxr 19/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=852,iface=MIXER,name='Mxr 19/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=884,iface=MIXER,name='Mxr 19/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=916,iface=MIXER,name='Mxr 19/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=948,iface=MIXER,name='Mxr 19/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=980,iface=MIXER,name='Mxr 19/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1012,iface=MIXER,name='Mxr 19/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=180,iface=MIXER,name='Mxr 19/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1044,iface=MIXER,name='Mxr 19/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1076,iface=MIXER,name='Mxr 19/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=212,iface=MIXER,name='Mxr 19/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=244,iface=MIXER,name='Mxr 19/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=276,iface=MIXER,name='Mxr 19/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=308,iface=MIXER,name='Mxr 19/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=340,iface=MIXER,name='Mxr 19/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=372,iface=MIXER,name='Mxr 19/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=67,iface=MIXER,name='Mxr 2/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=99,iface=MIXER,name='Mxr 2/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=387,iface=MIXER,name='Mxr 2/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=419,iface=MIXER,name='Mxr 2/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=451,iface=MIXER,name='Mxr 2/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=483,iface=MIXER,name='Mxr 2/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=515,iface=MIXER,name='Mxr 2/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=547,iface=MIXER,name='Mxr 2/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=579,iface=MIXER,name='Mxr 2/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=611,iface=MIXER,name='Mxr 2/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=643,iface=MIXER,name='Mxr 2/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=675,iface=MIXER,name='Mxr 2/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=131,iface=MIXER,name='Mxr 2/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=707,iface=MIXER,name='Mxr 2/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=739,iface=MIXER,name='Mxr 2/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=771,iface=MIXER,name='Mxr 2/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=803,iface=MIXER,name='Mxr 2/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=835,iface=MIXER,name='Mxr 2/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=867,iface=MIXER,name='Mxr 2/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=899,iface=MIXER,name='Mxr 2/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=931,iface=MIXER,name='Mxr 2/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=963,iface=MIXER,name='Mxr 2/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=995,iface=MIXER,name='Mxr 2/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=163,iface=MIXER,name='Mxr 2/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1027,iface=MIXER,name='Mxr 2/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1059,iface=MIXER,name='Mxr 2/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=195,iface=MIXER,name='Mxr 2/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=227,iface=MIXER,name='Mxr 2/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=259,iface=MIXER,name='Mxr 2/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=291,iface=MIXER,name='Mxr 2/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=323,iface=MIXER,name='Mxr 2/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=355,iface=MIXER,name='Mxr 2/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=85,iface=MIXER,name='Mxr 20/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=117,iface=MIXER,name='Mxr 20/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=405,iface=MIXER,name='Mxr 20/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=437,iface=MIXER,name='Mxr 20/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=469,iface=MIXER,name='Mxr 20/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=501,iface=MIXER,name='Mxr 20/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=533,iface=MIXER,name='Mxr 20/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=565,iface=MIXER,name='Mxr 20/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=597,iface=MIXER,name='Mxr 20/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=629,iface=MIXER,name='Mxr 20/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=661,iface=MIXER,name='Mxr 20/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=693,iface=MIXER,name='Mxr 20/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=149,iface=MIXER,name='Mxr 20/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=725,iface=MIXER,name='Mxr 20/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=757,iface=MIXER,name='Mxr 20/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=789,iface=MIXER,name='Mxr 20/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=821,iface=MIXER,name='Mxr 20/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=853,iface=MIXER,name='Mxr 20/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=885,iface=MIXER,name='Mxr 20/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=917,iface=MIXER,name='Mxr 20/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=949,iface=MIXER,name='Mxr 20/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=981,iface=MIXER,name='Mxr 20/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1013,iface=MIXER,name='Mxr 20/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=181,iface=MIXER,name='Mxr 20/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1045,iface=MIXER,name='Mxr 20/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1077,iface=MIXER,name='Mxr 20/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=213,iface=MIXER,name='Mxr 20/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=245,iface=MIXER,name='Mxr 20/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=277,iface=MIXER,name='Mxr 20/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=309,iface=MIXER,name='Mxr 20/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=341,iface=MIXER,name='Mxr 20/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=373,iface=MIXER,name='Mxr 20/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=86,iface=MIXER,name='Mxr 21/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=118,iface=MIXER,name='Mxr 21/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=406,iface=MIXER,name='Mxr 21/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=438,iface=MIXER,name='Mxr 21/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=470,iface=MIXER,name='Mxr 21/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=502,iface=MIXER,name='Mxr 21/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=534,iface=MIXER,name='Mxr 21/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=566,iface=MIXER,name='Mxr 21/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=598,iface=MIXER,name='Mxr 21/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=630,iface=MIXER,name='Mxr 21/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=662,iface=MIXER,name='Mxr 21/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=694,iface=MIXER,name='Mxr 21/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=150,iface=MIXER,name='Mxr 21/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=726,iface=MIXER,name='Mxr 21/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=758,iface=MIXER,name='Mxr 21/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=790,iface=MIXER,name='Mxr 21/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=822,iface=MIXER,name='Mxr 21/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=854,iface=MIXER,name='Mxr 21/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=886,iface=MIXER,name='Mxr 21/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=918,iface=MIXER,name='Mxr 21/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=950,iface=MIXER,name='Mxr 21/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=982,iface=MIXER,name='Mxr 21/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1014,iface=MIXER,name='Mxr 21/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=182,iface=MIXER,name='Mxr 21/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1046,iface=MIXER,name='Mxr 21/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1078,iface=MIXER,name='Mxr 21/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=214,iface=MIXER,name='Mxr 21/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=246,iface=MIXER,name='Mxr 21/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=278,iface=MIXER,name='Mxr 21/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=310,iface=MIXER,name='Mxr 21/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=342,iface=MIXER,name='Mxr 21/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=374,iface=MIXER,name='Mxr 21/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=87,iface=MIXER,name='Mxr 22/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=119,iface=MIXER,name='Mxr 22/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=407,iface=MIXER,name='Mxr 22/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=439,iface=MIXER,name='Mxr 22/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=471,iface=MIXER,name='Mxr 22/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=503,iface=MIXER,name='Mxr 22/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=535,iface=MIXER,name='Mxr 22/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=567,iface=MIXER,name='Mxr 22/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=599,iface=MIXER,name='Mxr 22/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=631,iface=MIXER,name='Mxr 22/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=663,iface=MIXER,name='Mxr 22/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=695,iface=MIXER,name='Mxr 22/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=151,iface=MIXER,name='Mxr 22/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=727,iface=MIXER,name='Mxr 22/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=759,iface=MIXER,name='Mxr 22/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=791,iface=MIXER,name='Mxr 22/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=823,iface=MIXER,name='Mxr 22/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=855,iface=MIXER,name='Mxr 22/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=887,iface=MIXER,name='Mxr 22/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=919,iface=MIXER,name='Mxr 22/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=951,iface=MIXER,name='Mxr 22/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=983,iface=MIXER,name='Mxr 22/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1015,iface=MIXER,name='Mxr 22/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=183,iface=MIXER,name='Mxr 22/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1047,iface=MIXER,name='Mxr 22/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1079,iface=MIXER,name='Mxr 22/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=215,iface=MIXER,name='Mxr 22/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=247,iface=MIXER,name='Mxr 22/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=279,iface=MIXER,name='Mxr 22/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=311,iface=MIXER,name='Mxr 22/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=343,iface=MIXER,name='Mxr 22/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=375,iface=MIXER,name='Mxr 22/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=88,iface=MIXER,name='Mxr 23/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=120,iface=MIXER,name='Mxr 23/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=408,iface=MIXER,name='Mxr 23/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=440,iface=MIXER,name='Mxr 23/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=472,iface=MIXER,name='Mxr 23/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=504,iface=MIXER,name='Mxr 23/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=536,iface=MIXER,name='Mxr 23/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=568,iface=MIXER,name='Mxr 23/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=600,iface=MIXER,name='Mxr 23/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=632,iface=MIXER,name='Mxr 23/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=664,iface=MIXER,name='Mxr 23/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=696,iface=MIXER,name='Mxr 23/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=152,iface=MIXER,name='Mxr 23/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=728,iface=MIXER,name='Mxr 23/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=760,iface=MIXER,name='Mxr 23/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=792,iface=MIXER,name='Mxr 23/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=824,iface=MIXER,name='Mxr 23/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=856,iface=MIXER,name='Mxr 23/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=888,iface=MIXER,name='Mxr 23/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=920,iface=MIXER,name='Mxr 23/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=952,iface=MIXER,name='Mxr 23/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=984,iface=MIXER,name='Mxr 23/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1016,iface=MIXER,name='Mxr 23/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=184,iface=MIXER,name='Mxr 23/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1048,iface=MIXER,name='Mxr 23/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1080,iface=MIXER,name='Mxr 23/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=216,iface=MIXER,name='Mxr 23/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=248,iface=MIXER,name='Mxr 23/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=280,iface=MIXER,name='Mxr 23/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=312,iface=MIXER,name='Mxr 23/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=344,iface=MIXER,name='Mxr 23/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=376,iface=MIXER,name='Mxr 23/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=89,iface=MIXER,name='Mxr 24/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=121,iface=MIXER,name='Mxr 24/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=409,iface=MIXER,name='Mxr 24/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=441,iface=MIXER,name='Mxr 24/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=473,iface=MIXER,name='Mxr 24/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=505,iface=MIXER,name='Mxr 24/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=537,iface=MIXER,name='Mxr 24/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=569,iface=MIXER,name='Mxr 24/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=601,iface=MIXER,name='Mxr 24/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=633,iface=MIXER,name='Mxr 24/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=665,iface=MIXER,name='Mxr 24/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=697,iface=MIXER,name='Mxr 24/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=153,iface=MIXER,name='Mxr 24/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=729,iface=MIXER,name='Mxr 24/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=761,iface=MIXER,name='Mxr 24/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=793,iface=MIXER,name='Mxr 24/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=825,iface=MIXER,name='Mxr 24/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=857,iface=MIXER,name='Mxr 24/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=889,iface=MIXER,name='Mxr 24/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=921,iface=MIXER,name='Mxr 24/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=953,iface=MIXER,name='Mxr 24/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=985,iface=MIXER,name='Mxr 24/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1017,iface=MIXER,name='Mxr 24/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=185,iface=MIXER,name='Mxr 24/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1049,iface=MIXER,name='Mxr 24/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1081,iface=MIXER,name='Mxr 24/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=217,iface=MIXER,name='Mxr 24/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=249,iface=MIXER,name='Mxr 24/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=281,iface=MIXER,name='Mxr 24/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=313,iface=MIXER,name='Mxr 24/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=345,iface=MIXER,name='Mxr 24/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=377,iface=MIXER,name='Mxr 24/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=90,iface=MIXER,name='Mxr 25/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=122,iface=MIXER,name='Mxr 25/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=410,iface=MIXER,name='Mxr 25/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=442,iface=MIXER,name='Mxr 25/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=474,iface=MIXER,name='Mxr 25/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=506,iface=MIXER,name='Mxr 25/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=538,iface=MIXER,name='Mxr 25/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=570,iface=MIXER,name='Mxr 25/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=602,iface=MIXER,name='Mxr 25/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=634,iface=MIXER,name='Mxr 25/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=666,iface=MIXER,name='Mxr 25/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=698,iface=MIXER,name='Mxr 25/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=154,iface=MIXER,name='Mxr 25/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=730,iface=MIXER,name='Mxr 25/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=762,iface=MIXER,name='Mxr 25/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=794,iface=MIXER,name='Mxr 25/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=826,iface=MIXER,name='Mxr 25/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=858,iface=MIXER,name='Mxr 25/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=890,iface=MIXER,name='Mxr 25/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=922,iface=MIXER,name='Mxr 25/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=954,iface=MIXER,name='Mxr 25/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=986,iface=MIXER,name='Mxr 25/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1018,iface=MIXER,name='Mxr 25/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=186,iface=MIXER,name='Mxr 25/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1050,iface=MIXER,name='Mxr 25/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1082,iface=MIXER,name='Mxr 25/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=218,iface=MIXER,name='Mxr 25/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=250,iface=MIXER,name='Mxr 25/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=282,iface=MIXER,name='Mxr 25/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=314,iface=MIXER,name='Mxr 25/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=346,iface=MIXER,name='Mxr 25/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=378,iface=MIXER,name='Mxr 25/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=91,iface=MIXER,name='Mxr 26/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=123,iface=MIXER,name='Mxr 26/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=411,iface=MIXER,name='Mxr 26/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=443,iface=MIXER,name='Mxr 26/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=475,iface=MIXER,name='Mxr 26/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=507,iface=MIXER,name='Mxr 26/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=539,iface=MIXER,name='Mxr 26/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=571,iface=MIXER,name='Mxr 26/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=603,iface=MIXER,name='Mxr 26/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=635,iface=MIXER,name='Mxr 26/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=667,iface=MIXER,name='Mxr 26/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=699,iface=MIXER,name='Mxr 26/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=155,iface=MIXER,name='Mxr 26/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=731,iface=MIXER,name='Mxr 26/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=763,iface=MIXER,name='Mxr 26/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=795,iface=MIXER,name='Mxr 26/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=827,iface=MIXER,name='Mxr 26/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=859,iface=MIXER,name='Mxr 26/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=891,iface=MIXER,name='Mxr 26/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=923,iface=MIXER,name='Mxr 26/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=955,iface=MIXER,name='Mxr 26/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=987,iface=MIXER,name='Mxr 26/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1019,iface=MIXER,name='Mxr 26/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=187,iface=MIXER,name='Mxr 26/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1051,iface=MIXER,name='Mxr 26/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1083,iface=MIXER,name='Mxr 26/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=219,iface=MIXER,name='Mxr 26/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=251,iface=MIXER,name='Mxr 26/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=283,iface=MIXER,name='Mxr 26/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=315,iface=MIXER,name='Mxr 26/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=347,iface=MIXER,name='Mxr 26/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=379,iface=MIXER,name='Mxr 26/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=92,iface=MIXER,name='Mxr 27/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=124,iface=MIXER,name='Mxr 27/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=412,iface=MIXER,name='Mxr 27/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=444,iface=MIXER,name='Mxr 27/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=476,iface=MIXER,name='Mxr 27/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=508,iface=MIXER,name='Mxr 27/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=540,iface=MIXER,name='Mxr 27/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=572,iface=MIXER,name='Mxr 27/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=604,iface=MIXER,name='Mxr 27/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=636,iface=MIXER,name='Mxr 27/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=668,iface=MIXER,name='Mxr 27/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=700,iface=MIXER,name='Mxr 27/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=156,iface=MIXER,name='Mxr 27/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=732,iface=MIXER,name='Mxr 27/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=764,iface=MIXER,name='Mxr 27/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=796,iface=MIXER,name='Mxr 27/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=828,iface=MIXER,name='Mxr 27/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=860,iface=MIXER,name='Mxr 27/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=892,iface=MIXER,name='Mxr 27/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=924,iface=MIXER,name='Mxr 27/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=956,iface=MIXER,name='Mxr 27/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=988,iface=MIXER,name='Mxr 27/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1020,iface=MIXER,name='Mxr 27/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=188,iface=MIXER,name='Mxr 27/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1052,iface=MIXER,name='Mxr 27/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1084,iface=MIXER,name='Mxr 27/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=220,iface=MIXER,name='Mxr 27/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=252,iface=MIXER,name='Mxr 27/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=284,iface=MIXER,name='Mxr 27/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=316,iface=MIXER,name='Mxr 27/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=348,iface=MIXER,name='Mxr 27/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=380,iface=MIXER,name='Mxr 27/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=93,iface=MIXER,name='Mxr 28/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=125,iface=MIXER,name='Mxr 28/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=413,iface=MIXER,name='Mxr 28/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=445,iface=MIXER,name='Mxr 28/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=477,iface=MIXER,name='Mxr 28/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=509,iface=MIXER,name='Mxr 28/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=541,iface=MIXER,name='Mxr 28/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=573,iface=MIXER,name='Mxr 28/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=605,iface=MIXER,name='Mxr 28/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=637,iface=MIXER,name='Mxr 28/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=669,iface=MIXER,name='Mxr 28/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=701,iface=MIXER,name='Mxr 28/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=157,iface=MIXER,name='Mxr 28/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=733,iface=MIXER,name='Mxr 28/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=765,iface=MIXER,name='Mxr 28/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=797,iface=MIXER,name='Mxr 28/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=829,iface=MIXER,name='Mxr 28/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=861,iface=MIXER,name='Mxr 28/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=893,iface=MIXER,name='Mxr 28/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=925,iface=MIXER,name='Mxr 28/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=957,iface=MIXER,name='Mxr 28/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=989,iface=MIXER,name='Mxr 28/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1021,iface=MIXER,name='Mxr 28/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=189,iface=MIXER,name='Mxr 28/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1053,iface=MIXER,name='Mxr 28/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1085,iface=MIXER,name='Mxr 28/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=221,iface=MIXER,name='Mxr 28/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=253,iface=MIXER,name='Mxr 28/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=285,iface=MIXER,name='Mxr 28/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=317,iface=MIXER,name='Mxr 28/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=349,iface=MIXER,name='Mxr 28/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=381,iface=MIXER,name='Mxr 28/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=94,iface=MIXER,name='Mxr 29/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=126,iface=MIXER,name='Mxr 29/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=414,iface=MIXER,name='Mxr 29/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=446,iface=MIXER,name='Mxr 29/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=478,iface=MIXER,name='Mxr 29/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=510,iface=MIXER,name='Mxr 29/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=542,iface=MIXER,name='Mxr 29/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=574,iface=MIXER,name='Mxr 29/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=606,iface=MIXER,name='Mxr 29/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=638,iface=MIXER,name='Mxr 29/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=670,iface=MIXER,name='Mxr 29/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=702,iface=MIXER,name='Mxr 29/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=158,iface=MIXER,name='Mxr 29/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=734,iface=MIXER,name='Mxr 29/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=766,iface=MIXER,name='Mxr 29/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=798,iface=MIXER,name='Mxr 29/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=830,iface=MIXER,name='Mxr 29/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=862,iface=MIXER,name='Mxr 29/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=894,iface=MIXER,name='Mxr 29/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=926,iface=MIXER,name='Mxr 29/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=958,iface=MIXER,name='Mxr 29/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=990,iface=MIXER,name='Mxr 29/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1022,iface=MIXER,name='Mxr 29/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=190,iface=MIXER,name='Mxr 29/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1054,iface=MIXER,name='Mxr 29/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1086,iface=MIXER,name='Mxr 29/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=222,iface=MIXER,name='Mxr 29/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=254,iface=MIXER,name='Mxr 29/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=286,iface=MIXER,name='Mxr 29/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=318,iface=MIXER,name='Mxr 29/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=350,iface=MIXER,name='Mxr 29/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=382,iface=MIXER,name='Mxr 29/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=68,iface=MIXER,name='Mxr 3/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=100,iface=MIXER,name='Mxr 3/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=388,iface=MIXER,name='Mxr 3/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=420,iface=MIXER,name='Mxr 3/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=452,iface=MIXER,name='Mxr 3/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=484,iface=MIXER,name='Mxr 3/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=516,iface=MIXER,name='Mxr 3/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=548,iface=MIXER,name='Mxr 3/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=580,iface=MIXER,name='Mxr 3/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=612,iface=MIXER,name='Mxr 3/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=644,iface=MIXER,name='Mxr 3/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=676,iface=MIXER,name='Mxr 3/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=132,iface=MIXER,name='Mxr 3/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=708,iface=MIXER,name='Mxr 3/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=740,iface=MIXER,name='Mxr 3/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=772,iface=MIXER,name='Mxr 3/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=804,iface=MIXER,name='Mxr 3/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=836,iface=MIXER,name='Mxr 3/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=868,iface=MIXER,name='Mxr 3/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=900,iface=MIXER,name='Mxr 3/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=932,iface=MIXER,name='Mxr 3/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=964,iface=MIXER,name='Mxr 3/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=996,iface=MIXER,name='Mxr 3/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=164,iface=MIXER,name='Mxr 3/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1028,iface=MIXER,name='Mxr 3/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1060,iface=MIXER,name='Mxr 3/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=196,iface=MIXER,name='Mxr 3/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=228,iface=MIXER,name='Mxr 3/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=260,iface=MIXER,name='Mxr 3/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=292,iface=MIXER,name='Mxr 3/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=324,iface=MIXER,name='Mxr 3/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=356,iface=MIXER,name='Mxr 3/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=95,iface=MIXER,name='Mxr 30/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=127,iface=MIXER,name='Mxr 30/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=415,iface=MIXER,name='Mxr 30/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=447,iface=MIXER,name='Mxr 30/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=479,iface=MIXER,name='Mxr 30/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=511,iface=MIXER,name='Mxr 30/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=543,iface=MIXER,name='Mxr 30/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=575,iface=MIXER,name='Mxr 30/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=607,iface=MIXER,name='Mxr 30/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=639,iface=MIXER,name='Mxr 30/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=671,iface=MIXER,name='Mxr 30/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=703,iface=MIXER,name='Mxr 30/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=159,iface=MIXER,name='Mxr 30/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=735,iface=MIXER,name='Mxr 30/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=767,iface=MIXER,name='Mxr 30/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=799,iface=MIXER,name='Mxr 30/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=831,iface=MIXER,name='Mxr 30/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=863,iface=MIXER,name='Mxr 30/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=895,iface=MIXER,name='Mxr 30/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=927,iface=MIXER,name='Mxr 30/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=959,iface=MIXER,name='Mxr 30/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=991,iface=MIXER,name='Mxr 30/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1023,iface=MIXER,name='Mxr 30/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=191,iface=MIXER,name='Mxr 30/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1055,iface=MIXER,name='Mxr 30/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1087,iface=MIXER,name='Mxr 30/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=223,iface=MIXER,name='Mxr 30/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=255,iface=MIXER,name='Mxr 30/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=287,iface=MIXER,name='Mxr 30/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=319,iface=MIXER,name='Mxr 30/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=351,iface=MIXER,name='Mxr 30/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=383,iface=MIXER,name='Mxr 30/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=96,iface=MIXER,name='Mxr 31/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=128,iface=MIXER,name='Mxr 31/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=416,iface=MIXER,name='Mxr 31/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=448,iface=MIXER,name='Mxr 31/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=480,iface=MIXER,name='Mxr 31/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=512,iface=MIXER,name='Mxr 31/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=544,iface=MIXER,name='Mxr 31/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=576,iface=MIXER,name='Mxr 31/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=608,iface=MIXER,name='Mxr 31/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=640,iface=MIXER,name='Mxr 31/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=672,iface=MIXER,name='Mxr 31/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=704,iface=MIXER,name='Mxr 31/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=160,iface=MIXER,name='Mxr 31/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=736,iface=MIXER,name='Mxr 31/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=768,iface=MIXER,name='Mxr 31/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=800,iface=MIXER,name='Mxr 31/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=832,iface=MIXER,name='Mxr 31/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=864,iface=MIXER,name='Mxr 31/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=896,iface=MIXER,name='Mxr 31/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=928,iface=MIXER,name='Mxr 31/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=960,iface=MIXER,name='Mxr 31/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=992,iface=MIXER,name='Mxr 31/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1024,iface=MIXER,name='Mxr 31/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=192,iface=MIXER,name='Mxr 31/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1056,iface=MIXER,name='Mxr 31/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1088,iface=MIXER,name='Mxr 31/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=224,iface=MIXER,name='Mxr 31/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=256,iface=MIXER,name='Mxr 31/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=288,iface=MIXER,name='Mxr 31/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=320,iface=MIXER,name='Mxr 31/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=352,iface=MIXER,name='Mxr 31/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=384,iface=MIXER,name='Mxr 31/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=69,iface=MIXER,name='Mxr 4/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=101,iface=MIXER,name='Mxr 4/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=389,iface=MIXER,name='Mxr 4/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=421,iface=MIXER,name='Mxr 4/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=453,iface=MIXER,name='Mxr 4/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=485,iface=MIXER,name='Mxr 4/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=517,iface=MIXER,name='Mxr 4/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=549,iface=MIXER,name='Mxr 4/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=581,iface=MIXER,name='Mxr 4/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=613,iface=MIXER,name='Mxr 4/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=645,iface=MIXER,name='Mxr 4/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=677,iface=MIXER,name='Mxr 4/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=133,iface=MIXER,name='Mxr 4/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=709,iface=MIXER,name='Mxr 4/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=741,iface=MIXER,name='Mxr 4/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=773,iface=MIXER,name='Mxr 4/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=805,iface=MIXER,name='Mxr 4/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=837,iface=MIXER,name='Mxr 4/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=869,iface=MIXER,name='Mxr 4/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=901,iface=MIXER,name='Mxr 4/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=933,iface=MIXER,name='Mxr 4/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=965,iface=MIXER,name='Mxr 4/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=997,iface=MIXER,name='Mxr 4/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=165,iface=MIXER,name='Mxr 4/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1029,iface=MIXER,name='Mxr 4/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1061,iface=MIXER,name='Mxr 4/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=197,iface=MIXER,name='Mxr 4/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=229,iface=MIXER,name='Mxr 4/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=261,iface=MIXER,name='Mxr 4/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=293,iface=MIXER,name='Mxr 4/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=325,iface=MIXER,name='Mxr 4/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=357,iface=MIXER,name='Mxr 4/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=70,iface=MIXER,name='Mxr 5/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=102,iface=MIXER,name='Mxr 5/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=390,iface=MIXER,name='Mxr 5/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=422,iface=MIXER,name='Mxr 5/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=454,iface=MIXER,name='Mxr 5/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=486,iface=MIXER,name='Mxr 5/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=518,iface=MIXER,name='Mxr 5/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=550,iface=MIXER,name='Mxr 5/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=582,iface=MIXER,name='Mxr 5/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=614,iface=MIXER,name='Mxr 5/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=646,iface=MIXER,name='Mxr 5/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=678,iface=MIXER,name='Mxr 5/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=134,iface=MIXER,name='Mxr 5/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=710,iface=MIXER,name='Mxr 5/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=742,iface=MIXER,name='Mxr 5/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=774,iface=MIXER,name='Mxr 5/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=806,iface=MIXER,name='Mxr 5/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=838,iface=MIXER,name='Mxr 5/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=870,iface=MIXER,name='Mxr 5/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=902,iface=MIXER,name='Mxr 5/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=934,iface=MIXER,name='Mxr 5/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=966,iface=MIXER,name='Mxr 5/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=998,iface=MIXER,name='Mxr 5/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=166,iface=MIXER,name='Mxr 5/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1030,iface=MIXER,name='Mxr 5/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1062,iface=MIXER,name='Mxr 5/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=198,iface=MIXER,name='Mxr 5/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=230,iface=MIXER,name='Mxr 5/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=262,iface=MIXER,name='Mxr 5/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=294,iface=MIXER,name='Mxr 5/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=326,iface=MIXER,name='Mxr 5/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=358,iface=MIXER,name='Mxr 5/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=71,iface=MIXER,name='Mxr 6/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=103,iface=MIXER,name='Mxr 6/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=391,iface=MIXER,name='Mxr 6/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=423,iface=MIXER,name='Mxr 6/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=455,iface=MIXER,name='Mxr 6/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=487,iface=MIXER,name='Mxr 6/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=519,iface=MIXER,name='Mxr 6/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=551,iface=MIXER,name='Mxr 6/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=583,iface=MIXER,name='Mxr 6/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=615,iface=MIXER,name='Mxr 6/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=647,iface=MIXER,name='Mxr 6/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=679,iface=MIXER,name='Mxr 6/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=135,iface=MIXER,name='Mxr 6/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=711,iface=MIXER,name='Mxr 6/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=743,iface=MIXER,name='Mxr 6/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=775,iface=MIXER,name='Mxr 6/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=807,iface=MIXER,name='Mxr 6/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=839,iface=MIXER,name='Mxr 6/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=871,iface=MIXER,name='Mxr 6/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=903,iface=MIXER,name='Mxr 6/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=935,iface=MIXER,name='Mxr 6/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=967,iface=MIXER,name='Mxr 6/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=999,iface=MIXER,name='Mxr 6/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=167,iface=MIXER,name='Mxr 6/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1031,iface=MIXER,name='Mxr 6/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1063,iface=MIXER,name='Mxr 6/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=199,iface=MIXER,name='Mxr 6/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=231,iface=MIXER,name='Mxr 6/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=263,iface=MIXER,name='Mxr 6/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=295,iface=MIXER,name='Mxr 6/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=327,iface=MIXER,name='Mxr 6/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=359,iface=MIXER,name='Mxr 6/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=72,iface=MIXER,name='Mxr 7/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=104,iface=MIXER,name='Mxr 7/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=392,iface=MIXER,name='Mxr 7/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=424,iface=MIXER,name='Mxr 7/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=456,iface=MIXER,name='Mxr 7/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=488,iface=MIXER,name='Mxr 7/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=520,iface=MIXER,name='Mxr 7/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=552,iface=MIXER,name='Mxr 7/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=584,iface=MIXER,name='Mxr 7/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=616,iface=MIXER,name='Mxr 7/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=648,iface=MIXER,name='Mxr 7/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=680,iface=MIXER,name='Mxr 7/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=136,iface=MIXER,name='Mxr 7/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=712,iface=MIXER,name='Mxr 7/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=744,iface=MIXER,name='Mxr 7/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=776,iface=MIXER,name='Mxr 7/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=808,iface=MIXER,name='Mxr 7/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=840,iface=MIXER,name='Mxr 7/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=872,iface=MIXER,name='Mxr 7/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=904,iface=MIXER,name='Mxr 7/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=936,iface=MIXER,name='Mxr 7/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=968,iface=MIXER,name='Mxr 7/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1000,iface=MIXER,name='Mxr 7/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=168,iface=MIXER,name='Mxr 7/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1032,iface=MIXER,name='Mxr 7/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1064,iface=MIXER,name='Mxr 7/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=200,iface=MIXER,name='Mxr 7/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=232,iface=MIXER,name='Mxr 7/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=264,iface=MIXER,name='Mxr 7/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=296,iface=MIXER,name='Mxr 7/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=328,iface=MIXER,name='Mxr 7/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=360,iface=MIXER,name='Mxr 7/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=73,iface=MIXER,name='Mxr 8/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=105,iface=MIXER,name='Mxr 8/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=393,iface=MIXER,name='Mxr 8/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=425,iface=MIXER,name='Mxr 8/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=457,iface=MIXER,name='Mxr 8/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=489,iface=MIXER,name='Mxr 8/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=521,iface=MIXER,name='Mxr 8/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=553,iface=MIXER,name='Mxr 8/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=585,iface=MIXER,name='Mxr 8/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=617,iface=MIXER,name='Mxr 8/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=649,iface=MIXER,name='Mxr 8/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=681,iface=MIXER,name='Mxr 8/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=137,iface=MIXER,name='Mxr 8/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=713,iface=MIXER,name='Mxr 8/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=745,iface=MIXER,name='Mxr 8/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=777,iface=MIXER,name='Mxr 8/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=809,iface=MIXER,name='Mxr 8/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=841,iface=MIXER,name='Mxr 8/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=873,iface=MIXER,name='Mxr 8/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=905,iface=MIXER,name='Mxr 8/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=937,iface=MIXER,name='Mxr 8/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=969,iface=MIXER,name='Mxr 8/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1001,iface=MIXER,name='Mxr 8/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=169,iface=MIXER,name='Mxr 8/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1033,iface=MIXER,name='Mxr 8/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1065,iface=MIXER,name='Mxr 8/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=201,iface=MIXER,name='Mxr 8/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=233,iface=MIXER,name='Mxr 8/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=265,iface=MIXER,name='Mxr 8/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=297,iface=MIXER,name='Mxr 8/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=329,iface=MIXER,name='Mxr 8/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=361,iface=MIXER,name='Mxr 8/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=74,iface=MIXER,name='Mxr 9/0 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=106,iface=MIXER,name='Mxr 9/1 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=394,iface=MIXER,name='Mxr 9/10 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=426,iface=MIXER,name='Mxr 9/11 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=458,iface=MIXER,name='Mxr 9/12 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=490,iface=MIXER,name='Mxr 9/13 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=522,iface=MIXER,name='Mxr 9/14 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=554,iface=MIXER,name='Mxr 9/15 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=586,iface=MIXER,name='Mxr 9/16 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=618,iface=MIXER,name='Mxr 9/17 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=650,iface=MIXER,name='Mxr 9/18 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=682,iface=MIXER,name='Mxr 9/19 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=138,iface=MIXER,name='Mxr 9/2 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=714,iface=MIXER,name='Mxr 9/20 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=746,iface=MIXER,name='Mxr 9/21 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=778,iface=MIXER,name='Mxr 9/22 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=810,iface=MIXER,name='Mxr 9/23 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=842,iface=MIXER,name='Mxr 9/24 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=874,iface=MIXER,name='Mxr 9/25 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=906,iface=MIXER,name='Mxr 9/26 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=938,iface=MIXER,name='Mxr 9/27 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=970,iface=MIXER,name='Mxr 9/28 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1002,iface=MIXER,name='Mxr 9/29 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=170,iface=MIXER,name='Mxr 9/3 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1034,iface=MIXER,name='Mxr 9/30 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=1066,iface=MIXER,name='Mxr 9/31 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=202,iface=MIXER,name='Mxr 9/4 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=234,iface=MIXER,name='Mxr 9/5 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=266,iface=MIXER,name='Mxr 9/6 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=298,iface=MIXER,name='Mxr 9/7 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=330,iface=MIXER,name='Mxr 9/8 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=0 + | dBminmaxmute-min=-90.10dB,max=12.00dB +numid=362,iface=MIXER,name='Mxr 9/9 Playback Volume' + ; type=INTEGER,access=rw---R--,values=1,min=0,max=1021,step=0 + : values=901 + | dBminmaxmute-min=-90.10dB,max=12.00dB diff --git a/snd-alpx-dkms/Controls/Alp882e_Controls.txt b/snd-alpx-dkms/Controls/Alp882e_Controls.txt new file mode 100644 index 0000000..aa14407 --- /dev/null +++ b/snd-alpx-dkms/Controls/Alp882e_Controls.txt @@ -0,0 +1,1108 @@ +numid=25,iface=MIXER,name='AES Capture Volume' +numid=26,iface=MIXER,name='AES Capture Volume',index=1 +numid=27,iface=MIXER,name='AES Capture Volume',index=2 +numid=28,iface=MIXER,name='AES Capture Volume',index=3 +numid=29,iface=MIXER,name='AES Capture Volume',index=4 +numid=30,iface=MIXER,name='AES Capture Volume',index=5 +numid=31,iface=MIXER,name='AES Capture Volume',index=6 +numid=32,iface=MIXER,name='AES Capture Volume',index=7 +numid=41,iface=MIXER,name='AES Playback Volume' +numid=42,iface=MIXER,name='AES Playback Volume',index=1 +numid=43,iface=MIXER,name='AES Playback Volume',index=2 +numid=44,iface=MIXER,name='AES Playback Volume',index=3 +numid=45,iface=MIXER,name='AES Playback Volume',index=4 +numid=46,iface=MIXER,name='AES Playback Volume',index=5 +numid=47,iface=MIXER,name='AES Playback Volume',index=6 +numid=48,iface=MIXER,name='AES Playback Volume',index=7 +numid=1098,iface=MIXER,name='AES SRC 1/2 Disable' +numid=1099,iface=MIXER,name='AES SRC 3/4 Disable' +numid=1100,iface=MIXER,name='AES SRC 5/6 Disable' +numid=1101,iface=MIXER,name='AES SRC 7/8 Disable' +numid=17,iface=MIXER,name='Ana Capture Volume' +numid=18,iface=MIXER,name='Ana Capture Volume',index=1 +numid=19,iface=MIXER,name='Ana Capture Volume',index=2 +numid=20,iface=MIXER,name='Ana Capture Volume',index=3 +numid=21,iface=MIXER,name='Ana Capture Volume',index=4 +numid=22,iface=MIXER,name='Ana Capture Volume',index=5 +numid=23,iface=MIXER,name='Ana Capture Volume',index=6 +numid=24,iface=MIXER,name='Ana Capture Volume',index=7 +numid=33,iface=MIXER,name='Ana Playback Volume' +numid=34,iface=MIXER,name='Ana Playback Volume',index=1 +numid=35,iface=MIXER,name='Ana Playback Volume',index=2 +numid=36,iface=MIXER,name='Ana Playback Volume',index=3 +numid=37,iface=MIXER,name='Ana Playback Volume',index=4 +numid=38,iface=MIXER,name='Ana Playback Volume',index=5 +numid=39,iface=MIXER,name='Ana Playback Volume',index=6 +numid=40,iface=MIXER,name='Ana Playback Volume',index=7 +numid=1090,iface=MIXER,name='Clk Eff' +numid=1089,iface=MIXER,name='Clk Eff Src' +numid=1094,iface=MIXER,name='Clk P0' +numid=1095,iface=MIXER,name='Clk P1' +numid=1096,iface=MIXER,name='Clk P2' +numid=1097,iface=MIXER,name='Clk P3' +numid=1093,iface=MIXER,name='Clk Src Down' +numid=1092,iface=MIXER,name='Clk Src Up' +numid=1102,iface=MIXER,name='Codec Analog Capture Volume' +numid=1103,iface=MIXER,name='Codec Analog Capture Volume',index=1 +numid=1104,iface=MIXER,name='Codec Analog Capture Volume',index=2 +numid=1105,iface=MIXER,name='Codec Analog Capture Volume',index=3 +numid=1106,iface=MIXER,name='Codec Analog Capture Volume',index=4 +numid=1107,iface=MIXER,name='Codec Analog Capture Volume',index=5 +numid=1108,iface=MIXER,name='Codec Analog Capture Volume',index=6 +numid=1109,iface=MIXER,name='Codec Analog Capture Volume',index=7 +numid=1,iface=MIXER,name='DAW Capture Volume' +numid=2,iface=MIXER,name='DAW Capture Volume',index=1 +numid=3,iface=MIXER,name='DAW Capture Volume',index=2 +numid=4,iface=MIXER,name='DAW Capture Volume',index=3 +numid=5,iface=MIXER,name='DAW Capture Volume',index=4 +numid=6,iface=MIXER,name='DAW Capture Volume',index=5 +numid=7,iface=MIXER,name='DAW Capture Volume',index=6 +numid=8,iface=MIXER,name='DAW Capture Volume',index=7 +numid=9,iface=MIXER,name='DAW Capture Volume',index=8 +numid=10,iface=MIXER,name='DAW Capture Volume',index=9 +numid=11,iface=MIXER,name='DAW Capture Volume',index=10 +numid=12,iface=MIXER,name='DAW Capture Volume',index=11 +numid=13,iface=MIXER,name='DAW Capture Volume',index=12 +numid=14,iface=MIXER,name='DAW Capture Volume',index=13 +numid=15,iface=MIXER,name='DAW Capture Volume',index=14 +numid=16,iface=MIXER,name='DAW Capture Volume',index=15 +numid=49,iface=MIXER,name='DAW Playback Volume' +numid=50,iface=MIXER,name='DAW Playback Volume',index=1 +numid=51,iface=MIXER,name='DAW Playback Volume',index=2 +numid=52,iface=MIXER,name='DAW Playback Volume',index=3 +numid=53,iface=MIXER,name='DAW Playback Volume',index=4 +numid=54,iface=MIXER,name='DAW Playback Volume',index=5 +numid=55,iface=MIXER,name='DAW Playback Volume',index=6 +numid=56,iface=MIXER,name='DAW Playback Volume',index=7 +numid=57,iface=MIXER,name='DAW Playback Volume',index=8 +numid=58,iface=MIXER,name='DAW Playback Volume',index=9 +numid=59,iface=MIXER,name='DAW Playback Volume',index=10 +numid=60,iface=MIXER,name='DAW Playback Volume',index=11 +numid=61,iface=MIXER,name='DAW Playback Volume',index=12 +numid=62,iface=MIXER,name='DAW Playback Volume',index=13 +numid=63,iface=MIXER,name='DAW Playback Volume',index=14 +numid=64,iface=MIXER,name='DAW Playback Volume',index=15 +numid=65,iface=MIXER,name='Mxr 0/0 Playback Volume' +numid=97,iface=MIXER,name='Mxr 0/1 Playback Volume' +numid=385,iface=MIXER,name='Mxr 0/10 Playback Volume' +numid=417,iface=MIXER,name='Mxr 0/11 Playback Volume' +numid=449,iface=MIXER,name='Mxr 0/12 Playback Volume' +numid=481,iface=MIXER,name='Mxr 0/13 Playback Volume' +numid=513,iface=MIXER,name='Mxr 0/14 Playback Volume' +numid=545,iface=MIXER,name='Mxr 0/15 Playback Volume' +numid=577,iface=MIXER,name='Mxr 0/16 Playback Volume' +numid=609,iface=MIXER,name='Mxr 0/17 Playback Volume' +numid=641,iface=MIXER,name='Mxr 0/18 Playback Volume' +numid=673,iface=MIXER,name='Mxr 0/19 Playback Volume' +numid=129,iface=MIXER,name='Mxr 0/2 Playback Volume' +numid=705,iface=MIXER,name='Mxr 0/20 Playback Volume' +numid=737,iface=MIXER,name='Mxr 0/21 Playback Volume' +numid=769,iface=MIXER,name='Mxr 0/22 Playback Volume' +numid=801,iface=MIXER,name='Mxr 0/23 Playback Volume' +numid=833,iface=MIXER,name='Mxr 0/24 Playback Volume' +numid=865,iface=MIXER,name='Mxr 0/25 Playback Volume' +numid=897,iface=MIXER,name='Mxr 0/26 Playback Volume' +numid=929,iface=MIXER,name='Mxr 0/27 Playback Volume' +numid=961,iface=MIXER,name='Mxr 0/28 Playback Volume' +numid=993,iface=MIXER,name='Mxr 0/29 Playback Volume' +numid=161,iface=MIXER,name='Mxr 0/3 Playback Volume' +numid=1025,iface=MIXER,name='Mxr 0/30 Playback Volume' +numid=1057,iface=MIXER,name='Mxr 0/31 Playback Volume' +numid=193,iface=MIXER,name='Mxr 0/4 Playback Volume' +numid=225,iface=MIXER,name='Mxr 0/5 Playback Volume' +numid=257,iface=MIXER,name='Mxr 0/6 Playback Volume' +numid=289,iface=MIXER,name='Mxr 0/7 Playback Volume' +numid=321,iface=MIXER,name='Mxr 0/8 Playback Volume' +numid=353,iface=MIXER,name='Mxr 0/9 Playback Volume' +numid=66,iface=MIXER,name='Mxr 1/0 Playback Volume' +numid=98,iface=MIXER,name='Mxr 1/1 Playback Volume' +numid=386,iface=MIXER,name='Mxr 1/10 Playback Volume' +numid=418,iface=MIXER,name='Mxr 1/11 Playback Volume' +numid=450,iface=MIXER,name='Mxr 1/12 Playback Volume' +numid=482,iface=MIXER,name='Mxr 1/13 Playback Volume' +numid=514,iface=MIXER,name='Mxr 1/14 Playback Volume' +numid=546,iface=MIXER,name='Mxr 1/15 Playback Volume' +numid=578,iface=MIXER,name='Mxr 1/16 Playback Volume' +numid=610,iface=MIXER,name='Mxr 1/17 Playback Volume' +numid=642,iface=MIXER,name='Mxr 1/18 Playback Volume' +numid=674,iface=MIXER,name='Mxr 1/19 Playback Volume' +numid=130,iface=MIXER,name='Mxr 1/2 Playback Volume' +numid=706,iface=MIXER,name='Mxr 1/20 Playback Volume' +numid=738,iface=MIXER,name='Mxr 1/21 Playback Volume' +numid=770,iface=MIXER,name='Mxr 1/22 Playback Volume' +numid=802,iface=MIXER,name='Mxr 1/23 Playback Volume' +numid=834,iface=MIXER,name='Mxr 1/24 Playback Volume' +numid=866,iface=MIXER,name='Mxr 1/25 Playback Volume' +numid=898,iface=MIXER,name='Mxr 1/26 Playback Volume' +numid=930,iface=MIXER,name='Mxr 1/27 Playback Volume' +numid=962,iface=MIXER,name='Mxr 1/28 Playback Volume' +numid=994,iface=MIXER,name='Mxr 1/29 Playback Volume' +numid=162,iface=MIXER,name='Mxr 1/3 Playback Volume' +numid=1026,iface=MIXER,name='Mxr 1/30 Playback Volume' +numid=1058,iface=MIXER,name='Mxr 1/31 Playback Volume' +numid=194,iface=MIXER,name='Mxr 1/4 Playback Volume' +numid=226,iface=MIXER,name='Mxr 1/5 Playback Volume' +numid=258,iface=MIXER,name='Mxr 1/6 Playback Volume' +numid=290,iface=MIXER,name='Mxr 1/7 Playback Volume' +numid=322,iface=MIXER,name='Mxr 1/8 Playback Volume' +numid=354,iface=MIXER,name='Mxr 1/9 Playback Volume' +numid=75,iface=MIXER,name='Mxr 10/0 Playback Volume' +numid=107,iface=MIXER,name='Mxr 10/1 Playback Volume' +numid=395,iface=MIXER,name='Mxr 10/10 Playback Volume' +numid=427,iface=MIXER,name='Mxr 10/11 Playback Volume' +numid=459,iface=MIXER,name='Mxr 10/12 Playback Volume' +numid=491,iface=MIXER,name='Mxr 10/13 Playback Volume' +numid=523,iface=MIXER,name='Mxr 10/14 Playback Volume' +numid=555,iface=MIXER,name='Mxr 10/15 Playback Volume' +numid=587,iface=MIXER,name='Mxr 10/16 Playback Volume' +numid=619,iface=MIXER,name='Mxr 10/17 Playback Volume' +numid=651,iface=MIXER,name='Mxr 10/18 Playback Volume' +numid=683,iface=MIXER,name='Mxr 10/19 Playback Volume' +numid=139,iface=MIXER,name='Mxr 10/2 Playback Volume' +numid=715,iface=MIXER,name='Mxr 10/20 Playback Volume' +numid=747,iface=MIXER,name='Mxr 10/21 Playback Volume' +numid=779,iface=MIXER,name='Mxr 10/22 Playback Volume' +numid=811,iface=MIXER,name='Mxr 10/23 Playback Volume' +numid=843,iface=MIXER,name='Mxr 10/24 Playback Volume' +numid=875,iface=MIXER,name='Mxr 10/25 Playback Volume' +numid=907,iface=MIXER,name='Mxr 10/26 Playback Volume' +numid=939,iface=MIXER,name='Mxr 10/27 Playback Volume' +numid=971,iface=MIXER,name='Mxr 10/28 Playback Volume' +numid=1003,iface=MIXER,name='Mxr 10/29 Playback Volume' +numid=171,iface=MIXER,name='Mxr 10/3 Playback Volume' +numid=1035,iface=MIXER,name='Mxr 10/30 Playback Volume' +numid=1067,iface=MIXER,name='Mxr 10/31 Playback Volume' +numid=203,iface=MIXER,name='Mxr 10/4 Playback Volume' +numid=235,iface=MIXER,name='Mxr 10/5 Playback Volume' +numid=267,iface=MIXER,name='Mxr 10/6 Playback Volume' +numid=299,iface=MIXER,name='Mxr 10/7 Playback Volume' +numid=331,iface=MIXER,name='Mxr 10/8 Playback Volume' +numid=363,iface=MIXER,name='Mxr 10/9 Playback Volume' +numid=76,iface=MIXER,name='Mxr 11/0 Playback Volume' +numid=108,iface=MIXER,name='Mxr 11/1 Playback Volume' +numid=396,iface=MIXER,name='Mxr 11/10 Playback Volume' +numid=428,iface=MIXER,name='Mxr 11/11 Playback Volume' +numid=460,iface=MIXER,name='Mxr 11/12 Playback Volume' +numid=492,iface=MIXER,name='Mxr 11/13 Playback Volume' +numid=524,iface=MIXER,name='Mxr 11/14 Playback Volume' +numid=556,iface=MIXER,name='Mxr 11/15 Playback Volume' +numid=588,iface=MIXER,name='Mxr 11/16 Playback Volume' +numid=620,iface=MIXER,name='Mxr 11/17 Playback Volume' +numid=652,iface=MIXER,name='Mxr 11/18 Playback Volume' +numid=684,iface=MIXER,name='Mxr 11/19 Playback Volume' +numid=140,iface=MIXER,name='Mxr 11/2 Playback Volume' +numid=716,iface=MIXER,name='Mxr 11/20 Playback Volume' +numid=748,iface=MIXER,name='Mxr 11/21 Playback Volume' +numid=780,iface=MIXER,name='Mxr 11/22 Playback Volume' +numid=812,iface=MIXER,name='Mxr 11/23 Playback Volume' +numid=844,iface=MIXER,name='Mxr 11/24 Playback Volume' +numid=876,iface=MIXER,name='Mxr 11/25 Playback Volume' +numid=908,iface=MIXER,name='Mxr 11/26 Playback Volume' +numid=940,iface=MIXER,name='Mxr 11/27 Playback Volume' +numid=972,iface=MIXER,name='Mxr 11/28 Playback Volume' +numid=1004,iface=MIXER,name='Mxr 11/29 Playback Volume' +numid=172,iface=MIXER,name='Mxr 11/3 Playback Volume' +numid=1036,iface=MIXER,name='Mxr 11/30 Playback Volume' +numid=1068,iface=MIXER,name='Mxr 11/31 Playback Volume' +numid=204,iface=MIXER,name='Mxr 11/4 Playback Volume' +numid=236,iface=MIXER,name='Mxr 11/5 Playback Volume' +numid=268,iface=MIXER,name='Mxr 11/6 Playback Volume' +numid=300,iface=MIXER,name='Mxr 11/7 Playback Volume' +numid=332,iface=MIXER,name='Mxr 11/8 Playback Volume' +numid=364,iface=MIXER,name='Mxr 11/9 Playback Volume' +numid=77,iface=MIXER,name='Mxr 12/0 Playback Volume' +numid=109,iface=MIXER,name='Mxr 12/1 Playback Volume' +numid=397,iface=MIXER,name='Mxr 12/10 Playback Volume' +numid=429,iface=MIXER,name='Mxr 12/11 Playback Volume' +numid=461,iface=MIXER,name='Mxr 12/12 Playback Volume' +numid=493,iface=MIXER,name='Mxr 12/13 Playback Volume' +numid=525,iface=MIXER,name='Mxr 12/14 Playback Volume' +numid=557,iface=MIXER,name='Mxr 12/15 Playback Volume' +numid=589,iface=MIXER,name='Mxr 12/16 Playback Volume' +numid=621,iface=MIXER,name='Mxr 12/17 Playback Volume' +numid=653,iface=MIXER,name='Mxr 12/18 Playback Volume' +numid=685,iface=MIXER,name='Mxr 12/19 Playback Volume' +numid=141,iface=MIXER,name='Mxr 12/2 Playback Volume' +numid=717,iface=MIXER,name='Mxr 12/20 Playback Volume' +numid=749,iface=MIXER,name='Mxr 12/21 Playback Volume' +numid=781,iface=MIXER,name='Mxr 12/22 Playback Volume' +numid=813,iface=MIXER,name='Mxr 12/23 Playback Volume' +numid=845,iface=MIXER,name='Mxr 12/24 Playback Volume' +numid=877,iface=MIXER,name='Mxr 12/25 Playback Volume' +numid=909,iface=MIXER,name='Mxr 12/26 Playback Volume' +numid=941,iface=MIXER,name='Mxr 12/27 Playback Volume' +numid=973,iface=MIXER,name='Mxr 12/28 Playback Volume' +numid=1005,iface=MIXER,name='Mxr 12/29 Playback Volume' +numid=173,iface=MIXER,name='Mxr 12/3 Playback Volume' +numid=1037,iface=MIXER,name='Mxr 12/30 Playback Volume' +numid=1069,iface=MIXER,name='Mxr 12/31 Playback Volume' +numid=205,iface=MIXER,name='Mxr 12/4 Playback Volume' +numid=237,iface=MIXER,name='Mxr 12/5 Playback Volume' +numid=269,iface=MIXER,name='Mxr 12/6 Playback Volume' +numid=301,iface=MIXER,name='Mxr 12/7 Playback Volume' +numid=333,iface=MIXER,name='Mxr 12/8 Playback Volume' +numid=365,iface=MIXER,name='Mxr 12/9 Playback Volume' +numid=78,iface=MIXER,name='Mxr 13/0 Playback Volume' +numid=110,iface=MIXER,name='Mxr 13/1 Playback Volume' +numid=398,iface=MIXER,name='Mxr 13/10 Playback Volume' +numid=430,iface=MIXER,name='Mxr 13/11 Playback Volume' +numid=462,iface=MIXER,name='Mxr 13/12 Playback Volume' +numid=494,iface=MIXER,name='Mxr 13/13 Playback Volume' +numid=526,iface=MIXER,name='Mxr 13/14 Playback Volume' +numid=558,iface=MIXER,name='Mxr 13/15 Playback Volume' +numid=590,iface=MIXER,name='Mxr 13/16 Playback Volume' +numid=622,iface=MIXER,name='Mxr 13/17 Playback Volume' +numid=654,iface=MIXER,name='Mxr 13/18 Playback Volume' +numid=686,iface=MIXER,name='Mxr 13/19 Playback Volume' +numid=142,iface=MIXER,name='Mxr 13/2 Playback Volume' +numid=718,iface=MIXER,name='Mxr 13/20 Playback Volume' +numid=750,iface=MIXER,name='Mxr 13/21 Playback Volume' +numid=782,iface=MIXER,name='Mxr 13/22 Playback Volume' +numid=814,iface=MIXER,name='Mxr 13/23 Playback Volume' +numid=846,iface=MIXER,name='Mxr 13/24 Playback Volume' +numid=878,iface=MIXER,name='Mxr 13/25 Playback Volume' +numid=910,iface=MIXER,name='Mxr 13/26 Playback Volume' +numid=942,iface=MIXER,name='Mxr 13/27 Playback Volume' +numid=974,iface=MIXER,name='Mxr 13/28 Playback Volume' +numid=1006,iface=MIXER,name='Mxr 13/29 Playback Volume' +numid=174,iface=MIXER,name='Mxr 13/3 Playback Volume' +numid=1038,iface=MIXER,name='Mxr 13/30 Playback Volume' +numid=1070,iface=MIXER,name='Mxr 13/31 Playback Volume' +numid=206,iface=MIXER,name='Mxr 13/4 Playback Volume' +numid=238,iface=MIXER,name='Mxr 13/5 Playback Volume' +numid=270,iface=MIXER,name='Mxr 13/6 Playback Volume' +numid=302,iface=MIXER,name='Mxr 13/7 Playback Volume' +numid=334,iface=MIXER,name='Mxr 13/8 Playback Volume' +numid=366,iface=MIXER,name='Mxr 13/9 Playback Volume' +numid=79,iface=MIXER,name='Mxr 14/0 Playback Volume' +numid=111,iface=MIXER,name='Mxr 14/1 Playback Volume' +numid=399,iface=MIXER,name='Mxr 14/10 Playback Volume' +numid=431,iface=MIXER,name='Mxr 14/11 Playback Volume' +numid=463,iface=MIXER,name='Mxr 14/12 Playback Volume' +numid=495,iface=MIXER,name='Mxr 14/13 Playback Volume' +numid=527,iface=MIXER,name='Mxr 14/14 Playback Volume' +numid=559,iface=MIXER,name='Mxr 14/15 Playback Volume' +numid=591,iface=MIXER,name='Mxr 14/16 Playback Volume' +numid=623,iface=MIXER,name='Mxr 14/17 Playback Volume' +numid=655,iface=MIXER,name='Mxr 14/18 Playback Volume' +numid=687,iface=MIXER,name='Mxr 14/19 Playback Volume' +numid=143,iface=MIXER,name='Mxr 14/2 Playback Volume' +numid=719,iface=MIXER,name='Mxr 14/20 Playback Volume' +numid=751,iface=MIXER,name='Mxr 14/21 Playback Volume' +numid=783,iface=MIXER,name='Mxr 14/22 Playback Volume' +numid=815,iface=MIXER,name='Mxr 14/23 Playback Volume' +numid=847,iface=MIXER,name='Mxr 14/24 Playback Volume' +numid=879,iface=MIXER,name='Mxr 14/25 Playback Volume' +numid=911,iface=MIXER,name='Mxr 14/26 Playback Volume' +numid=943,iface=MIXER,name='Mxr 14/27 Playback Volume' +numid=975,iface=MIXER,name='Mxr 14/28 Playback Volume' +numid=1007,iface=MIXER,name='Mxr 14/29 Playback Volume' +numid=175,iface=MIXER,name='Mxr 14/3 Playback Volume' +numid=1039,iface=MIXER,name='Mxr 14/30 Playback Volume' +numid=1071,iface=MIXER,name='Mxr 14/31 Playback Volume' +numid=207,iface=MIXER,name='Mxr 14/4 Playback Volume' +numid=239,iface=MIXER,name='Mxr 14/5 Playback Volume' +numid=271,iface=MIXER,name='Mxr 14/6 Playback Volume' +numid=303,iface=MIXER,name='Mxr 14/7 Playback Volume' +numid=335,iface=MIXER,name='Mxr 14/8 Playback Volume' +numid=367,iface=MIXER,name='Mxr 14/9 Playback Volume' +numid=80,iface=MIXER,name='Mxr 15/0 Playback Volume' +numid=112,iface=MIXER,name='Mxr 15/1 Playback Volume' +numid=400,iface=MIXER,name='Mxr 15/10 Playback Volume' +numid=432,iface=MIXER,name='Mxr 15/11 Playback Volume' +numid=464,iface=MIXER,name='Mxr 15/12 Playback Volume' +numid=496,iface=MIXER,name='Mxr 15/13 Playback Volume' +numid=528,iface=MIXER,name='Mxr 15/14 Playback Volume' +numid=560,iface=MIXER,name='Mxr 15/15 Playback Volume' +numid=592,iface=MIXER,name='Mxr 15/16 Playback Volume' +numid=624,iface=MIXER,name='Mxr 15/17 Playback Volume' +numid=656,iface=MIXER,name='Mxr 15/18 Playback Volume' +numid=688,iface=MIXER,name='Mxr 15/19 Playback Volume' +numid=144,iface=MIXER,name='Mxr 15/2 Playback Volume' +numid=720,iface=MIXER,name='Mxr 15/20 Playback Volume' +numid=752,iface=MIXER,name='Mxr 15/21 Playback Volume' +numid=784,iface=MIXER,name='Mxr 15/22 Playback Volume' +numid=816,iface=MIXER,name='Mxr 15/23 Playback Volume' +numid=848,iface=MIXER,name='Mxr 15/24 Playback Volume' +numid=880,iface=MIXER,name='Mxr 15/25 Playback Volume' +numid=912,iface=MIXER,name='Mxr 15/26 Playback Volume' +numid=944,iface=MIXER,name='Mxr 15/27 Playback Volume' +numid=976,iface=MIXER,name='Mxr 15/28 Playback Volume' +numid=1008,iface=MIXER,name='Mxr 15/29 Playback Volume' +numid=176,iface=MIXER,name='Mxr 15/3 Playback Volume' +numid=1040,iface=MIXER,name='Mxr 15/30 Playback Volume' +numid=1072,iface=MIXER,name='Mxr 15/31 Playback Volume' +numid=208,iface=MIXER,name='Mxr 15/4 Playback Volume' +numid=240,iface=MIXER,name='Mxr 15/5 Playback Volume' +numid=272,iface=MIXER,name='Mxr 15/6 Playback Volume' +numid=304,iface=MIXER,name='Mxr 15/7 Playback Volume' +numid=336,iface=MIXER,name='Mxr 15/8 Playback Volume' +numid=368,iface=MIXER,name='Mxr 15/9 Playback Volume' +numid=81,iface=MIXER,name='Mxr 16/0 Playback Volume' +numid=113,iface=MIXER,name='Mxr 16/1 Playback Volume' +numid=401,iface=MIXER,name='Mxr 16/10 Playback Volume' +numid=433,iface=MIXER,name='Mxr 16/11 Playback Volume' +numid=465,iface=MIXER,name='Mxr 16/12 Playback Volume' +numid=497,iface=MIXER,name='Mxr 16/13 Playback Volume' +numid=529,iface=MIXER,name='Mxr 16/14 Playback Volume' +numid=561,iface=MIXER,name='Mxr 16/15 Playback Volume' +numid=593,iface=MIXER,name='Mxr 16/16 Playback Volume' +numid=625,iface=MIXER,name='Mxr 16/17 Playback Volume' +numid=657,iface=MIXER,name='Mxr 16/18 Playback Volume' +numid=689,iface=MIXER,name='Mxr 16/19 Playback Volume' +numid=145,iface=MIXER,name='Mxr 16/2 Playback Volume' +numid=721,iface=MIXER,name='Mxr 16/20 Playback Volume' +numid=753,iface=MIXER,name='Mxr 16/21 Playback Volume' +numid=785,iface=MIXER,name='Mxr 16/22 Playback Volume' +numid=817,iface=MIXER,name='Mxr 16/23 Playback Volume' +numid=849,iface=MIXER,name='Mxr 16/24 Playback Volume' +numid=881,iface=MIXER,name='Mxr 16/25 Playback Volume' +numid=913,iface=MIXER,name='Mxr 16/26 Playback Volume' +numid=945,iface=MIXER,name='Mxr 16/27 Playback Volume' +numid=977,iface=MIXER,name='Mxr 16/28 Playback Volume' +numid=1009,iface=MIXER,name='Mxr 16/29 Playback Volume' +numid=177,iface=MIXER,name='Mxr 16/3 Playback Volume' +numid=1041,iface=MIXER,name='Mxr 16/30 Playback Volume' +numid=1073,iface=MIXER,name='Mxr 16/31 Playback Volume' +numid=209,iface=MIXER,name='Mxr 16/4 Playback Volume' +numid=241,iface=MIXER,name='Mxr 16/5 Playback Volume' +numid=273,iface=MIXER,name='Mxr 16/6 Playback Volume' +numid=305,iface=MIXER,name='Mxr 16/7 Playback Volume' +numid=337,iface=MIXER,name='Mxr 16/8 Playback Volume' +numid=369,iface=MIXER,name='Mxr 16/9 Playback Volume' +numid=82,iface=MIXER,name='Mxr 17/0 Playback Volume' +numid=114,iface=MIXER,name='Mxr 17/1 Playback Volume' +numid=402,iface=MIXER,name='Mxr 17/10 Playback Volume' +numid=434,iface=MIXER,name='Mxr 17/11 Playback Volume' +numid=466,iface=MIXER,name='Mxr 17/12 Playback Volume' +numid=498,iface=MIXER,name='Mxr 17/13 Playback Volume' +numid=530,iface=MIXER,name='Mxr 17/14 Playback Volume' +numid=562,iface=MIXER,name='Mxr 17/15 Playback Volume' +numid=594,iface=MIXER,name='Mxr 17/16 Playback Volume' +numid=626,iface=MIXER,name='Mxr 17/17 Playback Volume' +numid=658,iface=MIXER,name='Mxr 17/18 Playback Volume' +numid=690,iface=MIXER,name='Mxr 17/19 Playback Volume' +numid=146,iface=MIXER,name='Mxr 17/2 Playback Volume' +numid=722,iface=MIXER,name='Mxr 17/20 Playback Volume' +numid=754,iface=MIXER,name='Mxr 17/21 Playback Volume' +numid=786,iface=MIXER,name='Mxr 17/22 Playback Volume' +numid=818,iface=MIXER,name='Mxr 17/23 Playback Volume' +numid=850,iface=MIXER,name='Mxr 17/24 Playback Volume' +numid=882,iface=MIXER,name='Mxr 17/25 Playback Volume' +numid=914,iface=MIXER,name='Mxr 17/26 Playback Volume' +numid=946,iface=MIXER,name='Mxr 17/27 Playback Volume' +numid=978,iface=MIXER,name='Mxr 17/28 Playback Volume' +numid=1010,iface=MIXER,name='Mxr 17/29 Playback Volume' +numid=178,iface=MIXER,name='Mxr 17/3 Playback Volume' +numid=1042,iface=MIXER,name='Mxr 17/30 Playback Volume' +numid=1074,iface=MIXER,name='Mxr 17/31 Playback Volume' +numid=210,iface=MIXER,name='Mxr 17/4 Playback Volume' +numid=242,iface=MIXER,name='Mxr 17/5 Playback Volume' +numid=274,iface=MIXER,name='Mxr 17/6 Playback Volume' +numid=306,iface=MIXER,name='Mxr 17/7 Playback Volume' +numid=338,iface=MIXER,name='Mxr 17/8 Playback Volume' +numid=370,iface=MIXER,name='Mxr 17/9 Playback Volume' +numid=83,iface=MIXER,name='Mxr 18/0 Playback Volume' +numid=115,iface=MIXER,name='Mxr 18/1 Playback Volume' +numid=403,iface=MIXER,name='Mxr 18/10 Playback Volume' +numid=435,iface=MIXER,name='Mxr 18/11 Playback Volume' +numid=467,iface=MIXER,name='Mxr 18/12 Playback Volume' +numid=499,iface=MIXER,name='Mxr 18/13 Playback Volume' +numid=531,iface=MIXER,name='Mxr 18/14 Playback Volume' +numid=563,iface=MIXER,name='Mxr 18/15 Playback Volume' +numid=595,iface=MIXER,name='Mxr 18/16 Playback Volume' +numid=627,iface=MIXER,name='Mxr 18/17 Playback Volume' +numid=659,iface=MIXER,name='Mxr 18/18 Playback Volume' +numid=691,iface=MIXER,name='Mxr 18/19 Playback Volume' +numid=147,iface=MIXER,name='Mxr 18/2 Playback Volume' +numid=723,iface=MIXER,name='Mxr 18/20 Playback Volume' +numid=755,iface=MIXER,name='Mxr 18/21 Playback Volume' +numid=787,iface=MIXER,name='Mxr 18/22 Playback Volume' +numid=819,iface=MIXER,name='Mxr 18/23 Playback Volume' +numid=851,iface=MIXER,name='Mxr 18/24 Playback Volume' +numid=883,iface=MIXER,name='Mxr 18/25 Playback Volume' +numid=915,iface=MIXER,name='Mxr 18/26 Playback Volume' +numid=947,iface=MIXER,name='Mxr 18/27 Playback Volume' +numid=979,iface=MIXER,name='Mxr 18/28 Playback Volume' +numid=1011,iface=MIXER,name='Mxr 18/29 Playback Volume' +numid=179,iface=MIXER,name='Mxr 18/3 Playback Volume' +numid=1043,iface=MIXER,name='Mxr 18/30 Playback Volume' +numid=1075,iface=MIXER,name='Mxr 18/31 Playback Volume' +numid=211,iface=MIXER,name='Mxr 18/4 Playback Volume' +numid=243,iface=MIXER,name='Mxr 18/5 Playback Volume' +numid=275,iface=MIXER,name='Mxr 18/6 Playback Volume' +numid=307,iface=MIXER,name='Mxr 18/7 Playback Volume' +numid=339,iface=MIXER,name='Mxr 18/8 Playback Volume' +numid=371,iface=MIXER,name='Mxr 18/9 Playback Volume' +numid=84,iface=MIXER,name='Mxr 19/0 Playback Volume' +numid=116,iface=MIXER,name='Mxr 19/1 Playback Volume' +numid=404,iface=MIXER,name='Mxr 19/10 Playback Volume' +numid=436,iface=MIXER,name='Mxr 19/11 Playback Volume' +numid=468,iface=MIXER,name='Mxr 19/12 Playback Volume' +numid=500,iface=MIXER,name='Mxr 19/13 Playback Volume' +numid=532,iface=MIXER,name='Mxr 19/14 Playback Volume' +numid=564,iface=MIXER,name='Mxr 19/15 Playback Volume' +numid=596,iface=MIXER,name='Mxr 19/16 Playback Volume' +numid=628,iface=MIXER,name='Mxr 19/17 Playback Volume' +numid=660,iface=MIXER,name='Mxr 19/18 Playback Volume' +numid=692,iface=MIXER,name='Mxr 19/19 Playback Volume' +numid=148,iface=MIXER,name='Mxr 19/2 Playback Volume' +numid=724,iface=MIXER,name='Mxr 19/20 Playback Volume' +numid=756,iface=MIXER,name='Mxr 19/21 Playback Volume' +numid=788,iface=MIXER,name='Mxr 19/22 Playback Volume' +numid=820,iface=MIXER,name='Mxr 19/23 Playback Volume' +numid=852,iface=MIXER,name='Mxr 19/24 Playback Volume' +numid=884,iface=MIXER,name='Mxr 19/25 Playback Volume' +numid=916,iface=MIXER,name='Mxr 19/26 Playback Volume' +numid=948,iface=MIXER,name='Mxr 19/27 Playback Volume' +numid=980,iface=MIXER,name='Mxr 19/28 Playback Volume' +numid=1012,iface=MIXER,name='Mxr 19/29 Playback Volume' +numid=180,iface=MIXER,name='Mxr 19/3 Playback Volume' +numid=1044,iface=MIXER,name='Mxr 19/30 Playback Volume' +numid=1076,iface=MIXER,name='Mxr 19/31 Playback Volume' +numid=212,iface=MIXER,name='Mxr 19/4 Playback Volume' +numid=244,iface=MIXER,name='Mxr 19/5 Playback Volume' +numid=276,iface=MIXER,name='Mxr 19/6 Playback Volume' +numid=308,iface=MIXER,name='Mxr 19/7 Playback Volume' +numid=340,iface=MIXER,name='Mxr 19/8 Playback Volume' +numid=372,iface=MIXER,name='Mxr 19/9 Playback Volume' +numid=67,iface=MIXER,name='Mxr 2/0 Playback Volume' +numid=99,iface=MIXER,name='Mxr 2/1 Playback Volume' +numid=387,iface=MIXER,name='Mxr 2/10 Playback Volume' +numid=419,iface=MIXER,name='Mxr 2/11 Playback Volume' +numid=451,iface=MIXER,name='Mxr 2/12 Playback Volume' +numid=483,iface=MIXER,name='Mxr 2/13 Playback Volume' +numid=515,iface=MIXER,name='Mxr 2/14 Playback Volume' +numid=547,iface=MIXER,name='Mxr 2/15 Playback Volume' +numid=579,iface=MIXER,name='Mxr 2/16 Playback Volume' +numid=611,iface=MIXER,name='Mxr 2/17 Playback Volume' +numid=643,iface=MIXER,name='Mxr 2/18 Playback Volume' +numid=675,iface=MIXER,name='Mxr 2/19 Playback Volume' +numid=131,iface=MIXER,name='Mxr 2/2 Playback Volume' +numid=707,iface=MIXER,name='Mxr 2/20 Playback Volume' +numid=739,iface=MIXER,name='Mxr 2/21 Playback Volume' +numid=771,iface=MIXER,name='Mxr 2/22 Playback Volume' +numid=803,iface=MIXER,name='Mxr 2/23 Playback Volume' +numid=835,iface=MIXER,name='Mxr 2/24 Playback Volume' +numid=867,iface=MIXER,name='Mxr 2/25 Playback Volume' +numid=899,iface=MIXER,name='Mxr 2/26 Playback Volume' +numid=931,iface=MIXER,name='Mxr 2/27 Playback Volume' +numid=963,iface=MIXER,name='Mxr 2/28 Playback Volume' +numid=995,iface=MIXER,name='Mxr 2/29 Playback Volume' +numid=163,iface=MIXER,name='Mxr 2/3 Playback Volume' +numid=1027,iface=MIXER,name='Mxr 2/30 Playback Volume' +numid=1059,iface=MIXER,name='Mxr 2/31 Playback Volume' +numid=195,iface=MIXER,name='Mxr 2/4 Playback Volume' +numid=227,iface=MIXER,name='Mxr 2/5 Playback Volume' +numid=259,iface=MIXER,name='Mxr 2/6 Playback Volume' +numid=291,iface=MIXER,name='Mxr 2/7 Playback Volume' +numid=323,iface=MIXER,name='Mxr 2/8 Playback Volume' +numid=355,iface=MIXER,name='Mxr 2/9 Playback Volume' +numid=85,iface=MIXER,name='Mxr 20/0 Playback Volume' +numid=117,iface=MIXER,name='Mxr 20/1 Playback Volume' +numid=405,iface=MIXER,name='Mxr 20/10 Playback Volume' +numid=437,iface=MIXER,name='Mxr 20/11 Playback Volume' +numid=469,iface=MIXER,name='Mxr 20/12 Playback Volume' +numid=501,iface=MIXER,name='Mxr 20/13 Playback Volume' +numid=533,iface=MIXER,name='Mxr 20/14 Playback Volume' +numid=565,iface=MIXER,name='Mxr 20/15 Playback Volume' +numid=597,iface=MIXER,name='Mxr 20/16 Playback Volume' +numid=629,iface=MIXER,name='Mxr 20/17 Playback Volume' +numid=661,iface=MIXER,name='Mxr 20/18 Playback Volume' +numid=693,iface=MIXER,name='Mxr 20/19 Playback Volume' +numid=149,iface=MIXER,name='Mxr 20/2 Playback Volume' +numid=725,iface=MIXER,name='Mxr 20/20 Playback Volume' +numid=757,iface=MIXER,name='Mxr 20/21 Playback Volume' +numid=789,iface=MIXER,name='Mxr 20/22 Playback Volume' +numid=821,iface=MIXER,name='Mxr 20/23 Playback Volume' +numid=853,iface=MIXER,name='Mxr 20/24 Playback Volume' +numid=885,iface=MIXER,name='Mxr 20/25 Playback Volume' +numid=917,iface=MIXER,name='Mxr 20/26 Playback Volume' +numid=949,iface=MIXER,name='Mxr 20/27 Playback Volume' +numid=981,iface=MIXER,name='Mxr 20/28 Playback Volume' +numid=1013,iface=MIXER,name='Mxr 20/29 Playback Volume' +numid=181,iface=MIXER,name='Mxr 20/3 Playback Volume' +numid=1045,iface=MIXER,name='Mxr 20/30 Playback Volume' +numid=1077,iface=MIXER,name='Mxr 20/31 Playback Volume' +numid=213,iface=MIXER,name='Mxr 20/4 Playback Volume' +numid=245,iface=MIXER,name='Mxr 20/5 Playback Volume' +numid=277,iface=MIXER,name='Mxr 20/6 Playback Volume' +numid=309,iface=MIXER,name='Mxr 20/7 Playback Volume' +numid=341,iface=MIXER,name='Mxr 20/8 Playback Volume' +numid=373,iface=MIXER,name='Mxr 20/9 Playback Volume' +numid=86,iface=MIXER,name='Mxr 21/0 Playback Volume' +numid=118,iface=MIXER,name='Mxr 21/1 Playback Volume' +numid=406,iface=MIXER,name='Mxr 21/10 Playback Volume' +numid=438,iface=MIXER,name='Mxr 21/11 Playback Volume' +numid=470,iface=MIXER,name='Mxr 21/12 Playback Volume' +numid=502,iface=MIXER,name='Mxr 21/13 Playback Volume' +numid=534,iface=MIXER,name='Mxr 21/14 Playback Volume' +numid=566,iface=MIXER,name='Mxr 21/15 Playback Volume' +numid=598,iface=MIXER,name='Mxr 21/16 Playback Volume' +numid=630,iface=MIXER,name='Mxr 21/17 Playback Volume' +numid=662,iface=MIXER,name='Mxr 21/18 Playback Volume' +numid=694,iface=MIXER,name='Mxr 21/19 Playback Volume' +numid=150,iface=MIXER,name='Mxr 21/2 Playback Volume' +numid=726,iface=MIXER,name='Mxr 21/20 Playback Volume' +numid=758,iface=MIXER,name='Mxr 21/21 Playback Volume' +numid=790,iface=MIXER,name='Mxr 21/22 Playback Volume' +numid=822,iface=MIXER,name='Mxr 21/23 Playback Volume' +numid=854,iface=MIXER,name='Mxr 21/24 Playback Volume' +numid=886,iface=MIXER,name='Mxr 21/25 Playback Volume' +numid=918,iface=MIXER,name='Mxr 21/26 Playback Volume' +numid=950,iface=MIXER,name='Mxr 21/27 Playback Volume' +numid=982,iface=MIXER,name='Mxr 21/28 Playback Volume' +numid=1014,iface=MIXER,name='Mxr 21/29 Playback Volume' +numid=182,iface=MIXER,name='Mxr 21/3 Playback Volume' +numid=1046,iface=MIXER,name='Mxr 21/30 Playback Volume' +numid=1078,iface=MIXER,name='Mxr 21/31 Playback Volume' +numid=214,iface=MIXER,name='Mxr 21/4 Playback Volume' +numid=246,iface=MIXER,name='Mxr 21/5 Playback Volume' +numid=278,iface=MIXER,name='Mxr 21/6 Playback Volume' +numid=310,iface=MIXER,name='Mxr 21/7 Playback Volume' +numid=342,iface=MIXER,name='Mxr 21/8 Playback Volume' +numid=374,iface=MIXER,name='Mxr 21/9 Playback Volume' +numid=87,iface=MIXER,name='Mxr 22/0 Playback Volume' +numid=119,iface=MIXER,name='Mxr 22/1 Playback Volume' +numid=407,iface=MIXER,name='Mxr 22/10 Playback Volume' +numid=439,iface=MIXER,name='Mxr 22/11 Playback Volume' +numid=471,iface=MIXER,name='Mxr 22/12 Playback Volume' +numid=503,iface=MIXER,name='Mxr 22/13 Playback Volume' +numid=535,iface=MIXER,name='Mxr 22/14 Playback Volume' +numid=567,iface=MIXER,name='Mxr 22/15 Playback Volume' +numid=599,iface=MIXER,name='Mxr 22/16 Playback Volume' +numid=631,iface=MIXER,name='Mxr 22/17 Playback Volume' +numid=663,iface=MIXER,name='Mxr 22/18 Playback Volume' +numid=695,iface=MIXER,name='Mxr 22/19 Playback Volume' +numid=151,iface=MIXER,name='Mxr 22/2 Playback Volume' +numid=727,iface=MIXER,name='Mxr 22/20 Playback Volume' +numid=759,iface=MIXER,name='Mxr 22/21 Playback Volume' +numid=791,iface=MIXER,name='Mxr 22/22 Playback Volume' +numid=823,iface=MIXER,name='Mxr 22/23 Playback Volume' +numid=855,iface=MIXER,name='Mxr 22/24 Playback Volume' +numid=887,iface=MIXER,name='Mxr 22/25 Playback Volume' +numid=919,iface=MIXER,name='Mxr 22/26 Playback Volume' +numid=951,iface=MIXER,name='Mxr 22/27 Playback Volume' +numid=983,iface=MIXER,name='Mxr 22/28 Playback Volume' +numid=1015,iface=MIXER,name='Mxr 22/29 Playback Volume' +numid=183,iface=MIXER,name='Mxr 22/3 Playback Volume' +numid=1047,iface=MIXER,name='Mxr 22/30 Playback Volume' +numid=1079,iface=MIXER,name='Mxr 22/31 Playback Volume' +numid=215,iface=MIXER,name='Mxr 22/4 Playback Volume' +numid=247,iface=MIXER,name='Mxr 22/5 Playback Volume' +numid=279,iface=MIXER,name='Mxr 22/6 Playback Volume' +numid=311,iface=MIXER,name='Mxr 22/7 Playback Volume' +numid=343,iface=MIXER,name='Mxr 22/8 Playback Volume' +numid=375,iface=MIXER,name='Mxr 22/9 Playback Volume' +numid=88,iface=MIXER,name='Mxr 23/0 Playback Volume' +numid=120,iface=MIXER,name='Mxr 23/1 Playback Volume' +numid=408,iface=MIXER,name='Mxr 23/10 Playback Volume' +numid=440,iface=MIXER,name='Mxr 23/11 Playback Volume' +numid=472,iface=MIXER,name='Mxr 23/12 Playback Volume' +numid=504,iface=MIXER,name='Mxr 23/13 Playback Volume' +numid=536,iface=MIXER,name='Mxr 23/14 Playback Volume' +numid=568,iface=MIXER,name='Mxr 23/15 Playback Volume' +numid=600,iface=MIXER,name='Mxr 23/16 Playback Volume' +numid=632,iface=MIXER,name='Mxr 23/17 Playback Volume' +numid=664,iface=MIXER,name='Mxr 23/18 Playback Volume' +numid=696,iface=MIXER,name='Mxr 23/19 Playback Volume' +numid=152,iface=MIXER,name='Mxr 23/2 Playback Volume' +numid=728,iface=MIXER,name='Mxr 23/20 Playback Volume' +numid=760,iface=MIXER,name='Mxr 23/21 Playback Volume' +numid=792,iface=MIXER,name='Mxr 23/22 Playback Volume' +numid=824,iface=MIXER,name='Mxr 23/23 Playback Volume' +numid=856,iface=MIXER,name='Mxr 23/24 Playback Volume' +numid=888,iface=MIXER,name='Mxr 23/25 Playback Volume' +numid=920,iface=MIXER,name='Mxr 23/26 Playback Volume' +numid=952,iface=MIXER,name='Mxr 23/27 Playback Volume' +numid=984,iface=MIXER,name='Mxr 23/28 Playback Volume' +numid=1016,iface=MIXER,name='Mxr 23/29 Playback Volume' +numid=184,iface=MIXER,name='Mxr 23/3 Playback Volume' +numid=1048,iface=MIXER,name='Mxr 23/30 Playback Volume' +numid=1080,iface=MIXER,name='Mxr 23/31 Playback Volume' +numid=216,iface=MIXER,name='Mxr 23/4 Playback Volume' +numid=248,iface=MIXER,name='Mxr 23/5 Playback Volume' +numid=280,iface=MIXER,name='Mxr 23/6 Playback Volume' +numid=312,iface=MIXER,name='Mxr 23/7 Playback Volume' +numid=344,iface=MIXER,name='Mxr 23/8 Playback Volume' +numid=376,iface=MIXER,name='Mxr 23/9 Playback Volume' +numid=89,iface=MIXER,name='Mxr 24/0 Playback Volume' +numid=121,iface=MIXER,name='Mxr 24/1 Playback Volume' +numid=409,iface=MIXER,name='Mxr 24/10 Playback Volume' +numid=441,iface=MIXER,name='Mxr 24/11 Playback Volume' +numid=473,iface=MIXER,name='Mxr 24/12 Playback Volume' +numid=505,iface=MIXER,name='Mxr 24/13 Playback Volume' +numid=537,iface=MIXER,name='Mxr 24/14 Playback Volume' +numid=569,iface=MIXER,name='Mxr 24/15 Playback Volume' +numid=601,iface=MIXER,name='Mxr 24/16 Playback Volume' +numid=633,iface=MIXER,name='Mxr 24/17 Playback Volume' +numid=665,iface=MIXER,name='Mxr 24/18 Playback Volume' +numid=697,iface=MIXER,name='Mxr 24/19 Playback Volume' +numid=153,iface=MIXER,name='Mxr 24/2 Playback Volume' +numid=729,iface=MIXER,name='Mxr 24/20 Playback Volume' +numid=761,iface=MIXER,name='Mxr 24/21 Playback Volume' +numid=793,iface=MIXER,name='Mxr 24/22 Playback Volume' +numid=825,iface=MIXER,name='Mxr 24/23 Playback Volume' +numid=857,iface=MIXER,name='Mxr 24/24 Playback Volume' +numid=889,iface=MIXER,name='Mxr 24/25 Playback Volume' +numid=921,iface=MIXER,name='Mxr 24/26 Playback Volume' +numid=953,iface=MIXER,name='Mxr 24/27 Playback Volume' +numid=985,iface=MIXER,name='Mxr 24/28 Playback Volume' +numid=1017,iface=MIXER,name='Mxr 24/29 Playback Volume' +numid=185,iface=MIXER,name='Mxr 24/3 Playback Volume' +numid=1049,iface=MIXER,name='Mxr 24/30 Playback Volume' +numid=1081,iface=MIXER,name='Mxr 24/31 Playback Volume' +numid=217,iface=MIXER,name='Mxr 24/4 Playback Volume' +numid=249,iface=MIXER,name='Mxr 24/5 Playback Volume' +numid=281,iface=MIXER,name='Mxr 24/6 Playback Volume' +numid=313,iface=MIXER,name='Mxr 24/7 Playback Volume' +numid=345,iface=MIXER,name='Mxr 24/8 Playback Volume' +numid=377,iface=MIXER,name='Mxr 24/9 Playback Volume' +numid=90,iface=MIXER,name='Mxr 25/0 Playback Volume' +numid=122,iface=MIXER,name='Mxr 25/1 Playback Volume' +numid=410,iface=MIXER,name='Mxr 25/10 Playback Volume' +numid=442,iface=MIXER,name='Mxr 25/11 Playback Volume' +numid=474,iface=MIXER,name='Mxr 25/12 Playback Volume' +numid=506,iface=MIXER,name='Mxr 25/13 Playback Volume' +numid=538,iface=MIXER,name='Mxr 25/14 Playback Volume' +numid=570,iface=MIXER,name='Mxr 25/15 Playback Volume' +numid=602,iface=MIXER,name='Mxr 25/16 Playback Volume' +numid=634,iface=MIXER,name='Mxr 25/17 Playback Volume' +numid=666,iface=MIXER,name='Mxr 25/18 Playback Volume' +numid=698,iface=MIXER,name='Mxr 25/19 Playback Volume' +numid=154,iface=MIXER,name='Mxr 25/2 Playback Volume' +numid=730,iface=MIXER,name='Mxr 25/20 Playback Volume' +numid=762,iface=MIXER,name='Mxr 25/21 Playback Volume' +numid=794,iface=MIXER,name='Mxr 25/22 Playback Volume' +numid=826,iface=MIXER,name='Mxr 25/23 Playback Volume' +numid=858,iface=MIXER,name='Mxr 25/24 Playback Volume' +numid=890,iface=MIXER,name='Mxr 25/25 Playback Volume' +numid=922,iface=MIXER,name='Mxr 25/26 Playback Volume' +numid=954,iface=MIXER,name='Mxr 25/27 Playback Volume' +numid=986,iface=MIXER,name='Mxr 25/28 Playback Volume' +numid=1018,iface=MIXER,name='Mxr 25/29 Playback Volume' +numid=186,iface=MIXER,name='Mxr 25/3 Playback Volume' +numid=1050,iface=MIXER,name='Mxr 25/30 Playback Volume' +numid=1082,iface=MIXER,name='Mxr 25/31 Playback Volume' +numid=218,iface=MIXER,name='Mxr 25/4 Playback Volume' +numid=250,iface=MIXER,name='Mxr 25/5 Playback Volume' +numid=282,iface=MIXER,name='Mxr 25/6 Playback Volume' +numid=314,iface=MIXER,name='Mxr 25/7 Playback Volume' +numid=346,iface=MIXER,name='Mxr 25/8 Playback Volume' +numid=378,iface=MIXER,name='Mxr 25/9 Playback Volume' +numid=91,iface=MIXER,name='Mxr 26/0 Playback Volume' +numid=123,iface=MIXER,name='Mxr 26/1 Playback Volume' +numid=411,iface=MIXER,name='Mxr 26/10 Playback Volume' +numid=443,iface=MIXER,name='Mxr 26/11 Playback Volume' +numid=475,iface=MIXER,name='Mxr 26/12 Playback Volume' +numid=507,iface=MIXER,name='Mxr 26/13 Playback Volume' +numid=539,iface=MIXER,name='Mxr 26/14 Playback Volume' +numid=571,iface=MIXER,name='Mxr 26/15 Playback Volume' +numid=603,iface=MIXER,name='Mxr 26/16 Playback Volume' +numid=635,iface=MIXER,name='Mxr 26/17 Playback Volume' +numid=667,iface=MIXER,name='Mxr 26/18 Playback Volume' +numid=699,iface=MIXER,name='Mxr 26/19 Playback Volume' +numid=155,iface=MIXER,name='Mxr 26/2 Playback Volume' +numid=731,iface=MIXER,name='Mxr 26/20 Playback Volume' +numid=763,iface=MIXER,name='Mxr 26/21 Playback Volume' +numid=795,iface=MIXER,name='Mxr 26/22 Playback Volume' +numid=827,iface=MIXER,name='Mxr 26/23 Playback Volume' +numid=859,iface=MIXER,name='Mxr 26/24 Playback Volume' +numid=891,iface=MIXER,name='Mxr 26/25 Playback Volume' +numid=923,iface=MIXER,name='Mxr 26/26 Playback Volume' +numid=955,iface=MIXER,name='Mxr 26/27 Playback Volume' +numid=987,iface=MIXER,name='Mxr 26/28 Playback Volume' +numid=1019,iface=MIXER,name='Mxr 26/29 Playback Volume' +numid=187,iface=MIXER,name='Mxr 26/3 Playback Volume' +numid=1051,iface=MIXER,name='Mxr 26/30 Playback Volume' +numid=1083,iface=MIXER,name='Mxr 26/31 Playback Volume' +numid=219,iface=MIXER,name='Mxr 26/4 Playback Volume' +numid=251,iface=MIXER,name='Mxr 26/5 Playback Volume' +numid=283,iface=MIXER,name='Mxr 26/6 Playback Volume' +numid=315,iface=MIXER,name='Mxr 26/7 Playback Volume' +numid=347,iface=MIXER,name='Mxr 26/8 Playback Volume' +numid=379,iface=MIXER,name='Mxr 26/9 Playback Volume' +numid=92,iface=MIXER,name='Mxr 27/0 Playback Volume' +numid=124,iface=MIXER,name='Mxr 27/1 Playback Volume' +numid=412,iface=MIXER,name='Mxr 27/10 Playback Volume' +numid=444,iface=MIXER,name='Mxr 27/11 Playback Volume' +numid=476,iface=MIXER,name='Mxr 27/12 Playback Volume' +numid=508,iface=MIXER,name='Mxr 27/13 Playback Volume' +numid=540,iface=MIXER,name='Mxr 27/14 Playback Volume' +numid=572,iface=MIXER,name='Mxr 27/15 Playback Volume' +numid=604,iface=MIXER,name='Mxr 27/16 Playback Volume' +numid=636,iface=MIXER,name='Mxr 27/17 Playback Volume' +numid=668,iface=MIXER,name='Mxr 27/18 Playback Volume' +numid=700,iface=MIXER,name='Mxr 27/19 Playback Volume' +numid=156,iface=MIXER,name='Mxr 27/2 Playback Volume' +numid=732,iface=MIXER,name='Mxr 27/20 Playback Volume' +numid=764,iface=MIXER,name='Mxr 27/21 Playback Volume' +numid=796,iface=MIXER,name='Mxr 27/22 Playback Volume' +numid=828,iface=MIXER,name='Mxr 27/23 Playback Volume' +numid=860,iface=MIXER,name='Mxr 27/24 Playback Volume' +numid=892,iface=MIXER,name='Mxr 27/25 Playback Volume' +numid=924,iface=MIXER,name='Mxr 27/26 Playback Volume' +numid=956,iface=MIXER,name='Mxr 27/27 Playback Volume' +numid=988,iface=MIXER,name='Mxr 27/28 Playback Volume' +numid=1020,iface=MIXER,name='Mxr 27/29 Playback Volume' +numid=188,iface=MIXER,name='Mxr 27/3 Playback Volume' +numid=1052,iface=MIXER,name='Mxr 27/30 Playback Volume' +numid=1084,iface=MIXER,name='Mxr 27/31 Playback Volume' +numid=220,iface=MIXER,name='Mxr 27/4 Playback Volume' +numid=252,iface=MIXER,name='Mxr 27/5 Playback Volume' +numid=284,iface=MIXER,name='Mxr 27/6 Playback Volume' +numid=316,iface=MIXER,name='Mxr 27/7 Playback Volume' +numid=348,iface=MIXER,name='Mxr 27/8 Playback Volume' +numid=380,iface=MIXER,name='Mxr 27/9 Playback Volume' +numid=93,iface=MIXER,name='Mxr 28/0 Playback Volume' +numid=125,iface=MIXER,name='Mxr 28/1 Playback Volume' +numid=413,iface=MIXER,name='Mxr 28/10 Playback Volume' +numid=445,iface=MIXER,name='Mxr 28/11 Playback Volume' +numid=477,iface=MIXER,name='Mxr 28/12 Playback Volume' +numid=509,iface=MIXER,name='Mxr 28/13 Playback Volume' +numid=541,iface=MIXER,name='Mxr 28/14 Playback Volume' +numid=573,iface=MIXER,name='Mxr 28/15 Playback Volume' +numid=605,iface=MIXER,name='Mxr 28/16 Playback Volume' +numid=637,iface=MIXER,name='Mxr 28/17 Playback Volume' +numid=669,iface=MIXER,name='Mxr 28/18 Playback Volume' +numid=701,iface=MIXER,name='Mxr 28/19 Playback Volume' +numid=157,iface=MIXER,name='Mxr 28/2 Playback Volume' +numid=733,iface=MIXER,name='Mxr 28/20 Playback Volume' +numid=765,iface=MIXER,name='Mxr 28/21 Playback Volume' +numid=797,iface=MIXER,name='Mxr 28/22 Playback Volume' +numid=829,iface=MIXER,name='Mxr 28/23 Playback Volume' +numid=861,iface=MIXER,name='Mxr 28/24 Playback Volume' +numid=893,iface=MIXER,name='Mxr 28/25 Playback Volume' +numid=925,iface=MIXER,name='Mxr 28/26 Playback Volume' +numid=957,iface=MIXER,name='Mxr 28/27 Playback Volume' +numid=989,iface=MIXER,name='Mxr 28/28 Playback Volume' +numid=1021,iface=MIXER,name='Mxr 28/29 Playback Volume' +numid=189,iface=MIXER,name='Mxr 28/3 Playback Volume' +numid=1053,iface=MIXER,name='Mxr 28/30 Playback Volume' +numid=1085,iface=MIXER,name='Mxr 28/31 Playback Volume' +numid=221,iface=MIXER,name='Mxr 28/4 Playback Volume' +numid=253,iface=MIXER,name='Mxr 28/5 Playback Volume' +numid=285,iface=MIXER,name='Mxr 28/6 Playback Volume' +numid=317,iface=MIXER,name='Mxr 28/7 Playback Volume' +numid=349,iface=MIXER,name='Mxr 28/8 Playback Volume' +numid=381,iface=MIXER,name='Mxr 28/9 Playback Volume' +numid=94,iface=MIXER,name='Mxr 29/0 Playback Volume' +numid=126,iface=MIXER,name='Mxr 29/1 Playback Volume' +numid=414,iface=MIXER,name='Mxr 29/10 Playback Volume' +numid=446,iface=MIXER,name='Mxr 29/11 Playback Volume' +numid=478,iface=MIXER,name='Mxr 29/12 Playback Volume' +numid=510,iface=MIXER,name='Mxr 29/13 Playback Volume' +numid=542,iface=MIXER,name='Mxr 29/14 Playback Volume' +numid=574,iface=MIXER,name='Mxr 29/15 Playback Volume' +numid=606,iface=MIXER,name='Mxr 29/16 Playback Volume' +numid=638,iface=MIXER,name='Mxr 29/17 Playback Volume' +numid=670,iface=MIXER,name='Mxr 29/18 Playback Volume' +numid=702,iface=MIXER,name='Mxr 29/19 Playback Volume' +numid=158,iface=MIXER,name='Mxr 29/2 Playback Volume' +numid=734,iface=MIXER,name='Mxr 29/20 Playback Volume' +numid=766,iface=MIXER,name='Mxr 29/21 Playback Volume' +numid=798,iface=MIXER,name='Mxr 29/22 Playback Volume' +numid=830,iface=MIXER,name='Mxr 29/23 Playback Volume' +numid=862,iface=MIXER,name='Mxr 29/24 Playback Volume' +numid=894,iface=MIXER,name='Mxr 29/25 Playback Volume' +numid=926,iface=MIXER,name='Mxr 29/26 Playback Volume' +numid=958,iface=MIXER,name='Mxr 29/27 Playback Volume' +numid=990,iface=MIXER,name='Mxr 29/28 Playback Volume' +numid=1022,iface=MIXER,name='Mxr 29/29 Playback Volume' +numid=190,iface=MIXER,name='Mxr 29/3 Playback Volume' +numid=1054,iface=MIXER,name='Mxr 29/30 Playback Volume' +numid=1086,iface=MIXER,name='Mxr 29/31 Playback Volume' +numid=222,iface=MIXER,name='Mxr 29/4 Playback Volume' +numid=254,iface=MIXER,name='Mxr 29/5 Playback Volume' +numid=286,iface=MIXER,name='Mxr 29/6 Playback Volume' +numid=318,iface=MIXER,name='Mxr 29/7 Playback Volume' +numid=350,iface=MIXER,name='Mxr 29/8 Playback Volume' +numid=382,iface=MIXER,name='Mxr 29/9 Playback Volume' +numid=68,iface=MIXER,name='Mxr 3/0 Playback Volume' +numid=100,iface=MIXER,name='Mxr 3/1 Playback Volume' +numid=388,iface=MIXER,name='Mxr 3/10 Playback Volume' +numid=420,iface=MIXER,name='Mxr 3/11 Playback Volume' +numid=452,iface=MIXER,name='Mxr 3/12 Playback Volume' +numid=484,iface=MIXER,name='Mxr 3/13 Playback Volume' +numid=516,iface=MIXER,name='Mxr 3/14 Playback Volume' +numid=548,iface=MIXER,name='Mxr 3/15 Playback Volume' +numid=580,iface=MIXER,name='Mxr 3/16 Playback Volume' +numid=612,iface=MIXER,name='Mxr 3/17 Playback Volume' +numid=644,iface=MIXER,name='Mxr 3/18 Playback Volume' +numid=676,iface=MIXER,name='Mxr 3/19 Playback Volume' +numid=132,iface=MIXER,name='Mxr 3/2 Playback Volume' +numid=708,iface=MIXER,name='Mxr 3/20 Playback Volume' +numid=740,iface=MIXER,name='Mxr 3/21 Playback Volume' +numid=772,iface=MIXER,name='Mxr 3/22 Playback Volume' +numid=804,iface=MIXER,name='Mxr 3/23 Playback Volume' +numid=836,iface=MIXER,name='Mxr 3/24 Playback Volume' +numid=868,iface=MIXER,name='Mxr 3/25 Playback Volume' +numid=900,iface=MIXER,name='Mxr 3/26 Playback Volume' +numid=932,iface=MIXER,name='Mxr 3/27 Playback Volume' +numid=964,iface=MIXER,name='Mxr 3/28 Playback Volume' +numid=996,iface=MIXER,name='Mxr 3/29 Playback Volume' +numid=164,iface=MIXER,name='Mxr 3/3 Playback Volume' +numid=1028,iface=MIXER,name='Mxr 3/30 Playback Volume' +numid=1060,iface=MIXER,name='Mxr 3/31 Playback Volume' +numid=196,iface=MIXER,name='Mxr 3/4 Playback Volume' +numid=228,iface=MIXER,name='Mxr 3/5 Playback Volume' +numid=260,iface=MIXER,name='Mxr 3/6 Playback Volume' +numid=292,iface=MIXER,name='Mxr 3/7 Playback Volume' +numid=324,iface=MIXER,name='Mxr 3/8 Playback Volume' +numid=356,iface=MIXER,name='Mxr 3/9 Playback Volume' +numid=95,iface=MIXER,name='Mxr 30/0 Playback Volume' +numid=127,iface=MIXER,name='Mxr 30/1 Playback Volume' +numid=415,iface=MIXER,name='Mxr 30/10 Playback Volume' +numid=447,iface=MIXER,name='Mxr 30/11 Playback Volume' +numid=479,iface=MIXER,name='Mxr 30/12 Playback Volume' +numid=511,iface=MIXER,name='Mxr 30/13 Playback Volume' +numid=543,iface=MIXER,name='Mxr 30/14 Playback Volume' +numid=575,iface=MIXER,name='Mxr 30/15 Playback Volume' +numid=607,iface=MIXER,name='Mxr 30/16 Playback Volume' +numid=639,iface=MIXER,name='Mxr 30/17 Playback Volume' +numid=671,iface=MIXER,name='Mxr 30/18 Playback Volume' +numid=703,iface=MIXER,name='Mxr 30/19 Playback Volume' +numid=159,iface=MIXER,name='Mxr 30/2 Playback Volume' +numid=735,iface=MIXER,name='Mxr 30/20 Playback Volume' +numid=767,iface=MIXER,name='Mxr 30/21 Playback Volume' +numid=799,iface=MIXER,name='Mxr 30/22 Playback Volume' +numid=831,iface=MIXER,name='Mxr 30/23 Playback Volume' +numid=863,iface=MIXER,name='Mxr 30/24 Playback Volume' +numid=895,iface=MIXER,name='Mxr 30/25 Playback Volume' +numid=927,iface=MIXER,name='Mxr 30/26 Playback Volume' +numid=959,iface=MIXER,name='Mxr 30/27 Playback Volume' +numid=991,iface=MIXER,name='Mxr 30/28 Playback Volume' +numid=1023,iface=MIXER,name='Mxr 30/29 Playback Volume' +numid=191,iface=MIXER,name='Mxr 30/3 Playback Volume' +numid=1055,iface=MIXER,name='Mxr 30/30 Playback Volume' +numid=1087,iface=MIXER,name='Mxr 30/31 Playback Volume' +numid=223,iface=MIXER,name='Mxr 30/4 Playback Volume' +numid=255,iface=MIXER,name='Mxr 30/5 Playback Volume' +numid=287,iface=MIXER,name='Mxr 30/6 Playback Volume' +numid=319,iface=MIXER,name='Mxr 30/7 Playback Volume' +numid=351,iface=MIXER,name='Mxr 30/8 Playback Volume' +numid=383,iface=MIXER,name='Mxr 30/9 Playback Volume' +numid=96,iface=MIXER,name='Mxr 31/0 Playback Volume' +numid=128,iface=MIXER,name='Mxr 31/1 Playback Volume' +numid=416,iface=MIXER,name='Mxr 31/10 Playback Volume' +numid=448,iface=MIXER,name='Mxr 31/11 Playback Volume' +numid=480,iface=MIXER,name='Mxr 31/12 Playback Volume' +numid=512,iface=MIXER,name='Mxr 31/13 Playback Volume' +numid=544,iface=MIXER,name='Mxr 31/14 Playback Volume' +numid=576,iface=MIXER,name='Mxr 31/15 Playback Volume' +numid=608,iface=MIXER,name='Mxr 31/16 Playback Volume' +numid=640,iface=MIXER,name='Mxr 31/17 Playback Volume' +numid=672,iface=MIXER,name='Mxr 31/18 Playback Volume' +numid=704,iface=MIXER,name='Mxr 31/19 Playback Volume' +numid=160,iface=MIXER,name='Mxr 31/2 Playback Volume' +numid=736,iface=MIXER,name='Mxr 31/20 Playback Volume' +numid=768,iface=MIXER,name='Mxr 31/21 Playback Volume' +numid=800,iface=MIXER,name='Mxr 31/22 Playback Volume' +numid=832,iface=MIXER,name='Mxr 31/23 Playback Volume' +numid=864,iface=MIXER,name='Mxr 31/24 Playback Volume' +numid=896,iface=MIXER,name='Mxr 31/25 Playback Volume' +numid=928,iface=MIXER,name='Mxr 31/26 Playback Volume' +numid=960,iface=MIXER,name='Mxr 31/27 Playback Volume' +numid=992,iface=MIXER,name='Mxr 31/28 Playback Volume' +numid=1024,iface=MIXER,name='Mxr 31/29 Playback Volume' +numid=192,iface=MIXER,name='Mxr 31/3 Playback Volume' +numid=1056,iface=MIXER,name='Mxr 31/30 Playback Volume' +numid=1088,iface=MIXER,name='Mxr 31/31 Playback Volume' +numid=224,iface=MIXER,name='Mxr 31/4 Playback Volume' +numid=256,iface=MIXER,name='Mxr 31/5 Playback Volume' +numid=288,iface=MIXER,name='Mxr 31/6 Playback Volume' +numid=320,iface=MIXER,name='Mxr 31/7 Playback Volume' +numid=352,iface=MIXER,name='Mxr 31/8 Playback Volume' +numid=384,iface=MIXER,name='Mxr 31/9 Playback Volume' +numid=69,iface=MIXER,name='Mxr 4/0 Playback Volume' +numid=101,iface=MIXER,name='Mxr 4/1 Playback Volume' +numid=389,iface=MIXER,name='Mxr 4/10 Playback Volume' +numid=421,iface=MIXER,name='Mxr 4/11 Playback Volume' +numid=453,iface=MIXER,name='Mxr 4/12 Playback Volume' +numid=485,iface=MIXER,name='Mxr 4/13 Playback Volume' +numid=517,iface=MIXER,name='Mxr 4/14 Playback Volume' +numid=549,iface=MIXER,name='Mxr 4/15 Playback Volume' +numid=581,iface=MIXER,name='Mxr 4/16 Playback Volume' +numid=613,iface=MIXER,name='Mxr 4/17 Playback Volume' +numid=645,iface=MIXER,name='Mxr 4/18 Playback Volume' +numid=677,iface=MIXER,name='Mxr 4/19 Playback Volume' +numid=133,iface=MIXER,name='Mxr 4/2 Playback Volume' +numid=709,iface=MIXER,name='Mxr 4/20 Playback Volume' +numid=741,iface=MIXER,name='Mxr 4/21 Playback Volume' +numid=773,iface=MIXER,name='Mxr 4/22 Playback Volume' +numid=805,iface=MIXER,name='Mxr 4/23 Playback Volume' +numid=837,iface=MIXER,name='Mxr 4/24 Playback Volume' +numid=869,iface=MIXER,name='Mxr 4/25 Playback Volume' +numid=901,iface=MIXER,name='Mxr 4/26 Playback Volume' +numid=933,iface=MIXER,name='Mxr 4/27 Playback Volume' +numid=965,iface=MIXER,name='Mxr 4/28 Playback Volume' +numid=997,iface=MIXER,name='Mxr 4/29 Playback Volume' +numid=165,iface=MIXER,name='Mxr 4/3 Playback Volume' +numid=1029,iface=MIXER,name='Mxr 4/30 Playback Volume' +numid=1061,iface=MIXER,name='Mxr 4/31 Playback Volume' +numid=197,iface=MIXER,name='Mxr 4/4 Playback Volume' +numid=229,iface=MIXER,name='Mxr 4/5 Playback Volume' +numid=261,iface=MIXER,name='Mxr 4/6 Playback Volume' +numid=293,iface=MIXER,name='Mxr 4/7 Playback Volume' +numid=325,iface=MIXER,name='Mxr 4/8 Playback Volume' +numid=357,iface=MIXER,name='Mxr 4/9 Playback Volume' +numid=70,iface=MIXER,name='Mxr 5/0 Playback Volume' +numid=102,iface=MIXER,name='Mxr 5/1 Playback Volume' +numid=390,iface=MIXER,name='Mxr 5/10 Playback Volume' +numid=422,iface=MIXER,name='Mxr 5/11 Playback Volume' +numid=454,iface=MIXER,name='Mxr 5/12 Playback Volume' +numid=486,iface=MIXER,name='Mxr 5/13 Playback Volume' +numid=518,iface=MIXER,name='Mxr 5/14 Playback Volume' +numid=550,iface=MIXER,name='Mxr 5/15 Playback Volume' +numid=582,iface=MIXER,name='Mxr 5/16 Playback Volume' +numid=614,iface=MIXER,name='Mxr 5/17 Playback Volume' +numid=646,iface=MIXER,name='Mxr 5/18 Playback Volume' +numid=678,iface=MIXER,name='Mxr 5/19 Playback Volume' +numid=134,iface=MIXER,name='Mxr 5/2 Playback Volume' +numid=710,iface=MIXER,name='Mxr 5/20 Playback Volume' +numid=742,iface=MIXER,name='Mxr 5/21 Playback Volume' +numid=774,iface=MIXER,name='Mxr 5/22 Playback Volume' +numid=806,iface=MIXER,name='Mxr 5/23 Playback Volume' +numid=838,iface=MIXER,name='Mxr 5/24 Playback Volume' +numid=870,iface=MIXER,name='Mxr 5/25 Playback Volume' +numid=902,iface=MIXER,name='Mxr 5/26 Playback Volume' +numid=934,iface=MIXER,name='Mxr 5/27 Playback Volume' +numid=966,iface=MIXER,name='Mxr 5/28 Playback Volume' +numid=998,iface=MIXER,name='Mxr 5/29 Playback Volume' +numid=166,iface=MIXER,name='Mxr 5/3 Playback Volume' +numid=1030,iface=MIXER,name='Mxr 5/30 Playback Volume' +numid=1062,iface=MIXER,name='Mxr 5/31 Playback Volume' +numid=198,iface=MIXER,name='Mxr 5/4 Playback Volume' +numid=230,iface=MIXER,name='Mxr 5/5 Playback Volume' +numid=262,iface=MIXER,name='Mxr 5/6 Playback Volume' +numid=294,iface=MIXER,name='Mxr 5/7 Playback Volume' +numid=326,iface=MIXER,name='Mxr 5/8 Playback Volume' +numid=358,iface=MIXER,name='Mxr 5/9 Playback Volume' +numid=71,iface=MIXER,name='Mxr 6/0 Playback Volume' +numid=103,iface=MIXER,name='Mxr 6/1 Playback Volume' +numid=391,iface=MIXER,name='Mxr 6/10 Playback Volume' +numid=423,iface=MIXER,name='Mxr 6/11 Playback Volume' +numid=455,iface=MIXER,name='Mxr 6/12 Playback Volume' +numid=487,iface=MIXER,name='Mxr 6/13 Playback Volume' +numid=519,iface=MIXER,name='Mxr 6/14 Playback Volume' +numid=551,iface=MIXER,name='Mxr 6/15 Playback Volume' +numid=583,iface=MIXER,name='Mxr 6/16 Playback Volume' +numid=615,iface=MIXER,name='Mxr 6/17 Playback Volume' +numid=647,iface=MIXER,name='Mxr 6/18 Playback Volume' +numid=679,iface=MIXER,name='Mxr 6/19 Playback Volume' +numid=135,iface=MIXER,name='Mxr 6/2 Playback Volume' +numid=711,iface=MIXER,name='Mxr 6/20 Playback Volume' +numid=743,iface=MIXER,name='Mxr 6/21 Playback Volume' +numid=775,iface=MIXER,name='Mxr 6/22 Playback Volume' +numid=807,iface=MIXER,name='Mxr 6/23 Playback Volume' +numid=839,iface=MIXER,name='Mxr 6/24 Playback Volume' +numid=871,iface=MIXER,name='Mxr 6/25 Playback Volume' +numid=903,iface=MIXER,name='Mxr 6/26 Playback Volume' +numid=935,iface=MIXER,name='Mxr 6/27 Playback Volume' +numid=967,iface=MIXER,name='Mxr 6/28 Playback Volume' +numid=999,iface=MIXER,name='Mxr 6/29 Playback Volume' +numid=167,iface=MIXER,name='Mxr 6/3 Playback Volume' +numid=1031,iface=MIXER,name='Mxr 6/30 Playback Volume' +numid=1063,iface=MIXER,name='Mxr 6/31 Playback Volume' +numid=199,iface=MIXER,name='Mxr 6/4 Playback Volume' +numid=231,iface=MIXER,name='Mxr 6/5 Playback Volume' +numid=263,iface=MIXER,name='Mxr 6/6 Playback Volume' +numid=295,iface=MIXER,name='Mxr 6/7 Playback Volume' +numid=327,iface=MIXER,name='Mxr 6/8 Playback Volume' +numid=359,iface=MIXER,name='Mxr 6/9 Playback Volume' +numid=72,iface=MIXER,name='Mxr 7/0 Playback Volume' +numid=104,iface=MIXER,name='Mxr 7/1 Playback Volume' +numid=392,iface=MIXER,name='Mxr 7/10 Playback Volume' +numid=424,iface=MIXER,name='Mxr 7/11 Playback Volume' +numid=456,iface=MIXER,name='Mxr 7/12 Playback Volume' +numid=488,iface=MIXER,name='Mxr 7/13 Playback Volume' +numid=520,iface=MIXER,name='Mxr 7/14 Playback Volume' +numid=552,iface=MIXER,name='Mxr 7/15 Playback Volume' +numid=584,iface=MIXER,name='Mxr 7/16 Playback Volume' +numid=616,iface=MIXER,name='Mxr 7/17 Playback Volume' +numid=648,iface=MIXER,name='Mxr 7/18 Playback Volume' +numid=680,iface=MIXER,name='Mxr 7/19 Playback Volume' +numid=136,iface=MIXER,name='Mxr 7/2 Playback Volume' +numid=712,iface=MIXER,name='Mxr 7/20 Playback Volume' +numid=744,iface=MIXER,name='Mxr 7/21 Playback Volume' +numid=776,iface=MIXER,name='Mxr 7/22 Playback Volume' +numid=808,iface=MIXER,name='Mxr 7/23 Playback Volume' +numid=840,iface=MIXER,name='Mxr 7/24 Playback Volume' +numid=872,iface=MIXER,name='Mxr 7/25 Playback Volume' +numid=904,iface=MIXER,name='Mxr 7/26 Playback Volume' +numid=936,iface=MIXER,name='Mxr 7/27 Playback Volume' +numid=968,iface=MIXER,name='Mxr 7/28 Playback Volume' +numid=1000,iface=MIXER,name='Mxr 7/29 Playback Volume' +numid=168,iface=MIXER,name='Mxr 7/3 Playback Volume' +numid=1032,iface=MIXER,name='Mxr 7/30 Playback Volume' +numid=1064,iface=MIXER,name='Mxr 7/31 Playback Volume' +numid=200,iface=MIXER,name='Mxr 7/4 Playback Volume' +numid=232,iface=MIXER,name='Mxr 7/5 Playback Volume' +numid=264,iface=MIXER,name='Mxr 7/6 Playback Volume' +numid=296,iface=MIXER,name='Mxr 7/7 Playback Volume' +numid=328,iface=MIXER,name='Mxr 7/8 Playback Volume' +numid=360,iface=MIXER,name='Mxr 7/9 Playback Volume' +numid=73,iface=MIXER,name='Mxr 8/0 Playback Volume' +numid=105,iface=MIXER,name='Mxr 8/1 Playback Volume' +numid=393,iface=MIXER,name='Mxr 8/10 Playback Volume' +numid=425,iface=MIXER,name='Mxr 8/11 Playback Volume' +numid=457,iface=MIXER,name='Mxr 8/12 Playback Volume' +numid=489,iface=MIXER,name='Mxr 8/13 Playback Volume' +numid=521,iface=MIXER,name='Mxr 8/14 Playback Volume' +numid=553,iface=MIXER,name='Mxr 8/15 Playback Volume' +numid=585,iface=MIXER,name='Mxr 8/16 Playback Volume' +numid=617,iface=MIXER,name='Mxr 8/17 Playback Volume' +numid=649,iface=MIXER,name='Mxr 8/18 Playback Volume' +numid=681,iface=MIXER,name='Mxr 8/19 Playback Volume' +numid=137,iface=MIXER,name='Mxr 8/2 Playback Volume' +numid=713,iface=MIXER,name='Mxr 8/20 Playback Volume' +numid=745,iface=MIXER,name='Mxr 8/21 Playback Volume' +numid=777,iface=MIXER,name='Mxr 8/22 Playback Volume' +numid=809,iface=MIXER,name='Mxr 8/23 Playback Volume' +numid=841,iface=MIXER,name='Mxr 8/24 Playback Volume' +numid=873,iface=MIXER,name='Mxr 8/25 Playback Volume' +numid=905,iface=MIXER,name='Mxr 8/26 Playback Volume' +numid=937,iface=MIXER,name='Mxr 8/27 Playback Volume' +numid=969,iface=MIXER,name='Mxr 8/28 Playback Volume' +numid=1001,iface=MIXER,name='Mxr 8/29 Playback Volume' +numid=169,iface=MIXER,name='Mxr 8/3 Playback Volume' +numid=1033,iface=MIXER,name='Mxr 8/30 Playback Volume' +numid=1065,iface=MIXER,name='Mxr 8/31 Playback Volume' +numid=201,iface=MIXER,name='Mxr 8/4 Playback Volume' +numid=233,iface=MIXER,name='Mxr 8/5 Playback Volume' +numid=265,iface=MIXER,name='Mxr 8/6 Playback Volume' +numid=297,iface=MIXER,name='Mxr 8/7 Playback Volume' +numid=329,iface=MIXER,name='Mxr 8/8 Playback Volume' +numid=361,iface=MIXER,name='Mxr 8/9 Playback Volume' +numid=74,iface=MIXER,name='Mxr 9/0 Playback Volume' +numid=106,iface=MIXER,name='Mxr 9/1 Playback Volume' +numid=394,iface=MIXER,name='Mxr 9/10 Playback Volume' +numid=426,iface=MIXER,name='Mxr 9/11 Playback Volume' +numid=458,iface=MIXER,name='Mxr 9/12 Playback Volume' +numid=490,iface=MIXER,name='Mxr 9/13 Playback Volume' +numid=522,iface=MIXER,name='Mxr 9/14 Playback Volume' +numid=554,iface=MIXER,name='Mxr 9/15 Playback Volume' +numid=586,iface=MIXER,name='Mxr 9/16 Playback Volume' +numid=618,iface=MIXER,name='Mxr 9/17 Playback Volume' +numid=650,iface=MIXER,name='Mxr 9/18 Playback Volume' +numid=682,iface=MIXER,name='Mxr 9/19 Playback Volume' +numid=138,iface=MIXER,name='Mxr 9/2 Playback Volume' +numid=714,iface=MIXER,name='Mxr 9/20 Playback Volume' +numid=746,iface=MIXER,name='Mxr 9/21 Playback Volume' +numid=778,iface=MIXER,name='Mxr 9/22 Playback Volume' +numid=810,iface=MIXER,name='Mxr 9/23 Playback Volume' +numid=842,iface=MIXER,name='Mxr 9/24 Playback Volume' +numid=874,iface=MIXER,name='Mxr 9/25 Playback Volume' +numid=906,iface=MIXER,name='Mxr 9/26 Playback Volume' +numid=938,iface=MIXER,name='Mxr 9/27 Playback Volume' +numid=970,iface=MIXER,name='Mxr 9/28 Playback Volume' +numid=1002,iface=MIXER,name='Mxr 9/29 Playback Volume' +numid=170,iface=MIXER,name='Mxr 9/3 Playback Volume' +numid=1034,iface=MIXER,name='Mxr 9/30 Playback Volume' +numid=1066,iface=MIXER,name='Mxr 9/31 Playback Volume' +numid=202,iface=MIXER,name='Mxr 9/4 Playback Volume' +numid=234,iface=MIXER,name='Mxr 9/5 Playback Volume' +numid=266,iface=MIXER,name='Mxr 9/6 Playback Volume' +numid=298,iface=MIXER,name='Mxr 9/7 Playback Volume' +numid=330,iface=MIXER,name='Mxr 9/8 Playback Volume' +numid=362,iface=MIXER,name='Mxr 9/9 Playback Volume' diff --git a/snd-alpx-dkms/Controls/AlpDANTE_contents.txt b/snd-alpx-dkms/Controls/AlpDANTE_contents.txt new file mode 100644 index 0000000..f5e023d --- /dev/null +++ b/snd-alpx-dkms/Controls/AlpDANTE_contents.txt @@ -0,0 +1,11 @@ +numid=2,iface=CARD,name='Clk Eff' + ; type=INTEGER,access=r--v----,values=1,min=0,max=192,step=0 + : values=48 +numid=1,iface=CARD,name='Clk Eff Src' + ; type=ENUMERATED,access=r--v----,values=1,items=2 + ; Item #0 'Internal' + ; Item #1 'SIC' + : values=0 +numid=3,iface=CARD,name='Clk P0' + ; type=INTEGER,access=r-------,values=1,min=0,max=0,step=0 + : values=0 diff --git a/snd-alpx-dkms/Controls/AlpDANTE_controls.txt b/snd-alpx-dkms/Controls/AlpDANTE_controls.txt new file mode 100644 index 0000000..77caa4d --- /dev/null +++ b/snd-alpx-dkms/Controls/AlpDANTE_controls.txt @@ -0,0 +1,3 @@ +numid=2,iface=CARD,name='Clk Eff' +numid=1,iface=CARD,name='Clk Eff Src' +numid=3,iface=CARD,name='Clk P0' diff --git a/snd-alpx-dkms/Firmwares/alp222_multiboot_user_build_286_ublaze_2.9.bin b/snd-alpx-dkms/Firmwares/alp222_multiboot_user_build_286_ublaze_2.9.bin Binary files differnew file mode 100755 index 0000000..19e1328 --- /dev/null +++ b/snd-alpx-dkms/Firmwares/alp222_multiboot_user_build_286_ublaze_2.9.bin diff --git a/snd-alpx-dkms/Firmwares/alp882_multiboot_user_build_251_ublaze_1.11.bin b/snd-alpx-dkms/Firmwares/alp882_multiboot_user_build_251_ublaze_1.11.bin Binary files differnew file mode 100755 index 0000000..1ce717f --- /dev/null +++ b/snd-alpx-dkms/Firmwares/alp882_multiboot_user_build_251_ublaze_1.11.bin diff --git a/snd-alpx-dkms/ReleasesNotes.txt b/snd-alpx-dkms/ReleasesNotes.txt new file mode 100755 index 0000000..45cfe49 --- /dev/null +++ b/snd-alpx-dkms/ReleasesNotes.txt @@ -0,0 +1,507 @@ +Notes de versions du pilote Linux +================================= + +Notes de la version V3.4.3 (Support (AlpDANTE/Alp882e / Alp442e / Alp222e) tous modèles) +======================================================= +Contenu de la version : + + * Le pilote en version 3.4.3 + +Nouveautés + * Support des applications compilées avant le firmware 240 des Alp882e : adaptation de la liste des sources de synchronisation. Ce mode est activé via le paramètre alp882_pre_FW240_apps_support + + * Suppression de l'asterix postfixé dans les noms des cartes Alp222e lorsque le mode de compatibilité de firmware est activé. + + +Notes de la version V3.4.2 (Support (AlpDANTE/Alp882e / Alp442e / Alp222e) tous modèles) +======================================================= +Contenu de la version : + + * Le pilote en version 3.4.2 + +Nouveautés + + * Activation du loopback interne des cartes AlpDANTE via le paramètre du module : dante_loopback_enabled + + * Support des applications compilées avec les contrôles des cartes Alp222e des firmware pré-V283. Les valeurs des contrôles des sources de synchronisation des Alp222e ont changés en V283 ce qui implique une recompilation des applications utilisatrices. Cette fonctionnalité permet le support des applications SANS une re-compilation via une adaptation. Activation via le paramètre alp222_pre_FW283_apps_support. + + * Désactivation des logs d'accès aux contrôles dans la génération. + + * Mise à jour des éléments de copyright : année 2024. + + +Notes de la version V3.4.1 (Support (AlpDANTE/Alp882e / Alp442e / Alp222e) tous modèles) +======================================================= +Contenu de la version : + + * Le pilote en version 3.4.1 + +Nouveautés + * Support de Ubuntu 22.04 (noyaux 5.15 et 6.5) + * Support des distributions Debian 11 (noyau 5.10) , 12 (noyau 6.1). + * Support des distributions de la famille RedHat 8 (4.18) et RedHat 9 (5.14). + * Contournement du blocage de la lecture lors de cycles enchainés de lecture : "while($true) ; do aplay XXXX ; done". Ce contournement consiste à ajouter un delai de 200ms avant l'ouverture effective du flux dans le pilote. + * Suppression des cas de blocage lors de cycles Start/Stop très courts (<100ms) et répétitifs, des flux audios. + * Correction de l'erreur "DMAR NO_PASID, PTE" si "Virt I/O" / IOMMU est activé (BIOS et options du noyau). + + +Notes de la version V3.4.0 (Support (AlpDANTE/Alp882e / Alp442e / Alp222e) tous modèles) +======================================================= +Contenu de la version : + + * Le pilote en version 3.4.0 (PROTOTYPE) + +Nouveautés + * Intégrable dans les ServLink/Alp. + * XDMA : utilisation complète du DMAEngine fourni par Xilinx + * Support des noyaux 6.5 + * Support des noyaux pré 5.15. + * Support complet de CentOS9 (noyau 5.14.0-381) avec flux audio via le DMAEngine. + * Incorporation de regmap_mmio pour résoudre la dépendence au besoin + * Alp222e-MIC : gamme d'amplification des entrées MIC de -24dB à +56dB. + * Nouvelles versions de firmware supportées : Alp222e: V286 et Alp882e/Alp442e: V251. + * Correction erreur EPROBE_DEFER (-517) observée sur Ubuntu Server 22.04. + * Correction de l'arrêt des flux PLAYBACK lors de cycles Start/Stop courts sur les Alp222e. + + Notes de la version V3.3.2 (Support (AlpDANTE/Alp882e / Alp442e / Alp222e) tous modèles) +======================================================= +Contenu de la version : + + * Le pilote en version 3.3.2 + +Nouveautés + * Support CentOS9 (noyau 5.14.0-381) : définitions des structures des gpio. + * Ajout du script tools/build_virtual_boards_alsa_conf.sh pour la génération d'un fichier asoundrc déclarant des cartes ALP virtuelles à partir de cartes ALP physique présentes. + +Notes de la version V3.3.1 (Support (AlpDANTE/Alp882e / Alp442e / Alp222e) tous modèles) +======================================================= +Contenu de la version : + + * Le pilote en version 3.3.1 + +Nouveautés + * Support Debian 10. La version précédente ne compilait pas suite à un conflit de nommage entre le code du pilote et une macro du noyau. + + +Notes de la version V3.3.0 (Support (AlpDANTE/Alp882e / Alp442e / Alp222e) tous modèles) +======================================================= +Contenu de la version : + + * Le pilote en version 3.3.0 + +Nouveautés: + * AlpDANTE : Stockage de la configuration courante de la carte dans la mémoire Flash lors du démarrage du pilote (persistence de la FS donnée en paramètre) + * AlpDANTE: Indication du nom de la carte sur le réseau DANTE dans les informations d'identité de la carte dans les logs du noyau ET dans le pseudo fichier sysfs : /"sys/class/sound/cardX/device/dante_card_name" avec X le numéro de la carte AlpDANTE indiqué par la commande "aplay -l". Ce nom est celui de la carte visible dans le DANTE contrôleur. + + + Notes de la version V3.2.0 (Support (AlpDANTE/Alp882e / Alp442e / Alp222e) tous modèles) +======================================================= +Contenu de la version : + + * Le pilote en version 3.2.0 + +Nouveautés: + * Suppression de la foncitonnalité de mise à jour du firmware des carte AlpDANTE. La mise à jour se fait via un utilitaire fourni avec la mise à jour sous Windows. + +======================================================= +Contenu de la version : + + * Le pilote en version 3.1.0 + * Firmware V283/2.7 pour Alp222e (Mise à jour obligatoire des cartes avant utilisation de cette version du pilote) + * Firmware V247/1.10 pour les cartes multi-channels(Alp882e/Alp442e) (mise à jour obligatoire des cartes Alp882e avant utilisation de cette version du pilote). + * Firmware V316/1.8 pour les cartes AlpDANTE. + + Nouveautés: + * Support des cartes AlpDANTE : + * Support des différentes fréquences de fonctionnement via le paramètre de module : "dante_configured_fs"qui prend une valeur en Hz, ex : pour 48kHz, "dante_configured_fs=48000". La valeur par défaut est 48000. Toutes les cartes AlpDANTE fonctionnent alors à cette vitesse. + + * Script de mise à jour du firmware dans "tools/dante_card_update_firmware.sh", le firmware est livré dans une archive .zip inclue dans la livraison. + + * indication du numéro de série comme suffixe des partitions pour mise à jour présente lors de l'indication de mise à jour obligatoire. + + * Note : les cartes AlpDANTE n'expose pas de contrôle ALSA. + +* Script de mise à jour des cartes audio classiques est renommé en "tools/audio_card_update_firmware.sh" + +* Mise à disposition de la règle udev pour éviter la prise en compte des cartes Alp par PulseAudio. La règle est dans le fichier "udev/88-pulseaudio-no-alp.rules". Pour sa prise en compte, il faut re-démarrer le système. + +Notes de la version V2.3.1 (Support (Alp882e / Alp442e / Alp222e) tous modèles) +======================================================= +Contenu de la version : + + * Le pilote en version 2.3.1 + * Firmware V283/2.7 pour Alp222e (Mise à jour obligatoire des cartes avant utilisation de cette version du pilote) + * Firmware V247/1.10 pour les cartes multi-channels(Alp882e/Alp442e) (mise à jour obligatoire des cartes Alp882e avant utilisation de cette version du pilote). + +Nouveautés : + * Support officiel de RockyLinux 9.2 (noyau 5.14) + + +Notes de la version V2.3.0 (Support (Alp882e / Alp442e / Alp222e) tous modèles) +======================================================= +Contenu de la version : + + * Le pilote en version 2.3.0 + * Firmware V283/2.7 pour Alp222e (Mise à jour obligatoire des cartes avant utilisation de cette version du pilote) + * Firmware V247/1.10 pour les cartes multi-channels(Alp882e/Alp442e) (mise à jour obligatoire des cartes Alp882e avant utilisation de cette version du pilote). + +Nouveautés : + * Alp222 : Support de l'entrée de synchro inter-carte (nouvelle entrée dans les contrôles de synchro). + + +Notes de la version V2.2.0 (Support (Alp882e / Alp442e / Alp222e) tous modèles) +======================================================= +Contenu de la version : + + * Le pilote en version 2.2.0 + * Firmware V281/1.9 pour Alp222e + * Firmware V241/2.6 pour les cartes multi-channels(Alp882e/Alp442e) (mise à jour obligatoire des cartes Alp882e avant utilisation de cette version du pilote). + +Nouveautés : + + * Support des cartes Alp442e et Alp442e-MIC + * Alp882e-MIC : Support des entrées MIC dans le mixer + * En cas d'anomalie dans la dans la mémoire Flash, la carte passe en mode "DEAD" (LED de façade clignotent en alternance), cela nécessite un retour usine. + * Le pilote place toute carte multi-channel(442/882) ayant une version antérieure du firmware en mode dégradé ne permettant que la mise à jour du firmware. + + + +Notes de la version V2.1.0 (Support (Alp882e / Alp222e) tous modèles) +======================================================= +Contenu de la version : + + * Le pilote en version 2.1.0 + + Nouveautés + * Version du FPGA dans le fichier "ver_fpga" du sysfs de la carte + * Version du Micro-contrôleur dans le fichier "ver_mcu" du sysfs de la carte. Note, le contenu est une chaine "x.y" avec x : version majeur et y : version mineure. + + Ex. : "/sys/class/sound/card2/device/ver_mcu" et Ex. : "/sys/class/sound/card2/device/ver_fpga" + + Evolutions + * Renommage du pseudo fichier "reg_serial_number" en "serial_number" en cohérence avec ceux concernant les versions. + Ex. : "/sys/class/sound/card2/device/serial_number" + * Depuis V 2.0.0, le passage en mode PROD de la carte (visibilité de la mémoire flash) est assuré par le paramètre de module "with_board_in_prod_mode" qui remplace "with_board_in_user_mode". + + +Notes de la version V2.0.1 (Support (Alp882e / Alp222e) tous modèles) +======================================================= +Contenu de la version : + + * Le pilote en version 2.0.1 + + Nouveautés + * Indication du numéro de série dans le nommage de la partition de mise à jour du firmware (uniquement en mode USER). Voir ci-dessous + ---- +# cat /proc/mtd +dev: size erasesize name +mtd0: 00218000 00000000 "fw-user-updatable-270400000003" +mtd1: 00218000 00000000 "fw-user-updatable-270200000003" +mtd2: 00218000 00000000 "fw-user-updatable-270200000002" +---- + + * Fichier de configuration ALSA pour Alp882e avec paires stéréo virtuelles dans ./alsa_conf/asound-stereo_alp882.conf + + Corrections + * Elimination de la fausse détection de l'option MIC des Alp222e lors du premier chargement du pilote. + + +Notes de la version V2.0.0 (Support (Alp882e / Alp222e) tous modèles) +======================================================= + +Contenu de la version : + + * Le pilote en version 2.0.0 + * Le firmware Alp882e en version V208/1.6, lire la note ci-dessous !! + * Le firmware Alp222e en version V273/2.4 + + *ATTENTION* le firmware V208 des Alp882e impose d'avoir une zone de production avec une indication valide du modèle de carte sous peine de "bloquer" la carte avec potentiellement un retour usine obligatoire. Le pilote ne sait pas encore ré-activer une carte dans cet état. Si blocage, la procédure actuelle est de reprogrammer la carte avec la sonde JTAG avec un FW en version précédente, puis programmer une zone de production valide : Numéro de série et indication de modèle. DONC ne pas mettre ce Firmware dans les cartes prototype sans une modification de leurs zones de Production. + +* Les fichiers contenant les listes des contrôles des cartes Alp222e, Alp222e-MIC, Alp882e et Alp882e-MIC avec les sufixes "controls" et "contents". +* Le fichier recensant les informations de versions attendues selon les versions de firmware et pilote : Versions_attendues.txt + +Nouveautés: + * Supporte tous les modèles de cartes Alp222e et Alp882e via la valeur du champ "SubSystemId" PCIe. + * !!! Nouveau nommage des cartes : ajout du 'e' suffixe à la racine du modèle : "Alp222" devient "Alp222e". + * Accès au numéro de série via le fichier spécial "reg_serial_number" dans le sysfs de la carte : Ex. : "/sys/class/sound/card2/device/reg_serial_number" pour la carte 2 et plus depuis un accès direct à la mémoire Flash de la carte : "/dev/mtd". + * Ajout du fichier de configuration ALSA "asound-alp882.conf" permettant d'avoir des paires stéréos virtuelles à partir des canaux d'une Alp882e. + * Accès Flash limité à la seule zone du firmware utilisateur pour mise à jour en fonctionnement normal. Passage en mode PROD via un paramètre du module. + * Amélioration des indications d'identité des cartes dans les logs du noyau (numéro de série , indication de l'identifiant du modèle). + + Corrections + * Alp882e (firmware V208 et ultérieurs) : délai de 500ms avant ouverture de flux lors de changement de FS entre 2 ouvertures de flux internes. + + Notes de la version V1.999.11 (PROTOTYPE Support Alp882) +======================================================= + +VERSION transitoire pour validation de la correction du support des FS > 48kHz. + + +Notes de la version V1.999.10 (PROTOTYPE Support Alp882) +======================================================= + +Contenu de la version : + + * Le pilote en version 1.999.10 + * Les fichiers contenant les listes des contrôles des cartes Alp222e, Alp222e-MIC, Alp882e et Alp882e-MIC avec les sufixes "controls" et "contents". + * Le fichier recensant les informations de versions attendues selon les versions de firmware et pilote : Versions_attendues.txt + +Nouveautés: + * Activation du mode MIC des cartes Alp882e via le paramètre "with_882mic_option", Le mode LINE est activé par défaut. La carte se comporte comme une Alp882e et pas une Alp882e-MIC. + * Mémoire Flash : seule la zone "fw-user-updatable" est accessible en écriture. + * Récupération de la FS effective via un seul contrôle et pas deux (Base et Coefficient). + * Création du script "tools/ update_firmware.sh" de mise à jour du firmware comprenant le contournement d'une limitation du FGPA. Impose la présence de l'outil "dd". + * Support des cartes Alp222e-MIC ayant 0x0820 comme valeur du "SubsystemVendorId". + * Nouveau nommage des cartes : ajout du 'e' suffixe au à la racine du modèle : "Alp222" devient "Alp222e". + +Corrections + * Support correct des FS>48kHz (Tests faits avec outil Play.EXE). + +Limitations connues + * Délai de 1s avant ouverture de flux lors de changement de FS entre 2 ouvertures de flux internes. + +Limitations inconnues + * ... + + + +Notes de la version V1.999.9 (PROTOTYPE Support Alp882) +======================================================= + +Contenu de la version : + + * Firmware en version 191/1.3 + * Le pilote en version 1.999.9 + * Le fichier contenant la liste des contrôles de la carte : Liste_controles.txt et leurs contenus : Controls_Contents.txt + * Le fichier recensant les informations de versions attendues selon les versions de firmware et pilote : Versions_attendues.txt + +Nouveautés: + +Corrections + * RE-Corrections des adresses des registres d'amplification des entrées analogiques. Tests faits avec 882 ET 222 (cette fois). + +Limitations connues + * Le basculement automatique des sources d'horloges n'est pas pleinement opérationnel (basculement sur source interne à 32kHz si activation par défaut). + +Limitations inconnues + * ... + + +Notes de la version V1.999.8 (PROTOTYPE Support Alp882) +====================================================== + +Contenu de la version : + + * Firmware en version 191/1.3 + * Le pilote en version 1.999.8 + * Le fichier contenant la liste des contrôles de la carte : Liste_controles.txt et leurs contenus : Controls_Contents.txt + * Le fichier recensant les informations de versions attendues selon les versions de firmware et pilote : Versions_attendues.txt + +Nouveautés: + + + +Corrections + * Corrections des adresses des registres de contrôles des ASRC. + * Corrections des adresses des registres d'amplification des entrées analogiques. + +Limitations connues + * Le basculement automatique des sources d'horloges n'est pas pleinement opérationnel (basculement sur source interne à 32kHz si activation par défaut). + +Limitations inconnues + * ... + + +Notes de la version V1.999.7 (PROTOTYPE Support Alp882) +======================================================= + +Contenu de la version : + + * Firmware en version 191/1.3 + * Le pilote en version 1.999.7 + * Le fichier contenant la liste des contrôles de la carte : Liste_controles.txt et leurs contenus : Controls_Contents.txt + * Le fichier recensant les informations de versions attendues selon les versions de firmware et pilote : Versions_attendues.txt + +Nouveautés: + * Renommage des contrôles concernant la gestion des sources de synchronisation (voir après) + + +Corrections + * Mixer des cartes Alp882 opérationel. Configuration différente entre Alp222 et Alp882. + +Limitations connues + * Le basculement automatique des sources d'horloges n'est pas pleinement opérationnel (basculement sur source interne à 32kHz si activation par défaut). + +Limitations inconnues + * ... + +Renommage des sources de synchronisation + + * "Clk Src" => "Clk Eff Src" + * "Clk Base"=> "Clk Eff Base" + * "Clk Coef" => "Clk Eff Coef" + * "CkSc Up" => "Clk Src Up" + * "CkSc Down" => "Clk Src Down" +Cela assure une meilleure lecture et les contrôles sont consécutifs dans alsamixer. Les numIds n'ont pas changés. + + +Notes de la version V1.999.6 (PROTOTYPE Support Alp882) +======================================================= + +Contenu de la version : + + * Firmware en version 191/1.3 + * Le pilote en version 1.999.6 + * Le fichier contenant la liste des contrôles de la carte : Liste_controles.txt et leurs contenus : controls_contents.txt + * Le fichier recensant les informations de versions attendues selon les versions de firmware et pilote : Versions_attendues.txt + +Nouveautés: + * Ajout des contrôles de gestion des sources d'horloges pour une Alp882.( voir les Limitations plus bas) + * contrôles AES SRC sont en logique négative (1=> AES SRC désactivé). Libellé suffixé par "Disable". + +Corrections + +Limitations connues + * Le basculement automatique des sources d'horloges n'est pas pleinement opérationnel (basculement sur source interne à 32kHz si activation par défaut). + +Limitations inconnues + * ... + + +Notes de la version V1.999.5 (PROTOTYPE Support Alp882) +====================================================== + +Contenu de la version : + + * Firmware en version 191/1.3 + * Le pilote en version 1.999.5 + * Le fichier contenant la liste des contrôles de la carte : Liste_controles.txt et leurs contenus : controls_contents.txt + * Le fichier recensant les informations de versions attendues selon les versions de firmware et pilote : Versions_attendues.txt + +Nouveautés: + * Définitions de l'ensemble des contrôles (ajout des alimentation fantômes des entrées lignes) + * Le Mixer est opérationnel, attention par défaut ALSA va configurer les noeuds à 0. La carte est donc muette à cause de la configuration par d'faut d'ALSA. + * Modification de l'ordre des contrôles pour dégager un troc commun entre les modèles LINE et LINE/MIC des 882. + * Renommage des zones MTD de la carte pour être en rapport avec les spécifications + ---- + "golden" + "fw-user-updatable" + "init-config" + "user-config" + "production" + "test" + ---- + Attention, la zone "test" est appelée à disparaitre dans les versions suivantes. + + +Corrections + * Firmware V191/1.3 : configuration par défaut du Mixer corrigée. + * Contrôles des AES SRC modifient bien les bits de contrôle dans la carte. + + +Limitations connues + * MIXER non paramétrable : il fonctionne en mode transparent. + * FS max de 192kHz (FMW) , pas testée avec le pilote. + +Limitations inconnues + * ... + + +Notes de la version V1.999.4 (PROTOTYPE Support Alp882) +======================================================= + +Contenu de la version : + + * Firmware en version 191 + * Le pilote en version 1.999.4 + * Le fichier contenant la liste des contrôles de la carte : Liste_controles.txt et leurs contenus : controls_contents.txt + * Le fichier recensant les informations de versions attendues selon les versions de firmware et pilote : Versions_attendues.txt + +Nouveautés: + * Support version 191 du firmware (adresse du MIXER) + +Corrections + + +Limitations connues + * MIXER non paramétrable : il fonctionne en mode transparent. + * FS max de 192kHz (FMW) , pas testée avec le pilote. + +Limitations inconnues + * ... + +Notes de la version V1.999.3 (PROTOTYPE Support Alp882) +====================================================== + +Contenu de la version : + + * Firmware en version 102 + * Le pilote en version 1.999.3 + * Le fichier contenant la liste des contrôles de la carte : Liste_controles.txt et leurs contenus : controls_contents.txt + * Le fichier recensant les informations de versions attendues selon les versions de firmware et pilote : Versions_attendues.txt + +Nouveautés: + * Ajout de log pour pb de détection des GPIOs Input/Output + +Corrections + * GPIOs : corrections de la régression pour les Alp222 + +Limitations connues + * MIXER non paramétrable : il fonctionne en mode transparent. + * FS max de 8kHz. + +Limitations inconnues + * ... + + + +Notes de la version V1.999.2 (PROTOTYPE Support Alp882) +====================================================== + +Contenu de la version : + + * Firmware en version 102 + * Le pilote en version 1.999.2 + * Le fichier contenant la liste des contrôles de la carte : Liste_controles.txt et leurs contenus : controls_contents.txt + * Le fichier recensant les informations de versions attendues selon les versions de firmware et pilote : Versions_attendues.txt + * Les fichiers du firmware V102 : alp882_multiboot_build_102_ublaze_1.0.mcs : pour programmation complète via la sonde JTAG et l'outil VIVADO, alp882_multiboot_user_build_102_ublaze_1.0.bin : pour mise à jour in situ UNE fois le Fiwrmware en version 102). + + +Nouveautés: + * GPIOs : Ok au niveau logique + * Support de la mise à jour du Firmware (comme pour Alp222, via /dev/mtd1) + +Corrections + +Limitations connues + * MIXER non paramétrable : il fonctionne en mode transparent. + * FS max de 8kHz. + +Limitations inconnues + * ... + + + + +Notes de la version V1.999.1 (PROTOTYPE Support Alp882) +====================================================== + +Contenu de la version : + + * Firmware en version 0 (alp-882_dyn_mixer_conf.mcs pour reprogrammation complète) dans l'archive alp-882_dyn_mixer_conf.zip + * Le pilote en version 1.999.1 + * Le fichier contenant la liste des contrôles de la carte : Liste_controles.txt et leurs contenus : controls_contents.txt + * Le fichier recensant les informations de versions attendues selon les versions de firmware et pilote : Versions_attendues.txt + +Nouveautés: + * C'est le premier pilote/Firmware : hautement instable. + +Corrections + + +Limitations connues + * MIXER non fonctionnel : il fonctionne en mode transparent. + +Limitations inconnues + * + diff --git a/snd-alpx-dkms/VersionsAttendues.txt b/snd-alpx-dkms/VersionsAttendues.txt new file mode 100644 index 0000000..6d29f8f --- /dev/null +++ b/snd-alpx-dkms/VersionsAttendues.txt @@ -0,0 +1,32 @@ + +=== VERSION INDIQUEES ==== + +V_3.4.3: + +Pilote: +version 3.4.3 build date: Mar 15 2024, time: 16:43:24 + +FPGA : + + ************ +Created Alp Stereo MIC soundcard[1]{#270300000002} : Alp222eMIC - Alp222e-MIC (Alp 222e-MIC - 0x0840), + == Revisions == + * Build: 286 + * Design: 1.16 + * Control: 2.6 + * Ampli In: 2.1 + * Mixer: 3.1 + * Ampli Out: 2.1 + * MCU: 2.9 + +************ +Created Alp multi-channels soundcard[3]{#270500000264} : Alp882eMIC - Alp882e-MIC (Alp 882e MIC - 0x08c0) , + == Revisions == + * Build: 251 + * Design: 1.4 + * Control: 1.11 + * Ampli In: 2.1 + * Mixer: 4.3 + * Ampli Out: 2.1 + * MCU: 1.11 +************ diff --git a/snd-alpx-dkms/debian/changelog b/snd-alpx-dkms/debian/changelog new file mode 100644 index 0000000..a6f18b9 --- /dev/null +++ b/snd-alpx-dkms/debian/changelog @@ -0,0 +1,5 @@ +snd-alpx-dkms (3.4.3-1) unstable; urgency=medium + + * Initial version + + -- Christian Pointner <equinox@spreadspace.org> Fri, 10 May 2024 20:32:44 +0200 diff --git a/snd-alpx-dkms/debian/control b/snd-alpx-dkms/debian/control new file mode 100644 index 0000000..9a8c48a --- /dev/null +++ b/snd-alpx-dkms/debian/control @@ -0,0 +1,13 @@ +Source: snd-alpx-dkms +Section: kernel +Priority: optional +Maintainer: Christian Pointner <equinox@helsinki.at> +Build-Depends: debhelper-compat (= 13), + dh-sequence-dkms, +Standards-Version: 4.6.0 +Rules-Requires-Root: no + +Package: snd-alpx-dkms +Architecture: all +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: ALSA Driver for Digigram ALPx cards diff --git a/snd-alpx-dkms/debian/rules b/snd-alpx-dkms/debian/rules new file mode 100755 index 0000000..53b94b4 --- /dev/null +++ b/snd-alpx-dkms/debian/rules @@ -0,0 +1,18 @@ +#!/usr/bin/make -f + +include /usr/share/dpkg/pkg-info.mk + +%: + dh $@ --with dkms + +override_dh_install: + dh_install snd-alpx/* usr/src/snd-alpx-$(DEB_VERSION_UPSTREAM)/ + +override_dh_dkms: + dh_dkms -V $(DEB_VERSION_UPSTREAM) -- snd-alpx/dkms.conf + +override_dh_auto_configure: +override_dh_auto_build: +override_dh_auto_test: +override_dh_auto_install: +override_dh_auto_clean: diff --git a/snd-alpx-dkms/debian/source/format b/snd-alpx-dkms/debian/source/format new file mode 100644 index 0000000..d3827e7 --- /dev/null +++ b/snd-alpx-dkms/debian/source/format @@ -0,0 +1 @@ +1.0 diff --git a/snd-alpx-dkms/snd-alpx/.gitignore b/snd-alpx-dkms/snd-alpx/.gitignore new file mode 100644 index 0000000..8696913 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/.gitignore @@ -0,0 +1,10 @@ +*.o +*.o.d +*.ko +*.cmd +*.mod +*.mod.c +Module.symvers +modules.order +load_alp_driver.sh +*.orig diff --git a/snd-alpx-dkms/snd-alpx/Makefile b/snd-alpx-dkms/snd-alpx/Makefile new file mode 100644 index 0000000..fbfafbd --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/Makefile @@ -0,0 +1,115 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Support for Digigram AlpX PCI-e boards +# +# Copyright (c) 2024 Digigram Digital (info@digigram.com) +# + +#Get OS family out of /etc/os-release file, need "grep" command +OS_FAMILY := $(strip $(filter-out ID, $(subst =, ,$(shell grep ^ID= /etc/os-release)))) + +# *** GENERIC *** +#UBUNTU +ifneq ( ,$(findstring ubuntu, $(OS_FAMILY))) + KERNEL_FLAVOUR ?= KERNEL_GENERIC +else ifneq ( ,$(findstring debian, $(OS_FAMILY))) + # Debian => Generic kernel + KERNEL_FLAVOUR ?= KERNEL_GENERIC +else ifneq ( ,$(findstring rhel, $(OS_FAMILY))) +# *** RedHat *** + KERNEL_FLAVOUR ?= KERNEL_REDHAT +else ifneq ( ,$(findstring centos, $(OS_FAMILY))) +# CentOs => RedHat + KERNEL_FLAVOUR ?= KERNEL_REDHAT +else ifneq ( ,$(findstring fedora, $(OS_FAMILY))) + # fedora => RedHat + KERNEL_FLAVOUR ?= KERNEL_REDHAT +else ifneq ( ,$(findstring rocky, $(OS_FAMILY))) + # Rocky => RedHat + KERNEL_FLAVOUR ?= KERNEL_REDHAT +else +# GENERIC kernel by default + KERNEL_FLAVOUR ?= KERNEL_GENERIC +endif + + + +SND_ALPX_CCFLAGS += -DCONFIG_${KERNEL_FLAVOUR} + + +KERNEL_VERSION ?= $(shell uname -r) +KERNEL_PATH ?= /lib/modules/$(KERNEL_VERSION)/build + +LOAD_DRIVER_SCRIPT_NAME:="load_alp_driver.sh" +BUILD_LOADER_SCRIPT_PATH:=./tools/build-load-script.sh + +#Special config, MUST check the consistency ! +ifeq ( ,$(finsdtring VARIANT_MADI, $(SND_ALPX_CCFLAGS))) +SND_ALPX_CCFLAGS += -DCONFIG_ALP_MADI_PASSTHROUGH +endif + +#Activate the MCU logs dump (at driver level) +#SND_ALPX_CCFLAGS += -DCONFIG_ALPX_WITH_PROC_LOG + +#Activate CONTROLS Logs +#SND_ALPX_CCFLAGS += -DCONFIG_ALPX_LOG_CONTROLS + + +#The libXDMA Debug messages activation +# SND_ALPX_CCFLAGS += -D__LIBXDMA_DEBUG__ + +#Dump the DMA buffers(size in bytes, if 0 : all buffer). +#SND_ALPX_CCFLAGS += -DCONFIG_ALPX_DUMP_DMA_BUFFER +SND_ALPX_CCFLAGS += -DCONFIG_ALPX_DUMP_DMA_BUFFER_SIZE=128 + +#Module revision log, need to desable the date-time warning +SND_ALPX_CCFLAGS += -Wno-error=date-time -Wno-date-time + +#Enable the GPIO support in the card +ifeq (true,$(CONFIG_WITHOUT_GPIO)) +SND_ALPX_CCFLAGS += -DCONFIG_WITHOUT_GPIO +else +OPTIONNAL_UNIT += alpx_gpio.o +endif + + +#Activate The REG Debug feature +#SND_ALPX_CCFLAGS += -DWITH_REG_DEBUG + +ccflags-y += ${SND_ALPX_CCFLAGS} + +snd-alpx-xdma-y := snd_alpx_xdma.o +snd-alpx-y := $(OPTIONNAL_UNIT) alpx_axcmem.o alpx_core.o alpx_proc.o alpx_mtd.o alpx_controls.o alpx_streams.o alpx_cards.o alpx_xdma.o + +#ALPX module in first +obj-m := snd-alpx.o + +# XDMA Module creation +obj-m += snd-alpx-xdma.o + +#Embed regmap--mmio in XDMA module if not enabled, use the 4.19 version as this is the base required for XDMA support +ifndef CONFIG_REGMAP_MMIO +snd-alpx-xdma-y += core/generic/4.19/regmap-mmio.o +endif + +all: load-script + $(MAKE) -C $(KERNEL_PATH) M=$(CURDIR) modules + +clean: + $(MAKE) -C $(KERNEL_PATH) M=$(CURDIR) clean + rm -f ${LOAD_DRIVER_SCRIPT_NAME} + +.PHONY: clean dump_env + +#Add chmod to handle the exec right to the script. +load-script: + chmod 744 ${BUILD_LOADER_SCRIPT_PATH} && exec ${BUILD_LOADER_SCRIPT_PATH} ${LOAD_DRIVER_SCRIPT_NAME} + +dump_env: + @echo "SND_ALPX_CCFLAGS: $(SND_ALPX_CCFLAGS)" + @echo "obj-m: $(obj-m)" + @echo "snd-alpx obj: $(snd-alpx-y)" + @echo "config regmap: $(CONFIG_REGMAP_MMIO)" + @echo "GCC :" CONFIG_CC_VERSION_TEXT + @echo "GCC :" $(CONFIG_CC_VERSION_TEXT) + @echo "CONFIG_WITHOUT_GPIO: $(CONFIG_WITHOUT_GPIO)" diff --git a/snd-alpx-dkms/snd-alpx/alpx.h b/snd-alpx-dkms/snd-alpx/alpx.h new file mode 100644 index 0000000..2cad9b9 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/alpx.h @@ -0,0 +1,268 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* +* Support for Digigram AlpX PCI-e boards +* +* Copyright (c) 2024 Digigram Digital (info@digigram.com) +*/ + +#ifndef _ALPX_H_ +#define _ALPX_H_ + + +#include "alpx_reg.h" +#include "alpx_streams.h" + +#include <linux/version.h> + +#if !defined (CONFIG_WITHOUT_GPIO) +#define ALPX_WITH_GPIO +#include <linux/gpio.h> +#include <linux/gpio/driver.h> +#endif + +#include <linux/mtd/mtd.h> +#include <linux/mtd/partitions.h> +#include <linux/mutex.h> +#include <sound/pcm.h> + +/* Values */ + +#define CARD_NAME "Digigram AlpX" + +#define ALPX_VARIANT_FEATURE_GPIOS BIT(0) + +/* Structures */ + +enum alpx_variant_model { + ALPX_VARIANT_DEAD, + ALPX_VARIANT_MODEL_MADI, + ALPX_VARIANT_MODEL_MADI_LOOPBACK, + ALPX_VARIANT_MODEL_ALP222, + ALPX_VARIANT_MODEL_ALP222_MIC, + ALPX_VARIANT_MODEL_ALP882, + ALPX_VARIANT_MODEL_ALP882_MIC, + ALPX_VARIANT_MODEL_ALP442, + ALPX_VARIANT_MODEL_ALP442_MIC, + ALPX_VARIANT_MODEL_ALPDANTE, +}; + +/* Flash partitions IDs */ +enum ALPX_FLASH_PARTITION_ID { + ALPX_FLASH_PARTITION_GOLDEN_ID = 0, + ALPX_FLASH_PARTITION_FW_ID, + ALPX_FLASH_PARTITION_INIT_CFG_ID, + ALPX_FLASH_PARTITION_USER_CFG_ID, + ALPX_FLASH_PARTITION_PRODUCTION_ID, + ALPX_FLASH_PARTITION_QTY +}; + +/* Flash partitions IDs in DEAD mode ! only production */ +enum ALPX_DEAD_FLASH_PARTITION_ID { + ALPX_DEAD_FLASH_PARTITION_GOLDEN_PROD_ID = 0, + ALPX_DEAD_FLASH_PARTITION_PRODUCTION_ID, + ALPX_DEAD_FLASH_PARTITION_QTY +}; + +/* Structures */ + + +struct alpx_variant_gpios { + unsigned int base; + unsigned int inputs_reg_offset; + unsigned int inputs_qty; + unsigned int outputs_reg_offset; + unsigned int outputs_qty; +}; + +struct alpx_flash_partitions { + struct mtd_partition* partitions; + uint32_t qty; + uint32_t qty_for_fw_update; +}; + +struct alpx_variant { + enum alpx_variant_model model; + const char *shortname; + const char *longname; + const char *mixername; + u64 features; + + struct alpx_control_descriptor *control_descriptors; + unsigned int control_descriptors_count; + + struct snd_pcm_hardware* playback_hw; + struct snd_pcm_hardware* capture_hw; + struct alpx_variant_gpios gpios; + uint32_t flash_golden_production_base; + struct alpx_flash_partitions flash_partitions; +}; + + +struct alpx_config { + spinlock_t lock; + unsigned int users; + + unsigned int rate; +}; + +struct alpx_identity { + uint16_t sub_system_id; /* PCIe sub-system Id as read out of Production area*/ + uint32_t ver_fpga; /* FPGA version */ + uint32_t ver_mcu; /* MCU version.revision !! */ + uint64_t serial_number; /* Card full identifier tag */ +}; + +struct alpx_device { + struct device *dev; + struct pci_dev *pci_dev; +#if defined(ALPX_WITH_GPIO) + struct gpio_chip gpio_chip; +#endif + void *base; + + struct platform_device *xdma_pdev; + struct alpx_config config; + + struct alpx_control *controls; + unsigned int controls_index; + unsigned int controls_count; + + struct alpx_pipe capture; + struct alpx_pipe playback; + + const struct alpx_variant *variant; + + struct mutex proc_mutex; + + struct mtd_info mtd_info; +#ifdef WITH_REG_DEBUG + uint32_t dbg_reg_offset; +#endif + struct alpx_identity identity; +}; + +/* Constants */ + +// The flash chip size (in bytes). +#define ALPX_FLASH_CHIP_SIZE 0x800000 + +// Sector size conversions +#define ALPX_FLASH_SECTOR_SHIFT 12 +#define ALPX_FLASH_SECTOR_SIZE (1 << ALPX_FLASH_SECTOR_SHIFT) + +/* Amplifiers gains */ +#define ALP_AMPLIFIER_GAIN_MIN_cdB -9010 +#define ALP_AMPLIFIER_GAIN_MAX_cdB 1200 + +#define ALP_AMPLIFIER_GAIN_MIN_REG 0 +#define ALP_AMPLIFIER_GAIN_MAX_REG 1021 + +/* MIC Gains tange in dB */ +#define ALP222_MIC_GAINS_MIN_REG_VAL 10 +#define ALP222_MIC_GAINS_MAX_REG_VAL 65 +#define ALP222_MIC_REG_GAIN_SHIFT 9 +#define ALP222_MIC_GAIN_MIN_cdB 1000 +#define ALP222_MIC_GAIN_MAX_cdB 6500 + + +/* ALP222 ANALOG Equalization amplifiers */ +#define ALP222_ANALOG_EQ_GAIN_MIN_cdB -8800 +#define ALP222_ANALOG_EQ_GAIN_MAX_cdB 3900 + +#define ALP222_ANALOG_EQ_GAIN_MIN_REG 0 +#define ALP222_ANALOG_EQ_GAIN_MAX_REG 255 + +/* Registers offset range : from 0x60000 up to 0x7C200*/ +#define ALP222_MIN_REG_OFFSET 0x60000 +#define ALP222_MAX_REG_OFFSET 0x7C200 + +/* Special revisions */ +/* -The design version is 1.5- */ +#define ALP222_1_5_DESIGN_VERSION ((1<<16)|(5)) + +/* BUILD version register appears in version :... */ +#define ALP222_DESIGN_WITH_BUILD_REGISTER_VERSION ALP222_1_5_DESIGN_VERSION + + +/* Range of the LINE/MIC gains (in register domain)*/ +#define ALPMC_LINE_ANALOG_GAIN_MIN_REG 0 +#define ALPMC_LINE_ANALOG_GAIN_MIN_cdB -2400 + +#define ALPMC_MIC_ANALOG_GAIN_MIN_REG ALPMC_LINE_ANALOG_GAIN_MIN_REG +#define ALPMC_MIC_ANALOG_GAIN_MIN_cdB ALPMC_LINE_ANALOG_GAIN_MIN_cdB + + +/* Gain formula : G = (0.5*(N-1)-24), N : register value */ +/* 161 => +56dB */ +#define ALPMC_MIC_ANALOG_GAIN_MAX_REG 162 +#define ALPMC_MIC_ANALOG_GAIN_MAX_cdB 5600 + +/* 82 => +16dB */ +#define ALPMC_LINE_ANALOG_GAIN_MAX_REG 82 +#define ALPMC_LINE_ANALOG_GAIN_MAX_cdB 1600 + +static bool inline alpx_is_madi(struct alpx_device *alpx_dev) +{ + return alpx_dev->variant->model == ALPX_VARIANT_MODEL_MADI || + alpx_dev->variant->model == ALPX_VARIANT_MODEL_MADI_LOOPBACK; +} + +static bool inline alpx_is_222_line(struct alpx_device *alpx_dev) +{ + return alpx_dev->variant->model == ALPX_VARIANT_MODEL_ALP222; +} + +static bool inline alpx_is_222_mic(struct alpx_device *alpx_dev) +{ + return alpx_dev->variant->model == ALPX_VARIANT_MODEL_ALP222_MIC; +} + +static bool inline alpx_is_222(struct alpx_device *alpx_dev) +{ + return alpx_is_222_line(alpx_dev) || alpx_is_222_mic(alpx_dev); +} + +static bool inline alpx_is_882_line(struct alpx_device *alpx_dev) +{ + return alpx_dev->variant->model == ALPX_VARIANT_MODEL_ALP882; +} + +static bool inline alpx_is_882_mic(struct alpx_device *alpx_dev) +{ + return alpx_dev->variant->model == ALPX_VARIANT_MODEL_ALP882_MIC; +} + +static bool inline alpx_is_882(struct alpx_device *alpx_dev) +{ + return alpx_is_882_line(alpx_dev) || alpx_is_882_line(alpx_dev); +} + +static bool inline alpx_is_442_line(struct alpx_device *alpx_dev) +{ + return alpx_dev->variant->model == ALPX_VARIANT_MODEL_ALP442; +} + +static bool inline alpx_is_442_mic(struct alpx_device *alpx_dev) +{ + return alpx_dev->variant->model == ALPX_VARIANT_MODEL_ALP442_MIC; +} + +static bool inline alpx_is_442(struct alpx_device *alpx_dev) +{ + return alpx_is_442_line(alpx_dev) || alpx_is_442_line(alpx_dev); +} + +static bool inline alpx_is_multichannel(struct alpx_device *alpx_dev) +{ + return alpx_is_882(alpx_dev) || alpx_is_442(alpx_dev); +} + +static bool inline alpx_is_dante (struct alpx_device *alpx_dev) +{ + return alpx_dev->variant->model == ALPX_VARIANT_MODEL_ALPDANTE; +} + +unsigned int +alpx_get_samples_counter(struct alpx_device *alpx_dev); + +#endif diff --git a/snd-alpx-dkms/snd-alpx/alpx_axcmem.c b/snd-alpx-dkms/snd-alpx/alpx_axcmem.c new file mode 100644 index 0000000..4966b10 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/alpx_axcmem.c @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* +* Support for Digigram AlpX PCI-e boards +* +* Copyright (c) 2024 Digigram Digital (info@digigram.com) +*/ + +#include "alpx_axcmem.h" + +#include <linux/module.h> +#include <linux/printk.h> +#include <asm/byteorder.h> + +/* Items sizes in bytes*/ +static const unsigned int AXCMEM_PAGE_SIZE = 32; +static const unsigned int AXCMEM_LINE_SIZE = 4; + +/* AxCMem area offset */ +static const uint32_t AXCMEM_AREA_OFFSET = 0x72000; + + +void* alpx_axcmem_getRegAddr(struct alpx_device* alp, + const struct alpx_axcmem_loc* loc) +{ + dev_dbg(alp->dev," BAR:%p, loc{%d:%d:%d}\n", + alp->base, + loc->page, loc->line, loc->row); + + return (uint8_t*)alp->base + + AXCMEM_AREA_OFFSET + + loc->page * AXCMEM_PAGE_SIZE + + loc->line * AXCMEM_LINE_SIZE + + loc->row; +} + +void* alpx_axcmem_getPointedRegAddrByRefLoc(struct alpx_device* alp, + const struct alpx_axcmem_loc* ref_loc, + const struct alpx_axcmem_loc* loc) +{ + void* const ref_reg_addr = alpx_axcmem_getRegAddr(alp, ref_loc); + + dev_dbg(alp->dev, "BAR:%p, base:%p=>%d, loc{%d:%d:%d}\n", + alp->base, ref_reg_addr, alpx_axcmem_getRegU8Value(ref_reg_addr), + loc->page, loc->line, loc->row); + + return (uint8_t*)alp->base + AXCMEM_AREA_OFFSET + alpx_axcmem_getRegU8Value(ref_reg_addr) * AXCMEM_PAGE_SIZE + + loc->page * AXCMEM_PAGE_SIZE + + loc->line * AXCMEM_LINE_SIZE + + loc->row; +} + +int alpx_acxmem_getByteArrayByRefLoc(struct alpx_device* alp, + const struct alpx_axcmem_loc* ref_loc, + const struct alpx_axcmem_loc* loc, + unsigned char* dst, + unsigned int length) +{ + unsigned int idx = 0; + const unsigned char* src = NULL; + + if ((alp == NULL) || + (ref_loc == NULL) || + (loc == NULL) || + (dst == NULL)) { + return -EINVAL; + } + + if (length == 0) + return 0; + + src = (unsigned char*) alpx_axcmem_getPointedRegAddrByRefLoc(alp, ref_loc, loc); + + for (idx = 0 ; idx < length ; ++idx) { + dst[idx] = src[idx]; + dev_dbg(alp->dev, " src[%d]: 0x%02x => dst[%d]: 0x%02x\n", idx, src[idx], idx, dst[idx]); + } + + return 0; +} + +uint32_t alpx_axcmem_getRegU8Value_ptr(void* addr) +{ + return alpx_axcmem_getRegU8Value(addr); +} + +void alpx_axcmem_setRegU8Value_ptr(void* addr, uint32_t value) +{ + alpx_axcmem_setRegU8Value(addr, value); +} + +uint32_t alpx_axcmem_getRegU16Value_ptr(void* addr) +{ + return alpx_axcmem_getRegU16Value(addr); +} + +void alpx_axcmem_setRegU16Value_ptr(void* addr, uint32_t value) +{ + alpx_axcmem_setRegU16Value(addr, value); +} + +uint32_t alpx_axcmem_getRegBEU16Value_ptr(void* addr) +{ + return alpx_axcmem_getRegBEU16Value(addr); +} + +void alpx_axcmem_setRegBEU16Value_ptr(void* addr, uint32_t value) +{ + alpx_axcmem_setRegBEU16Value(addr, value); +} + +uint32_t alpx_axcmem_getRegU32Value_ptr(void* addr) +{ + return alpx_axcmem_getRegU32Value(addr); +} + +void alpx_axcmem_setRegU32Value_ptr(void* addr, uint32_t value) +{ + alpx_axcmem_setRegU32Value(addr, value); +} + +uint32_t alpx_axcmem_getRegBEU32Value_ptr(void* addr) +{ + return alpx_axcmem_getRegBEU32Value(addr); +} + +void alpx_axcmem_setRegBEU32Value_ptr(void* addr, uint32_t value) +{ + alpx_axcmem_setRegBEU32Value(addr, value); +} diff --git a/snd-alpx-dkms/snd-alpx/alpx_axcmem.h b/snd-alpx-dkms/snd-alpx/alpx_axcmem.h new file mode 100644 index 0000000..20b35a0 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/alpx_axcmem.h @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* +* Support for Digigram AlpX PCI-e boards +* +* Copyright (c) 2024 Digigram Digital (info@digigram.com) +*/ + +#ifndef _ALPX_AXCMEM_H_ +#define _ALPX_AXCMEM_H_ + +#include "alpx.h" + +#include <linux/types.h> +#include <linux/io.h> + + +/** Types **/ + +/* Register's location in AXCMEM area */ +struct alpx_axcmem_loc +{ + uint32_t page; /* page index, absolute or relative to a page group */ + uint32_t line; /* line index */ + uint32_t row; /* Row index */ +}; + +/** Services **/ +/* Navigation */ + +/* return the register's address given the alp device and register's location */ +void* alpx_axcmem_getRegAddr(struct alpx_device* alp, + const struct alpx_axcmem_loc* loc); + +/* Return the register's address in a pointed page through the given reference register's localation, base is the address of the used PCI BAR */ +void* alpx_axcmem_getPointedRegAddrByRefLoc(struct alpx_device* alp, + const struct alpx_axcmem_loc* ref_loc, + const struct alpx_axcmem_loc* loc); + + + +/* Values, these functions check the value alignement ! Use assertion !*/ +/* Values Little Endian by default, "BE" for big endian */ +static inline uint8_t alpx_axcmem_getRegU8Value(void* addr) +{ + return readb(addr); +} + +static inline void alpx_axcmem_setRegU8Value(void* addr, uint8_t value) +{ + writeb(value, addr); +} + +static inline uint16_t alpx_axcmem_getRegU16Value(void* addr) +{ + return le16_to_cpu(readw(addr)); +} + +static inline void alpx_axcmem_setRegU16Value(void* addr, uint16_t value) +{ + writew(cpu_to_le16(value), addr); +} + +static inline uint16_t alpx_axcmem_getRegBEU16Value(void* addr) +{ + return be16_to_cpu(alpx_axcmem_getRegU16Value(addr)); + +} + +static inline void alpx_axcmem_setRegBEU16Value(void* addr, uint16_t value) +{ + writew(cpu_to_be16(value), addr); +} + + +static inline uint32_t alpx_axcmem_getRegU32Value(void* addr) +{ + return le32_to_cpu(readl(addr)); +} + +static inline void alpx_axcmem_setRegU32Value(void* addr, uint32_t value) +{ + + writel(cpu_to_le32(value), addr); +} + +static inline uint32_t alpx_axcmem_getRegBEU32Value(void* addr) +{ + return be32_to_cpu(readl(addr)); +} + +static inline void alpx_axcmem_setRegBEU32Value(void* addr, uint32_t value) +{ + + writel(cpu_to_be32(value), addr); +} +/* Same but can be used as ptr : not inlined*/ +uint32_t alpx_axcmem_getRegU8Value_ptr(void* addr); +void alpx_axcmem_setRegU8Value_ptr(void* addr, uint32_t value); +uint32_t alpx_axcmem_getRegU16Value_ptr(void* addr); +void alpx_axcmem_setRegU16Value_ptr(void* addr, uint32_t value); +uint32_t alpx_axcmem_getRegBEU16Value_ptr(void* addr); +void alpx_axcmem_setRegBEU16Value_ptr(void* addr, uint32_t value); +uint32_t alpx_axcmem_getRegU32Value_ptr(void* addr); +void alpx_axcmem_setRegU32Value_ptr(void* addr, uint32_t value); +uint32_t alpx_axcmem_getRegBEU32Value_ptr(void* addr); +void alpx_axcmem_setRegBEU32Value_ptr(void* addr, uint32_t value); + + +int alpx_acxmem_getByteArrayByRefLoc(struct alpx_device* alp, + const struct alpx_axcmem_loc* ref_loc, + const struct alpx_axcmem_loc* loc, + unsigned char* dst, + unsigned int length); + +#endif /*_ALPX_AXCMEM_H_*/ diff --git a/snd-alpx-dkms/snd-alpx/alpx_cards.c b/snd-alpx-dkms/snd-alpx/alpx_cards.c new file mode 100644 index 0000000..7f9ec3a --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/alpx_cards.c @@ -0,0 +1,545 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* +* Support for Digigram AlpX PCI-e boards +* +* Copyright (c) 2024 Digigram Digital (info@digigram.com) +*/ + +#include <linux/pci.h> + +#include "alpx_cards.h" +#include "alpx_reg.h" +#include "alpx_mtd.h" +#include "alpx_axcmem.h" +#include "alpx_variants_dante.h" + +#include <linux/delay.h> + +void alpstereo_print_identity(struct alpx_device *alpx_dev, struct snd_card *card, const unsigned char* label) +{ + const unsigned int design_revision = readl(ALPX_REG(alpx_dev, ALP, CONTROL, DESIGN_VERSION)); + + //Add Build information, only for design >= 1.8 + if (design_revision >= ALP222_DESIGN_WITH_BUILD_REGISTER_VERSION) { + const unsigned int build_version = alpx_dev->identity.ver_fpga; + const unsigned int ctrl_revision = readl(ALPX_COMMON_REG(alpx_dev, ALP222, CONTROL, VERSION)); + const unsigned int mxr_revision = readl(ALPX_COMMON_REG(alpx_dev, ALP222, MIXER, VERSION)); + const unsigned int ampli_in_revision = readl(ALPX_COMMON_REG(alpx_dev, ALP222, AMPLI_IN, VERSION)); + const unsigned int ampli_out_revision = readl(ALPX_COMMON_REG(alpx_dev, ALP222, AMPLI_OUT, VERSION)); + const unsigned int proc_revision = alpx_dev->identity.ver_mcu; + + dev_info( alpx_dev->dev,\ + "\n************ \n" + "%s Alp Stereo %s soundcard[%d]{#%llu} : %s - %s (%s - 0x%04x), \n\t== Revisions ==\n\t* Build: \t\t%u\n\t* Design: \t\t%u.%lu\n\t* Control: \t\t%u.%lu\n\t* Ampli In:\t\t%u.%lu\n\t* Mixer: \t\t%u.%lu\n" + "\t* Ampli Out:\t\t%u.%lu\n\t* MCU:\t\t\t%u.%lu\n" + "************\n", + label, + alpx_is_222_mic(alpx_dev) ? "MIC":"", + card->number, + alpx_dev->identity.serial_number, + card->id, + card->shortname, + card->longname, + alpx_dev->identity.sub_system_id, + build_version, + ALPX_COMMON_VERSION_VERSION(design_revision), + ALPX_COMMON_VERSION_REVISION(design_revision), + + ALPX_COMMON_VERSION_VERSION(ctrl_revision), + ALPX_COMMON_VERSION_REVISION(ctrl_revision), + + ALPX_COMMON_VERSION_VERSION(ampli_in_revision), + ALPX_COMMON_VERSION_REVISION(ampli_in_revision), + + ALPX_COMMON_VERSION_VERSION(mxr_revision), + ALPX_COMMON_VERSION_REVISION(mxr_revision), + + ALPX_COMMON_VERSION_VERSION(ampli_out_revision), + ALPX_COMMON_VERSION_REVISION(ampli_out_revision), + + ALPX_COMMON_VERSION_VERSION(proc_revision), + ALPX_COMMON_VERSION_REVISION(proc_revision) + ); + } + else { + const unsigned int ctrl_revision = readl(ALPX_COMMON_REG(alpx_dev, ALP222, CONTROL, VERSION)); + const unsigned int mxr_revision = readl(ALPX_COMMON_REG(alpx_dev, ALP222, MIXER, VERSION)); + const unsigned int ampli_in_revision = readl(ALPX_COMMON_REG(alpx_dev, ALP222, AMPLI_IN, VERSION)); + const unsigned int ampli_out_revision = readl(ALPX_COMMON_REG(alpx_dev, ALP222, AMPLI_OUT, VERSION)); + const unsigned int proc_revision = readl(ALPX_REG(alpx_dev, ALP, PROC, VERSION)); +dev_info(alpx_dev->dev, "Serial# : %llu\n", alpx_dev->identity.serial_number); + dev_info( alpx_dev->dev,\ + "\n************ \n" + "%s Alp222 soundcard[%d] {#%llu} : %s - %s (%s - 0x%04x), \n\t== Revisions ==\n\t* Design: \t\t%u.%lu\n\t* Control: \t\t%u.%lu\n\t* Ampli In:\t\t%u.%lu\n\t* Mixer: \t\t%u.%lu\n" + "\t* Ampli Out:\t\t%u.%lu\n\t* MCU:\t\t\t%u.%lu\n" + "************\n", + label, + card->number, + alpx_dev->identity.serial_number, + card->id, + card->shortname, + card->longname, + alpx_dev->identity.sub_system_id, + ALPX_COMMON_VERSION_VERSION(design_revision), + ALPX_COMMON_VERSION_REVISION(design_revision), + + ALPX_COMMON_VERSION_VERSION(ctrl_revision), + ALPX_COMMON_VERSION_REVISION(ctrl_revision), + + ALPX_COMMON_VERSION_VERSION(ampli_in_revision), + ALPX_COMMON_VERSION_REVISION(ampli_in_revision), + + ALPX_COMMON_VERSION_VERSION(mxr_revision), + ALPX_COMMON_VERSION_REVISION(mxr_revision), + + ALPX_COMMON_VERSION_VERSION(ampli_out_revision), + ALPX_COMMON_VERSION_REVISION(ampli_out_revision), + + ALPX_COMMON_VERSION_VERSION(proc_revision), + ALPX_COMMON_VERSION_REVISION(proc_revision) + ); + } +} + +void alpmadi_print_identity(struct alpx_device *alpx_dev, struct snd_card *card, const unsigned char* label) +{ + + const unsigned int ctrl_revision = readl(ALPX_COMMON_REG(alpx_dev, ALPMADI, CONTROL, VERSION)); + const unsigned int mxr_revision = readl(ALPX_COMMON_REG(alpx_dev, ALPMADI, MIXER, VERSION)); + const unsigned int meas_daw_in_revision = readl(ALPX_COMMON_REG(alpx_dev, ALPMADI, MEAS_DAW_IN, VERSION)); + const unsigned int meas_daw_out_revision = readl(ALPX_COMMON_REG(alpx_dev, ALPMADI, MEAS_DAW_OUT, VERSION)); + const unsigned int meas_madi_in_revision = readl(ALPX_COMMON_REG(alpx_dev, ALPMADI, MEAS_MADI_IN, VERSION)); + const unsigned int meas_madi_out_revision = readl(ALPX_COMMON_REG(alpx_dev, ALPMADI, MEAS_MADI_OUT, VERSION)); + const unsigned int gain_madi_in_revision = readl(ALPX_COMMON_REG(alpx_dev, ALPMADI, GAIN_MADI_IN, VERSION)); + const unsigned int gain_madi_out_revision = readl(ALPX_COMMON_REG(alpx_dev, ALPMADI, GAIN_MADI_OUT, VERSION)); + const unsigned int gain_daw_in_revision = readl(ALPX_COMMON_REG(alpx_dev, ALPMADI, GAIN_DAW_IN, VERSION)); + const unsigned int gain_daw_out_revision = readl(ALPX_COMMON_REG(alpx_dev, ALPMADI, GAIN_DAW_OUT, VERSION)); + const unsigned int router_in_revision = readl(ALPX_COMMON_REG(alpx_dev, ALPMADI, ROUTER_IN, VERSION)); + + dev_info( alpx_dev->dev,\ + "************ \n" + "%s AlpMadi soundcard[%d]{#%llu} : %s - %s (%s - 0x%04x), \n\t== Revisions ==\n\t * Control: \t\t%u.%lu\n\t * Mixer: \t\t%u.%lu\n\t * Gain Daw In:\t%u.%lu\n\t * Gain Daw Out:\t%u.%lu\n\t * Gain MADI In:\t\t%u.%lu\n\t * Gain MADI Out:\t%u.%lu\n\t * Meas DAW In:\t%u.%lu\n\t * Meas Daw Out:\t%u.%lu\n\t * Meas MADI In:\t\t%u.%lu\n\t * Meas MADI Out:\t%u.%lu\n\t * Router:\t\t%u.%lu\n" + "************\n", + label, + card->number, + alpx_dev->identity.serial_number, + card->id, + card->shortname, + card->longname, + alpx_dev->identity.sub_system_id, + ALPX_COMMON_VERSION_VERSION(ctrl_revision), + ALPX_COMMON_VERSION_REVISION(ctrl_revision), + + ALPX_COMMON_VERSION_VERSION(mxr_revision), + ALPX_COMMON_VERSION_REVISION(mxr_revision), + + ALPX_COMMON_VERSION_VERSION(gain_daw_in_revision), + ALPX_COMMON_VERSION_REVISION(gain_daw_in_revision), + ALPX_COMMON_VERSION_VERSION(gain_daw_out_revision), + ALPX_COMMON_VERSION_REVISION(gain_daw_out_revision), + + ALPX_COMMON_VERSION_VERSION(gain_madi_in_revision), + ALPX_COMMON_VERSION_REVISION(gain_madi_in_revision), + ALPX_COMMON_VERSION_VERSION(gain_madi_out_revision), + ALPX_COMMON_VERSION_REVISION(gain_madi_out_revision), + + ALPX_COMMON_VERSION_VERSION(meas_daw_in_revision), + ALPX_COMMON_VERSION_REVISION(meas_daw_in_revision), + ALPX_COMMON_VERSION_VERSION(meas_daw_out_revision), + ALPX_COMMON_VERSION_REVISION(meas_daw_out_revision), + + ALPX_COMMON_VERSION_VERSION(meas_madi_in_revision), + ALPX_COMMON_VERSION_REVISION(meas_madi_in_revision), + ALPX_COMMON_VERSION_VERSION(meas_madi_out_revision), + ALPX_COMMON_VERSION_REVISION(meas_madi_out_revision), + + ALPX_COMMON_VERSION_VERSION(router_in_revision), + ALPX_COMMON_VERSION_REVISION(router_in_revision)); +} + +void alpmultichan_print_identity(struct alpx_device *alpx_dev, struct snd_card *card, const unsigned char* label) +{ + const unsigned int design_revision = readl(ALPX_REG(alpx_dev, ALP, CONTROL, DESIGN_VERSION)); + const unsigned int build_version = alpx_dev->identity.ver_fpga; + const unsigned int ctrl_revision = readl(ALPX_COMMON_REG(alpx_dev, ALPMC, CONTROL, VERSION)); + const unsigned int mxr_revision = readl(ALPX_COMMON_REG(alpx_dev, ALPMC, MIXER, VERSION)); + const unsigned int ampli_in_revision = readl(ALPX_COMMON_REG(alpx_dev, ALPMC, AMPLI_IN, VERSION)); + const unsigned int ampli_out_revision = readl(ALPX_COMMON_REG(alpx_dev, ALPMC, AMPLI_OUT, VERSION)); + const unsigned int proc_revision = alpx_dev->identity.ver_mcu; + + dev_info( alpx_dev->dev,\ + "\n************ \n" + "%s Alp multi-channels soundcard[%d]{#%llu} : %s - %s (%s - 0x%04x) , \n\t== Revisions ==\n\t* Build: \t\t%u\n\t* Design: \t\t%u.%lu\n\t* Control: \t\t%u.%lu\n\t* Ampli In:\t\t%u.%lu\n\t* Mixer: \t\t%u.%lu\n" + "\t* Ampli Out:\t\t%u.%lu\n\t* MCU:\t\t\t%u.%lu\n" + "************\n", + label, + card->number, + alpx_dev->identity.serial_number, + card->id, + card->shortname, + card->longname, + alpx_dev->identity.sub_system_id, + build_version, + ALPX_COMMON_VERSION_VERSION(design_revision), + ALPX_COMMON_VERSION_REVISION(design_revision), + + ALPX_COMMON_VERSION_VERSION(ctrl_revision), + ALPX_COMMON_VERSION_REVISION(ctrl_revision), + + ALPX_COMMON_VERSION_VERSION(ampli_in_revision), + ALPX_COMMON_VERSION_REVISION(ampli_in_revision), + + ALPX_COMMON_VERSION_VERSION(mxr_revision), + ALPX_COMMON_VERSION_REVISION(mxr_revision), + + ALPX_COMMON_VERSION_VERSION(ampli_out_revision), + ALPX_COMMON_VERSION_REVISION(ampli_out_revision), + + ALPX_COMMON_VERSION_VERSION(proc_revision), + ALPX_COMMON_VERSION_REVISION(proc_revision)); +} + +static int alpx_card_read_serial_number(struct alpx_device* alpx_dev) +{ + unsigned char raw_serial[9]; + int ret = alpx_mtd_read_shared(alpx_dev, ALPX_SERIAL_OFFSET_IN_PRODUCTION, + raw_serial, + sizeof(raw_serial) - 1); + + raw_serial[sizeof(raw_serial) - 1] = 0; + + if (ret){ + dev_err(alpx_dev->dev, "Error %d when reading Shared Area\n", ret); + /* DEFAULT VALUES */ + alpx_dev->identity.serial_number = (~ 0); + return -EIO; + } + + dev_dbg(alpx_dev->dev, " %s() : BEFORE shift %llu // 0x%llx\n", __func__, (uint64_t)raw_serial, (uint64_t)raw_serial); + + //Conversion RAW => Little endian (not use be64_to_cpu() ?? Should be tested later) + alpx_dev->identity.serial_number = ((uint64_t)raw_serial[0])<<32 | ((uint64_t)raw_serial[1]) << 24 | + ((uint64_t)raw_serial[2]) << 16 | + ((uint64_t)raw_serial[3]) << 8 | + ((uint64_t)raw_serial[4]); + + return 0; +} + +int alpxxx_finalize_identity(struct alpx_device* alpx_dev) +{ + alpx_dev->identity.ver_mcu = readl(ALPX_REG(alpx_dev, ALP, PROC, VERSION)); + alpx_dev->identity.ver_fpga = readl(ALPX_REG(alpx_dev, ALP, CONTROL, BUILD_VERSION)) & ALP_CONTROL_BUILD_VERSION_MASK; + return 0; +} + +int alpstereo_finalize_identity(struct alpx_device* alpx_dev) +{ + + int ret = alpxxx_finalize_identity(alpx_dev); + if (ret){ + dev_err(alpx_dev->dev, "Error %d when finalizing base identity\n", ret); + return ret; + } + + ret = alpx_mtd_load_shared_from(alpx_dev, + alpx_dev->variant->flash_partitions.partitions[ALPX_FLASH_PARTITION_PRODUCTION_ID].offset); + + /* DEFAULT VALUES */ + alpx_dev->identity.sub_system_id = (~ 0); + alpx_dev->identity.sub_system_id = (~ 0); + + if (ret){ + dev_err(alpx_dev->dev, "Error %d when extracting Production Area\n", ret); + return -EIO; + } + + alpx_card_read_serial_number(alpx_dev); + alpx_dev->identity.sub_system_id = alpx_dev->pci_dev->subsystem_device; + + return 0; +} + +int alpmultichan_finalize_identity(struct alpx_device* alpx_dev) +{ + int ret = alpxxx_finalize_identity(alpx_dev); + if (ret){ + dev_err(alpx_dev->dev, "Error %d when finalizing base identity\n", ret); + return ret; + } + + ret = alpx_mtd_load_shared_from(alpx_dev, + alpx_dev->variant->flash_partitions.partitions[ALPX_FLASH_PARTITION_PRODUCTION_ID].offset); + + /* DEFAULT VALUES */ + alpx_dev->identity.sub_system_id = alpx_dev->pci_dev->subsystem_device; + + if (ret){ + dev_err(alpx_dev->dev, "Error %d when extracting Production Area\n", ret); + return -EIO; + } + + alpx_card_read_serial_number(alpx_dev); + + return 0; +} + +int alpdante_finalize_identity(struct alpx_device* alpx_dev) +{ + void* fir_reg = NULL; + void* csppr_reg = NULL; + void* ublaze_version_reg = NULL; + void* design_bloc_version_reg = NULL; + void* low_serial_reg = NULL; + void* high_serial_reg = NULL; + + uint32_t low_serial_raw = 0; + uint32_t high_serial_raw = 0; + + dev_info(alpx_dev->dev, "DANTE card detected, finalizing identity\n"); + /* All this is extracted from AXcMEM registers */ + + fir_reg = alpx_axcmem_getRegAddr(alpx_dev, &ALPDANTE_FIR_LOC); + + csppr_reg = alpx_axcmem_getRegAddr(alpx_dev, &ALPDANTE_CSPPR_LOC); + + ublaze_version_reg = alpx_axcmem_getPointedRegAddrByRefLoc(alpx_dev, &ALPDANTE_CSPPR_LOC, &ALPDANTE_UBLAZE_VERSION_LOC); + + design_bloc_version_reg = alpx_axcmem_getPointedRegAddrByRefLoc(alpx_dev, &ALPDANTE_CSPPR_LOC, &ALPDANTE_DESIGN_BLOC_VERSION_LOC); + + low_serial_reg = alpx_axcmem_getPointedRegAddrByRefLoc(alpx_dev, &ALPDANTE_CSPPR_LOC, &ALPDANTE_LOW_SERIAL_NUM_LOC); + + high_serial_reg = alpx_axcmem_getPointedRegAddrByRefLoc(alpx_dev, &ALPDANTE_CSPPR_LOC, &ALPDANTE_HIGH_SERIAL_NUM_LOC); + + + dev_dbg(alpx_dev->dev, "FIR[0x%lx]=>%d\n", (uint8_t*)fir_reg - (uint8_t*)alpx_dev->base, alpx_axcmem_getRegBEU16Value(fir_reg)); + + dev_dbg(alpx_dev->dev, "CSPPR[0x%lx]=> %d\n", (uint8_t*)csppr_reg - (uint8_t*)alpx_dev->base, alpx_axcmem_getRegU8Value(csppr_reg)); + + dev_dbg(alpx_dev->dev, "uBlaze Version[0x%lx]=> %d\n", (uint8_t*)ublaze_version_reg - (uint8_t*)alpx_dev->base, alpx_axcmem_getRegU16Value(ublaze_version_reg)); + + dev_dbg(alpx_dev->dev, "Design bloc Version[0x%lx]=> %d\n", (uint8_t*)design_bloc_version_reg - (uint8_t*)alpx_dev->base, alpx_axcmem_getRegU16Value(design_bloc_version_reg)); + + alpx_dev->identity.ver_mcu = alpx_axcmem_getRegU16Value(ublaze_version_reg); + alpx_dev->identity.ver_fpga = alpx_axcmem_getRegBEU16Value(fir_reg); + + low_serial_raw = alpx_axcmem_getRegU32Value(low_serial_reg); + high_serial_raw = alpx_axcmem_getRegU32Value(high_serial_reg); + + dev_dbg(alpx_dev->dev, "Low serial number[0x%lx]=> 0x%x\n", (uint8_t*)low_serial_reg - (uint8_t*)alpx_dev->base, low_serial_raw); + + dev_dbg(alpx_dev->dev, "High serial number[0x%lx]=> 0x%x\n", (uint8_t*)high_serial_reg - (uint8_t*)alpx_dev->base, high_serial_raw); + + alpx_dev->identity.serial_number = ((uint64_t)high_serial_raw)<<8 | (((uint64_t)low_serial_raw) >> 24); + + /* DEFAULT VALUES */ + alpx_dev->identity.sub_system_id = alpx_dev->pci_dev->subsystem_device; + + return 0; +} + +void alpdante_print_identity(struct alpx_device *alpx_dev, struct snd_card *card, const unsigned char* label) +{ + void* design_bloc_version_reg = design_bloc_version_reg = alpx_axcmem_getPointedRegAddrByRefLoc(alpx_dev, &ALPDANTE_CSPPR_LOC, &ALPDANTE_DESIGN_BLOC_VERSION_LOC); + + const unsigned int design_bloc_version = alpx_axcmem_getRegU16Value(design_bloc_version_reg); + char dante_name[ALPDANTE_NETWORK_NAME_LENGTH]; + + dante_name[ALPDANTE_NETWORK_NAME_LENGTH - 1] = 0; + alpdante_get_dante_name(alpx_dev, dante_name, ALPDANTE_NETWORK_NAME_LENGTH); + + dev_info( alpx_dev->dev, + "\n************ \n" + "%s Alp DANTE soundcard[%d]{#%llu / %s }: %s - %s (%s - 0x%04x) , \n\t== Revisions ==\n\t* Build: \t\t%u\n\t* Design: \t\t%u.%lu\n\t* MCU:\t\t\t%u.%lu\n" + "************\n", + label, + card->number, + alpx_dev->identity.serial_number, + dante_name, + card->id, + card->shortname, + card->longname, + alpx_dev->identity.sub_system_id, + alpx_dev->identity.ver_fpga, + ALPX_DANTE_VERSION_VERSION(design_bloc_version), + ALPX_DANTE_VERSION_REVISION(design_bloc_version), + ALPX_DANTE_VERSION_VERSION(alpx_dev->identity.ver_mcu), + ALPX_DANTE_VERSION_REVISION(alpx_dev->identity.ver_mcu)); +} + +int alpdante_get_dante_name(struct alpx_device* alpx_dev, char* name, unsigned int length) +{ + if (length < ALPDANTE_NETWORK_NAME_LENGTH) { + dev_warn(alpx_dev->dev, "name parameter must be at least %d char long !\n", ALPDANTE_NETWORK_NAME_LENGTH); + return -EINVAL; + } + + return alpx_acxmem_getByteArrayByRefLoc(alpx_dev, &ALPDANTE_CNAMPR_LOC, + &ALPDANTE_NAME_LOC, + name, + length); +} + +int alpdante_store_config(struct alpx_device* alpx_dev) +{ + void* fsdr_reg = alpx_axcmem_getPointedRegAddrByRefLoc(alpx_dev, &ALPDANTE_FPPR_LOC, + &ALPDANTE_FSDR_LOC); + + void* fcr_reg = alpx_axcmem_getPointedRegAddrByRefLoc(alpx_dev, &ALPDANTE_FPPR_LOC, + &ALPDANTE_FCR_LOC); + + void* fcar_reg = alpx_axcmem_getPointedRegAddrByRefLoc(alpx_dev, &ALPDANTE_FPPR_LOC, + &ALPDANTE_FCAR_LOC); + + void* smalar_reg = alpx_axcmem_getRegAddr(alpx_dev, &ALPDANTE_SMALAR_LOC); + + + unsigned int waitLoopQty = ALPDANTE_FLASH_LOCK_ACCESS_TRY_QTY; + u32 cmd_status = 0; + int result = 0; + + dev_info(alpx_dev->dev, "Storing configuration ...\n"); + + //Wait for availability + while ((alpx_axcmem_getRegU8Value(smalar_reg) != ALPDANTE_SMALAR_AVAILABLE) && (--waitLoopQty)) { + dev_dbg(alpx_dev->dev," FCR:0x%x : Not yet available, wai a bit...\n", alpx_axcmem_getRegU8Value(smalar_reg)); + mdelay(ALPDANTE_FLASH_WAIT_STEP_TIME); + } + + if (waitLoopQty != 0) { + alpx_axcmem_setRegU8Value(smalar_reg, ALPDANTE_SMALAR_IN_USE); + dev_dbg(alpx_dev->dev," Semaphore taken\n"); + } + else { + dev_err(alpx_dev->dev, "!! Flash memory unavailable !!\n "); + return -EBUSY; + } + + //Write sequence + alpx_axcmem_setRegU8Value(fsdr_reg, 1); + alpx_axcmem_setRegU8Value(fcr_reg, ALPDANTE_FPPR_SAVE_REGISTERS_CMD_ID); + + //Wait for completion + waitLoopQty = ALPDANTE_FPPR_SAVE_REGS_CMD_COMPLETION_WAIT_STEPS_QTY; + while ((alpx_axcmem_getRegU8Value(fcr_reg) != ALPDANTE_FPPR_NOPE_CMD_ID) && (--waitLoopQty)) { + dev_dbg(alpx_dev->dev,"FCR: 0x%x : Cmd in progress, wait a bit...\n", alpx_axcmem_getRegU8Value(fcr_reg)); + mdelay(ALPDANTE_FLASH_WAIT_STEP_TIME); + } + + if (waitLoopQty==0) { + dev_err(alpx_dev->dev, "!! Flash Command TIMEOUT!!\n"); + result = -EIO; + goto EXIT; + } + + cmd_status = ALPDANTE_FPPR_CMD_STATUS(alpx_axcmem_getRegU32Value(fcar_reg)); + + dev_info(alpx_dev->dev, "Configuration %s (0x%x)\n", cmd_status ? "NOT STORED !" : "STORED", cmd_status); + result = (cmd_status == 0) ? 0 : -EIO; + +EXIT: + alpx_axcmem_setRegU8Value(smalar_reg, ALPDANTE_SMALAR_AVAILABLE); + dev_dbg(alpx_dev->dev," Semaphore released\n"); + return result; +} + +int alpdante_card_setup(struct alpx_device *alpx_dev, struct snd_card *card, unsigned int configured_fs, bool is_loopback_enabled) +{ + unsigned int sr_config_value = 0; + void* sr_config_reg = alpx_axcmem_getPointedRegAddrByRefLoc(alpx_dev, &ALPDANTE_CLKPR_LOC, + &ALPDANTE_SRConfig_LOC); + + unsigned int fppr_prod_test_value = 0; + void* fppr_prod_test_reg = alpx_axcmem_getPointedRegAddrByRefLoc(alpx_dev, &ALPDANTE_ERRTST_LOC, + &ALPDANTE_PROD_TEST_LOC); + + dev_dbg(alpx_dev->dev, "Setting AlpDANTE card {S/N: %llu} ...\n", alpx_dev->identity.serial_number); + + switch (configured_fs) { + case 44100: + sr_config_value = ALPDANTE_CLK_MANAGER_CLK_VALUE_44_1K; + alpx_dev->variant->capture_hw->rates=SNDRV_PCM_RATE_44100; + alpx_dev->variant->capture_hw->channels_min = 64; + alpx_dev->variant->capture_hw->channels_max = 64; + alpx_dev->variant->capture_hw->rate_min = configured_fs; + alpx_dev->variant->capture_hw->rate_max = configured_fs; + break; + case 48000: + sr_config_value = ALPDANTE_CLK_MANAGER_CLK_VALUE_48K; + alpx_dev->variant->capture_hw->rates=SNDRV_PCM_RATE_48000; + alpx_dev->variant->capture_hw->channels_min = 64; + alpx_dev->variant->capture_hw->channels_max = 64; + alpx_dev->variant->capture_hw->rate_min = configured_fs; + alpx_dev->variant->capture_hw->rate_max = configured_fs; + break; + case 88200: + sr_config_value = ALPDANTE_CLK_MANAGER_CLK_VALUE_88_2K; + alpx_dev->variant->capture_hw->rates=SNDRV_PCM_RATE_88200; + alpx_dev->variant->capture_hw->channels_min = 32; + alpx_dev->variant->capture_hw->channels_max = 32; + alpx_dev->variant->capture_hw->rate_min = configured_fs; + alpx_dev->variant->capture_hw->rate_max = configured_fs; + break; + case 96000: + sr_config_value = ALPDANTE_CLK_MANAGER_CLK_VALUE_96K; + alpx_dev->variant->capture_hw->rates=SNDRV_PCM_RATE_96000; + alpx_dev->variant->capture_hw->channels_min = 32; + alpx_dev->variant->capture_hw->channels_max = 32; + alpx_dev->variant->capture_hw->rate_min = configured_fs; + alpx_dev->variant->capture_hw->rate_max = configured_fs; + break; + case 176400: + sr_config_value = ALPDANTE_CLK_MANAGER_CLK_VALUE_176_4K; + alpx_dev->variant->capture_hw->rates=SNDRV_PCM_RATE_176400; + alpx_dev->variant->capture_hw->channels_min = 16; + alpx_dev->variant->capture_hw->channels_max = 16; + alpx_dev->variant->capture_hw->rate_min = configured_fs; + alpx_dev->variant->capture_hw->rate_max = configured_fs; + break; + case 192000: + sr_config_value = ALPDANTE_CLK_MANAGER_CLK_VALUE_192K; + alpx_dev->variant->capture_hw->rates=SNDRV_PCM_RATE_192000; + alpx_dev->variant->capture_hw->channels_min = 16; + alpx_dev->variant->capture_hw->channels_max = 16; + alpx_dev->variant->capture_hw->rate_min = configured_fs; + alpx_dev->variant->capture_hw->rate_max = configured_fs; + break; + default: + dev_err(alpx_dev->dev, "AlpDANTE card {S/N: %llu}; %dHz : unsupported FS, keep default %dHz !\n", alpx_dev->identity.serial_number, configured_fs, alpx_dev->variant->capture_hw->rate_min); + }; + + dev_dbg(alpx_dev->dev, "Setting AlpDANTE card {S/N: %llu}: FS:%dHz => reg=0x%x\n", alpx_dev->identity.serial_number, + alpx_dev->variant->capture_hw->rate_min, sr_config_value); + + alpx_axcmem_setRegU8Value(sr_config_reg, sr_config_value); + + + dev_info(alpx_dev->dev, "AlpDANTE card {S/N: %llu}: loopback mode %s.\n", + alpx_dev->identity.serial_number, + is_loopback_enabled ? "ENABLED" : "DISABLED"); + + fppr_prod_test_value = alpx_axcmem_getRegU8Value(fppr_prod_test_reg); + fppr_prod_test_value = is_loopback_enabled ? + (ALPDANTE_PROD_TEST_LOOPBACK | fppr_prod_test_value) : + (fppr_prod_test_value & ~ALPDANTE_PROD_TEST_LOOPBACK); + alpx_axcmem_setRegU8Value(fppr_prod_test_reg, fppr_prod_test_value); + + dev_dbg(alpx_dev->dev, "fppr_prod_test_value = 0x%x, reg: 0x%x\n", fppr_prod_test_value, + alpx_axcmem_getRegU8Value(fppr_prod_test_reg)); + + return alpdante_store_config(alpx_dev); +} + +/* Helpers */ +unsigned int +alpx_get_samples_counter(struct alpx_device *alpx_dev) +{ + if (alpx_dev->variant->model != ALPX_VARIANT_MODEL_ALPDANTE) { + return readl(ALPX_REG(alpx_dev, ALP, CLK_MANAGER, SAMPLES_COUNT)); + } + else { + void* sample_count_reg = alpx_axcmem_getPointedRegAddrByRefLoc(alpx_dev, &ALPDANTE_CSPPR_LOC, &ALPDANTE_SAMPLE_COUNT_LOC); + return alpx_axcmem_getRegU32Value(sample_count_reg); + } + return 0; +} diff --git a/snd-alpx-dkms/snd-alpx/alpx_cards.h b/snd-alpx-dkms/snd-alpx/alpx_cards.h new file mode 100644 index 0000000..9e2aab6 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/alpx_cards.h @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* +* Support for Digigram AlpX PCI-e boards +* +* Copyright (c) 2024 Digigram Digital (info@digigram.com) +*/ + + +/* This file contains the card centered services */ +#ifndef _ALPX_CARDS_H +#define _ALPX_CARDS_H + +#include "alpx.h" +#include <sound/core.h> + +void alpstereo_print_identity(struct alpx_device *alpx_dev, struct snd_card *card, const unsigned char* label); +void alpmadi_print_identity(struct alpx_device *alpx_dev, struct snd_card *card, const unsigned char* label); +void alpmultichan_print_identity(struct alpx_device *alpx_dev, struct snd_card *card, const unsigned char* label); +void alpdante_print_identity(struct alpx_device *alpx_dev, struct snd_card *card, const unsigned char* label); +int alpdante_card_setup(struct alpx_device *alpx_dev, struct snd_card *card, unsigned int configured_fs, bool is_loopback_enabled); +int alpstereo_finalize_identity(struct alpx_device* alpx_dev); +int alpmultichan_finalize_identity(struct alpx_device* alpx_dev); +int alpdante_finalize_identity(struct alpx_device* alpx_dev); +int alpdante_store_config(struct alpx_device* alpx_dev); +int alpdante_get_dante_name(struct alpx_device* alpx_dev, char* name, unsigned int length); + +#endif diff --git a/snd-alpx-dkms/snd-alpx/alpx_controls.c b/snd-alpx-dkms/snd-alpx/alpx_controls.c new file mode 100644 index 0000000..397fe99 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/alpx_controls.c @@ -0,0 +1,2096 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* +* Support for Digigram AlpX PCI-e boards +* +* Copyright (c) 2024 Digigram Digital (info@digigram.com) +*/ + +#include "alpx_controls.h" +#include "alpx_variants_stereo.h" +#include "alpx_variants_mc.h" +#include "alpx_variants_dead.h" +#include "alpx_variants_madi.h" + +#include <sound/core.h> +#include <sound/control.h> +#include <sound/tlv.h> +#include <linux/slab.h> + +/* Amplifiers */ + +static int alpx_control_amplifier_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *info) +{ + struct alpx_device *alpx_dev = snd_kcontrol_chip(kcontrol); + const unsigned long control_index = kcontrol->private_value; + + const struct alpx_control* control = &alpx_dev->controls[control_index]; + + const struct alpx_control_descriptor_amplifier* descr = + (struct alpx_control_descriptor_amplifier*) &control->descriptor->data.ampli; + + dev_dbg( alpx_dev->dev," for volume[%u] (controls[%lu]){%p}.\n", + control->data.ampli.idx, + control_index, + control); + + info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + info->count = 1; //Single channel amplifier + info->value.integer.min = descr->reg_gain_min; + info->value.integer.max = descr->reg_gain_max; + + return 0; +} + +static int alpx_control_amplifier_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *elem_value) +{ + const struct alpx_device *alpx_dev = snd_kcontrol_chip(kcontrol); + unsigned int control_index = kcontrol->private_value; + const struct alpx_control* control = &alpx_dev->controls[control_index]; + + const struct alpx_control_amplifier* ampli = &control->data.ampli; + + const u32 offset = control->descriptor->base + ALP_INDEX_TO_REG_OFFSET(ampli->idx); + + u32 value; + + value = readl(alpx_dev->base + offset); + + dev_dbg( alpx_dev->dev," volume[%u](controls[%u]){%p} : 0x%x <= [0x%p:%x:%x]\n", + control->data.ampli.idx, + control_index, + control, + value, + alpx_dev->base, + control->descriptor->base, + ALP_INDEX_TO_REG_OFFSET(ampli->idx)); + + elem_value->value.integer.value[0] = value; + + return 0; +} + +static int alpx_control_amplifier_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *elem_value) +{ + const struct alpx_device *alpx_dev = snd_kcontrol_chip(kcontrol); + unsigned int control_index = kcontrol->private_value; + const struct alpx_control* control = &alpx_dev->controls[control_index]; + const struct alpx_control_amplifier* ampli = &control->data.ampli; + + const u32 offset = control->descriptor->base + ALP_INDEX_TO_REG_OFFSET(ampli->idx); + const u32 value = elem_value->value.integer.value[0]; + + dev_dbg( alpx_dev->dev," volume[%u](controls[%u]){%p} : 0x%x => [0x%p:%x:%x]\n", + control->data.ampli.idx, + control_index, + control, + value, + alpx_dev->base, + control->descriptor->base, + ALP_INDEX_TO_REG_OFFSET(ampli->idx)); + + writel(value, alpx_dev->base + offset); + + return 1; /* Value changed */ +} + + +static struct snd_kcontrol_new alpx_control_amplifier = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + + .info = alpx_control_amplifier_info, + .get = alpx_control_amplifier_get, + .put = alpx_control_amplifier_put, +}; + +static int alpx_control_amplifier_register(struct snd_card *card, + struct alpx_control_descriptor *descriptor, + unsigned int idx) +{ + struct alpx_device *alpx_dev = card->private_data; + char name[64] = { 0 }; + const unsigned int control_index = alpx_dev->controls_index; + struct alpx_control *control = &alpx_dev->controls[control_index]; + int ret; + + control->descriptor = descriptor; + control->data.ampli.idx = idx; + + snprintf(name, sizeof(name), "%s Volume", /* Just add FUNCTION, see alsa driver guide */ + control->descriptor->prefix); + + dev_dbg( alpx_dev->dev,"creating amplifier %s[%u] in controls[%u] linked to [0x%x:0x%x].\n", + name, + control->data.ampli.idx, + control_index, + control->descriptor->base, + ALP_INDEX_TO_REG_OFFSET(control->data.ampli.idx)); + + alpx_control_amplifier.name = name; + alpx_control_amplifier.private_value = control_index; + alpx_control_amplifier.index = control->data.ampli.idx; + alpx_control_amplifier.access = descriptor->access; + alpx_control_amplifier.tlv.p = descriptor->data.ampli.gains_scale; + + ret = snd_ctl_add(card, snd_ctl_new1(&alpx_control_amplifier, alpx_dev)); + if (ret) + return ret; + + alpx_dev->controls_index++; + + return 0; +} + +static int alpx_controls_amplifier_register(struct snd_card *card, + struct alpx_control_descriptor *descriptor) +{ + const unsigned int items_count = descriptor->data.ampli.lines_count; + unsigned int i; + int ret; + + for (i = 0; i < items_count; i++) { + ret = alpx_control_amplifier_register(card, descriptor, i); + if (ret) + return ret; + } + + return ret; +} + +/* Codec : analog equalization*/ + +static int alpx_control_codec_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *info) +{ + const struct alpx_device *alpx_dev = snd_kcontrol_chip(kcontrol); + const unsigned int control_index = kcontrol->private_value; + const struct alpx_control *control = &alpx_dev->controls[control_index]; + const struct alpx_control_descriptor_codec* descr = &control->descriptor->data.codec; + + info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + info->count = 1; /* single line */ + info->value.integer.min = descr->reg_gain_min; + info->value.integer.max = descr->reg_gain_max; + + return 0; +} + +static int alpx_control_codec_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *elem_value) +{ + const struct alpx_device *alpx_dev = snd_kcontrol_chip(kcontrol); + const unsigned int control_index = kcontrol->private_value; + const struct alpx_control *control = &alpx_dev->controls[control_index]; + const unsigned int idx = control->data.codec.idx; + + const u32 offset = control->descriptor->base + control->descriptor->data.codec.offset + + ALPX_CODEC_CTRL_GAIN_REG(idx); + + elem_value->value.integer.value[0] = readl(alpx_dev->base + offset); + + + dev_dbg( alpx_dev->dev,"0x%lx <= [0x%x:%x]\n", + elem_value->value.integer.value[0], + control->descriptor->base, + control->descriptor->data.codec.offset + ALPX_CODEC_CTRL_GAIN_REG(idx)); + + return 0; +} + +static int alpx_control_codec_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *elem_value) +{ + const struct alpx_device *alpx_dev = snd_kcontrol_chip(kcontrol); + const unsigned int control_index = kcontrol->private_value; + const struct alpx_control *control = &alpx_dev->controls[control_index]; + const unsigned int idx = control->data.codec.idx; + + const u32 offset = control->descriptor->base + control->descriptor->data.codec.offset + + ALPX_CODEC_CTRL_GAIN_REG(idx); + + const u32 value = elem_value->value.integer.value[0]; + + dev_dbg( alpx_dev->dev," 0x%x => [0x%x:%x]\n", + value, + control->descriptor->base, + control->descriptor->data.codec.offset + ALPX_CODEC_CTRL_GAIN_REG(idx)); + + writel(value, alpx_dev->base + offset); + + return 1; +} + + +static struct snd_kcontrol_new alpx_control_codec = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + + .info = alpx_control_codec_info, + .get = alpx_control_codec_get, + .put = alpx_control_codec_put, +}; + +static int alpx_control_codec_register(struct snd_card *card, + struct alpx_control_descriptor *descriptor, + unsigned int idx) +{ + struct alpx_device *alpx_dev = card->private_data; + char name[64] = { 0 }; + unsigned int control_index = alpx_dev->controls_index; + struct alpx_control *control = &alpx_dev->controls[control_index]; + int ret; + + control->descriptor = descriptor; + control->data.codec.idx = idx; + + snprintf(name, sizeof(name), "%s Volume", descriptor->prefix); + + alpx_control_codec.name = name; + alpx_control_codec.private_value = control_index; + alpx_control_codec.index = control->data.codec.idx; + alpx_control_codec.access = descriptor->access; + alpx_control_codec.tlv.p = descriptor->data.codec.gains_scale; + + dev_dbg( alpx_dev->dev," creating codec eq %s[%u] in controls[%u] linked to [0x%x:0x%x].\n", + name, + control->data.codec.idx, + control_index, + control->descriptor->base, + ALPX_CODEC_CTRL_GAIN_REG(control->data.codec.idx)); + + ret = snd_ctl_add(card, snd_ctl_new1(&alpx_control_codec, alpx_dev)); + if (ret) + return ret; + + alpx_dev->controls_index++; + + return 0; +} + +static int alpx_controls_codec_register(struct snd_card *card, + struct alpx_control_descriptor *descriptor) +{ + const unsigned int items_count = descriptor->data.codec.lines_count; + unsigned int i; + int ret; + + for (i = 0; i < items_count; i++) { + ret = alpx_control_codec_register(card, descriptor, i); + if (ret) + return ret; + } + + return ret; +} + +/* Router */ + +static int alpx_control_router_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *info) +{ + struct alpx_device *alpx_dev = snd_kcontrol_chip(kcontrol); + unsigned int control_index = kcontrol->private_value; + struct alpx_control *control = &alpx_dev->controls[control_index]; + struct alpx_control_descriptor_router *router = + &control->descriptor->data.router; + + return snd_ctl_enum_info(info, 1, router->entries_count, router->entries); +} + +static int alpx_control_router_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *elem_value) +{ + struct alpx_device *alpx_dev = snd_kcontrol_chip(kcontrol); + unsigned int control_index = kcontrol->private_value; + struct alpx_control *control = &alpx_dev->controls[control_index]; + unsigned int index = control->data.router.index; + unsigned int index_value; + u32 offset, value; + + offset = control->descriptor->base + ALPX_ROUTER_REG(index); + value = readl(alpx_dev->base + offset); + + dev_dbg( alpx_dev->dev,"0x%x <= [0x%p:%x:%x]\n", + value, + alpx_dev->base, + control->descriptor->base, + ALPX_ROUTER_REG(index)); + + index_value = ALPX_ROUTER_VALUE(index, value); + elem_value->value.enumerated.item[0] = index_value; + + return 0; +} + +static int alpx_control_router_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *elem_value) +{ + struct alpx_device *alpx_dev = snd_kcontrol_chip(kcontrol); + unsigned int control_index = kcontrol->private_value; + struct alpx_control *control = &alpx_dev->controls[control_index]; + unsigned int index = control->data.router.index; + unsigned int index_value; + u32 offset, value; + + offset = control->descriptor->base + ALPX_ROUTER_REG(index); + value = readl(alpx_dev->base + offset); + index_value = ALPX_ROUTER_VALUE(index, value); + +#if defined(CONFIG_ALPX_LOG_CONTROLS) + dev_dbg( alpx_dev->dev," 0x%x => [0x%p:%x:%x:%d]\n", + value, + alpx_dev->base, + control->descriptor->base, + ALPX_ROUTER_REG(index), + index_value); +#endif + + if (index_value == elem_value->value.enumerated.item[0]) + return 0; + + index_value = elem_value->value.enumerated.item[0]; + + value &= ~ALPX_ROUTER_MASK(index); + value |= ALPX_ROUTER_SEL(index, index_value); + + writel(value, alpx_dev->base + offset); + + return 1; +} + +static struct snd_kcontrol_new alpx_control_router = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + + .info = alpx_control_router_info, + .get = alpx_control_router_get, + .put = alpx_control_router_put, +}; + +static int alpx_control_router_register(struct snd_card *card, + struct alpx_control_descriptor *descriptor, + unsigned int index) +{ + struct alpx_device *alpx_dev = card->private_data; + char name[64] = { 0 }; + unsigned int control_index = alpx_dev->controls_index; + struct alpx_control *control = &alpx_dev->controls[control_index]; + int ret; + + control->descriptor = descriptor; + control->data.router.index = index; + + snprintf(name, sizeof(name), "%s Route", descriptor->prefix); + + alpx_control_router.name = name; + alpx_control_router.private_value = control_index; + alpx_control_router.index = index; + alpx_control_router.access = descriptor->access; + + ret = snd_ctl_add(card, snd_ctl_new1(&alpx_control_router, alpx_dev)); + if (ret) + return ret; + + alpx_dev->controls_index++; + + return 0; +} +/* RESERVED controls */ +static int alpx_control_reserved_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *info) +{ + info->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + info->count = 1; + info->value.integer.min = 0; + info->value.integer.max = 1; + + return 0; +} + +static int alpx_control_reserved_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *elem_value) +{ + elem_value->value.integer.value[0] = 0; + return 0; +} + +static int alpx_control_reserved_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *elem_value) +{ + return 0; +} + +static struct snd_kcontrol_new alpx_control_reserved = { + .iface = SNDRV_CTL_ELEM_IFACE_CARD, + + .info = alpx_control_reserved_info, + .get = alpx_control_reserved_get, + .put = alpx_control_reserved_put, +}; + +static int alpx_control_reserved_register(struct snd_card *card, + struct alpx_control_descriptor *descriptor) +{ + struct alpx_device *alpx_dev = card->private_data; + char name[64] = { 0 }; + unsigned int control_index = alpx_dev->controls_index; + struct alpx_control *control = &alpx_dev->controls[control_index]; + int ret; + + control->descriptor = descriptor; + snprintf(name, sizeof(name), "%s", descriptor->prefix); + + alpx_control_reserved.name = name; + alpx_control_reserved.private_value = control_index; + alpx_control_reserved.index = 0; + alpx_control_reserved.access = SNDRV_CTL_ELEM_ACCESS_INACTIVE; + + ret = snd_ctl_add(card, snd_ctl_new1(&alpx_control_reserved, alpx_dev)); + if (ret) + return ret; + + alpx_dev->controls_index++; + + return 0; + +} + +/* Constant */ +static int alpx_control_constant_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *info) +{ + struct alpx_device *alpx_dev = snd_kcontrol_chip(kcontrol); + const unsigned long control_index = kcontrol->private_value; + + const struct alpx_control* control = &alpx_dev->controls[control_index]; + + const struct alpx_control_descriptor_constant* descr = + (struct alpx_control_descriptor_constant*) &control->descriptor->data.constant; + + dev_dbg(alpx_dev->dev, "INFO constant control \n"); + + info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + info->count = 1; + info->value.integer.min = descr->value; + info->value.integer.max = descr->value; + + return 0; +} + +static int alpx_control_constant_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *elem_value) +{ + + struct alpx_device *alpx_dev = snd_kcontrol_chip(kcontrol); + const unsigned long control_index = kcontrol->private_value; + + const struct alpx_control* control = &alpx_dev->controls[control_index]; + + const struct alpx_control_descriptor_constant* descr = + (struct alpx_control_descriptor_constant*) &control->descriptor->data.constant; + + dev_dbg(alpx_dev->dev, "GET constant control \n"); + + elem_value->value.integer.value[0] = descr->value; + return 0; +} + + +static struct snd_kcontrol_new alpx_control_constant = { + .iface = SNDRV_CTL_ELEM_IFACE_CARD, + + .info = alpx_control_constant_info, + .get = alpx_control_constant_get, + .put = NULL, +}; + +static int alpx_control_constant_register(struct snd_card *card, + struct alpx_control_descriptor *descriptor) +{ + struct alpx_device *alpx_dev = card->private_data; + char name[64] = { 0 }; + unsigned int control_index = alpx_dev->controls_index; + struct alpx_control *control = &alpx_dev->controls[control_index]; + int ret; + + dev_dbg(alpx_dev->dev, "Registering constant control for %s\n", card->longname); + + control->descriptor = descriptor; + snprintf(name, sizeof(name), "%s", descriptor->prefix); + + alpx_control_constant.name = name; + alpx_control_constant.private_value = control_index; + alpx_control_constant.index = 0; + alpx_control_constant.access = SNDRV_CTL_ELEM_ACCESS_READ; /* ENFORCE Read only */ + + ret = snd_ctl_add(card, snd_ctl_new1(&alpx_control_constant, alpx_dev)); + if (ret) + return ret; + + alpx_dev->controls_index++; + + return 0; +} + +/* AXCMem Relative choice control */ +static int alpx_control_axcmem_rel_choice_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *info) +{ + struct alpx_device *alpx_dev = snd_kcontrol_chip(kcontrol); + const unsigned long control_index = kcontrol->private_value; + + const struct alpx_control* control = &alpx_dev->controls[control_index]; + + const struct alpx_control_descriptor_axcmem_rel_choice* choice_descr = + (struct alpx_control_descriptor_axcmem_rel_choice*) &control->descriptor->data.axcmem_rel_choice; + + dev_dbg(alpx_dev->dev, "INFO choice control\n"); + + return snd_ctl_enum_info(info, 1, choice_descr->entries_count, choice_descr->entries); +} + +static int alpx_control_axcmem_rel_choice_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *elem_value) +{ + struct alpx_device *alpx_dev = snd_kcontrol_chip(kcontrol); + const unsigned long control_index = kcontrol->private_value; + + const struct alpx_control* control = &alpx_dev->controls[control_index]; + + const struct alpx_control_descriptor_axcmem_rel_choice* choice_descr = + (struct alpx_control_descriptor_axcmem_rel_choice*) &control->descriptor->data.axcmem_rel_choice; + + const unsigned int choice_index = elem_value->value.enumerated.item[0]; + + unsigned int reg_value = choice_descr->getter(alpx_axcmem_getPointedRegAddrByRefLoc(alpx_dev, + &choice_descr->base_loc, + &choice_descr->reg_loc)); + + unsigned int choice_value = 0; + + if (choice_index >= choice_descr->entries_count ) { + dev_err(alpx_dev->dev, "Index out of bound : %d > %d !\n", choice_index, choice_descr->entries_count - 1); + return -EINVAL; + } + + choice_value = (control->descriptor->data.axcmem_rel_choice.entries_values[choice_index] << choice_descr->pos); + + reg_value &= choice_descr->mask; + reg_value |= choice_value; + + choice_descr->setter(alpx_axcmem_getPointedRegAddrByRefLoc(alpx_dev, + &choice_descr->base_loc, + &choice_descr->reg_loc), + reg_value); + + dev_dbg(alpx_dev->dev, "%s: index = %d, value = 0x%x, mask: 0x%08x => reg_value=0x%08x\n", + control->descriptor->prefix, + elem_value->value.enumerated.item[0], + choice_value, + choice_descr->mask, + choice_descr->getter(alpx_axcmem_getPointedRegAddrByRefLoc(alpx_dev, + &choice_descr->base_loc, + &choice_descr->reg_loc))); + return 0; +} + +static int alpx_control_axcmem_rel_choice_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *elem_value) +{ + + struct alpx_device *alpx_dev = snd_kcontrol_chip(kcontrol); + const unsigned long control_index = kcontrol->private_value; + + const struct alpx_control* control = &alpx_dev->controls[control_index]; + + const struct alpx_control_descriptor_axcmem_rel_choice* choice = + (struct alpx_control_descriptor_axcmem_rel_choice*) &control->descriptor->data.axcmem_rel_choice; + + const unsigned int reg_value = choice->getter(alpx_axcmem_getPointedRegAddrByRefLoc(alpx_dev, + &choice->base_loc, + &choice->reg_loc)); + + const unsigned int read_value = (reg_value & choice->mask) >> choice->pos; + unsigned int value_index = 0; + + for (value_index = 0; value_index < choice->entries_count; ++value_index) { + u32 entry_value = choice->entries_values[value_index]; + + if (read_value == entry_value) { + elem_value->value.enumerated.item[0] = value_index; + dev_dbg(alpx_dev->dev, "%s: reg_value=0x%08x, mask: 0x%08x => index = %d\n", + control->descriptor->prefix, + reg_value, + choice->mask, + value_index); + return 0; + } + } + + dev_err(alpx_dev->dev, "%s: unknown choice for: reg_value=0x%08x, mask: 0x%08x => value = %d\n", + control->descriptor->prefix, + reg_value, + choice->mask, + (reg_value & choice->mask)>>choice->pos); + + return -EINVAL; +} + +static struct snd_kcontrol_new alpx_control_axcmem_rel_choice = { + .iface = SNDRV_CTL_ELEM_IFACE_CARD, + .info = alpx_control_axcmem_rel_choice_info, + .get = alpx_control_axcmem_rel_choice_get, + .put = alpx_control_axcmem_rel_choice_put, +}; + +int alpx_control_axcmem_rel_choice_register (struct snd_card *card, + struct alpx_control_descriptor *descriptor) +{ + struct alpx_device *alpx_dev = card->private_data; + char name[64] = { 0 }; + unsigned int control_index = alpx_dev->controls_index; + struct alpx_control *control = &alpx_dev->controls[control_index]; + int ret; + + dev_dbg(alpx_dev->dev, "Registering choice control for %s\n", card->longname); + + control->descriptor = descriptor; + snprintf(name, sizeof(name), "%s", descriptor->prefix); + + alpx_control_axcmem_rel_choice.name = name; + alpx_control_axcmem_rel_choice.private_value = control_index; + alpx_control_axcmem_rel_choice.index = 0; + alpx_control_axcmem_rel_choice.access = descriptor->access; + + ret = snd_ctl_add(card, snd_ctl_new1(&alpx_control_axcmem_rel_choice, alpx_dev)); + if (ret) + return ret; + + alpx_dev->controls_index++; + + return 0; + +} + +/* AxCMem Value */ +static int alpx_control_axcmem_rel_value_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *info) +{ + struct alpx_device *alpx_dev = snd_kcontrol_chip(kcontrol); + const unsigned long control_index = kcontrol->private_value; + + const struct alpx_control* control = &alpx_dev->controls[control_index]; + + const struct alpx_control_descriptor_axcmem_rel_value* value_descr = + (struct alpx_control_descriptor_axcmem_rel_value*) &control->descriptor->data.axcmem_rel_value; + + dev_dbg(alpx_dev->dev, "INFO Value control \n"); + + info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + info->count = 1; + info->value.integer.min = value_descr->min; + info->value.integer.max = value_descr->max; + + return 0; +} + +static int alpx_control_axcmem_rel_value_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *elem_value) +{ + struct alpx_device *alpx_dev = snd_kcontrol_chip(kcontrol); + const unsigned long control_index = kcontrol->private_value; + + const struct alpx_control* control = &alpx_dev->controls[control_index]; + + const struct alpx_control_descriptor_axcmem_rel_value* value_descr = + (struct alpx_control_descriptor_axcmem_rel_value*) &control->descriptor->data.axcmem_rel_value; + + unsigned int reg_value = value_descr->getter(alpx_axcmem_getPointedRegAddrByRefLoc(alpx_dev, + &value_descr->base_loc, + &value_descr->reg_loc)); + + reg_value &= value_descr->mask; + reg_value |= ((elem_value->value.integer.value[0] & value_descr->mask) << value_descr->pos); + + value_descr->setter(alpx_axcmem_getPointedRegAddrByRefLoc(alpx_dev, + &value_descr->base_loc, + &value_descr->reg_loc), + reg_value); + + dev_dbg(alpx_dev->dev, "%s: reg_value=0x%08x, mask: 0x%08x => index = %ld\n", + control->descriptor->prefix, + value_descr->getter(alpx_axcmem_getPointedRegAddrByRefLoc(alpx_dev, + &value_descr->base_loc, + &value_descr->reg_loc)), + value_descr->mask, + elem_value->value.integer.value[0]); + + return 0; +} + +static int alpx_control_axcmem_rel_value_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *elem_value) +{ + + struct alpx_device *alpx_dev = snd_kcontrol_chip(kcontrol); + const unsigned long control_index = kcontrol->private_value; + + const struct alpx_control* control = &alpx_dev->controls[control_index]; + + const struct alpx_control_descriptor_axcmem_rel_value* value_descr = + (struct alpx_control_descriptor_axcmem_rel_value*) &control->descriptor->data.axcmem_rel_value; + + const unsigned int reg_value = value_descr->getter(alpx_axcmem_getPointedRegAddrByRefLoc(alpx_dev, + &value_descr->base_loc, + &value_descr->reg_loc)); + + elem_value->value.integer.value[0] = (reg_value & value_descr->mask) >> value_descr->pos; + + dev_dbg(alpx_dev->dev, "%s: reg_value=0x%08x, mask: 0x%08x => value: 0x%lx\n", + control->descriptor->prefix, + reg_value, + value_descr->mask, + elem_value->value.integer.value[0]); + + return 0; +} + +static struct snd_kcontrol_new alpx_control_axcmem_rel_value = { + .iface = SNDRV_CTL_ELEM_IFACE_CARD, + .info = alpx_control_axcmem_rel_value_info, + .get = alpx_control_axcmem_rel_value_get, + .put = alpx_control_axcmem_rel_value_put, +}; + +int alpx_control_axcmem_rel_value_register (struct snd_card *card, + struct alpx_control_descriptor *descriptor) +{ + struct alpx_device *alpx_dev = card->private_data; + char name[64] = { 0 }; + unsigned int control_index = alpx_dev->controls_index; + struct alpx_control *control = &alpx_dev->controls[control_index]; + int ret; + + dev_dbg(alpx_dev->dev, "Registering VALUE control for %s\n", card->longname); + + control->descriptor = descriptor; + snprintf(name, sizeof(name), "%s", descriptor->prefix); + + alpx_control_axcmem_rel_value.name = name; + alpx_control_axcmem_rel_value.private_value = control_index; + alpx_control_axcmem_rel_value.index = 0; + alpx_control_axcmem_rel_value.access = descriptor->access; + + ret = snd_ctl_add(card, snd_ctl_new1(&alpx_control_axcmem_rel_value, alpx_dev)); + if (ret) + return ret; + + alpx_dev->controls_index++; + return 0; +} + +/* Mixer */ + +static int alpx_control_mixer_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *info) +{ + struct alpx_device *alpx_dev = snd_kcontrol_chip(kcontrol); + const unsigned long control_index = kcontrol->private_value; + + const struct alpx_control* control = &alpx_dev->controls[control_index]; + + const struct alpx_control_descriptor_mixer* descr = + (struct alpx_control_descriptor_mixer*) &control->descriptor->data.mixer; + + + + + info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + info->count = 1; + info->value.integer.min = descr->reg_gain_min; + info->value.integer.max = descr->reg_gain_max; + + return 0; +} + +static int alpx_control_mixer_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *elem_value) +{ + struct alpx_device *alpx_dev = snd_kcontrol_chip(kcontrol); + unsigned int control_index = kcontrol->private_value; + struct alpx_control *control = &alpx_dev->controls[control_index]; + unsigned int lines_count = control->descriptor->data.mixer.lines_count; + unsigned int mixer_in = control->data.mixer.mixer_in; + unsigned int mixer_out = control->data.mixer.mixer_out; + u32 offset, reg_value; + + //Registers layout depends on the card's variant + switch(alpx_dev->variant->model) { + case ALPX_VARIANT_MODEL_ALP882: + case ALPX_VARIANT_MODEL_ALP882_MIC: + case ALPX_VARIANT_MODEL_ALP442: + case ALPX_VARIANT_MODEL_ALP442_MIC: + offset = control->descriptor->base + + ALPMC_MIXER_GAIN_REG(lines_count, mixer_in, mixer_out); + reg_value = readl(alpx_dev->base + offset); + elem_value->value.integer.value[0] = ALPMC_MIXER_GAIN_VALUE(reg_value); + + #if defined(CONFIG_ALPX_LOG_CONTROLS) + dev_dbg( alpx_dev->dev," %ld (0x%lx <= 0x%x)<= (%d,%d,%d)[REG:%x:%02x]\n", + elem_value->value.integer.value[0], + ALPMC_MIXER_GAIN_VALUE(reg_value), + reg_value, + lines_count, mixer_in, mixer_out, + control->descriptor->base, + ALPMC_MIXER_GAIN_REG(lines_count, mixer_in, mixer_out)); + #endif + break; + + case ALPX_VARIANT_MODEL_ALP222: + case ALPX_VARIANT_MODEL_ALP222_MIC: + offset = control->descriptor->base + + ALP222_MIXER_GAIN_REG(lines_count, mixer_in, mixer_out); + reg_value = readl(alpx_dev->base + offset); + elem_value->value.integer.value[0] = ALP222_MIXER_GAIN_VALUE(mixer_in, reg_value); + + #if defined(CONFIG_ALPX_LOG_CONTROLS) + dev_dbg( alpx_dev->dev," %ld (0x%lx <= 0x%x)<= (%d,%d,%d)[REG:%x:%02x]\n", + elem_value->value.integer.value[0], + ALP222_MIXER_GAIN_VALUE(mixer_in, reg_value), + reg_value, + lines_count, mixer_in, mixer_out, + control->descriptor->base, + ALP222_MIXER_GAIN_REG(lines_count, mixer_in, mixer_out)); + #endif + break; + + default: + //No mixer by default ! + elem_value->value.integer.value[0] = 0; + return 0; + }; + + + return 0; +} + +static int alpx_control_mixer_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *elem_value) +{ + struct alpx_device *alpx_dev = snd_kcontrol_chip(kcontrol); + unsigned int control_index = kcontrol->private_value; + struct alpx_control *control = &alpx_dev->controls[control_index]; + unsigned int lines_count = control->descriptor->data.mixer.lines_count; + unsigned int mixer_in = control->data.mixer.mixer_in; + unsigned int mixer_out = control->data.mixer.mixer_out; + unsigned int mixer_value; + u32 offset, reg_value; + + mixer_value = elem_value->value.integer.value[0]; + + switch(alpx_dev->variant->model) { + case ALPX_VARIANT_MODEL_ALP882: + case ALPX_VARIANT_MODEL_ALP882_MIC: + case ALPX_VARIANT_MODEL_ALP442: + case ALPX_VARIANT_MODEL_ALP442_MIC: + offset = control->descriptor->base + + ALPMC_MIXER_GAIN_REG(lines_count, mixer_in, mixer_out); + reg_value = readl(alpx_dev->base + offset); + + reg_value &= ~ALPMC_MIXER_GAIN_MASK; + + #if defined(CONFIG_ALPX_LOG_CONTROLS) + dev_dbg( alpx_dev->dev," 0x%x (0x%lx => 0x%x)=> (%d,%d,%d)[REG:%x:%02x]\n", + mixer_value, + ALPMC_MIXER_GAIN_SEL(mixer_value), + reg_value, + lines_count, mixer_in, mixer_out, + control->descriptor->base, + ALPMC_MIXER_GAIN_REG(lines_count, mixer_in, mixer_out)); + #endif + + reg_value |= ALPMC_MIXER_GAIN_SEL(mixer_value); + break; + + case ALPX_VARIANT_MODEL_ALP222: + case ALPX_VARIANT_MODEL_ALP222_MIC: + offset = control->descriptor->base + + ALP222_MIXER_GAIN_REG(lines_count, mixer_in, mixer_out); + reg_value = readl(alpx_dev->base + offset); + + reg_value &= ~ALP222_MIXER_GAIN_MASK(mixer_in); + + #if defined(CONFIG_ALPX_LOG_CONTROLS) + dev_dbg( alpx_dev->dev," 0x%x (0x%lx => 0x%x)=> (%d,%d,%d)[REG:%x:%02x]\n", + mixer_value, + ALP222_MIXER_GAIN_SEL(mixer_in, mixer_value), + reg_value, + lines_count, mixer_in, mixer_out, + control->descriptor->base, + ALP222_MIXER_GAIN_REG(lines_count, mixer_in, mixer_out)); + #endif + + reg_value |= ALP222_MIXER_GAIN_SEL(mixer_in, mixer_value); + + break; + default: + //Nothing to do for others cards yet + return 0; + } + + + + writel(reg_value, alpx_dev->base + offset); + + return 1; +} + +static struct snd_kcontrol_new alpx_control_mixer = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + + .info = alpx_control_mixer_info, + .get = alpx_control_mixer_get, + .put = alpx_control_mixer_put, +}; + +static int alpx_control_mixer_register(struct snd_card *card, + struct alpx_control_descriptor *descriptor, + unsigned int mixer_in, + unsigned int mixer_out) +{ + struct alpx_device* const alpx_dev = card->private_data; + const unsigned int control_index = alpx_dev->controls_index; + struct alpx_control* const control = &alpx_dev->controls[control_index]; +#if defined(CONFIG_ALPX_LOG_CONTROLS) + const unsigned int lines_count = descriptor->data.mixer.lines_count; +#endif + char name[64] = { 0 }; + int ret; + + control->descriptor = descriptor; + control->data.mixer.mixer_in = mixer_in; + control->data.mixer.mixer_out = mixer_out; + + snprintf(name, sizeof(name), "%s %u/%u Playback Volume", descriptor->prefix, + mixer_in, mixer_out); + + alpx_control_mixer.name = name; + alpx_control_mixer.private_value = control_index; + alpx_control_mixer.access = descriptor->access; + alpx_control_mixer.tlv.p = descriptor->data.mixer.gains_scale; + +#if defined(CONFIG_ALPX_LOG_CONTROLS) + dev_dbg( alpx_dev->dev," creating mixer %s in controls[%u] linked to [0x%x:0x%x].\n", + name, + control_index, + control->descriptor->base, + ALP222_MIXER_GAIN_REG(lines_count, mixer_in, mixer_out)); +#endif + + ret = snd_ctl_add(card, snd_ctl_new1(&alpx_control_mixer, alpx_dev)); + if (ret) + return ret; + + alpx_dev->controls_index++; + + return 0; +} +/* Field */ + +static int alpx_control_choice_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *info) +{ + struct alpx_device *alpx_dev = snd_kcontrol_chip(kcontrol); + unsigned int control_index = kcontrol->private_value; + struct alpx_control *control = &alpx_dev->controls[control_index]; + struct alpx_control_descriptor_choice *choice = + &control->descriptor->data.choice; + +#if defined(CONFIG_ALPX_LOG_CONTROLS) + dev_dbg( alpx_dev->dev," Field %d entries.\n", choice->entries_count); +#endif + + return snd_ctl_enum_info(info, 1, choice->entries_count, choice->entries); +} + +static int alpx_control_choice_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *elem_value) +{ + struct alpx_device *alpx_dev = snd_kcontrol_chip(kcontrol); + unsigned int control_index = kcontrol->private_value; + struct alpx_control *control = &alpx_dev->controls[control_index]; + u32 offset, value; + unsigned int i; + + offset = control->descriptor->base + + control->descriptor->data.choice.offset; + + value = readl(alpx_dev->base + offset); + value &= control->descriptor->data.choice.mask; + value >>= control->descriptor->data.choice.pos; + +#if defined(CONFIG_ALPX_LOG_CONTROLS) + dev_info( alpx_dev->dev," GET[%d] 0x%x (0x%x)<= [0x%p:%x:%x]\n", + control_index, + value, + readl(alpx_dev->base + offset), + alpx_dev->base, + control->descriptor->base, + control->descriptor->data.choice.offset); +#endif + + for (i = 0; i < control->descriptor->data.choice.entries_count; i++) { + u32 entry_value = + control->descriptor->data.choice.entries_values[i]; + + if (value == entry_value) { + elem_value->value.enumerated.item[0] = i; + + dev_info( alpx_dev->dev,"GET[%d]: Reg: %d => Sync[%d] (%s) \n", + control_index, + value, + i, + control->descriptor->data.translated_choice.entries[i]); + + return 0; + } + } + + return -EINVAL; +} + +static int alpx_control_choice_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *elem_value) +{ + struct alpx_device *alpx_dev = snd_kcontrol_chip(kcontrol); + unsigned int control_index = kcontrol->private_value; + struct alpx_control *control = &alpx_dev->controls[control_index]; + unsigned int index_value; + u32 offset, reg_value; + + offset = control->descriptor->base + + control->descriptor->data.choice.offset; + reg_value = readl(alpx_dev->base + offset); + + reg_value &= ~control->descriptor->data.choice.mask; + + index_value = elem_value->value.enumerated.item[0]; + reg_value |= control->descriptor->data.choice.entries_values[index_value] << control->descriptor->data.choice.pos ; + + +#if defined(CONFIG_ALPX_LOG_CONTROLS) + dev_info( alpx_dev->dev,"PUT[%d] 0x%x ->([%d]0x%x) 0x%x => [0x%p:%x:%x]\n", + control_index, + readl(alpx_dev->base + offset), + index_value, + control->descriptor->data.choice.entries_values[index_value], + reg_value, + alpx_dev->base, + control->descriptor->base, + control->descriptor->data.choice.offset); +#endif + + dev_info( alpx_dev->dev,"PUT[%d]: Sync[%d] (%s) => Reg: %d\n", + control_index, + index_value, + control->descriptor->data.choice.entries[index_value], + control->descriptor->data.choice.entries_values[index_value]); + + writel(reg_value, alpx_dev->base + offset); + + return 1; +} + +static struct snd_kcontrol_new alpx_control_choice = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + + .info = alpx_control_choice_info, + .get = alpx_control_choice_get, + .put = alpx_control_choice_put, +}; + +static int alpx_control_choice_register(struct snd_card *card, + struct alpx_control_descriptor *descriptor) +{ + struct alpx_device *alpx_dev = card->private_data; + unsigned int control_index = alpx_dev->controls_index; + struct alpx_control *control = &alpx_dev->controls[control_index]; + int ret = 0; + + control->descriptor = descriptor; + + alpx_control_choice.name = descriptor->prefix; + alpx_control_choice.private_value = control_index; + alpx_control_choice.access = descriptor->access; + +#if defined(CONFIG_ALPX_LOG_CONTROLS) + dev_dbg( alpx_dev->dev,"registering CHOICE %s[%d]\n", + alpx_control_choice.name, + control_index); +#endif + + ret = snd_ctl_add(card, snd_ctl_new1(&alpx_control_choice, alpx_dev)); + if (ret) + return ret; + + alpx_dev->controls_index++; + + return 0; +} + +/* Translated choice */ + + +static int alpx_control_translated_choice_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *info) +{ + struct alpx_device *alpx_dev = snd_kcontrol_chip(kcontrol); + unsigned int control_index = kcontrol->private_value; + struct alpx_control *control = &alpx_dev->controls[control_index]; + struct alpx_control_descriptor_translated_choice *choice = + &control->descriptor->data.translated_choice; + +#if defined(CONFIG_ALPX_LOG_CONTROLS) + dev_dbg( alpx_dev->dev," Field %d entries.\n", choice->entries_count); +#endif + + return snd_ctl_enum_info(info, 1, choice->entries_count, choice->entries); +} + +static int alpx_control_translated_choice_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *elem_value) +{ + struct alpx_device *alpx_dev = snd_kcontrol_chip(kcontrol); + unsigned int control_index = kcontrol->private_value; + struct alpx_control *control = &alpx_dev->controls[control_index]; + u32 offset, value; + + offset = control->descriptor->base + + control->descriptor->data.translated_choice.offset; + + value = readl(alpx_dev->base + offset); + value &= control->descriptor->data.translated_choice.mask; + value >>= control->descriptor->data.translated_choice.pos; + +#if defined(CONFIG_ALPX_LOG_CONTROLS) + dev_dbg( alpx_dev->dev," 0x%x (0x%x)<= [0x%p:%x:%x]\n", + value, + readl(alpx_dev->base + offset), + alpx_dev->base, + control->descriptor->base, + control->descriptor->data.translated_choice.offset); +#endif + + + if (value < control->descriptor->data.translated_choice.card_entries_count) { + const unsigned int app_value = control->descriptor->data.translated_choice.card_entries_values[value]; + dev_info( alpx_dev->dev,"GET[%d]: Reg: %d => %d: App Sync: %s \n", + control_index, + value, + app_value, + control->descriptor->data.translated_choice.entries[app_value]); + elem_value->value.enumerated.item[0] = app_value; + return 0; + } + + return -EINVAL; +} + +static int alpx_control_translated_choice_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *elem_value) +{ + struct alpx_device *alpx_dev = snd_kcontrol_chip(kcontrol); + unsigned int control_index = kcontrol->private_value; + struct alpx_control *control = &alpx_dev->controls[control_index]; + unsigned int index_value; + u32 offset, reg_value; + + offset = control->descriptor->base + + control->descriptor->data.translated_choice.offset; + reg_value = readl(alpx_dev->base + offset); + + reg_value &= ~control->descriptor->data.translated_choice.mask; + + index_value = elem_value->value.enumerated.item[0]; + + //Avoid error :RESET the source if BUGGED !! + if (index_value >= control->descriptor->data.translated_choice.entries_count) + index_value = 0; + + reg_value |= control->descriptor->data.translated_choice.entries_values[index_value] << control->descriptor->data.translated_choice.pos ; + +#if defined(CONFIG_ALPX_LOG_CONTROLS) + dev_dbg( alpx_dev->dev,"0x%x ->([%d]0x%x) 0x%x => [0x%p:%x:%x]\n", + readl(alpx_dev->base + offset), + index_value, + control->descriptor->data.translated_choice.entries_values[index_value], + reg_value, + alpx_dev->base, + control->descriptor->base, + control->descriptor->data.translated_choice.offset); +#endif + + dev_info( alpx_dev->dev,"PUT[%d]: App Sync[%d] (%s) => Reg: %d\n", + control_index, + index_value, + control->descriptor->data.translated_choice.entries[index_value], + control->descriptor->data.translated_choice.entries_values[index_value]); + + //Avoid out of range values + if (control->descriptor->data.translated_choice.entries_values[index_value] <= ALP222_CLK_MANAGER_CLK_SRC_MAX) { + writel(reg_value, alpx_dev->base + offset); + } + + return 1; +} + + +static struct snd_kcontrol_new alpx_control_translated_choice = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + + .info = alpx_control_translated_choice_info, + .get = alpx_control_translated_choice_get, + .put = alpx_control_translated_choice_put, +}; + +static int alpx_control_translated_choice_register(struct snd_card *card, + struct alpx_control_descriptor *descriptor) +{ + struct alpx_device *alpx_dev = card->private_data; + unsigned int control_index = alpx_dev->controls_index; + struct alpx_control *control = &alpx_dev->controls[control_index]; + int ret = 0; + + control->descriptor = descriptor; + + alpx_control_translated_choice.name = descriptor->prefix; + alpx_control_translated_choice.private_value = control_index; + alpx_control_translated_choice.access = descriptor->access; + +#if defined(CONFIG_ALPX_LOG_CONTROLS) + dev_dbg( alpx_dev->dev,"registering Translated CHOICE %s[%d]\n", + alpx_control_translated_choice.name, + control_index); +#endif + + ret = snd_ctl_add(card, snd_ctl_new1(&alpx_control_translated_choice, alpx_dev)); + if (ret) + return ret; + + alpx_dev->controls_index++; + + return 0; +} + +/* Flags */ +static int alpx_control_flag_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *info) +{ +#if defined(CONFIG_ALPX_LOG_CONTROLS) + struct alpx_device *alpx_dev = snd_kcontrol_chip(kcontrol); + unsigned int control_index = kcontrol->private_value; + struct alpx_control *control = &alpx_dev->controls[control_index]; + struct alpx_control_descriptor_choice *choice = + &control->descriptor->data.choice; + + dev_dbg( alpx_dev->dev," Flag %d entries.\n", choice->entries_count); +#endif + + info->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + info->count = 1; + info->value.integer.min = 0; + info->value.integer.max = 1; + + return 0; +} + +static int alpx_control_flag_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *elem_value) +{ + struct alpx_device *alpx_dev = snd_kcontrol_chip(kcontrol); + unsigned int control_index = kcontrol->private_value; + struct alpx_control *control = &alpx_dev->controls[control_index]; + u32 offset, value; + + offset = control->descriptor->base + + control->descriptor->data.flag.offset; + + value = readl(alpx_dev->base + offset); + value &= control->descriptor->data.flag.mask; + value >>= control->descriptor->data.flag.pos; + +#if defined(CONFIG_ALPX_LOG_CONTROLS) + dev_dbg( alpx_dev->dev,"0x%x (0x%x)<= [0x%p:%x:%x]\n", + value, + readl(alpx_dev->base + offset), + alpx_dev->base, + control->descriptor->base, + control->descriptor->data.flag.offset); +#endif + + elem_value->value.enumerated.item[0] = value; + + return 0; +} + +static int alpx_control_flag_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *elem_value) +{ + struct alpx_device *alpx_dev = snd_kcontrol_chip(kcontrol); + unsigned int control_index = kcontrol->private_value; + struct alpx_control *control = &alpx_dev->controls[control_index]; + unsigned int new_value; + u32 offset, reg_value; + + offset = control->descriptor->base + + control->descriptor->data.flag.offset; + reg_value = readl(alpx_dev->base + offset); + + reg_value &= ~control->descriptor->data.flag.mask; + + new_value = elem_value->value.enumerated.item[0]; + reg_value |= new_value << control->descriptor->data.flag.pos; + +#if defined(CONFIG_ALPX_LOG_CONTROLS) + dev_dbg( alpx_dev->dev,"0x%x -> 0x%x => [0x%p:%x:%x]\n", + readl(alpx_dev->base + offset), + reg_value, + alpx_dev->base, + control->descriptor->base, + control->descriptor->data.flag.offset); +#endif + + writel(reg_value, alpx_dev->base + offset); + + return 1; +} + +static struct snd_kcontrol_new alpx_control_flag = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + + .info = alpx_control_flag_info, + .get = alpx_control_flag_get, + .put = alpx_control_flag_put, +}; + + +static int alpx_control_flag_register(struct snd_card *card, + struct alpx_control_descriptor *descriptor) +{ + struct alpx_device *alpx_dev = card->private_data; + unsigned int control_index = alpx_dev->controls_index; + struct alpx_control *control = &alpx_dev->controls[control_index]; + int ret; + + control->descriptor = descriptor; + + alpx_control_flag.name = descriptor->prefix; + alpx_control_flag.private_value = control_index; + alpx_control_flag.access = descriptor->access; + + ret = snd_ctl_add(card, snd_ctl_new1(&alpx_control_flag, alpx_dev)); + if (ret) + return ret; + + alpx_dev->controls_index++; + + return 0; +} + +/* Flags_channels */ +static struct alpx_control* alpx_lookup_codec_pga_control(struct alpx_device * alpx_dev, unsigned int side) +{ + //Lookup the LINE PGA associated to the given side + unsigned int ctrl_idx = 0; +dev_dbg(alpx_dev->dev," alpx_dev->controls_count = %d, side:%d\n", alpx_dev->controls_count, side); + + for (ctrl_idx = 0 ; ctrl_idx < (alpx_dev->controls_count - 1) ; ctrl_idx++) { + if ((alpx_dev->controls[ctrl_idx].descriptor->type == ALPX_CONTROL_TYPE_ANALOG_EQ) && + (alpx_dev->controls[ctrl_idx].data.codec.idx == side)){ + dev_dbg(alpx_dev->dev," found LINE EQ ctrl[%d]{%d: 0x%x:%x}\n", + ctrl_idx, alpx_dev->controls[ctrl_idx].data.codec.idx, + alpx_dev->controls[ctrl_idx].descriptor->base, ALPX_CODEC_CTRL_GAIN_REG(side)); + + //return alpx_dev->controls[ctrl_idx].descriptor->base + ALPX_CODEC_CTRL_GAIN_REG(side); + return &alpx_dev->controls[ctrl_idx]; + } + } + dev_err(alpx_dev->dev," NOTHING FOUND\n"); + return NULL; +} + + +static struct alpx_control* alpx_lookup_codec_mic_gain_control(struct alpx_device * alpx_dev, unsigned int pos) +{ + //Lookup the LINE PGA associated to the given side + unsigned int ctrl_idx = 0; +dev_dbg(alpx_dev->dev," alpx_dev->controls_count = %d, pos:%d\n", alpx_dev->controls_count, pos); + + for (ctrl_idx = 0 ; ctrl_idx < (alpx_dev->controls_count - 1) ; ctrl_idx++) { +#if 0 + dev_dbg(alpx_dev->dev,"idx:%d, descriptor : %p (%s), t:%d\n", + ctrl_idx, + &alpx_dev->controls[ctrl_idx].descriptor, + alpx_dev->controls[ctrl_idx].descriptor->prefix, + alpx_dev->controls[ctrl_idx].descriptor->type); +#endif + if ((alpx_dev->controls[ctrl_idx].descriptor->type == ALPX_CONTROL_TYPE_GAINS_EMBEDDED) && + (alpx_dev->controls[ctrl_idx].descriptor->data.mic_gains.pos == pos)){ + dev_dbg(alpx_dev->dev," found MIC Gain ctrl[%d]{0x%x:%x}\n", ctrl_idx, + alpx_dev->controls[ctrl_idx].descriptor->base, alpx_dev->controls[ctrl_idx].descriptor->data.mic_gains.offset); + + //return alpx_dev->controls[ctrl_idx].descriptor->base + alpx_dev->controls[ctrl_idx].descriptor->data.mic_gains.offset; + return &alpx_dev->controls[ctrl_idx]; + } + } + dev_err(alpx_dev->dev,"NOTHING FOUND\n"); + return NULL; +} + +static void alpx_mic_handle_activate_change(struct alpx_device * alpx_dev, struct alpx_control * mic_control, u32 mic_pos, unsigned int is_mic_on) +{ + struct alpx_control* mic_gain_ctrl = NULL; + struct alpx_control* line_eq_gain_ctrl = NULL; + u32 line_codec_reg_offset = 0; + u32 mic_gain_offset; + u32 mic_gain_mask; + u32 line_side = 0; + u32 mic_side_pos = 0; + + + dev_dbg(alpx_dev->dev,"%s(%p, %p,%d,%d) : CALLED\n",__func__, + alpx_dev, + mic_control, + mic_pos, + is_mic_on); + + //Find the right LINE PGA register + switch(mic_pos) { + case ALP222_MIC_EN_L_POS: + dev_dbg(alpx_dev->dev,"LEFT %s\n", is_mic_on ? "On" : "Off"); + line_side = 0; + mic_side_pos = ALP222_MIC_GAIN_L_POS; + break; + case ALP222_MIC_EN_R_POS: + dev_dbg(alpx_dev->dev," RIGHT %s\n",is_mic_on ? "On" : "Off"); + line_side = 1; + mic_side_pos = ALP222_MIC_GAIN_R_POS; + break; + default: + dev_dbg(alpx_dev->dev," Unknown mic position %d !!\n", mic_pos); + return; + }; + + + line_eq_gain_ctrl = alpx_lookup_codec_pga_control(alpx_dev, line_side); + line_codec_reg_offset = line_eq_gain_ctrl->descriptor->base + ALPX_CODEC_CTRL_GAIN_REG(line_side); + mic_gain_ctrl = alpx_lookup_codec_mic_gain_control(alpx_dev, mic_side_pos); + + if (line_eq_gain_ctrl == NULL){ + dev_warn(alpx_dev->dev,"No line EQ ctrl found !\n"); + return; + } + + if ( mic_gain_ctrl == NULL){ + dev_warn(alpx_dev->dev,"No MIC ctrl found !!\n"); + return; + } + + mic_gain_mask = mic_gain_ctrl->descriptor->data.mic_gains.mask; + mic_gain_offset = mic_gain_ctrl->descriptor->base + mic_gain_ctrl->descriptor->data.mic_gains.offset; + + + dev_dbg(alpx_dev->dev,"PGA offset :0x%x, MIC %s offset : 0x%x, MIC mask: 0x%08x\n", + line_codec_reg_offset, + mic_control->descriptor->prefix, + mic_gain_offset, + mic_gain_mask); + +#if 1 + dev_dbg(alpx_dev->dev,"BEFORE MIC %s stored:0X%x, regMIC:0x%x, regPGA:0x%x\n", + is_mic_on ? "On" : "Off", + mic_control->data.mic.stored_gain_in_reg, + readl(alpx_dev->base + mic_gain_offset), + readl(alpx_dev->base + line_codec_reg_offset)); + + //Now handle the mute state change + if (is_mic_on == 0) { + //MIC is going to be MUTED + //restore the LINE gain and store the current MIC gain. + writel(mic_control->data.mic.stored_gain_in_reg, alpx_dev->base + line_codec_reg_offset); + mic_control->data.mic.stored_gain_in_reg = readl(alpx_dev->base + mic_gain_offset); + //MUTE with MIC with ZERO in gain + writel(mic_control->data.mic.stored_gain_in_reg & ~mic_gain_mask, alpx_dev->base + mic_gain_offset); + //Keep the gain only + mic_control->data.mic.stored_gain_in_reg &= mic_gain_mask; + + } else { + //LINE is going to be MUTED + //Restore the MIC gain and store the line gain and MUTE line + u32 mic_reg_value = readl(alpx_dev->base + mic_gain_offset); + writel(mic_control->data.mic.stored_gain_in_reg | (mic_reg_value & ~mic_gain_mask), alpx_dev->base + mic_gain_offset); + mic_control->data.mic.stored_gain_in_reg = readl(alpx_dev->base + line_codec_reg_offset); + //MUTE LINE with 0 in LINE + writel(0, alpx_dev->base + line_codec_reg_offset); + } + + dev_dbg(alpx_dev->dev," AFTER MIC %s stored: 0x%x, regMIC:0x%x, regPGA:0x%x\n", + is_mic_on ? "On" : "Off", + mic_control->data.mic.stored_gain_in_reg, + readl(alpx_dev->base + mic_gain_offset), + readl(alpx_dev->base + line_codec_reg_offset)); +#endif +} + +static int alpx_control_flags_embedded_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *info) +{ + + struct alpx_device *alpx_dev = snd_kcontrol_chip(kcontrol); + unsigned int control_index = kcontrol->private_value; + struct alpx_control *control = &alpx_dev->controls[control_index]; + struct alpx_control_descriptor *control_desc = control->descriptor; + +#if defined(CONFIG_ALPX_LOG_CONTROLS) + dev_dbg( alpx_dev->dev,"Flags %d entries.\n", control_desc->data.mic_flags.lines_count); +#endif + + info->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + info->count = 1; //One line per control + info->value.integer.min = 0; + info->value.integer.max = 1; + return 0; +} + +static int alpx_control_flags_embedded_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *elem_value) +{ + struct alpx_device *alpx_dev = snd_kcontrol_chip(kcontrol); + unsigned int control_index = kcontrol->private_value; + struct alpx_control *control = &alpx_dev->controls[control_index]; + struct alpx_control_descriptor *control_desc = control->descriptor; + u32 offset, value; + + /* read the composite register */ + offset = control_desc->base + + control_desc->data.mic_flags.offset; + + value = readl(alpx_dev->base + offset); + + +#if defined(CONFIG_ALPX_LOG_CONTROLS) + dev_dbg( alpx_dev->dev,"0x%x (0x%x)<= [0x%p:%x:%x]\n", + value, + readl(alpx_dev->base + offset), + alpx_dev->base, + control_desc->base, + control_desc->data.mic_flags.offset); +#endif + + elem_value->value.enumerated.item[0] = value & control_desc->data.mic_flags.mask; + elem_value->value.enumerated.item[0] >>= control_desc->data.mic_flags.pos; + +#if defined(CONFIG_ALPX_LOG_CONTROLS) + dev_dbg( alpx_dev->dev,"item[0]=%d\n", + elem_value->value.enumerated.item[0]); +#endif + + return 0; +} + +static int alpx_control_flags_embedded_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *elem_value) +{ + struct alpx_device *alpx_dev = snd_kcontrol_chip(kcontrol); + unsigned int control_index = kcontrol->private_value; + struct alpx_control *control = &alpx_dev->controls[control_index]; + struct alpx_control_descriptor *control_desc = control->descriptor; + const unsigned int new_state = elem_value->value.enumerated.item[0]; + const u32 offset = control_desc->base + + control_desc->data.mic_flags.offset; + u32 reg_value; + u32 current_state; + + + reg_value = readl(alpx_dev->base + offset); + + dev_dbg(alpx_dev->dev," ctrl[%d]=>%p{name:%s pos:%d reg:0x%08x} : %d\n", control_index, control, control_desc->prefix, control_desc->data.mic_flags.pos, reg_value, new_state); + + current_state = (reg_value & control_desc->data.mic_flags.mask) >> control_desc->data.mic_flags.pos; + + if (current_state == new_state) { + dev_dbg(alpx_dev->dev,"EXIT W/O state change\n"); + return 0; + } + + //* SET the bit according to the associated line */ + reg_value &= ~control_desc->data.mic_flags.mask; + reg_value |= new_state << control_desc->data.mic_flags.pos; + writel(reg_value, alpx_dev->base + offset); + + //Handle the MUTE state transition Only for MIC enable/disable + if ((control_desc->data.mic_flags.pos == ALP222_MIC_EN_L_POS) || + (control_desc->data.mic_flags.pos == ALP222_MIC_EN_R_POS)){ + alpx_mic_handle_activate_change(alpx_dev, control,control_desc->data.mic_flags.pos, new_state); + } + + +#if defined(CONFIG_ALPX_LOG_CONTROLS) + dev_dbg( alpx_dev->dev," item[0]=%d\n", + elem_value->value.enumerated.item[0]); + dev_dbg( alpx_dev->dev," 0x%x -> 0x%x => [0x%p:%x:%x]\n", + readl(alpx_dev->base + offset), + reg_value, + alpx_dev->base, + control_desc->base, + control_desc->data.mic_flags.offset); +#endif + + dev_dbg(alpx_dev->dev," EXIT\n"); + return 1; +} + +static struct snd_kcontrol_new alpx_control_flags_embedded = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + + .info = alpx_control_flags_embedded_info, + .get = alpx_control_flags_embedded_get, + .put = alpx_control_flags_embedded_put, +}; + +static int alpx_control_flags_embedded_register(struct snd_card *card, + struct alpx_control_descriptor *descriptor) +{ + struct alpx_device *alpx_dev = card->private_data; + unsigned int control_index = alpx_dev->controls_index; + struct alpx_control *control = &alpx_dev->controls[control_index]; + int ret; + + control->descriptor = descriptor; + + alpx_control_flags_embedded.name = descriptor->prefix; + alpx_control_flags_embedded.private_value = control_index; + alpx_control_flags_embedded.access = descriptor->access; + + ret = snd_ctl_add(card, snd_ctl_new1(&alpx_control_flags_embedded, alpx_dev)); + if (ret) + return ret; + + alpx_dev->controls_index++; + + //Mut the MIC + alpx_mic_handle_activate_change(alpx_dev, control, descriptor->data.mic_flags.pos, 0); + + return 0; +} + +/* Gains mixed */ + +static u32 alpx_mic_gain_db_to_reg (u32 db) +{ + /* Gain range is 10 to 65, skip special value 0*/ + if (db <= ALP222_MIC_GAINS_MIN_REG_VAL){ + return 1; + } else if (db < ALP222_MIC_GAINS_MAX_REG_VAL){ + return db - ALP222_MIC_REG_GAIN_SHIFT; + } else { + return (ALP222_MIC_GAINS_MAX_REG_VAL + 1 - ALP222_MIC_REG_GAIN_SHIFT); + } +} + +static u32 alpx_mic_gain_reg_to_db (u32 reg) +{ + /* Skip reg == 0 */ + if (reg <= 1) { + return ALP222_MIC_GAINS_MIN_REG_VAL; + } else if (reg < (ALP222_MIC_GAINS_MAX_REG_VAL + 1 - ALP222_MIC_REG_GAIN_SHIFT)) { + return reg + ALP222_MIC_REG_GAIN_SHIFT; + } else { + return ALP222_MIC_GAINS_MAX_REG_VAL; + } +} + +static int alpx_control_gains_embedded_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *info) +{ + + struct alpx_device *alpx_dev = snd_kcontrol_chip(kcontrol); + unsigned int control_index = kcontrol->private_value; + struct alpx_control *control = &alpx_dev->controls[control_index]; + struct alpx_control_descriptor *control_desc = control->descriptor; + +#if defined(CONFIG_ALPX_LOG_CONTROLS) + dev_dbg( alpx_dev->dev," Gains %d entries.\n", control_desc->data.mic_gains.lines_count); +#endif + + info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + info->count = 1; //One control per item ! + info->value.integer.min = control_desc->data.mic_gains.min; + info->value.integer.max = control_desc->data.mic_gains.max; + + return 0; +} + +static int alpx_control_gains_embedded_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *elem_value) +{ + struct alpx_device *alpx_dev = snd_kcontrol_chip(kcontrol); + unsigned int control_index = kcontrol->private_value; + struct alpx_control *control = &alpx_dev->controls[control_index]; + u32 offset, reg_value, raw_value; + struct alpx_control_descriptor *control_desc = control->descriptor; + + /* read the composite register */ + offset = control_desc->base + control_desc->data.mic_gains.offset; + + reg_value = readl(alpx_dev->base + offset); + + + +#if defined(CONFIG_ALPX_LOG_CONTROLS) + dev_dbg( alpx_dev->dev," 0x%x (0x%x)<= [0x%p:%x:%x]\n", + reg_value, + readl(alpx_dev->base + offset), + alpx_dev->base, + control_desc->base, + control_desc->data.mic_gains.offset); +#endif + //* GET the bit according to the associated line */ + raw_value = reg_value & (control_desc->data.mic_gains.mask); + raw_value >>= (control_desc->data.mic_gains.pos); + //Convert Raw value into dB + elem_value->value.integer.value[0] = alpx_mic_gain_reg_to_db(raw_value); + + #if defined(CONFIG_ALPX_LOG_CONTROLS) + dev_dbg( alpx_dev->dev,"value[0]=%ld / raw: 0x%x\n", + elem_value->value.integer.value[0], + raw_value); +#endif + + return 0; +} + +static int alpx_control_gains_embedded_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *elem_value) +{ + struct alpx_device *alpx_dev = snd_kcontrol_chip(kcontrol); + unsigned int control_index = kcontrol->private_value; + struct alpx_control *control = &alpx_dev->controls[control_index]; + const unsigned int new_value = alpx_mic_gain_db_to_reg(elem_value->value.integer.value[0]); + u32 offset, reg_value; + struct alpx_control_descriptor *control_desc = control->descriptor; + + offset = control_desc->base + + control_desc->data.mic_gains.offset; + reg_value = readl(alpx_dev->base + offset); + + //* SET the bit according to the associated line */ + reg_value &= ~(control_desc->data.mic_gains.mask); + reg_value |= new_value << (control_desc->data.mic_gains.pos); + + + + +#if defined(CONFIG_ALPX_LOG_CONTROLS) + dev_dbg( alpx_dev->dev,"value[0]=%ld, reg_value: 0x%x\n", + elem_value->value.integer.value[0], + reg_value ); + dev_dbg( alpx_dev->dev,"0x%x -> 0x%x => [0x%p:%x:%x]\n", + readl(alpx_dev->base + offset), + reg_value, + alpx_dev->base, + control_desc->base, + control_desc->data.mic_gains.offset); +#endif + + writel(reg_value, alpx_dev->base + offset); + + + return 1; +} + + +static struct snd_kcontrol_new alpx_control_gains_embedded = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + + .info = alpx_control_gains_embedded_info, + .get = alpx_control_gains_embedded_get, + .put = alpx_control_gains_embedded_put, +}; + +static int alpx_control_gains_embedded_register(struct snd_card *card, + struct alpx_control_descriptor *alp_descriptor) +{ + struct alpx_device *alpx_dev = card->private_data; + unsigned int control_index = alpx_dev->controls_index; + struct alpx_control *control = &alpx_dev->controls[control_index]; + int ret; + char name[64] = { 0 }; + control->descriptor = alp_descriptor; + + snprintf(name, sizeof(name), "%s Volume", alp_descriptor->prefix); + + alpx_control_gains_embedded.name = name; + alpx_control_gains_embedded.private_value = control_index; + alpx_control_gains_embedded.access = alp_descriptor->access; + alpx_control_gains_embedded.tlv.p = alp_descriptor->data.mic_gains.gains_scale; + + + dev_dbg(alpx_dev->dev," mic: %s, gain offset : 0x%x, gains scale : %p\n", + name, + alp_descriptor->data.mic_gains.offset, + alp_descriptor->data.mic_gains.gains_scale); + + ret = snd_ctl_add(card, snd_ctl_new1(&alpx_control_gains_embedded, alpx_dev)); + if (ret) + return ret; + + alpx_dev->controls_index++; + + return 0; +} + +/* Controls */ + +static int alpx_controls_router_register(struct snd_card *card, + struct alpx_control_descriptor *descriptor) +{ + unsigned int i; + int ret; + + for (i = 0; i < descriptor->data.router.lines_count; i++) { + ret = alpx_control_router_register(card, descriptor, i); + if (ret) + return ret; + } + + return 0; +} + +static int alpx_controls_mixer_register(struct snd_card *card, + struct alpx_control_descriptor *descriptor) +{ + unsigned int lines_count = descriptor->data.mixer.lines_count; + unsigned int i, o; + int ret; + + for (o = 0; o < lines_count; o++) { + for (i = 0; i < lines_count; i++) { + ret = alpx_control_mixer_register(card, descriptor, i, o); + if (ret) + return ret; + } + } + + return 0; +} + +#if 0 +static int alpx_controls_gains_embedded_register(struct snd_card *card, + struct alpx_control_descriptor *descriptor) +{ + unsigned int lines_count = descriptor->data.mixer.lines_count; + unsigned int i; + int ret = 0; + + for (i = 0; !ret && i < lines_count; i++) { + ret = alpx_control_gains_embedded_register(card, descriptor, i); + } + + return ret; +} + +static int alpx_controls_flags_embedded_register(struct snd_card *card, + struct alpx_control_descriptor *descriptor) +{ + unsigned int lines_count = descriptor->data.mixer.lines_count; + unsigned int i, o; + int ret = 0; + + for (i = 0;!ret && i < lines_count; i++) { + ret = alpx_control_flags_embedded_register(card, descriptor, i, o); + } + + return ret; +} +#endif + + +/* AlpX Controls */ +int alpx_controls_register(struct snd_card *card) +{ + struct alpx_device *alpx_dev = card->private_data; + const struct alpx_variant *variant = alpx_dev->variant; + unsigned int controls_count = 0; + unsigned int i; + int ret; + + dev_dbg(alpx_dev->dev, "Registering controls for %s\n", card->longname); + + if (alpx_dev->controls) + return -EBUSY; + + for (i = 0; i < variant->control_descriptors_count; i++) { + struct alpx_control_descriptor *descriptor = + &variant->control_descriptors[i]; + + switch (descriptor->type) { + case ALPX_CONTROL_TYPE_CHOICE: + case ALPX_CONTROL_TYPE_FLAG: + case ALPX_CONTROL_TYPE_TRANSLATED_CHOICE: + /* One control for each descriptor. */ + controls_count++; + break; + case ALPX_CONTROL_TYPE_AMPLIFIER: + /* Amplified lines */ + controls_count += descriptor->data.ampli.lines_count; + break; + case ALPX_CONTROL_TYPE_ROUTER: + /* One control for each router line. */ + controls_count += descriptor->data.router.lines_count; + break; + case ALPX_CONTROL_TYPE_MIXER: + /* One control for each mixer line intersection. */ + controls_count += descriptor->data.mixer.lines_count * + descriptor->data.mixer.lines_count; + break; + case ALPX_CONTROL_TYPE_ANALOG_EQ: + controls_count += descriptor->data.codec.lines_count; + break; + case ALPX_CONTROL_TYPE_GAINS_EMBEDDED: + controls_count += descriptor->data.mic_gains.lines_count; + break; + case ALPX_CONTROL_TYPE_FLAGS_EMBEDDED: + controls_count += descriptor->data.mic_flags.lines_count; + break; + case ALPX_CONTROL_RESERVED: + controls_count ++; + break; + case ALPX_CONTROL_TYPE_CONSTANT: + controls_count++; + break; + case ALPX_CONTROL_TYPE_AXCMEM_REL_CHOICE: + controls_count++; + break; + case ALPX_CONTROL_TYPE_AXCMEM_REL_VALUE: + controls_count++; + break; + default: + return -EINVAL; + } + } + + alpx_dev->controls = kcalloc(controls_count, + sizeof(struct alpx_control), GFP_KERNEL); + + if (!alpx_dev->controls) + return -ENOMEM; + + alpx_dev->controls_count = controls_count; + + dev_dbg(alpx_dev->dev," alpx_dev->controls_count = %d\n", alpx_dev->controls_count); + + for (i = 0; i < variant->control_descriptors_count; i++) { + struct alpx_control_descriptor *alp_descriptor = + &variant->control_descriptors[i]; + + dev_dbg(alpx_dev->dev,"descriptor[%d]:{%d, %s}\n", + i, alp_descriptor->type, alp_descriptor->prefix); + + switch (alp_descriptor->type) { + case ALPX_CONTROL_TYPE_AMPLIFIER: + ret = alpx_controls_amplifier_register(card, alp_descriptor); + if (ret) + return ret; + break; + case ALPX_CONTROL_TYPE_ANALOG_EQ: + ret = alpx_controls_codec_register(card, alp_descriptor); + if (ret) + return ret; + break; + case ALPX_CONTROL_TYPE_ROUTER: + ret = alpx_controls_router_register(card, alp_descriptor); + if (ret) + return ret; + break; + case ALPX_CONTROL_TYPE_MIXER: + ret = alpx_controls_mixer_register(card, alp_descriptor); + if (ret) + return ret; + break; + case ALPX_CONTROL_TYPE_CHOICE: + ret = alpx_control_choice_register(card, alp_descriptor); + if (ret) + return ret; + break; + case ALPX_CONTROL_TYPE_TRANSLATED_CHOICE: + ret = alpx_control_translated_choice_register(card, alp_descriptor); + if (ret) + return ret; + break; + case ALPX_CONTROL_TYPE_FLAG: + ret = alpx_control_flag_register(card, alp_descriptor); + if (ret) + return ret; + break; + case ALPX_CONTROL_TYPE_GAINS_EMBEDDED: + ret = alpx_control_gains_embedded_register(card, alp_descriptor); + if (ret) + return ret; + break; + case ALPX_CONTROL_TYPE_FLAGS_EMBEDDED: + ret = alpx_control_flags_embedded_register(card, alp_descriptor); + if (ret) + return ret; + break; + case ALPX_CONTROL_RESERVED: + ret = alpx_control_reserved_register(card, alp_descriptor); + if (ret) + return ret; + break; + case ALPX_CONTROL_TYPE_CONSTANT: + ret = alpx_control_constant_register(card, alp_descriptor); + if (ret) + return ret; + break; + case ALPX_CONTROL_TYPE_AXCMEM_REL_CHOICE: + ret = alpx_control_axcmem_rel_choice_register(card, alp_descriptor); + if (ret) + return ret; + break; + case ALPX_CONTROL_TYPE_AXCMEM_REL_VALUE: + ret = alpx_control_axcmem_rel_value_register(card, alp_descriptor); + if (ret) + return ret; + break; + } + } + return 0; +} + +int alp222_mic_controls_default_config(struct alpx_device * alpx_dev) +{ + //By default CM is enabled and DC is disabled + uint32_t ctrl_reg = readl(alpx_dev->base + ALP222_CONTROL_BASE + ALP222_MIC_CONTROL_REG); + + dev_dbg(alpx_dev->dev," mic::ctrl_reg[0x%08x:%x]=0x%08x\n", + ALP222_CONTROL_BASE, ALP222_MIC_CONTROL_REG, + readl(alpx_dev->base + ALP222_CONTROL_BASE + ALP222_MIC_CONTROL_REG)); + + //remove DC and CM bits + ctrl_reg &= ~(ALP222_MIC_DC_L_MASK | ALP222_MIC_DC_R_MASK); + ctrl_reg &= ~(ALP222_MIC_CM_L_MASK | ALP222_MIC_CM_R_MASK); + + //Then set the default value, only CM + ctrl_reg |= (1<<ALP222_MIC_CM_L_POS) | (1<<ALP222_MIC_CM_R_POS); + + writel(ctrl_reg, alpx_dev->base + ALP222_CONTROL_BASE + ALP222_MIC_CONTROL_REG); + + dev_dbg(alpx_dev->dev," mic::ctrl_reg[0x%08x:%x]=0x%08x\n", + ALP222_CONTROL_BASE, ALP222_MIC_CONTROL_REG, + readl(alpx_dev->base + ALP222_CONTROL_BASE + ALP222_MIC_CONTROL_REG)); + + return 0; +} diff --git a/snd-alpx-dkms/snd-alpx/alpx_controls.h b/snd-alpx-dkms/snd-alpx/alpx_controls.h new file mode 100644 index 0000000..567d583 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/alpx_controls.h @@ -0,0 +1,194 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* +* Support for Digigram AlpX PCI-e boards +* +* Copyright (c) 2024 Digigram Digital (info@digigram.com) +*/ + +#ifndef _ALPX_CONTROLS_H +#define _ALPX_CONTROLS_H + +#include "alpx.h" +#include "alpx_axcmem.h" + + +enum alpx_control_type { + ALPX_CONTROL_TYPE_AMPLIFIER = 0, /* Amplification stage*/ + ALPX_CONTROL_TYPE_ANALOG_EQ, /* Analog CODEC stage*/ + ALPX_CONTROL_TYPE_ROUTER, /* Router stage*/ + ALPX_CONTROL_TYPE_MIXER, /* Mixer stage*/ + ALPX_CONTROL_TYPE_CHOICE, /* misc controls */ + ALPX_CONTROL_TYPE_FLAG, /* boolean controls */ + ALPX_CONTROL_TYPE_FLAGS_EMBEDDED, /* Boolean controls embedded with others in the same register*/ + ALPX_CONTROL_TYPE_GAINS_EMBEDDED, /* Amplifier controls embedded with others in the same register*/ + ALPX_CONTROL_RESERVED, /* RESERVED Control, used to keep NumId if some controls are removed */ + ALPX_CONTROL_TYPE_CONSTANT, /* CONSTANT Control, used for a mere constant value */ + ALPX_CONTROL_TYPE_AXCMEM_REL_CHOICE, /*AXCM Relativ position Control*/ + ALPX_CONTROL_TYPE_AXCMEM_REL_VALUE, /*AXCM Relativ position Control*/ + ALPX_CONTROL_TYPE_TRANSLATED_CHOICE, /* Enumerated controls with translation tables for compatibility issue between Apps and FW */ +}; + +struct alpx_control_descriptor_amplifier { + const unsigned int* gains_scale; /* Amplifier gains scale for application id cdB (snd_kcontrol_tlv_rw_t*) */ + unsigned int reg_gain_min; /* min value for the register value*/ + unsigned int reg_gain_max; /* max value for the register value*/ + unsigned int lines_count; /* lines of this amplifier */ +}; + +struct alpx_control_descriptor_codec { + u32 offset; /* Offset of the associated register */ + const unsigned int* gains_scale; /* Amplifier gains scale for application id cdB (snd_kcontrol_tlv_rw_t*) */ + unsigned int reg_gain_min; /* min value for the register value*/ + unsigned int reg_gain_max; /* max value for the register value*/ + unsigned int lines_count; +}; + +struct alpx_control_descriptor_router { + unsigned int lines_count; + + const char **entries; + unsigned int entries_count; +}; + +struct alpx_control_descriptor_mixer { + const unsigned int* gains_scale; /* Amplifier gains scale for application id cdB (snd_kcontrol_tlv_rw_t*) */ + unsigned int reg_gain_min; /* min value for the register value*/ + unsigned int reg_gain_max; /* max value for the register value*/ + unsigned int lines_count; +}; + +struct alpx_control_descriptor_choice { + u32 offset; + u32 mask; + u32 pos; /* start bit position in the register */ + + const char **entries; + u32 *entries_values; + unsigned int entries_count; +}; + +struct alpx_control_descriptor_translated_choice { + u32 offset; + u32 mask; + u32 pos; /* start bit position in the register */ + + const char **entries; + u32 *entries_values; /*Entries in card's context */ + unsigned int entries_count; + u32* card_entries_values; /*Entries in register's context */ + unsigned int card_entries_count; +}; + +struct alpx_control_descriptor_flag { + u32 offset; + u32 mask; + u32 pos; +}; + +struct alpx_control_descriptor_flags_embedded { + u32 offset; + u32 mask; + u32 pos; + unsigned int lines_count; +}; +/* To be used when the amplifier controls are mixed with others in the same register*/ +struct alpx_control_descriptor_gains_embedded { + const unsigned int* gains_scale; /* Amplifier gains scale for application id cdB (snd_kcontrol_tlv_rw_t*)*/ + unsigned int min ; + unsigned int max; + unsigned int lines_count ; + unsigned int offset; + unsigned int mask; + unsigned int pos; + unsigned int width; +}; + + +struct alpx_control_descriptor_constant { + u32 value; +}; + +struct alpx_control_descriptor_axcmem_rel_choice { + struct alpx_axcmem_loc base_loc; + struct alpx_axcmem_loc reg_loc; + u32 mask; + u32 pos; + uint32_t (*getter) (void* addr); + void (*setter) (void* addr, uint32_t value); + const char** entries; + u32* entries_values; + unsigned int entries_count; +}; + +struct alpx_control_descriptor_axcmem_rel_value { + struct alpx_axcmem_loc base_loc; + struct alpx_axcmem_loc reg_loc; + u32 mask; + u32 pos; + u32 min; + u32 max; + uint32_t (*getter) (void* addr); + void (*setter) (void* addr, uint32_t value); +}; + +/*****************************************************/ +struct alpx_control_descriptor { + enum alpx_control_type type; + u32 base; + const char *prefix; + unsigned int access; /*Control access in ALSA way (se https://www.kernel.org/doc/html/v4.17/sound/kernel-api/writing-an-alsa-driver.html?highlight=sndrv_ctl_elem_access_readwrite#access-flags)*/ + union { + struct alpx_control_descriptor_amplifier ampli; + struct alpx_control_descriptor_codec codec; + struct alpx_control_descriptor_router router; + struct alpx_control_descriptor_mixer mixer; + struct alpx_control_descriptor_choice choice; + struct alpx_control_descriptor_flag flag; + struct alpx_control_descriptor_flags_embedded mic_flags; + struct alpx_control_descriptor_gains_embedded mic_gains; + struct alpx_control_descriptor_constant constant; + struct alpx_control_descriptor_axcmem_rel_choice axcmem_rel_choice; + struct alpx_control_descriptor_axcmem_rel_value axcmem_rel_value; + struct alpx_control_descriptor_translated_choice translated_choice; + } data; +}; + +struct alpx_control_amplifier { + unsigned int gain; + unsigned int idx; +}; + +struct alpx_control_router { + unsigned int index; +}; + +struct alpx_control_mixer { + unsigned int mixer_in; + unsigned int mixer_out; +}; + +struct alpx_control_codec{ + unsigned int idx; +}; + +struct alpx_control_mic { + unsigned int stored_gain_in_reg; +}; + +struct alpx_control { + struct alpx_control_descriptor *descriptor; + + union { + struct alpx_control_amplifier ampli; + struct alpx_control_router router; + struct alpx_control_mixer mixer; + struct alpx_control_codec codec; + struct alpx_control_mic mic; + + } data; +}; + +int alpx_controls_register(struct snd_card *card); +int alp222_mic_controls_default_config(struct alpx_device * alpx_dev); + +#endif diff --git a/snd-alpx-dkms/snd-alpx/alpx_core.c b/snd-alpx-dkms/snd-alpx/alpx_core.c new file mode 100644 index 0000000..0fb4d82 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/alpx_core.c @@ -0,0 +1,901 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* +* Support for Digigram AlpX PCI-e boards +* +* Copyright (c) 2024 Digigram Digital (info@digigram.com) +*/ + +#include "alpx.h" +#include "alpx_reg.h" +#include "alpx_mtd.h" +#include "alpx_led.h" +#include "alpx_controls.h" +#include "alpx_streams.h" +#include "alpx_version.h" +#include "alpx_variants_stereo.h" +#include "alpx_variants_stereo_apps_preFW283.h" +#include "alpx_variants_mc.h" +#include "alpx_variants_882_apps_preFW240.h" +#include "alpx_variants_dead.h" +#include "alpx_variants_madi.h" +#include "alpx_variants_dante.h" +#include "alpx_cards.h" +#include "alpx_xdma.h" +#include "snd_alpx_xdma.h" + + +#include <linux/version.h> +#include <linux/kmod.h> + +#if !defined (CONFIG_WITHOUT_GPIO) +#define ALPX_WITH_GPIO +#include <linux/gpio.h> +#include <linux/gpio/driver.h> +#include "alpx_gpio.h" +#define ALPX_GPIO_OPTION_STRING "" +#else +#warning !! GPIOs are DISABLED !! +#define ALPX_GPIO_OPTION_STRING "(without GPIO)" +#endif + + +#include <linux/mtd/partitions.h> +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/platform_device.h> +#include <linux/delay.h> +#include <linux/version.h> +#include <sound/control.h> +#include <sound/core.h> +#include <sound/initval.h> +#include <sound/pcm.h> +#include <linux/string.h> + + +#if KERNEL_VERSION(6, 7, 0) > LINUX_VERSION_CODE +#include "core/generic/6.3/amd_xdma.h" +#include "include/6.3/amd_xdma.h" +#else +#include <linux/platform_data/amd_xdma.h> +#include <linux/dma/amd_xdma.h> +#endif + +#ifdef WITH_REG_DEBUG +#include <linux/device.h> +#endif + +/* Constants */ + +/* Structures */ + +/* Parameters */ + +#define ALPX_DEFAULT_CARD_NAME "Digigram AlpX" + +static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; +module_param_array(index, int, NULL, 0444); +MODULE_PARM_DESC(index, "Index value for " ALPX_DEFAULT_CARD_NAME " soundcard."); + +static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; +module_param_array(id, charp, NULL, 0444); +MODULE_PARM_DESC(id, "ID string for " ALPX_DEFAULT_CARD_NAME " soundcard."); + +static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; +module_param_array(enable, bool, NULL, 0444); +MODULE_PARM_DESC(enable, "Enable " ALPX_DEFAULT_CARD_NAME " soundcard."); + +unsigned int log_transfers = 0; +module_param(log_transfers, uint, 0644); +MODULE_PARM_DESC(log_transfers, "0: no transfer logged(default), 1 : transfers logged"); + +static bool with_board_in_prod_mode = false; +module_param(with_board_in_prod_mode, bool, 0644); +MODULE_PARM_DESC(with_board_in_prod_mode, "0: board in USER mode(default) ; 1: board in PRODUCTION mode "); + +static bool with_board_in_dead_mode = false; +module_param(with_board_in_dead_mode, bool, 0644); +MODULE_PARM_DESC(with_board_in_dead_mode, "0: board in NORMAL mode(default) ; 1: board in DEAD mode "); + +static unsigned int dante_configured_fs = ALPDANTE_DEFAULT_FS; +module_param(dante_configured_fs, uint, 0644); +MODULE_PARM_DESC(dante_configured_fs, "Configured FS for Alp DANTE card (value in Hz, default: 48000)"); + +static bool dante_loopback_enabled = false; +module_param(dante_loopback_enabled, bool, 0644); +MODULE_PARM_DESC(dante_loopback_enabled, "Enable the Loopback for Alp DANTE card (default: FALSE)"); + +static bool alp222_pre_FW283_apps_support = false; +module_param(alp222_pre_FW283_apps_support, bool, 0644); +MODULE_PARM_DESC(alp222_pre_FW283_apps_support, "For ALp222e cards ONLY, Enable the compatibility mode for applications written for PRE V283 Firmwares (default: FALSE)"); + +static bool alp882_pre_FW240_apps_support = false; +module_param(alp882_pre_FW240_apps_support, bool, 0644); +MODULE_PARM_DESC(alp882_pre_FW240_apps_support, "For ALp882e cards ONLY, Enable the compatibility mode for applications written for PRE V240 Firmwares (default: FALSE)"); + + +/* Below, this is significant only if WITH_REG_DEBUG is defined */ +#ifdef WITH_REG_DEBUG +#warning BUILD with Registers Debug enabled + +static ssize_t reg_offset_show(struct device* dev, struct device_attribute* attr, char* buf ) +{ + + //HOWTO struct dev TO struct alpx_device : + struct snd_card* const card = dev_get_drvdata(dev); + struct alpx_device* const alpx_dev = card->private_data; + + dev_dbg( dev,"%s(): CALLED for card: 0x%p : REG OFFSET: 0x%08x\n", __func__, + alpx_dev, + alpx_dev->dbg_reg_offset); + + + return scnprintf(buf, PAGE_SIZE, "0x%08x\n", alpx_dev->dbg_reg_offset); +} + +static ssize_t reg_offset_store(struct device* dev, struct device_attribute* attr, const char* buf , size_t count) +{ + //HOWTO struct dev TO struct alpx_device : + struct snd_card* const card = dev_get_drvdata(dev); + struct alpx_device* const alpx_dev = card->private_data; + + unsigned int reg_offset = 0; + if (kstrtou32(buf, 0, ®_offset) < 0) + return -EINVAL; + + //Check offset range + if ((reg_offset < ALP222_MIN_REG_OFFSET) && + (reg_offset > ALP222_MAX_REG_OFFSET)) + return -EINVAL; + + alpx_dev->dbg_reg_offset = reg_offset; + dev_dbg( dev,"%s(): CALLED for alpx: %p, reg_offset: 0x%08x\n", __func__, alpx_dev, alpx_dev->dbg_reg_offset); + + return count; +} + +//static struct device_attribute dev_reg_addr = __ATTR_RW(reg_addr); +static struct device_attribute dev_reg_offset = __ATTR_RW(reg_offset); + +/******************************/ +static ssize_t reg_value_show(struct device* dev, struct device_attribute* attr, char* buf ) +{ + + //HOWTO struct dev TO struct alpx_device : + struct snd_card* const card = dev_get_drvdata(dev); + struct alpx_device* const alpx_dev = card->private_data; + /* Read the register once to cope with 'clear on read' registers */ + const uint32_t reg_value = readl(alpx_dev->base+ alpx_dev->dbg_reg_offset); + + dev_dbg( dev,"%s(): CALLED for %p, (dev:%p): [0x%08x] => 0x%08x\n", __func__, + alpx_dev, dev, + alpx_dev->dbg_reg_offset, + reg_value); + + return scnprintf(buf, PAGE_SIZE, "0x%08x\n", reg_value); +} + +static ssize_t reg_value_store(struct device* dev, struct device_attribute* attr, const char* buf , size_t count) +{ + //HOWTO struct dev TO struct alpx_device : + struct snd_card* const card = dev_get_drvdata(dev); + struct alpx_device* const alpx_dev = card->private_data; + + uint32_t reg_value = 0; + if (kstrtou32(buf, 0, ®_value) < 0) + return -EINVAL; + + + writel(reg_value, alpx_dev->base + alpx_dev->dbg_reg_offset); + + dev_dbg( dev,"%s(): CALLED for alpx: %p, [0x%08x] <= 0x%08x, Check:0x%08x\n", __func__, + alpx_dev, + alpx_dev->dbg_reg_offset, + reg_value, + readl(alpx_dev->base+ alpx_dev->dbg_reg_offset)); + + return count; +} + +static struct device_attribute dev_reg_value = __ATTR_RW(reg_value); + +#endif + +/******************************/ +static ssize_t serial_number_show(struct device* dev, struct device_attribute* attr, char* buf ) +{ + + struct snd_card* const card = dev_get_drvdata(dev); + struct alpx_device* alpx_dev = card->private_data; + + dev_dbg(alpx_dev->dev, " %s() : AFTER shift %llu / 0x%llx\n", __func__, alpx_dev->identity.serial_number, alpx_dev->identity.serial_number); + + return scnprintf(buf, PAGE_SIZE, "%llu\n", alpx_dev->identity.serial_number); +} + +static struct device_attribute dev_serial_number = __ATTR_RO(serial_number); +/***************************************/ + +static ssize_t ver_fpga_show(struct device* dev, struct device_attribute* attr, char* buf ) +{ + + struct snd_card* const card = dev_get_drvdata(dev); + struct alpx_device* alpx_dev = card->private_data; + + return scnprintf(buf, PAGE_SIZE, "%u\n", alpx_dev->identity.ver_fpga); +} + +static struct device_attribute dev_ver_fpga = __ATTR_RO(ver_fpga); + +/***************************************/ +static ssize_t ver_mcu_show(struct device* dev, struct device_attribute* attr, char* buf ) +{ + + struct snd_card* const card = dev_get_drvdata(dev); + struct alpx_device* alpx_dev = card->private_data; + + return scnprintf(buf, PAGE_SIZE, "%u.%lu\n", + ALPX_COMMON_VERSION_VERSION(alpx_dev->identity.ver_mcu), + ALPX_COMMON_VERSION_REVISION(alpx_dev->identity.ver_mcu) ); +} + +static struct device_attribute dev_ver_mcu = __ATTR_RO(ver_mcu); +/***************************************/ +static ssize_t dante_card_name_show(struct device* dev, struct device_attribute* attr, char* buf ) +{ + + struct snd_card* const card = dev_get_drvdata(dev); + struct alpx_device* alpx_dev = card->private_data; + + int result = alpdante_get_dante_name(alpx_dev, buf, ALPDANTE_NETWORK_NAME_LENGTH); + return (!result) ? strlcat(buf, "\n", PAGE_SIZE) : 0; +} + +static struct device_attribute dev_dante_card_name = __ATTR_RO(dante_card_name); +/***************************************/ + +/* PCI */ + +static void alpx_card_private_free(struct snd_card *card) +{ + struct alpx_device *alpx_dev = card->private_data; + +#if defined (ALPX_WITH_GPIO) + if (alpx_dev->variant->features & ALPX_VARIANT_FEATURE_GPIOS) + alpx_gpio_unregister(alpx_dev); +#endif + + if (alpx_dev->controls) + kfree(alpx_dev->controls); + + /* dirty crash avoid when dma fails and frees card before pipes are init. */ +} + +static inline unsigned int is_alp222_with_mic_option(struct alpx_device* alpx_dev) +{ + const u32 reg_mic = readl(alpx_dev->base + ALP222_CONTROL_BASE + ALP222_MIC_CONTROL_REG); + dev_dbg(alpx_dev->dev, "Daughter_Control[0x%08x:%x] = 0x%08x\n", + ALP222_CONTROL_BASE, + ALP222_MIC_CONTROL_REG, + reg_mic); + return reg_mic & (1<<ALP222_MIC_HERE_POS); +} + +static int alpx_core_set_pci_bus(struct alpx_device* alpx_dev) +{ + int ret = pci_enable_device(alpx_dev->pci_dev); + if (ret) { + dev_err(alpx_dev->dev, "failed to enable PCI device\n"); + return ret; + } + + /* Enable PCI relaxed ordering. */ + pcie_capability_set_word(alpx_dev->pci_dev, PCI_EXP_DEVCTL, + PCI_EXP_DEVCTL_RELAX_EN); + + /* Enable extended tagging. */ + pcie_capability_set_word(alpx_dev->pci_dev, PCI_EXP_DEVCTL, + PCI_EXP_DEVCTL_EXT_TAG); + + /* Set maximum memory read request. */ + pcie_set_readrq(alpx_dev->pci_dev, 512); + + pci_set_master(alpx_dev->pci_dev); + + return ret; +} + + +/****************************************************************/ +/* +* This function will HANDLE the XMA module dependency either from kernel or +* from the package according to the kernel's version. +* Return an error the kernel's module is in bad version (kernel <6.7) as no CYLLIC DMA +* was yet supported. +* MUST be CALLED after alpx_xdma_register() to get the xdma_dev +*/ +static int alpx_core_handle_xdma_dep (struct device *dev, struct platform_device* xdma_dev) +{ + + dev_info(dev, "Handling XDMA support for Linux : %d.\n", LINUX_VERSION_CODE); + +#if KERNEL_VERSION(6, 3, 0) > LINUX_VERSION_CODE + dev_info(dev, "OLD Kernel, USE snd-alpx-xdma.\n"); + //NO XDMA in the kernel Force the dependency to package's xdma module already done before call by + // SND_ALPX_XDMA_DEP(); + +#elif KERNEL_VERSION(6, 7, 0) <= LINUX_VERSION_CODE + #if IS_ENABLED(CONFIG_XILINX_XDMA) + dev_info(dev, "Kernel XDMA Ok, USE xdma.\n"); + //NO XDMA in the kernel Force the dependency to package's xdma module. + xdma_get_user_irq(xdma_dev, 256); //Dumb irq to for an error : no way + #else + dev_info(dev, "Kernel XDMA NOT enabled, USE snd-alpx-xdma.\n"); + //Dependency already handled by SND_ALPX_XDMA_DEP() call defined accordingly !! + #endif +#elif (KERNEL_VERSION(6, 3, 0) <= LINUX_VERSION_CODE) && \ + (KERNEL_VERSION(6, 7, 0) > LINUX_VERSION_CODE) + //FORCE snd-alpx-xdma use as kernel's one w/o cyclic support + #if IS_ENABLED(CONFIG_XILINX_XDMA) + #if IS_MODULE(CONFIG_XILINX_XDMA) + #warning "Xilinx XDMA module must be unloaded before use : NOT COMPLIANT !!" + #else + #error "Xilinx XDMA moule in Kernel is not COMPLIANT, Kernel must be Reconfigured/Rebuild without it !!!!" + #endif + #endif +#endif + return 0; +} +/****************************************************************************/ +static int alpx_probe(struct pci_dev *pci_dev, + const struct pci_device_id *pci_device_id) +{ + static int card_idx = 0; + struct device *dev = &pci_dev->dev; + struct alpx_device *alpx_dev; + struct snd_card *card; + struct snd_pcm *pcm; + int ret; + int is_update_required = 0; + + /* Module identity */ + + dev_info(dev,"version %s %s build date: %s, time: %s. %s, %s\n", + ALPX_MODULE_VERSION, + ALPX_GPIO_OPTION_STRING, + __DATE__ , + __TIME__, + SND_ALPX_XDMA_DEP(), + log_transfers ? "Transfers Logged":""); + + /* Ensure dependency on AlpX XDMA support if needed*/ + SND_ALPX_XDMA_DEP(); + + /* Card */ + + if (card_idx >= SNDRV_CARDS) + return -ENODEV; + + if (!enable[card_idx]) { + card_idx++; + return -ENOENT; + } + + dev_dbg(dev,"%s() : PCI Id : Vendor: 0x04%x, Device: 0x%04x, subvendor: 0x%04x, subdevice: 0x%04x\n", __func__, + pci_device_id->vendor, + pci_device_id->device, + pci_device_id->subvendor, + pci_device_id->subdevice); + + dev_dbg(dev,"%s() : PCI dev: Vendor: 0x04%x, Device: 0x%04x, subvendor: 0x%04x, subdevice: 0x%04x\n", __func__, + pci_dev->vendor, + pci_dev->device, + pci_dev->subsystem_vendor, + pci_dev->subsystem_device); + + + ret = snd_card_new(dev, index[card_idx], id[card_idx], THIS_MODULE, + sizeof(*alpx_dev), &card); + if (ret) { + dev_err(dev," snd_card_new() => %d\n", ret); + return ret; + } + + card->private_free = alpx_card_private_free; + + /* PCI */ + + pci_set_drvdata(pci_dev, card); + + alpx_dev = card->private_data; + alpx_dev->dev = dev; + alpx_dev->pci_dev = pci_dev; + + ret = alpx_core_set_pci_bus(alpx_dev); + if (ret){ + dev_err(dev," alpx_core_set_pci_bus(alpx_dev) => %d\n", ret); + goto error_card; + } + + //Map USER BAR now to get access to all card's resources + alpx_dev->base = pci_ioremap_bar(pci_dev, 0); + + /* PCI */ + + ret = pci_enable_device(pci_dev); + if (ret) { + dev_err(dev, "failed to enable PCI device\n"); + goto error_card; + } + + /* Enable PCI relaxed ordering. */ + pcie_capability_set_word(pci_dev, PCI_EXP_DEVCTL, + PCI_EXP_DEVCTL_RELAX_EN); + + /* Enable extended tagging. */ + pcie_capability_set_word(pci_dev, PCI_EXP_DEVCTL, + PCI_EXP_DEVCTL_EXT_TAG); + + /* Set maximum memory read request. */ + pcie_set_readrq(pci_dev, 512); + + pci_set_master(pci_dev); + + /* XDMA */ + + alpx_dev->xdma_pdev = alpx_xdma_register(pci_dev); + if (!alpx_dev->xdma_pdev) { + dev_err(dev," alpx_xdma_register(alpx_dev) => %d\n", ret); + goto disable_pci_dev; + } + + /* XDMA dependency handling*/ + ret = alpx_core_handle_xdma_dep(dev, alpx_dev->xdma_pdev); + if (ret) { + dev_err(dev, "Error %d when handling xdma dependency !\n", ret); + goto disable_pci_dev; + } + + /* Variant */ + + //Use PCI Id to select the actual variant : WARNING, MIC option is checked with user's registers !! + switch (pci_dev->subsystem_device){ + case ALPX_PCI_ID_SUBSYSTEM_ALP222: + /* HANDLE Alp222_MIC with LINE PCI Id : firmwares ante V272*/ + if (alp222_pre_FW283_apps_support) { + dev_warn(alpx_dev->dev, "!!! Alp2220 Pre FW283 Application compatibility mode ACTIVATED !!!"); + } + if (!is_alp222_with_mic_option(alpx_dev)) { + alpx_dev->variant = (!alp222_pre_FW283_apps_support) ? &alp222_variant : &alp222_app_preFW283_variant; + } + else { + alpx_dev->variant = (!alp222_pre_FW283_apps_support) ? &alp222_mic_variant : &alp222_app_preFW283_mic_variant; + alp222_mic_controls_default_config(alpx_dev); + } + break; + case ALPX_PCI_ID_SUBSYSTEM_ALP222_MIC: + if (alp222_pre_FW283_apps_support) { + dev_warn(alpx_dev->dev, "!!! Alp222 Pre FW283 Application compatibility mode ACTIVATED !!!"); + } + alpx_dev->variant = (!alp222_pre_FW283_apps_support) ? &alp222_mic_variant : &alp222_app_preFW283_mic_variant; + alp222_mic_controls_default_config(alpx_dev); + break; + case ALPX_PCI_ID_SUBSYSTEM_MADI: + alpx_dev->variant = &alpx_madi_variant; + break; + case ALPX_PCI_ID_SUBSYSTEM_ALP882: + if (alp882_pre_FW240_apps_support) + dev_warn(alpx_dev->dev, "!!! Alp882 LINE with Pre FW240 Application compatibility mode ACTIVATED !!!"); + alpx_dev->variant = (!alp882_pre_FW240_apps_support) ? &alp882_line_variant : &alp882_app_preFW240_line_variant; + break; + case ALPX_PCI_ID_SUBSYSTEM_ALP882_MIC: + if (alp882_pre_FW240_apps_support) + dev_warn(alpx_dev->dev, "!!! Alp882 MIC with Pre FW240 Application compatibility mode ACTIVATED !!!"); + alpx_dev->variant = (!alp882_pre_FW240_apps_support) ? &alp882_mic_variant : &alp882_app_preFW240_mic_variant; + break; + case ALPX_PCI_ID_SUBSYSTEM_ALP442: + alpx_dev->variant = &alp442_line_variant; + break; + case ALPX_PCI_ID_SUBSYSTEM_ALP442_MIC: + alpx_dev->variant = &alp442_mic_variant; + break; + case ALPX_PCI_ID_SUBSYSTEM_MADI_ALP_DEAD: + alpx_dev->variant = &alpx_dead_variant; + break; + case ALPX_PCI_ID_SUBSYSTEM_ALPDANTE: + alpx_dev->variant = &alpx_dante_variant; + break; + default: + dev_warn(alpx_dev->dev,"ALPX Driver: Model Id 0x%04x is not supported => DEAD by default Here !\n", + pci_dev->subsystem_device); + alpx_dev->variant = &alpx_dead_variant; + } + + /* FORCED DEAD mode, not for DANTE card */ + if (with_board_in_dead_mode) + { + /* Check DEAD mode for supported variants*/ + if (alpx_dev->variant->model != ALPX_VARIANT_MODEL_ALPDANTE) { + alpx_dev->variant = &alpx_dead_variant; + dev_warn(alpx_dev->dev, " !!! Board forced in DEAD mode !!\n"); + } + else { + dev_err(alpx_dev->dev, " NO DEAD mode supported for this board : %s\n", alpx_dev->variant->shortname); + ret = -EINVAL; + goto unregister_xdma; + } + } + + /* MTD */ + if (alpx_dev->variant->flash_partitions.qty != 0) { +// /* mtd Handle the PRODUCTION access or DEAD card, BUT not for DANTE cards*/ + with_board_in_prod_mode &= (alpx_dev->variant->model != ALPX_VARIANT_MODEL_ALPDANTE); + + if ( with_board_in_prod_mode || + (alpx_dev->variant->model == ALPX_VARIANT_DEAD)) { + dev_warn( alpx_dev->dev," Flash in PRODUCTION mode or DEAD card: full access !\n"); + ret = alpx_mtd_probe(alpx_dev, alpx_dev->variant->flash_partitions.partitions ,alpx_dev->variant->flash_partitions.qty); + } + else { + dev_dbg( alpx_dev->dev," Flash in USER mode: firmware update access only.\n"); + ret = alpx_mtd_probe(alpx_dev, + &alpx_dev->variant->flash_partitions.partitions[ALPX_FLASH_PARTITION_FW_ID] , + alpx_dev->variant->flash_partitions.qty_for_fw_update); + } + + if (ret) + goto unregister_xdma; + } + + if (alpx_dev->variant->model == ALPX_VARIANT_DEAD) { + dev_warn(alpx_dev->dev," !!!! DEAD card found : Flash in PROD mode and nothing else !!\n"); + return 0; + } + + /* finalize identity */ + switch (alpx_dev->variant->model) { + case ALPX_VARIANT_MODEL_ALP882: + case ALPX_VARIANT_MODEL_ALP882_MIC: + case ALPX_VARIANT_MODEL_ALP442: + case ALPX_VARIANT_MODEL_ALP442_MIC: + alpmultichan_finalize_identity(alpx_dev); + /* Check FW compatibility */ + if (alpx_dev->identity.ver_fpga < ALPMC_SUPPORTED_BASE_FW_VERSION) { + dev_warn(alpx_dev->dev, "UNSUPPORTED MultiChannels firmware version %d (supported started at %d), UPDATE required !!\n", + alpx_dev->identity.ver_fpga, + ALPMC_SUPPORTED_BASE_FW_VERSION); + is_update_required = 1; + } + + break; + case ALPX_VARIANT_MODEL_ALP222: + case ALPX_VARIANT_MODEL_ALP222_MIC: + alpstereo_finalize_identity(alpx_dev); + /* Check FW compatibility */ + if (alpx_dev->identity.ver_fpga < ALP222_SUPPORTED_BASE_FW_VERSION) { + dev_warn(alpx_dev->dev, "UNSUPPORTED Stereo firmware version %d (supported started at %d), UPDATE required !!\n", + alpx_dev->identity.ver_fpga, + ALP222_SUPPORTED_BASE_FW_VERSION); +// is_update_required = 1; + } + break; + case ALPX_VARIANT_MODEL_ALPDANTE: + alpdante_finalize_identity(alpx_dev); + /* Check FW compatibility */ + if (alpx_dev->identity.ver_fpga < ALPDANTE_SUPPORTED_BASE_FW_VERSION) { + dev_warn(alpx_dev->dev, "UNSUPPORTED AlpDANTE firmware version %d (supported started at %d), UPDATE required !!\n", + alpx_dev->identity.ver_fpga, + ALPDANTE_SUPPORTED_BASE_FW_VERSION); + is_update_required = 1; + } + break; + default: + dev_warn(alpx_dev->dev, " identity not finalized for this model : %d\n", alpx_dev->variant->model); + } + + + /* Remount MTD with SERIAL number added only in USER mod, to clearly identify the cards */ + if (!with_board_in_prod_mode ) { + + //Build a special partition table to add the serial number (A COPY) !! + struct mtd_partition fw_partitions_table[ALPX_FLASH_PARTITION_QTY]; + char part_names[ALPX_FLASH_PARTITION_QTY][128]; + unsigned int part_idx = 0; + + for (part_idx = 0 ; part_idx < alpx_dev->variant->flash_partitions.qty_for_fw_update ; ++part_idx) { + + fw_partitions_table[part_idx] = alpx_dev->variant->flash_partitions.partitions[ALPX_FLASH_PARTITION_FW_ID + part_idx]; + scnprintf(part_names[part_idx], PAGE_SIZE, "%s-%llu", + fw_partitions_table[part_idx].name, + alpx_dev->identity.serial_number); + + fw_partitions_table[part_idx].name = part_names[part_idx]; + } + + dev_dbg( alpx_dev->dev," Flash in USER mode: firmware partitionS with S/N appened.\n"); + /* Replace the current partitions */ + alpx_mtd_remove(alpx_dev); + ret = alpx_mtd_probe(alpx_dev, + fw_partitions_table, + alpx_dev->variant->flash_partitions.qty_for_fw_update); + } + + if (ret){ + dev_err(alpx_dev->dev," Error %d when re-creating Firmware partition\n", ret); + goto unregister_xdma; + } + + //Stop here if update required. + if (is_update_required == 1) + return 0; + + /* Information */ + + strcpy(card->driver, "Driver AlpX"); + + //Check if replaced by parameters, default : use the variant names + dev_dbg( alpx_dev->dev,"%s() : id[%d] = %s\n", __func__, + card_idx, + id[card_idx] == NULL ? "NULL" : id[card_idx]); + + if (id[card_idx]) + sprintf(card->shortname, id[card_idx]); + else + sprintf(card->shortname, alpx_dev->variant->shortname); + + strcpy(card->longname, alpx_dev->variant->longname); + strcpy(card->mixername, alpx_dev->variant->mixername); + + /* Pipes */ + + spin_lock_init(&alpx_dev->config.lock); + + alpx_pipe_init(&alpx_dev->playback, true); + alpx_pipe_init(&alpx_dev->capture, false); + + /* PCM */ + + ret = snd_pcm_new(card, card->shortname, 0, 1, 1, &pcm); + if (ret) { + dev_err(dev," snd_pcm_new(card) => %d\n", ret); + goto unregister_xdma; + } + + pcm->private_data = alpx_dev; + + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &alpx_playback_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &alpx_capture_ops); + + pcm->info_flags = 0; + + strcpy(pcm->name, card->longname); + + /* Controls */ + + ret = alpx_controls_register(card); + if (ret) { + dev_err(dev," alpx_controls_register(card) => %d\n", ret); + goto unregister_xdma; + } + + /* Buffer */ + +#if KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE + snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, dev, + alpx_dev->variant->playback_hw->buffer_bytes_max, + alpx_dev->variant->playback_hw->buffer_bytes_max); +#else + snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, dev, + alpx_dev->variant->playback_hw->buffer_bytes_max, + alpx_dev->variant->playback_hw->buffer_bytes_max); +#endif +#if defined (ALPX_WITH_GPIO) + /* GPIO */ + + if (alpx_dev->variant->features & ALPX_VARIANT_FEATURE_GPIOS) + ret = alpx_gpio_register(alpx_dev, card->shortname); + + if (ret) { + dev_err(dev," alpx_gpio_register(alpx_dev) => %d\n", ret); + goto unregister_xdma; + } +#endif + /* Proc */ + ret = alpx_proc_probe(alpx_dev); + if (ret) { + dev_err(dev," alpx_proc_probe(alpx_dev) => %d\n", ret); + goto unregister_xdma; + } + + /* Card */ + + ret = snd_card_register(card); + if (ret){ + dev_err(dev," snd_card_register(card) => %d\n", ret); + goto error_proc; + } + + /* Sys FS files */ + /* Reg debug */ +#ifdef WITH_REG_DEBUG + dev_info(dev,"REG_DEBUG activated\n"); + alpx_dev->dbg_reg_offset = ALP222_MIN_REG_OFFSET; + + ret = device_create_file(dev, &dev_reg_offset); + if (ret) + { + dev_err(dev," device_create_file(addr) => %d\n", ret); + } + else + { + dev_err(dev," device_create_file(addr) : Ok\n"); + } + + ret = device_create_file(dev, &dev_reg_value); + if (ret) + { + dev_err(dev," device_create_file(value) => %d\n", ret); + } +#endif + + /* Serial number file */ + ret = device_create_file(dev, &dev_serial_number); + if (ret) + { + dev_err(dev," Serial Number device_create_file() => %d\n", ret); + } + + /* FPGA version file */ + ret = device_create_file(dev, &dev_ver_fpga); + if (ret) + { + dev_err(dev," FPGA Version device_create_file() => %d\n", ret); + } + + /* MCU version file */ + ret = device_create_file(dev, &dev_ver_mcu); + if (ret) + { + dev_err(dev," MCU Version device_create_file() => %d\n", ret); + } + + /* DANTE card's name */ + if (alpx_dev->variant->model == ALPX_VARIANT_MODEL_ALPDANTE) { + ret = device_create_file(dev, &dev_dante_card_name); + if (ret) + { + dev_err(dev," DANTE card's name device_create_file() => %d\n", ret); + } + } + + /* Production area replication from USER to GOLDEN if needed*/ + if (((alpx_dev->variant->model == ALPX_VARIANT_MODEL_ALP222) || + (alpx_dev->variant->model == ALPX_VARIANT_MODEL_ALP222_MIC)) && + alpx_mtd_is_available(alpx_dev) && + !alpx_mtd_is_golden_prod_area_valid(alpx_dev)) { + dev_info(alpx_dev->dev," Production area in GOLDEN must be INITIALIZED\n"); + ret = alpx_mtd_replicate_prod_area(alpx_dev); + if (!ret) { + dev_info(alpx_dev->dev," Production area in GOLDEN is INITIALIZED\n"); + } + else { + dev_warn(alpx_dev->dev," Production area in GOLDEN NOT CORRECTLY INITIALIZED !!\n"); + } + } + + switch (alpx_dev->variant->model){ + case ALPX_VARIANT_MODEL_ALP222: + case ALPX_VARIANT_MODEL_ALP222_MIC: + alpstereo_print_identity(alpx_dev, card, "Created"); + break; + case ALPX_VARIANT_MODEL_ALP882: + case ALPX_VARIANT_MODEL_ALP882_MIC: + case ALPX_VARIANT_MODEL_ALP442: + case ALPX_VARIANT_MODEL_ALP442_MIC: + alpmultichan_print_identity(alpx_dev, card, "Created"); + break; + case ALPX_VARIANT_MODEL_MADI: + case ALPX_VARIANT_MODEL_MADI_LOOPBACK: + alpmadi_print_identity(alpx_dev, card, "Created"); + break; + case ALPX_VARIANT_MODEL_ALPDANTE: + alpdante_print_identity(alpx_dev, card, "Created"); + alpdante_card_setup(alpx_dev, card, dante_configured_fs, dante_loopback_enabled); + break; + default: + dev_warn(alpx_dev->dev," !!! UNKNOW variant identity: %d !!!!\n", alpx_dev->variant->model); + }; + + card_idx++; + + return 0; + +error_proc: + dev_err(alpx_dev->dev," %s(): Error : 0x%x when creating proc entry\n", __func__, ret); + alpx_proc_remove(alpx_dev); +unregister_xdma: + alpx_xdma_unregister(pci_dev, alpx_dev->xdma_pdev); +disable_pci_dev: + pci_disable_device(pci_dev); +error_card: + dev_err(alpx_dev->dev," %s(): Error : 0x%x when creating the card\n", __func__, ret); + snd_card_free(card); + + return ret; +} + +static void alpx_remove(struct pci_dev *pci_dev) +{ + struct snd_card *card = pci_get_drvdata(pci_dev); + struct alpx_device *alpx_dev = card->private_data; + + switch (alpx_dev->variant->model){ + case ALPX_VARIANT_MODEL_ALP222: + case ALPX_VARIANT_MODEL_ALP222_MIC: + alpstereo_print_identity(alpx_dev, card, "Deleted"); + break; + case ALPX_VARIANT_MODEL_ALP882: + case ALPX_VARIANT_MODEL_ALP882_MIC: + case ALPX_VARIANT_MODEL_ALP442: + case ALPX_VARIANT_MODEL_ALP442_MIC: + if (card != NULL) { + alpmultichan_print_identity(alpx_dev, card, "Deleted"); + } + break; + case ALPX_VARIANT_MODEL_MADI: + case ALPX_VARIANT_MODEL_MADI_LOOPBACK: + alpmadi_print_identity(alpx_dev, card, "Deleted"); + break; + case ALPX_VARIANT_MODEL_ALPDANTE: + alpdante_print_identity(alpx_dev, card, "Deleted"); + break; + default: + dev_warn(alpx_dev->dev," !!! UNKNOW variant identity: %d !!!!\n", alpx_dev->variant->model); + } + + /* Reg debug */ +#ifdef WITH_REG_DEBUG + device_remove_file(alpx_dev->dev, &dev_reg_offset); + device_remove_file(alpx_dev->dev, &dev_reg_value); +#endif + device_remove_file(alpx_dev->dev, &dev_serial_number); + device_remove_file(alpx_dev->dev, &dev_ver_fpga); + device_remove_file(alpx_dev->dev, &dev_ver_mcu); + + if (alpx_dev->variant->model == ALPX_VARIANT_MODEL_ALPDANTE) { + device_remove_file(alpx_dev->dev, &dev_dante_card_name); + } + + alpx_mtd_remove(alpx_dev); + alpx_proc_remove(alpx_dev); + + if (alpx_dev->xdma_pdev != NULL) { + alpx_xdma_unregister(pci_dev, alpx_dev->xdma_pdev); + } + + if (card != NULL) { + snd_card_free(card); + } + + pci_disable_device(alpx_dev->pci_dev); +} + +static const struct pci_device_id alpx_pci_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_DIGIGRAM, ALPX_PCI_ID_DEVICE) }, + { 0 } +}; + +MODULE_DEVICE_TABLE(pci, alpx_pci_ids); + +static struct pci_driver alpx_driver = { + .name = KBUILD_MODNAME, + .id_table = alpx_pci_ids, + .probe = alpx_probe, + .remove = alpx_remove, +}; + +module_pci_driver(alpx_driver); + +MODULE_DESCRIPTION("AlpX audio cards driver"); +MODULE_AUTHOR("Digigram Digital"); +MODULE_VERSION(ALPX_MODULE_VERSION); +MODULE_LICENSE("GPL"); diff --git a/snd-alpx-dkms/snd-alpx/alpx_gpio.c b/snd-alpx-dkms/snd-alpx/alpx_gpio.c new file mode 100644 index 0000000..4734057 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/alpx_gpio.c @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* +* Support for Digigram AlpX PCI-e boards +* +* Copyright (c) 2024 Digigram Digital (info@digigram.com) +*/ + + +#include "alpx_gpio.h" + +#include <linux/io.h> + +static inline bool alpx_gpio_is_an_input (struct alpx_device *alpx_dev, unsigned offset) +{ + return offset < alpx_dev->variant->gpios.inputs_qty; +} + + +int alpx_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct alpx_device *alpx_dev = gpiochip_get_data(chip); + u32 value; + + if (alpx_gpio_is_an_input(alpx_dev, offset)) { + value = readl(alpx_dev->base + alpx_dev->variant->gpios.base + alpx_dev->variant->gpios.inputs_reg_offset); + + dev_dbg( alpx_dev->dev,"[0x%08x] =>[0x%08x]\n", alpx_dev->variant->gpios.base + alpx_dev->variant->gpios.inputs_reg_offset, value); + } + else { + value = readl(alpx_dev->base + alpx_dev->variant->gpios.base + alpx_dev->variant->gpios.outputs_reg_offset); + + dev_dbg( alpx_dev->dev,"[0x%08x] =>[0x%08x]\n", alpx_dev->variant->gpios.base + alpx_dev->variant->gpios.outputs_reg_offset, value); + //translate offset -> bit rank + offset -= alpx_dev->variant->gpios.inputs_qty; + } + + return ALPX_GPIO_VALUE(offset, value); +} + +void alpx_gpio_set(struct gpio_chip *chip, unsigned offset, + int gpio_value) +{ + struct alpx_device *alpx_dev = gpiochip_get_data(chip); + unsigned int value; + + + if (alpx_gpio_is_an_input(alpx_dev, offset)) + return; + + //translate Offset to bit rank + offset -= alpx_dev->variant->gpios.inputs_qty; + + value = readl(alpx_dev->base + alpx_dev->variant->gpios.base + alpx_dev->variant->gpios.outputs_reg_offset ); + + dev_dbg( alpx_dev->dev,"read [0x%08x] =>0x%08x\n",alpx_dev->variant->gpios.base + alpx_dev->variant->gpios.outputs_reg_offset, value); + + + value &= ~ALPX_GPIO_MASK(offset); + value |= ALPX_GPIO_SEL(offset, gpio_value); + + dev_dbg( alpx_dev->dev,"write 0x%08x =>[0x%08x]\n", value , alpx_dev->variant->gpios.base + alpx_dev->variant->gpios.outputs_reg_offset); + + writel(value, alpx_dev->base + alpx_dev->variant->gpios.base + alpx_dev->variant->gpios.outputs_reg_offset); +} + +int alpx_gpio_get_direction(struct gpio_chip *chip, unsigned offset) +{ + struct alpx_device *alpx_dev = gpiochip_get_data(chip); + + if (offset >= chip->ngpio) + return -EINVAL; + + dev_dbg( alpx_dev->dev,"Offset %d is %s\n", + offset, alpx_gpio_is_an_input(alpx_dev, offset) ? "INPUT" : "OUTPUT"); + + return alpx_gpio_is_an_input(alpx_dev, offset) ? GPIOF_DIR_IN : GPIOF_DIR_OUT; +} + +int alpx_gpio_direction_output(struct gpio_chip *chip, unsigned offset, + int gpio_value) +{ + struct alpx_device *alpx_dev = gpiochip_get_data(chip); + if (alpx_gpio_is_an_input(alpx_dev, offset)) + return -EINVAL; + + alpx_gpio_set(chip, offset, gpio_value); + + return 0; +} + +int alpx_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +{ + /* All ports handle INPUTs operations */ + return 0; +} + +int alpx_gpio_register(struct alpx_device *alpx_dev, const char* card_name) +{ + struct gpio_chip *chip = &alpx_dev->gpio_chip; + + chip->parent = alpx_dev->dev; + chip->owner = THIS_MODULE; + chip->label = card_name; + chip->base = -1; + + chip->ngpio = alpx_dev->variant->gpios.inputs_qty + alpx_dev->variant->gpios.outputs_qty; + chip->get = alpx_gpio_get; + chip->set = alpx_gpio_set; + chip->get_direction = alpx_gpio_get_direction; + chip->direction_output = alpx_gpio_direction_output; + chip->direction_input = alpx_gpio_direction_input; + + dev_dbg( alpx_dev->dev,"%s(): creating GP(%d)I(%d)O for %s.\n", __func__, + alpx_dev->variant->gpios.inputs_qty, + alpx_dev->variant->gpios.outputs_qty, + chip->label); + + return gpiochip_add_data(chip, alpx_dev); +} + +void alpx_gpio_unregister(struct alpx_device *alpx_dev) +{ + struct gpio_chip* const chip = &alpx_dev->gpio_chip; + if (chip->parent == alpx_dev->dev) + gpiochip_remove(chip); +} + diff --git a/snd-alpx-dkms/snd-alpx/alpx_gpio.h b/snd-alpx-dkms/snd-alpx/alpx_gpio.h new file mode 100644 index 0000000..90395a0 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/alpx_gpio.h @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* +* Support for Digigram AlpX PCI-e boards +* +* Copyright (c) 2024 Digigram Digital (info@digigram.com) +*/ + +#ifndef _ALPX_GPIOS_H +#define _ALPX_GPIOS_H +#include "alpx.h" + +#include <linux/gpio.h> +#include <linux/gpio/driver.h> + +int alpx_gpio_get(struct gpio_chip *chip, unsigned offset); +void alpx_gpio_set(struct gpio_chip *chip, unsigned offset, + int gpio_value); +int alpx_gpio_get_direction(struct gpio_chip *chip, unsigned offset); +int alpx_gpio_direction_output(struct gpio_chip *chip, unsigned offset, + int gpio_value); +int alpx_gpio_direction_input(struct gpio_chip *chip, unsigned offset); +int alpx_gpio_register(struct alpx_device *alpx_dev, const char* card_name); +void alpx_gpio_unregister(struct alpx_device *alpx_dev); + +#endif diff --git a/snd-alpx-dkms/snd-alpx/alpx_led.h b/snd-alpx-dkms/snd-alpx/alpx_led.h new file mode 100644 index 0000000..b69d836 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/alpx_led.h @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* +* Support for Digigram AlpX PCI-e boards +* +* Copyright (c) 2024 Digigram Digital (info@digigram.com) +*/ + +#ifndef _ALPX_LEDS_H +#define _ALPX_LEDS_H + +#include "alpx.h" + +#include <linux/io.h> + +static inline void alpmadi_set_led_state(struct alpx_device *alpx_dev, bool blink) +{ + writel(blink ? 1 : 0, ALPX_REG(alpx_dev, ALPMADI, CONTROL, BLINK_LED)); + + dev_dbg( alpx_dev->dev,"%s(): LED %s, val:0x%08x/\n", __func__, + blink ? "On":"Off",readl(ALPX_REG(alpx_dev, ALPMADI, CONTROL, BLINK_LED))); +} + +#endif diff --git a/snd-alpx-dkms/snd-alpx/alpx_mtd.c b/snd-alpx-dkms/snd-alpx/alpx_mtd.c new file mode 100644 index 0000000..d0ddd52 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/alpx_mtd.c @@ -0,0 +1,318 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* +* Support for Digigram AlpX PCI-e boards +* +* Copyright (c) 2024 Digigram Digital (info@digigram.com) +*/ + +#include "alpx_mtd.h" +#include "alpx.h" +#include "alpx_reg.h" + +static const u32 ALPX_FLASH_ERASED_AREA_VALUE = 0xFFFFFFFF; + + +int alpx_mtd_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + struct alpx_device *alpx_dev = mtd->priv; + size_t size; + u32 page_index; + u32 offset; + u32 cmd; + int ret; + + page_index = from >> ALPX_FLASH_SECTOR_SHIFT; + offset = from & (ALPX_FLASH_SECTOR_SIZE-1); + + while (len) { + if ((offset + len) > ALPX_FLASH_SECTOR_SIZE) + size = ALPX_FLASH_SECTOR_SIZE - offset; + else + size = len; + + cmd = ALP_PROC_COMMAND_MAKE_P16( + ALP_PROC_CMD_READ_FLASH_SECTOR, page_index); + + dev_dbg(alpx_dev->dev,"Reading %zu bytes Flash sector 0x%x.\n", size, page_index); + + mutex_lock(&alpx_dev->proc_mutex); + ret = alpx_proc_cmd(alpx_dev, cmd); + if (ret) { + mutex_unlock(&alpx_dev->proc_mutex); + dev_err(alpx_dev->dev, + "cmd(CMD_READ_FLASH_SECTOR, 0x%x) failed (%d)\n", + page_index, ret); + + return ret; + } + + memcpy_fromio(buf, ALPX_AREA(alpx_dev, ALP, SHARED) + offset, + size); + mutex_unlock(&alpx_dev->proc_mutex); + + if (retlen) + *retlen += size; + buf += size; + len -= size; + offset = 0; + page_index++; + } + return 0; +} + +int alpx_mtd_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf) +{ + struct alpx_device *alpx_dev = mtd->priv; + size_t size; + u32 page_index; + u32 offset; + u32 cmd; + int ret; + + page_index = to >> ALPX_FLASH_SECTOR_SHIFT; + offset = to & (ALPX_FLASH_SECTOR_SIZE-1); + + while (len) { + if ((offset + len) > ALPX_FLASH_SECTOR_SIZE) + size = ALPX_FLASH_SECTOR_SIZE - offset; + else + size = len; + + dev_dbg(alpx_dev->dev,"Writing %zu bytes to sector 0x%x.\n", size, page_index); + + mutex_lock(&alpx_dev->proc_mutex); + if (size != ALPX_FLASH_SECTOR_SIZE) { + /* Partial page write -> read modify write*/ + cmd = ALP_PROC_COMMAND_MAKE_P16( + ALP_PROC_CMD_READ_FLASH_SECTOR, page_index); + + ret = alpx_proc_cmd(alpx_dev, cmd); + if (ret) { + mutex_unlock(&alpx_dev->proc_mutex); + dev_err(alpx_dev->dev, + "cmd(CMD_READ_FLASH_SECTOR, 0x%x) failed (%d)\n", + page_index, ret); + return ret; + } + } + + memcpy_toio(ALPX_AREA(alpx_dev, ALP, SHARED) + offset, buf, + size); + + cmd = ALP_PROC_COMMAND_MAKE_P16( + ALP_PROC_CMD_WRITE_FLASH_SECTOR, page_index); + + ret = alpx_proc_cmd(alpx_dev, cmd); + if (ret) { + mutex_unlock(&alpx_dev->proc_mutex); + dev_err(alpx_dev->dev, + "cmd(CMD_WRITE_FLASH_SECTOR, 0x%x) failed (%d)\n", + page_index, ret); + return ret; + } + mutex_unlock(&alpx_dev->proc_mutex); + + if (retlen) + *retlen += size; + buf += size; + len -= size; + offset = 0; + page_index++; + } + return 0; +} + +int alpx_mtd_probe(struct alpx_device *alpx_dev, const struct mtd_partition* partitions, u32 partitions_size) +{ + struct mtd_info *mtd = &alpx_dev->mtd_info; + + /* Setup the MTD structure */ + mtd->type = MTD_RAM; + mtd->flags = MTD_WRITEABLE | MTD_NO_ERASE; + mtd->size = ALPX_FLASH_CHIP_SIZE; + mtd->writesize = ALPX_FLASH_SECTOR_SIZE; + mtd->writebufsize = mtd->writesize; + mtd->priv = alpx_dev; + + mtd->owner = THIS_MODULE; + mtd->dev.parent = alpx_dev->dev; + mtd->_read = alpx_mtd_read; + mtd->_write = alpx_mtd_write; + + return mtd_device_register(mtd, partitions, + partitions_size); +} + +int alpx_mtd_remove(struct alpx_device *alpx_dev) +{ + return alpx_dev->variant->flash_partitions.qty ? mtd_device_unregister(&alpx_dev->mtd_info) : 0; +} + +/* Read one Flash's page into the shared area NO LOCK DONE !!*/ +static int alpx_mtd_load_one_page_into_shared_area(struct alpx_device* alpx_dev, u32 from) +{ + u32 page_index = from >> ALPX_FLASH_SECTOR_SHIFT; + u32 cmd = ALP_PROC_COMMAND_MAKE_P16( + ALP_PROC_CMD_READ_FLASH_SECTOR, page_index); + size_t size = ALPX_FLASH_SECTOR_SIZE; + + int ret; + + /* Check requested length below FLASH sector's size, TODO check page_index too TODO check form is aligned on page */ + if (from % ALPX_FLASH_SECTOR_SIZE != 0) + return -EINVAL; + + dev_dbg(alpx_dev->dev,"Reading %zu bytes Flash sector 0x%x (0x%x).\n", size, page_index, from); + + + ret = alpx_proc_cmd(alpx_dev, cmd); + if (ret) { + dev_err(alpx_dev->dev, + "cmd(CMD_READ_FLASH_SECTOR, 0x%x) failed (%d)\n", + page_index, ret); + return ret; + } + print_hex_dump_bytes("LOADED Shared area :", DUMP_PREFIX_NONE, ALPX_AREA(alpx_dev, ALP, SHARED), 32); + return ret; +} + +/* Store the shared area into the Flash at the to address. NO LOCK DONE */ +static int alpx_mtd_store_one_page_into_shared_area(struct alpx_device* alpx_dev, u32 to) +{ + u32 page_index = to >> ALPX_FLASH_SECTOR_SHIFT; + u32 cmd = ALP_PROC_COMMAND_MAKE_P16( + ALP_PROC_CMD_WRITE_FLASH_SECTOR, page_index); + size_t size = ALPX_FLASH_SECTOR_SIZE; + + int ret; + + print_hex_dump_bytes("STORED Shared area :", DUMP_PREFIX_NONE, ALPX_AREA(alpx_dev, ALP, SHARED), 32); + + /* Check requested length below FLASH sector's size, TODO check page_index too TODO check form is aligned on page */ + if (to % ALPX_FLASH_SECTOR_SIZE != 0) + return -EINVAL; + + dev_dbg(alpx_dev->dev,"Storing %zu bytes to Flash sector 0x%x.\n", size, page_index); + + ret = alpx_proc_cmd(alpx_dev, cmd); + if (ret) { + dev_err(alpx_dev->dev, + "cmd(ALP_PROC_CMD_WRITE_FLASH_SECTOR, 0x%x) failed (%d)\n", + page_index, ret); + return ret; + } + + return ret; +} + +int alpx_mtd_is_golden_prod_area_valid(struct alpx_device* alpx_dev) +{ + int ret = 0; + + mutex_lock(&alpx_dev->proc_mutex); + ret = alpx_mtd_load_one_page_into_shared_area(alpx_dev, alpx_dev->variant->flash_golden_production_base); + + if (!ret) { + //Now check Production area validity per se : something set in and not in erased state + ret = (*(u32*)ALPX_AREA(alpx_dev, ALP, SHARED)) != ALPX_FLASH_ERASED_AREA_VALUE; + } + else { + dev_err(alpx_dev->dev, "Error %d when loading shared area from flash.\n", ret); + } + mutex_unlock(&alpx_dev->proc_mutex); + return ret; +} + +int alpx_mtd_replicate_prod_area(struct alpx_device* alpx_dev) +{ + /* Read the USER's Production area and then write it to the GOLDEN'sProduction area */ + //Read User + + int ret = 0; + mutex_lock(&alpx_dev->proc_mutex); + + ret= alpx_mtd_load_one_page_into_shared_area(alpx_dev, + alpx_dev->variant->flash_partitions.partitions[ALPX_FLASH_PARTITION_PRODUCTION_ID].offset); + if (!ret) { + //Write it to the GOLDEN's area + ret = alpx_mtd_store_one_page_into_shared_area(alpx_dev, alpx_dev->variant->flash_golden_production_base); + if (ret) { + dev_err(alpx_dev->dev,"Error %d when storing the USER's Production area into GOLDEN.\n", ret); + } + } + else { + dev_err(alpx_dev->dev,"Error %d when reading the USER's Production area.\n", ret); + } + + mutex_unlock(&alpx_dev->proc_mutex); + return ret; +} + +int alpx_mtd_read_from(struct alpx_device* alpx_dev, + uint32_t from, + unsigned char* to, + unsigned int length) +{ + int ret = 0; + + //Check : never read more than SHARE area length + if (length > ALP_SHARED_SIZE) + return -EINVAL; + + mutex_lock(&alpx_dev->proc_mutex); + //Load the PRODUCTION into the shared AREA, then extract the Serial Number + ret= alpx_mtd_load_one_page_into_shared_area(alpx_dev, from); + + if (!ret) { + unsigned int idx = 0; + //NO memcpy() when dealing with SHARED Area + for (idx = 0 ; idx < length; ++idx) { + to[idx] = *(((unsigned char*)ALPX_AREA(alpx_dev, ALP, SHARED))+idx); + } + print_hex_dump_bytes("READ:", DUMP_PREFIX_NONE, to, length); + } else { + dev_err(alpx_dev->dev, " Error 0x%x when reading Flash memory at %d.\n", ret, from); + } + + mutex_unlock(&alpx_dev->proc_mutex); + + return ret; +} + +int alpx_mtd_load_shared_from(struct alpx_device* alpx_dev, uint32_t from) +{ + //Only one page at the moment, must be ALP_SHARED_SIZE bytes after. + return alpx_mtd_load_one_page_into_shared_area(alpx_dev, from); +} + +int alpx_mtd_read_shared(struct alpx_device* alpx_dev, + uint32_t at, + unsigned char* to, + unsigned int length) +{ + unsigned int idx; + //NO memcpy() when dealing with SHARED Area + for (idx = 0 ; idx < length; ++idx) { + to[idx] = *(((unsigned char*)ALPX_AREA(alpx_dev, ALP, SHARED))+idx + at); + } + print_hex_dump_bytes("READ:", DUMP_PREFIX_NONE, to, length); + return 0; +} + +int alpx_mtd_clean_shared(struct alpx_device* alpx_dev) +{ + unsigned int idx; + //NO memcpy() when dealing with SHARED Area + for (idx = 0 ; idx < (ALPX_FLASH_SECTOR_SIZE / sizeof(unsigned int)); ++idx) { + *(unsigned int*)(ALPX_AREA(alpx_dev, ALP, SHARED)+idx) = 0; + } + return 0; +} + +int alpx_mtd_is_available(struct alpx_device* alpx_dev) +{ + //DANTE : no MTD available yet + return alpx_dev->variant->model != ALPX_VARIANT_MODEL_ALPDANTE; +} diff --git a/snd-alpx-dkms/snd-alpx/alpx_mtd.h b/snd-alpx-dkms/snd-alpx/alpx_mtd.h new file mode 100644 index 0000000..1735619 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/alpx_mtd.h @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* +* Support for Digigram AlpX PCI-e boards +* +* Copyright (c) 2024 Digigram Digital (info@digigram.com) +*/ +#ifndef _ALPX_MTD_H +#define _ALPX_MTD_H + +#include "alpx.h" +#include "alpx_proc.h" +#include <linux/mtd/partitions.h> + +int alpx_mtd_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf); +int alpx_mtd_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf); +int alpx_mtd_probe(struct alpx_device *alpx_dev, const struct mtd_partition* partitions, u32 partitions_size); +int alpx_mtd_remove(struct alpx_device *alpx_dev); + +/* Check validity of PRODUCTION area in Golden Region : Serial Number set */ +int alpx_mtd_is_golden_prod_area_valid(struct alpx_device* alpx_dev); + +/*replicate the USER's Production area into the GOLDEN's Production area */ +int alpx_mtd_replicate_prod_area(struct alpx_device* alpx_dev); + +/* Read lenght Bytes out of the flash FROM to the TO buffer using the SHARED area => length limited*/ +int alpx_mtd_read_from(struct alpx_device* alpx_dev, + uint32_t from, + unsigned char* to, + unsigned int length); + +/* Load the SHARED Area with Flash data "from" , NOT MT safe */ +int alpx_mtd_load_shared_from(struct alpx_device* alpx_dev, uint32_t from); + +/* Read Shared Area "at" to for "length" bytes NOT MT safe */ +int alpx_mtd_read_shared(struct alpx_device* alpx_dev, + uint32_t at, + unsigned char* to, + unsigned int length); + +/* Clean the Shared Area NOT MT safe */ +int alpx_mtd_clean_shared(struct alpx_device* alpx_dev); + +/* return true if the MTD is availble for the given device */ +int alpx_mtd_is_available(struct alpx_device* alpx_dev); + +#endif diff --git a/snd-alpx-dkms/snd-alpx/alpx_proc.c b/snd-alpx-dkms/snd-alpx/alpx_proc.c new file mode 100644 index 0000000..65d9daa --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/alpx_proc.c @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* +* Support for Digigram AlpX PCI-e boards +* +* Copyright (c) 2024 Digigram Digital (info@digigram.com) +*/ + +#include "alpx_proc.h" + +#if defined(CONFIG_ALPX_WITH_PROC_LOG) +int alpx_proc_log_dump(struct alpx_device *alpx_dev) +{ + static unsigned char log_buffer[ALP_PROC_LOG_LENGTH]; + unsigned char logged_word = 0; + unsigned int addr = 0; + //unsigned int idx = 0; + struct alpx_device zero_base; + zero_base.base = 0; + + + dev_dbg( alpx_dev->dev,"%s(): uBlaze Log (%d):", __func__, ALP_PROC_LOG_LENGTH); + + for (addr = 0; addr < ALP_PROC_LOG_LENGTH ; addr += sizeof (u32)) { +#if 0 + dev_dbg( alpx_dev->dev,"%s() : log reg: %p + 0x%x => %p\n", __func__, + alpx_dev->base, + ALP_PROC_LOG_BASE + addr, + ALPX_AREA(alpx_dev, ALP, PROC_LOG) + addr); +#endif + logged_word = readl(ALPX_AREA(alpx_dev, ALP, PROC_LOG) + addr); + *(unsigned int*)&log_buffer[addr] = logged_word; +#if 0 + dev_dbg( alpx_dev->dev,"%s() : [0x%x] =>%d\n", __func__, + ALP_PROC_LOG_BASE + addr, + logged_word); +#endif + +#if 0 + for (idx = 0 ; idx < sizeof(u32) ; ++idx) { + printk("%c",(unsigned char)logged_word); + logged_word >>= 8; + } +#endif +print_hex_dump_bytes(alpx_dev->dev,"LOG", DUMP_PREFIX_NONE, + log_buffer, ALP_PROC_LOG_LENGTH); + } + + return 0; +} +#endif + +int alpx_proc_cmd(struct alpx_device *alpx_dev, u32 command) +{ + u32 status; + u32 fails; + int ret; + + /* Set status to detect proc register update */ + writel(0xFFFFFFFF, ALPX_REG(alpx_dev, ALP, PROC, STATUS)); + + /* Post command */ + writel(command, ALPX_REG(alpx_dev, ALP, PROC, COMMAND)); + + /* Poll status for first update */ + ret = readl_poll_timeout(ALPX_REG(alpx_dev, ALP, PROC, STATUS), + status, status != 0xFFFFFFFF, 10, 1000000); + if (ret) { + dev_err(alpx_dev->dev, "cmd 0x%08X timeout (status=%x)\n", + command, status); + alpx_proc_log_dump(alpx_dev); + return ret; + } + + /* Continue polling for end of processing */ + ret = readl_poll_timeout(ALPX_REG(alpx_dev, ALP, PROC, STATUS), + status, !(status & ALP_PROC_STATUS_PENDING), + 10, 1000000); + if (ret) { + dev_err(alpx_dev->dev, "cmd 0x%08X timeout (status=%x)\n", + command, status); + alpx_proc_log_dump(alpx_dev); + return ret; + } + + mdelay(1); + + /* Command processing is done -> check results */ + status = readl(ALPX_REG(alpx_dev, ALP, PROC, STATUS)); + fails = readl(ALPX_REG(alpx_dev, ALP, PROC, FAILS)); + + dev_dbg(alpx_dev->dev,"cmd 0x%08X => status: 0x%x, fail:0x%x\n", command, status, fails); + + if ((status & ALP_PROC_STATUS_FAIL) && + (fails != ALP_PROC_FAILS_FAIL_NONE)) { + dev_err(alpx_dev->dev, "cmd 0x%08X failed (status=%x, fails=%x)\n", + command, status, fails); + alpx_proc_log_dump(alpx_dev); + return -EIO; + } + + alpx_proc_log_dump(alpx_dev); + + return 0; +} + +int alpx_proc_probe(struct alpx_device *alpx_dev) +{ + mutex_init(&alpx_dev->proc_mutex); + return 0; +} + +int alpx_proc_remove(struct alpx_device *alpx_dev) +{ + mutex_destroy(&alpx_dev->proc_mutex); + return 0; +} diff --git a/snd-alpx-dkms/snd-alpx/alpx_proc.h b/snd-alpx-dkms/snd-alpx/alpx_proc.h new file mode 100644 index 0000000..8328a14 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/alpx_proc.h @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* +* Support for Digigram AlpX PCI-e boards +* +* Copyright (c) 2024 Digigram Digital (info@digigram.com) +*/ + +#ifndef _ALPX_PROC_H +#define _ALPX_PROC_H + +#include "alpx.h" +#include <linux/iopoll.h> + +#if defined(CONFIG_ALPX_WITH_PROC_LOG) +int alpx_proc_log_dump(struct alpx_device *alpx_dev); +#else +/* Empty def */ +#define alpx_proc_log_dump(p) +#endif + +int alpx_proc_cmd(struct alpx_device *alpx_dev, u32 command); +int alpx_proc_probe(struct alpx_device *alpx_dev); +int alpx_proc_remove(struct alpx_device *alpx_dev); + + +#endif diff --git a/snd-alpx-dkms/snd-alpx/alpx_reg.h b/snd-alpx-dkms/snd-alpx/alpx_reg.h new file mode 100644 index 0000000..276e16d --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/alpx_reg.h @@ -0,0 +1,619 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* +* Support for Digigram AlpX PCI-e boards +* +* Copyright (c) 2024 Digigram Digital (info@digigram.com) +*/ + +#ifndef _ALPX_REG_H_ +#define _ALPX_REG_H_ + +/* Macros */ + +#define ALPX_BASE(variant, group) \ + (variant ## _ ## group ## _BASE) + +#define ALPX_OFFSET(variant, group, reg) \ + ((variant ## _ ## group ## _BASE) + \ + (variant ## _ ## group ## _ ## reg ## _REG)) + +#define ALPX_AREA(alpx_dev, variant, group) \ + ((alpx_dev)->base + ALPX_BASE(variant, group)) + +#define ALPX_ITEM_REG(variant, group, index) \ + ((variant ## _ ## group ## _BASE) + \ + (variant ## _ ## group ## _ ## index)) + +#define ALPX_REG(alpx_dev, variant, group, reg) \ + ((alpx_dev)->base + ALPX_OFFSET(variant, group, reg)) + +#define ALPX_REG_ARRAY(alpx_dev, variant, group, index) \ + ((alpx_dev)->base + ALPX_ITEM_REG(variant, group, index)) + +#define ALPX_COMMON_OFFSET(variant, group, reg) \ + ((variant ## _ ## group ## _BASE) + \ + (ALPX_COMMON_ ## reg ## _REG)) + +#define ALPX_COMMON_REG(alpx_dev, variant, group, reg) \ + ((alpx_dev)->base + ALPX_COMMON_OFFSET(variant, group, reg)) + +/* Conversion Register index to register offset, register are 32 bits words */ +#define ALP_INDEX_TO_REG_OFFSET(i) ((i) * 4) + + +/* PCI */ + +#define ALPX_PCI_BAR 0 +#define ALPX_PCI_ID_DEVICE 0x0002 + +#define ALPX_PCI_ID_SUBSYSTEM_MADI 0x0020 +#define ALPX_PCI_ID_SUBSYSTEM_ALP222 0x0040 +#define ALPX_PCI_ID_SUBSYSTEM_ALP222_MIC 0x0840 +#define ALPX_PCI_ID_SUBSYSTEM_ALP442 0x0080 +#define ALPX_PCI_ID_SUBSYSTEM_ALP442_MIC 0x0880 +#define ALPX_PCI_ID_SUBSYSTEM_ALP882 0x00C0 +#define ALPX_PCI_ID_SUBSYSTEM_ALP882_MIC 0x08C0 +#define ALPX_PCI_ID_SUBSYSTEM_MADI_LOOPBACK 0x0000 +#define ALPX_PCI_ID_SUBSYSTEM_ALPDANTE 0x00E0 + + +/* This one is a very special one : The production area is invalid */ +#define ALPX_PCI_ID_SUBSYSTEM_MADI_ALP_DEAD 0xDEAD + +/* UNKNOWN */ +#define ALPUNKNOWN_GPIO_BASE 0xFFFFF + +/* ALPX Base */ + +#define ALP_SHARED_BASE 0x50000 +#define ALP_SHARED_SIZE 8 * 1024 +#define ALP_PROC_BASE 0x60000 +#define ALP_CONTROL_BASE 0x70000 +#define ALP_CLK_MANAGER_BASE ALP_CONTROL_BASE + + +/* Alpxxx Flash defs */ +/** Common size for all the data areas in Flash, exclude the FIRMWARE **/ +#define ALPxxx_FLASH_DATA_AREAS_SIZE (32*1024) + +/** PRODUCTION Area in GOLDEN Region **/ +#define ALPxxx_FLASH_GOLDEN_PRODUCTION_BASE 0x228000 + +/* PRODUCTION structure */ +#define ALPX_SERIAL_OFFSET_IN_PRODUCTION 0 + +/* BUILD version register : common addresses */ +#define ALP_CONTROL_DESIGN_VERSION_REG 0x100 +#define ALP_CONTROL_BUILD_VERSION_REG 0x104 + +#define ALP_CONTROL_BUILD_VERSION_MASK GENMASK(15,0) + + +/** Multi-channels cards **/ + +/* Clock Manager */ +#define ALPMC_CLK_MANAGER_CONFIG_REG 0x24 +#define ALPMC_CLK_MANAGER_CONFIG_FS(v) ((v) & GENMASK(4, 0)) +#define ALPMC_CLK_MANAGER_CONFIG_FS_MASK GENMASK(4, 0) + + +#define ALPMC_CLK_MANAGER_EFFECTIVE_FS(v) (((v) & GENMASK(20, 16)) >> 16) +#define ALPMC_CLK_MANAGER_EFFECTIVE_FS_INVALID 0 +#define ALPMC_CLK_MANAGER_EFFECTIVE_FS_32K 5 +#define ALPMC_CLK_MANAGER_EFFECTIVE_FS_44_1K 6 +#define ALPMC_CLK_MANAGER_EFFECTIVE_FS_48K 7 +#define ALPMC_CLK_MANAGER_EFFECTIVE_FS_DOUBLE BIT(3) +#define ALPMC_CLK_MANAGER_EFFECTIVE_FS_QUAD BIT(4) +#define ALPMC_CLK_MANAGER_EFFECTIVE_FS_BASE_MASK GENMASK(2, 0) + + +#define ALPMC_CLK_MANAGER_CONFIG_CLK_CURRENT_VALUE_MASK GENMASK(20, 16) +#define ALPMC_CLK_MANAGER_CONFIG_CLK_CURRENT_VALUE_POS 16 +#define ALPMC_CLK_MANAGER_CONFIG_CLK_CURRENT_VALUE_QTY 8 + +#define ALPMC_CLK_MANAGER_SOURCE(v) (((v) & GENMASK(23, 21)) >> 21) +#define ALPMC_CLK_MANAGER_SOURCE_INTERNAL 0 +#define ALPMC_CLK_MANAGER_SOURCE_SIC 1 +#define ALPMC_CLK_MANAGER_SOURCE_WCLK_IN 2 +#define ALPMC_CLK_MANAGER_SOURCE_AES_SYNC 3 +#define ALPMC_CLK_MANAGER_SOURCE_AES_AUDIO_12 4 +#define ALPMC_CLK_MANAGER_SOURCE_AES_AUDIO_34 5 +#define ALPMC_CLK_MANAGER_SOURCE_AES_AUDIO_56 6 +#define ALPMC_CLK_MANAGER_SOURCE_AES_AUDIO_78 7 +#define ALPMC_CLK_MANAGER_SOURCE_DANTE 8 + +/* Pre FW V240 compatibility support */ +#define ALP882_APP_PREFW240_CLK_MANAGER_SOURCE_WCLK_IN 0 +#define ALP882_APP_PREFW240_CLK_MANAGER_SOURCE_AES_SYNC 1 +#define ALP882_APP_PREFW240_CLK_MANAGER_SOURCE_AES_AUDIO_12 2 +#define ALP882_APP_PREFW240_CLK_MANAGER_SOURCE_AES_AUDIO_34 3 +#define ALP882_APP_PREFW240_CLK_MANAGER_SOURCE_AES_AUDIO_56 4 +#define ALP882_APP_PREFW240_CLK_MANAGER_SOURCE_AES_AUDIO_78 5 +#define ALP882_APP_PREFW240_CLK_MANAGER_SOURCE_INTERNAL 6 + +#define ALPMC_CLK_MANAGER_CONFIG_CLK_SRC_MASK GENMASK(23, 21) +#define ALPMC_CLK_MANAGER_CONFIG_CLK_SRC_POS 21 + +#define ALPMC_CLK_MANAGER_BASE ALP_CLK_MANAGER_BASE +#define ALPMC_CONTROL_BASE ALP_CLK_MANAGER_BASE +#define ALPMC_GPIO_BASE 0x45000 +#define ALPMC_CODEC_CTRL_BASE 0x71000 +#define ALPMC_MIXER_BASE 0x74000 +#define ALPMC_AMPLI_IN_BASE 0x79000 +#define ALPMC_AMPLI_OUT_BASE 0x7c000 + +/* FS switch delay required by HW (in ms) */ +#define ALPMC_FS_SWITCH_DELAY 500 + +/* Supported Firmware versions */ +#define ALPMC_SUPPORTED_BASE_FW_VERSION 247 +#define ALP222_SUPPORTED_BASE_FW_VERSION 283 +/* The base Firmware version for AlpDANTE supported by this driver */ +#define ALPDANTE_SUPPORTED_BASE_FW_VERSION 316 + + + +/* GPIO */ + +#define ALPMC_GPIO_INPUT_REG 0x08 +#define ALPMC_GPIO_INPUT_QTY 8 +#define ALPMC_GPIO_OUTPUT_REG 0x0C +#define ALPMC_GPIO_OUTPUT_QTY 8 + +/* ALPMC Gain access*/ +#define ALPMC_GAIN_TABLE_BASE(c) (0xc + (c) * 0x4) + +/* Codec */ +#define ALPMC_INPUT_PARAMS_REG 0x2C +#define ALPMC_MIC_INPUT_PH_1_MASK BIT(0) +#define ALPMC_MIC_INPUT_PH_2_MASK BIT(1) +#define ALPMC_MIC_INPUT_PH_3_MASK BIT(2) +#define ALPMC_MIC_INPUT_PH_4_MASK BIT(3) +#define ALPMC_MIC_INPUT_PH_5_MASK BIT(4) +#define ALPMC_MIC_INPUT_PH_6_MASK BIT(5) +#define ALPMC_MIC_INPUT_PH_7_MASK BIT(6) +#define ALPMC_MIC_INPUT_PH_8_MASK BIT(7) + +#define ALPMC_MIC_INPUT_PH_1_POS 0 +#define ALPMC_MIC_INPUT_PH_2_POS 1 +#define ALPMC_MIC_INPUT_PH_3_POS 2 +#define ALPMC_MIC_INPUT_PH_4_POS 3 +#define ALPMC_MIC_INPUT_PH_5_POS 4 +#define ALPMC_MIC_INPUT_PH_6_POS 5 +#define ALPMC_MIC_INPUT_PH_7_POS 6 +#define ALPMC_MIC_INPUT_PH_8_POS 7 + +#define ALPMC_CODEC_PGA_REGS 0x0C + +#define ALPMC_CODEC_AES_SRC_CONTROL_REG 0x08 +#define ALPMC_CODEC_AES_SRC_CONTROL_AUTO_DISABLE_1_2 BIT(0) +#define ALPMC_CODEC_AES_SRC_CONTROL_AUTO_DISABLE_3_4 BIT(1) +#define ALPMC_CODEC_AES_SRC_CONTROL_AUTO_DISABLE_5_6 BIT(2) +#define ALPMC_CODEC_AES_SRC_CONTROL_AUTO_DISABLE_7_8 BIT(3) + +#define ALPMC_CODEC_AES_SRC_1_2_MASK BIT(0) +#define ALPMC_CODEC_AES_SRC_1_2_POS 0 +#define ALPMC_CODEC_AES_SRC_3_4_MASK BIT(1) +#define ALPMC_CODEC_AES_SRC_3_4_POS 1 +#define ALPMC_CODEC_AES_SRC_5_6_MASK BIT(2) +#define ALPMC_CODEC_AES_SRC_5_6_POS 2 +#define ALPMC_CODEC_AES_SRC_7_8_MASK BIT(3) +#define ALPMC_CODEC_AES_SRC_7_8_POS 3 + +/* MC Mixer */ +/* One Gain value per register */ +#define ALPMC_MIXER_ENTRIES_IN_REG 1 + +#define ALPMC_MIXER_GAIN_MASK GENMASK(ALPX_MIXER_GAIN_BITS - 1, 0) + +#define ALPMC_MIXER_GAIN_SEL(v) ((v) & GENMASK(ALPX_MIXER_GAIN_BITS - 1, 0)) + +#define ALPMC_MIXER_GAIN_VALUE(v) ((v) & GENMASK(ALPX_MIXER_GAIN_BITS-1, 0)) + +#define ALPMC_MIXER_GAIN_REG(size, in, out) (ALPX_MIXER_REG_ENTRIES_OFFSET + (out) * ((size) * 4 / ALPMC_MIXER_ENTRIES_IN_REG) + ((in) / ALPMC_MIXER_ENTRIES_IN_REG) * 4) + + +/* Dedicated to ALP882 */ + +#define ALP882_CHANNELS_DAW_COUNT 16 +#define ALP882_CHANNELS_ANALOG_COUNT 8 +#define ALP882_CHANNELS_AES_COUNT 8 + +#define ALP882_CHANNELS_IN_DAW_OFFSET 0 +#define ALP882_CHANNELS_IN_ANALOG_OFFSET (ALP882_CHANNELS_IN_DAW_OFFSET + \ + ALP882_CHANNELS_DAW_COUNT) +#define ALP882_CHANNELS_IN_AES_OFFSET (ALP882_CHANNELS_IN_ANALOG_OFFSET + \ + ALP882_CHANNELS_ANALOG_COUNT) + +#define ALP882_CHANNELS_OUT_ANALOG_OFFSET 0 +#define ALP882_CHANNELS_OUT_AES_OFFSET (ALP882_CHANNELS_OUT_ANALOG_OFFSET + \ + ALP882_CHANNELS_ANALOG_COUNT) +#define ALP882_CHANNELS_OUT_DAW_OFFSET (ALP882_CHANNELS_OUT_AES_OFFSET + \ + ALP882_CHANNELS_AES_COUNT) + + +/* ALP882 Clock Manager */ +#define ALP882_CLK_MANAGER_CONFIG_CLK_SRC_QTY 8 + +/* Alp 882 clk source in Pre 240 FW */ +#define ALP882_APP_PREFW240_CLK_MANAGER_CLK_SRC_QTY 7 + +/* Mixer 882 */ +#define ALP882_MIXER_SIZE 32 + +/* Dedicated to ALP442 */ + +#define ALP442_CHANNELS_ANALOG_COUNT 4 +#define ALP442_CHANNELS_AES_COUNT 4 +#define ALP442_CHANNELS_DAW_COUNT (ALP442_CHANNELS_ANALOG_COUNT + \ + ALP442_CHANNELS_AES_COUNT) + + +#define ALP442_CHANNELS_IN_DAW_OFFSET 0 +#define ALP442_CHANNELS_IN_ANALOG_OFFSET (ALP442_CHANNELS_IN_DAW_OFFSET + \ + ALP442_CHANNELS_DAW_COUNT) +#define ALP442_CHANNELS_IN_AES_OFFSET (ALP442_CHANNELS_IN_ANALOG_OFFSET + \ + ALP442_CHANNELS_ANALOG_COUNT) + +#define ALP442_CHANNELS_OUT_ANALOG_OFFSET 0 +#define ALP442_CHANNELS_OUT_AES_OFFSET (ALP442_CHANNELS_OUT_ANALOG_OFFSET + \ + ALP442_CHANNELS_ANALOG_COUNT) +#define ALP442_CHANNELS_OUT_DAW_OFFSET (ALP442_CHANNELS_OUT_AES_OFFSET + \ + ALP442_CHANNELS_AES_COUNT) + + +/* ALP442 Clock Manager */ +#define ALP442_CLK_MANAGER_CONFIG_CLK_SRC_QTY 6 +#define ALP442_CLK_MANAGER_SOURCE_INTERNAL ALPMC_CLK_MANAGER_SOURCE_INTERNAL + +/* Mixer 442 */ +#define ALP442_MIXER_SIZE (ALP442_CHANNELS_ANALOG_COUNT + \ + ALP442_CHANNELS_AES_COUNT + \ + ALP442_CHANNELS_DAW_COUNT) + + + +/* Alp 222 */ + +#define ALP222_ANALOG_QTY 0x2 +#define ALP222_AES3_QTY 0x2 + +#define ALP222_EXT_CHANNEL_QTY (ALP222_ANALOG_QTY + ALP222_AES3_QTY) + +#define ALP222_DAW_QTY ALP222_EXT_CHANNEL_QTY + + +#define ALP222_CLK_MANAGER_BASE ALP_CLK_MANAGER_BASE +#define ALP222_CONTROL_BASE ALP_CLK_MANAGER_BASE +#define ALP222_AMPLI_IN_BASE 0x79000 +#define ALP222_AMPLI_OUT_BASE 0x7c000 +#define ALP222_CODEC_CTRL_BASE 0x71000 +#define ALP222_GPIO_BASE 0x45000 +#define ALP222_MIXER_BASE 0x73000 + +#define ALP222_DAW_PLAYBACK_AMPLI_BASE ALP222_AMPLI_IN_BASE + ALPX_GAIN_REG(0) +#define ALP222_ANALOG_CAPTURE_AMPLI_BASE ALP222_AMPLI_IN_BASE + ALPX_GAIN_REG(ALP222_DAW_QTY) +#define ALP222_AES3_CAPTURE_AMPLI_BASE ALP222_AMPLI_IN_BASE + ALPX_GAIN_REG(ALP222_DAW_QTY + ALP222_ANALOG_QTY) + +#define ALP222_ANALOG_PLAYBACK_AMPLI_BASE ALP222_AMPLI_OUT_BASE + ALPX_GAIN_REG(0) +#define ALP222_AES3_PLAYBACK_AMPLI_BASE ALP222_AMPLI_OUT_BASE + ALPX_GAIN_REG(ALP222_ANALOG_QTY) +#define ALP222_DAW_CAPTURE_AMPLI_BASE ALP222_AMPLI_OUT_BASE + ALPX_GAIN_REG(ALP222_ANALOG_QTY + ALP222_AES3_QTY) + + +/* Alp222 GPIO */ +#define ALP222_GPIO_INPUT_REG 0x00 +#define ALP222_GPIO_INPUT_QTY 2 +#define ALP222_GPIO_OUTPUT_REG 0x08 +#define ALP222_GPIO_OUTPUT_QTY 2 + +/* Alp222 CODEC*/ +#define ALP222_CODEC_PGA_REGS 0x08 + +/* Alp MADI */ +#define ALP222_MADI_QTY 0x40 + +#define ALPMADI_CHANNEL_QTY ALP222_MADI_QTY + +//MADI Unit & DAW Unit +#define ALPMADI_AUDIO_UNIT_QTY 2 + +#define ALPMADI_CLK_MANAGER_BASE ALP_CLK_MANAGER_BASE +#define ALPMADI_CONTROL_BASE ALP_CLK_MANAGER_BASE +#define ALPMADI_ROUTER_IN_BASE 0x71000 +#define ALPMADI_MIXER_BASE 0x72000 +#define ALPMADI_ROUTER_OUT_BASE 0x73000 +#define ALPMADI_MEAS_DAW_IN_BASE 0x74000 +#define ALPMADI_GAIN_DAW_IN_BASE 0x75000 +#define ALPMADI_MEAS_DAW_OUT_BASE 0x76000 +#define ALPMADI_GAIN_DAW_OUT_BASE 0x77000 +#define ALPMADI_MEAS_MADI_IN_BASE 0x78000 +#define ALPMADI_GAIN_MADI_IN_BASE 0x79000 +#define ALPMADI_MEAS_MADI_OUT_BASE 0x7A000 +#define ALPMADI_GAIN_MADI_OUT_BASE 0x7B000 +#define ALPMADI_GPIO_BASE ALPUNKNOWN_GPIO_BASE + +#define ALPMADI_GPIO_INPUT_REG 0xFF +#define ALPMADI_GPIO_OUTPUT_REG 0xFF + +/* Common */ + +#define ALPX_COMMON_ID_REG 0x0 + + +#define ALPX_COMMON_VERSION_REG 0x4 +#define ALPX_COMMON_VERSION_VERSION(v) ((v) >> 16) +#define ALPX_COMMON_VERSION_REVISION(v) ((v) & GENMASK(15, 0)) + +#define ALPX_DANTE_VERSION_VERSION(v) ((v) >> 8) +#define ALPX_DANTE_VERSION_REVISION(v) ((v) & GENMASK(7, 0)) + + +/* Common Clock 222/882 models*/ + +#define ALPxxx_CLK_MANAGER_CLK_VALUES_QTY 14 + +/* Values below use the full 5 bits of clock definitions : factor | base */ +#define ALPxxx_CLK_MANAGER_CLK_VALUE_8K (0) +#define ALPxxx_CLK_MANAGER_CLK_VALUE_11_025K (1) +#define ALPxxx_CLK_MANAGER_CLK_VALUE_16K (2) +#define ALPxxx_CLK_MANAGER_CLK_VALUE_22_05K (3) +#define ALPxxx_CLK_MANAGER_CLK_VALUE_24K (4) +#define ALPxxx_CLK_MANAGER_CLK_VALUE_32K (5) +#define ALPxxx_CLK_MANAGER_CLK_VALUE_44_1K (6) +#define ALPxxx_CLK_MANAGER_CLK_VALUE_48K (7) +#define ALPxxx_CLK_MANAGER_CLK_VALUE_64K (0xD) +#define ALPxxx_CLK_MANAGER_CLK_VALUE_128K (0x15) +#define ALPxxx_CLK_MANAGER_CLK_VALUE_88_2K (0xE) +#define ALPxxx_CLK_MANAGER_CLK_VALUE_176_4K (0x16) +#define ALPxxx_CLK_MANAGER_CLK_VALUE_96K (0xF) +#define ALPxxx_CLK_MANAGER_CLK_VALUE_192K (0x17) + +/* ALP222 Clock Manager */ + +#define ALP222_CLK_MANAGER_CONFIG_REG 0x28 +#define ALP222_CLK_MANAGER_CONFIG_FS_MASK GENMASK(4, 0) +#define ALP222_CLK_MANAGER_CONFIG_CLK_CURRENT_VALUE_MASK GENMASK(20, 16) +#define ALP222_CLK_MANAGER_CONFIG_CLK_CURRENT_VALUE_POS 16 + + +#define ALP222_CLK_MANAGER_CLK_SRC_MASK GENMASK(23, 21) +#define ALP222_CLK_MANAGER_CLK_SRC_POS 21 +#define ALP222_CLK_MANAGER_CLK_SRC_QTY 5 +#define ALP222_CLK_MANAGER_CLK_SRC_INTERNAL (0) +#define ALP222_CLK_MANAGER_CLK_SRC_SIC (1) +#define ALP222_CLK_MANAGER_CLK_SRC_WCLK (2) +#define ALP222_CLK_MANAGER_CLK_SRC_AES_SYNC (3) +#define ALP222_CLK_MANAGER_CLK_SRC_AES_AUDIO (4) +#define ALP222_CLK_MANAGER_CLK_SRC_MAX ALP222_CLK_MANAGER_CLK_SRC_AES_AUDIO + +/* Pre FW 283 clock sources definitions */ +#define ALP222_APPS_PREFW283_CLK_MANAGER_CLK_SRC_QTY 4 +#define ALP222_CLK_MANAGER_APPSPREFW283_CLK_SRC_WCLK 0 +#define ALP222_CLK_MANAGER_APPSPREFW283_CLK_SRC_AES_SYNC 1 +#define ALP222_CLK_MANAGER_APPSPREFW283_CLK_SRC_AES_AUDIO 2 +#define ALP222_CLK_MANAGER_APPSPREFW283_CLK_SRC_INTERNAL 3 + +/* ALPMADI Clock Manager */ + +#define ALPMADI_CLK_MANAGER_CONFIG_REG 0x1C +#define ALPMADI_CLK_MANAGER_CONFIG_FS_MASK GENMASK(10, 8) +#define ALPMADI_CLK_MANAGER_CONFIG_FS_44_1K (0 << 8) +#define ALPMADI_CLK_MANAGER_CONFIG_FS_48K (1 << 8) +#define ALPMADI_CLK_MANAGER_CONFIG_FS_88_2K (2 << 8) +#define ALPMADI_CLK_MANAGER_CONFIG_FS_96K (3 << 8) +#define ALPMADI_CLK_MANAGER_CONFIG_FS_176_4K (4 << 8) +#define ALPMADI_CLK_MANAGER_CONFIG_FS_192K (5 << 8) + +/* AlpDANTE Clock Manager clock registervalues*/ +#define ALPDANTE_CLK_MANAGER_CLK_VALUE_44_1K 0x01 +#define ALPDANTE_CLK_MANAGER_CLK_VALUE_48K 0x00 +#define ALPDANTE_CLK_MANAGER_CLK_VALUE_88_2K 0x03 +#define ALPDANTE_CLK_MANAGER_CLK_VALUE_96K 0x02 +#define ALPDANTE_CLK_MANAGER_CLK_VALUE_176_4K 0x05 +#define ALPDANTE_CLK_MANAGER_CLK_VALUE_192K 0x04 + +/* ALPX PROC */ +/* Embedded processor dedicated area length (in bytes) */ +#define ALP_PROC_AREA_LENGTH 0x800U + +#define ALP_PROC_VERSION_REG 0x00 + +#define ALP_PROC_STATUS_REG 0x04 +#define ALP_PROC_STATUS_FAIL BIT(0) +#define ALP_PROC_STATUS_PENDING BIT(1) + +#define ALP_PROC_FAILS_REG 0x08 +#define ALP_PROC_FAILS_FAIL_NONE 0 + +#define ALP_PROC_COMMAND_REG 0x0C + +#define ALP_PROC_COMMAND_MAKE_P16(_cmd, _p16) ((((_p16) & 0x0FFFF) << 8) | \ + (_cmd)) +#define ALP_PROC_CMD_READ_FLASH_SECTOR 0x10 +#define ALP_PROC_CMD_WRITE_FLASH_SECTOR 0x0A + +#define ALP_PROC_FWCONFIG_REG 0x10 +#define ALP_PROC_FWCONFIG_CLKSRC_UP_MASK GENMASK(0,0) +#define ALP_PROC_FWCONFIG_CLKSRC_UP_POS 0 + +#define ALP_PROC_FWCONFIG_CLKSRC_DOWN_MASK GENMASK(1,1) +#define ALP_PROC_FWCONFIG_CLKSRC_DOWN_POS 1 + + +/* PROC Logs base register */ +#define ALP_PROC_LOG_OFFSET 0x40U +#define ALP_PROC_LOG_BASE ALP_PROC_BASE + ALP_PROC_LOG_OFFSET + +/* Log length, -8 ?? but done in the reference application from Easii-IC (log.c) */ +#define ALP_PROC_LOG_LENGTH ALP_PROC_AREA_LENGTH - ALP_PROC_LOG_OFFSET - 8U + +/* Clock source priority def */ +#define ALP_PROC_CLK_SOURCE_PRIO_REG 0x14 + +#define ALP_PROC_CLK_SOURCE_PRIO0_MASK GENMASK(3,0) +#define ALP_PROC_CLK_SOURCE_PRIO0_POS 0 + +#define ALP_PROC_CLK_SOURCE_PRIO1_MASK GENMASK(7,4) +#define ALP_PROC_CLK_SOURCE_PRIO1_POS 4 + +#define ALP_PROC_CLK_SOURCE_PRIO2_MASK GENMASK(11,8) +#define ALP_PROC_CLK_SOURCE_PRIO2_POS 8 + +#define ALP_PROC_CLK_SOURCE_PRIO3_MASK GENMASK(15,12) +#define ALP_PROC_CLK_SOURCE_PRIO3_POS 12 + +/* ALPX GPIO */ +#define ALPX_GPIO_MASK(i) BIT(i) +#define ALPX_GPIO_SEL(i, v) (((v) << (i)) & ALPX_GPIO_MASK(i)) +#define ALPX_GPIO_VALUE(i, v) (((v) & ALPX_GPIO_MASK(i)) >> (i)) + +/* Control */ +#define ALP_CONTROL_PCIE_SUBSYS_ID_REG 0x8 +#define ALP_CONTROL_SAMPLES_CNT_REG 0x18 +#define ALP_CLK_MANAGER_SAMPLES_COUNT_REG 0x18 + +#define ALP222_CONTROL_PCIE_MASK_IT_REG 0xc +#define ALP222_CONTROL_WC_RTERM_REG 0x1c +#define ALP222_CONTROL_PCIE_WARM_RESET_REG 0x10 +#define ALP222_CONTROL_PCIE_WARM_RESET_VALUE 0xc07d8e51 +#define ALP222_CONTROL_PCIE_COLD_RESET_REG 0x14 +#define ALP222_CONTROL_PCIE_COLD_RESET_VALUE 0x8e5ef96a +#define ALP222_CONTROL_FS_REG 0x28 +#define ALP222_CODEC_CTRL_ASRC_REG 0x10 +#define ALP222_MIC_CONTROL_REG 0x24 + +#define ALPMADI_CONTROL_WARM_REBOOT_FPGA_REG 0x10 +#define ALPMADI_CONTROL_COLD_REBOOT_FPGA_REG 0x14 +#define ALPMADI_CONTROL_BLINK_LED_REG 0x20 +#define ALPMADI_CONTROL_EXT_ITF_CONFIG_REG 0x24 +#define ALPMADI_CONTROL_FS_SEL_REG 0x28 + +#define ALPMADI_CONTROL_EXT0_STATUS_CTRL_REG 0x2c +#define ALPMADI_CONTROL_EXT1_STATUS_CTRL_REG 0x30 +#define ALPMADI_CONTROL_EXT2_STATUS_CTRL_REG 0x34 +#define ALPMADI_CONTROL_EXT3_STATUS_CTRL_REG 0x38 +#define ALPMADI_CONTROL_PI_PARAMS_REG 0x3c + + +#define ALPMADI_CONTROL_BLINK_LED_EN BIT(0) +#define ALPMADI_CONTROL_PI_PARAMS_KI(v) ((v) & GENMASK(15, 0)) +#define ALPMADI_CONTROL_PI_PARAMS_KP(v) (((v) << 16) & GENMASK(31, 16)) +#define ALPMADI_CONTROL_EXT_ITF_CONFIG_MADI_LINK(v) ((v) & GENMASK(1, 0)) +#define ALPMADI_CONTROL_EXT_ITF_CONFIG_BNC_SIGNAL(v) (((v<<8)) & GENMASK(8, 8)) + +/* Codec */ +#define ALPX_CODEC_CTRL_GAIN_REG(i) ((i) * 0x4) + +/* Gains */ +#define ALPX_GAIN_VALUE_BITS 10 +#define ALPX_GAIN_REG_ENTRIES_OFFSET 0xC +#define ALPX_GAIN_REG(i) (ALPX_GAIN_REG_ENTRIES_OFFSET + (i) * 0x4) + +/* Router */ +#define ALPMADI_ROUTER_SIZE 128 + +#define ALPX_ROUTER_REG_ENTRIES_OFFSET 0x8 + +/* RAW ACCESS to router register i*/ +#define ALPX_ROUTER_REG(i) (0x8 + ((i) / 4) * 0x4) + +#define ALPX_ROUTER_SHIFT(i) (((i) % 4) * 8) +#define ALPX_ROUTER_MASK(i) (GENMASK(7, 0) << \ + ALPX_ROUTER_SHIFT(i)) +#define ALPX_ROUTER_SEL(i, v) (((v) & GENMASK(7, 0)) << \ + ALPX_ROUTER_SHIFT(i)) +#define ALPX_ROUTER_VALUE(i, v) (((v) >> \ + ALPX_ROUTER_SHIFT(i)) & \ + GENMASK(7, 0)) + +#define ALPMADI_ROUTER_PORT(i) (ALPX_ROUTER_REG_ENTRIES_OFFSET + ((i) * 0x4)) + +#define ALPMADI_ROUTER_IN_PORT(i) ALPMADI_ROUTER_PORT(i) + +#define ALPMADI_ROUTER_OUT_PORT(i) ALPMADI_ROUTER_PORT(i) + +/* Mixer */ +#define ALPX_MIXER_GAIN_BITS 10 +#define ALPX_GAIN_0dB 0x385 +#define ALPX_GAIN_MUTE 0x000 + +/** Mixer 222 **/ + +/* Mixer Input i, output j & j+1*/ +#define ALP222_MIXER_SIZE 8 +#define ALPMADI_MIXER_SIZE 16 + +//2 gains per register +#define ALPMADI_MIXER_BANK_SIZE 2 + +#define ALP222_MIXER_ENTRIES_IN_REG 2 + +//#define ALPX_GAIN_REG_VALUE_STEP_PER_DB 10 +#define ALPX_GAIN_dB_TO_10ofdB (dB) ((db) * 10) + + +#define ALPX_GAIN_REG_VALUE_FROM_10ofDB(val10ofdb) (ALPX_GAIN_0dB + (val10ofdb)) + +#define ALPX_MIXER_REG_ENTRIES_OFFSET 0x8 + +/* Return the @reg for the given (input/output) in the mixer. MIND the register structure !! */ +//MADI structured as In into Outs +//EDF MADI formula TO BE CHECKED +//#define ALPMADI_MIXER_GAIN_REG(mixerSize, inputId, outputId) (0x8 + ((((mixerSize) * (inputId) + (outputId)) * 4 / ALPX_MIXER_ENTRIES_IN_REG))) + +// Structured as : Out from Ins +#define ALP222_MIXER_GAIN_REG(size, in, out) (ALPX_MIXER_REG_ENTRIES_OFFSET + (out) * ((size) * 4 / ALP222_MIXER_ENTRIES_IN_REG) + ((in) / ALP222_MIXER_ENTRIES_IN_REG) * 4) + +//Odd entry is in higher bits +#define ALP222_MIXER_GAIN_SHIFT_STEP(i) (((i) & 1) ? ALPX_MIXER_GAIN_BITS : 0) + +#define ALP222_MIXER_GAIN_MASK(i) (GENMASK(ALPX_MIXER_GAIN_BITS-1, 0) << \ + ALP222_MIXER_GAIN_SHIFT_STEP(i)) + +#define ALP222_MIXER_GAIN_SEL(i, v) (((v) & GENMASK(ALPX_MIXER_GAIN_BITS-1, 0)) << \ + ALP222_MIXER_GAIN_SHIFT_STEP(i)) + +#define ALP222_MIXER_GAIN_VALUE(i, v) (((v) >> \ + ALP222_MIXER_GAIN_SHIFT_STEP(i)) & \ + GENMASK(ALPX_MIXER_GAIN_BITS-1, 0)) + + +//Build the mixer register +//#define ALP222_MIXER_REG_VALUE(left, right) ((left)<< ALP_GAIN_VALUE_BITS | (right)) + +// Flags access +#define ALP222_CODEC_CTRL_ASRC_MASK GENMASK(0, 0) +#define ALP222_CODEC_CTRL_ASRC_POS 0 + +// MIC Options defs +#define ALP222_MIC_GAIN_L_MASK GENMASK(7,0) +#define ALP222_MIC_GAIN_L_POS 0 +#define ALP222_MIC_GAIN_WIDTH 8 + +#define ALP222_MIC_GAIN_R_MASK GENMASK(15,8) +#define ALP222_MIC_GAIN_R_POS 8 + + +#define ALP222_MIC_DC_L_MASK GENMASK(16,16) +#define ALP222_MIC_DC_L_POS 16 +#define ALP222_MIC_CM_L_MASK GENMASK(17,17) +#define ALP222_MIC_CM_L_POS 17 +#define ALP222_MIC_PH_L_MASK GENMASK(18,18) +#define ALP222_MIC_PH_L_POS 18 + +#define ALP222_MIC_DC_R_MASK GENMASK(19,19) +#define ALP222_MIC_DC_R_POS 19 +#define ALP222_MIC_CM_R_MASK GENMASK(20,20) +#define ALP222_MIC_CM_R_POS 20 +#define ALP222_MIC_PH_R_MASK GENMASK(21,21) +#define ALP222_MIC_PH_R_POS 21 + +#define ALP222_MIC_EN_L_MASK GENMASK(22,22) +#define ALP222_MIC_EN_R_MASK GENMASK(23,23) +#define ALP222_MIC_EN_L_POS 22 +#define ALP222_MIC_EN_R_POS 23 + + +#define ALP222_MIC_HERE_POS 31 + +#endif diff --git a/snd-alpx-dkms/snd-alpx/alpx_streams.c b/snd-alpx-dkms/snd-alpx/alpx_streams.c new file mode 100644 index 0000000..9215752 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/alpx_streams.c @@ -0,0 +1,730 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* +* Support for Digigram AlpX PCI-e boards +* +* Copyright (c) 2024 Digigram Digital (info@digigram.com) +*/ + +#include <linux/version.h> + +#include "alpx_reg.h" +#include "alpx.h" +#include "alpx_streams.h" +#include "alpx_led.h" + +#include <sound/asound.h> +#include <sound/core.h> +#include <linux/io.h> + + +extern unsigned int log_transfers; //defined in alpx_core.c + +#if !IS_ENABLED(CONFIG_SND_DMAENGINE_PCM) + #if defined (CONFIG_KERNEL_GENERIC) + #if KERNEL_VERSION(5, 17, 0) <= LINUX_VERSION_CODE + #include "core/generic/5.17/dmaengine_pcm.h" + #include "core/generic/5.17/pcm_dmaengine.c" + #elif KERNEL_VERSION(5, 12, 0) <= LINUX_VERSION_CODE + #include "core/generic/5.12/dmaengine_pcm.h" + #include "core/generic/5.12/pcm_dmaengine.c" + #elif KERNEL_VERSION(5, 7, 0) <= LINUX_VERSION_CODE + #include "core/generic/5.7/dmaengine_pcm.h" + #include "core/generic/5.7/pcm_dmaengine.c" + #elif KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE + #include "core/generic/5.5/dmaengine_pcm.h" + #include "core/generic/5.5/pcm_dmaengine.c" + #elif KERNEL_VERSION(5, 2, 0) <= LINUX_VERSION_CODE + #include "core/generic/5.2/dmaengine_pcm.h" + #include "core/generic/5.2/pcm_dmaengine.c" + #elif KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + #include "core/generic/4.19/dmaengine_pcm.h" + #include "core/generic/4.19/pcm_dmaengine.c" + #endif + #elif defined (CONFIG_KERNEL_REDHAT) + #if KERNEL_VERSION(5, 14, 0) <= LINUX_VERSION_CODE + #include "core/RedHat/5.14/dmaengine_pcm.h" + #include "core/RedHat/5.14/pcm_dmaengine.c" + #elif KERNEL_VERSION(4, 18, 0) == LINUX_VERSION_CODE + #include "core/RedHat/4.18/dmaengine_pcm.h" + #include "core/RedHat/4.18/pcm_dmaengine.c" + #else + #error RedHat kernel not supported yet. + #endif + #endif +#elif defined (CONFIG_KERNEL_GENERIC) + #include <sound/dmaengine_pcm.h> +#else + #error "No valid DMA Engine support!" +#endif + +/* The size (in bytes) of sample's container */ +const unsigned int ALPX_SAMPLE_CONTAINER_SIZE = 4; + + +/* Configure */ + +static int alpmadi_configure(struct alpx_device *alpx_dev, unsigned int rate) +{ + u32 config_fs, value; + + dev_dbg(alpx_dev->dev, "%s(): requesting rate %d\n", __func__, rate); + + switch (rate) { + case 44100: + config_fs = ALPMADI_CLK_MANAGER_CONFIG_FS_44_1K; + break; + case 48000: + config_fs = ALPMADI_CLK_MANAGER_CONFIG_FS_48K; + break; + case 88200: + config_fs = ALPMADI_CLK_MANAGER_CONFIG_FS_88_2K; + break; + case 96000: + config_fs = ALPMADI_CLK_MANAGER_CONFIG_FS_96K; + break; + case 176400: + config_fs = ALPMADI_CLK_MANAGER_CONFIG_FS_176_4K; + break; + case 192000: + config_fs = ALPMADI_CLK_MANAGER_CONFIG_FS_192K; + break; + default: + return -EINVAL; + } + + value = readl(ALPX_REG(alpx_dev, ALPMADI, CLK_MANAGER, CONFIG)); + dev_dbg(alpx_dev->dev, "%s(): alpMadi clk manager config %x\n", __func__, value); + + value &= ~ALPMADI_CLK_MANAGER_CONFIG_FS_MASK; + value |= config_fs; + + writel(value, ALPX_REG(alpx_dev, ALPMADI, CLK_MANAGER, CONFIG)); + dev_dbg(alpx_dev->dev, "%s(): alpMadi clk manager set to %x\n", __func__, value); + + return 0; +} + +static int alpdante_configure(struct alpx_device *alpx_dev, unsigned int rate) +{ + dev_dbg(alpx_dev->dev, "%s(): requesting rate %dHz\n", __func__, rate); + + if (alpx_dev->variant->capture_hw->rate_min == rate) { + dev_dbg(alpx_dev->dev, "%s(): requested rate %dHz is supported\n", __func__, rate); + return 0; + } + else { + dev_dbg(alpx_dev->dev, "Requested %dHz not supported, Currently supported rate is %dHz\n", rate, + alpx_dev->variant->capture_hw->rate_min); + return -EINVAL; + } + +} + +static int alpstereo_configure(struct alpx_device *alpx_dev, unsigned int rate) +{ + u32 config_fs, read_value, target_value; + u32 try_qty = 10; /* retries */ + + dev_dbg(alpx_dev->dev, "%s(): requesting rate %d\n", __func__, rate); + + switch (rate) { + case 8000: + config_fs = ALPxxx_CLK_MANAGER_CLK_VALUE_8K; + break; + case 11025: + config_fs = ALPxxx_CLK_MANAGER_CLK_VALUE_11_025K; + break; + case 16000: + config_fs = ALPxxx_CLK_MANAGER_CLK_VALUE_16K; + break; + case 22000: + config_fs = ALPxxx_CLK_MANAGER_CLK_VALUE_22_05K; + break; + case 24000: + config_fs = ALPxxx_CLK_MANAGER_CLK_VALUE_24K; + break; + case 32000: + config_fs = ALPxxx_CLK_MANAGER_CLK_VALUE_32K; + break; + case 44100: + config_fs = ALPxxx_CLK_MANAGER_CLK_VALUE_44_1K; + break; + case 48000: + config_fs = ALPxxx_CLK_MANAGER_CLK_VALUE_48K; + break; + case 64000: + config_fs = ALPxxx_CLK_MANAGER_CLK_VALUE_64K; + break; + case 88200: + config_fs = ALPxxx_CLK_MANAGER_CLK_VALUE_88_2K; + break; + case 96000: + config_fs = ALPxxx_CLK_MANAGER_CLK_VALUE_96K; + break; + case 128000: + config_fs = ALPxxx_CLK_MANAGER_CLK_VALUE_128K; + break; + case 176400: + config_fs = ALPxxx_CLK_MANAGER_CLK_VALUE_176_4K; + break; + case 192000: + config_fs = ALPxxx_CLK_MANAGER_CLK_VALUE_192K; + break; + default: + return -EINVAL; + } + + read_value = readl(ALPX_REG(alpx_dev, ALP222, CLK_MANAGER, CONFIG)); + + /* Only if needed */ + if ((read_value & ALP222_CLK_MANAGER_CONFIG_FS_MASK) == config_fs) + return 0; + + read_value &= ~ALP222_CLK_MANAGER_CONFIG_FS_MASK; + target_value = read_value | config_fs; + + do { + writel(target_value, ALPX_REG(alpx_dev, ALP222, CLK_MANAGER, CONFIG)); + dev_dbg(alpx_dev->dev, "%s(): alp222 new clk config set to %x try: %d\n", + __func__, target_value, try_qty); + + /* Add a delay to give time to the card to initialize its + * internals (PLL, buses,...) to avoid internal stalls. + */ + mdelay(1); + + read_value = readl(ALPX_REG(alpx_dev, ALP222, CLK_MANAGER, CONFIG)); + dev_dbg(alpx_dev->dev, "%s(): alp222 check clk config: %x\n", __func__, read_value); + } while (--try_qty && + ((read_value & ALP222_CLK_MANAGER_CONFIG_FS_MASK ) != + (target_value & ALP222_CLK_MANAGER_CONFIG_FS_MASK))); + + if ((read_value & ALP222_CLK_MANAGER_CONFIG_FS_MASK) != + (target_value & ALP222_CLK_MANAGER_CONFIG_FS_MASK)) + dev_err(alpx_dev->dev, "%s(): alp222 ERROR clk config, expected: 0x%x, actual: 0x%x, \n", __func__, + target_value, read_value); + + dev_dbg(alpx_dev->dev, "%s(): alp222 new current clk config: 0x%x\n", __func__, + readl(ALPX_REG(alpx_dev, ALP222, CLK_MANAGER, CONFIG))); + + return (read_value & ALP222_CLK_MANAGER_CONFIG_FS_MASK) == + (target_value & ALP222_CLK_MANAGER_CONFIG_FS_MASK) ? 0 : -EIO; +} + +static int alpmultichannel_configure(struct alpx_device *alpx_dev, unsigned int rate) +{ + u32 config_fs, value; + u32 effective_fs, source; + /* XXX: check clock source, if not internal, error out if rate is not + external one */ + dev_dbg(alpx_dev->dev, "%s(): requesting rate %d\n", __func__, rate); + + value = readl(ALPX_REG(alpx_dev, ALPMC, CLK_MANAGER, CONFIG)); + + + + source = ALPMC_CLK_MANAGER_SOURCE(value); + effective_fs = ALPMC_CLK_MANAGER_EFFECTIVE_FS(value); + + switch (rate) { + case 8000: + config_fs = ALPxxx_CLK_MANAGER_CLK_VALUE_8K; + break; + case 11025: + config_fs = ALPxxx_CLK_MANAGER_CLK_VALUE_11_025K; + break; + case 16000: + config_fs = ALPxxx_CLK_MANAGER_CLK_VALUE_16K; + break; + case 22050: + config_fs = ALPxxx_CLK_MANAGER_CLK_VALUE_22_05K; + break; + case 24000: + config_fs = ALPxxx_CLK_MANAGER_CLK_VALUE_24K; + break; + case 32000: + config_fs = ALPxxx_CLK_MANAGER_CLK_VALUE_32K; + break; + case 44100: + config_fs = ALPxxx_CLK_MANAGER_CLK_VALUE_44_1K; + break; + case 48000: + config_fs = ALPxxx_CLK_MANAGER_CLK_VALUE_48K; + break; + case 64000: + config_fs = ALPxxx_CLK_MANAGER_CLK_VALUE_64K; + break; + case 88200: + config_fs = ALPxxx_CLK_MANAGER_CLK_VALUE_88_2K; + break; + case 96000: + config_fs = ALPxxx_CLK_MANAGER_CLK_VALUE_96K; + break; + case 128000: + config_fs = ALPxxx_CLK_MANAGER_CLK_VALUE_128K; + break; + case 176400: + config_fs = ALPxxx_CLK_MANAGER_CLK_VALUE_176_4K; + break; + case 192000: + config_fs = ALPxxx_CLK_MANAGER_CLK_VALUE_192K; + break; + default: + return -EINVAL; + } + + if (source != ALPMC_CLK_MANAGER_SOURCE_INTERNAL) { + unsigned int effective_rate; + + switch(effective_fs) { + case ALPxxx_CLK_MANAGER_CLK_VALUE_8K : + effective_rate = 8000; + break; + case ALPxxx_CLK_MANAGER_CLK_VALUE_11_025K : + effective_rate = 11025; + break; + case ALPxxx_CLK_MANAGER_CLK_VALUE_16K : + effective_rate = 16000; + break; + case ALPxxx_CLK_MANAGER_CLK_VALUE_22_05K : + effective_rate = 22050; + break; + case ALPxxx_CLK_MANAGER_CLK_VALUE_24K : + effective_rate = 24000; + break; + case ALPxxx_CLK_MANAGER_CLK_VALUE_32K: + effective_rate = 32000; + break; + case ALPxxx_CLK_MANAGER_CLK_VALUE_44_1K: + effective_rate = 44100; + break; + case ALPxxx_CLK_MANAGER_CLK_VALUE_48K : + effective_rate = 48000; + break; + case ALPxxx_CLK_MANAGER_CLK_VALUE_64K : + effective_rate = 64000; + break; + case ALPxxx_CLK_MANAGER_CLK_VALUE_88_2K : + effective_rate = 88200; + break; + case ALPxxx_CLK_MANAGER_CLK_VALUE_96K : + effective_rate = 96000; + break; + case ALPxxx_CLK_MANAGER_CLK_VALUE_128K : + effective_rate = 128000; + break; + case ALPxxx_CLK_MANAGER_CLK_VALUE_176_4K : + effective_rate = 176400; + break; + case ALPxxx_CLK_MANAGER_CLK_VALUE_192K : + effective_rate = 192000; + break; + default : + dev_err(alpx_dev->dev, + "Invalid effective sample rate\n"); + return -EINVAL; + }; + + if (effective_rate != rate) { + dev_err(alpx_dev->dev, + "Requested sample rate (%u) does not match external clock sample rate (%u)\n", + rate, effective_rate); + return -EINVAL; + } + } else { + if (ALPMC_CLK_MANAGER_CONFIG_FS(value) != config_fs) { + + value &= ~ALPMC_CLK_MANAGER_CONFIG_FS_MASK; + value |= config_fs; + + writel(value, ALPX_REG(alpx_dev, ALPMC, CLK_MANAGER, CONFIG)); + //Add a delay to give time to the card (PLL, internal buses,...), w/o, the setting is not effective ! + mdelay(ALPMC_FS_SWITCH_DELAY); + } + } + + dev_dbg(alpx_dev->dev, "%s() : %s new current clk config: 0x%x\n", __func__, + alpx_dev->variant->shortname, + readl(ALPX_REG(alpx_dev, ALPMC, CLK_MANAGER, CONFIG))); + + return 0; +} + +static int alpx_configure(struct alpx_device *alpx_dev, unsigned int rate) +{ + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&alpx_dev->config.lock, flags); + + if (alpx_dev->config.users > 0 && rate != alpx_dev->config.rate) { + ret = -EINVAL; + goto complete; + } + + alpx_dev->config.rate = rate; + + if (alpx_is_882(alpx_dev)) + ret = alpmultichannel_configure(alpx_dev, rate); + else if (alpx_is_222(alpx_dev)) + ret = alpstereo_configure(alpx_dev, rate); + else if (alpx_is_madi(alpx_dev)) + ret = alpmadi_configure(alpx_dev, rate); + else if (alpx_is_dante(alpx_dev)) + ret = alpdante_configure(alpx_dev, rate); + else + snd_BUG(); + + if (!ret) + alpx_dev->config.users++; + +complete: + spin_unlock_irqrestore(&alpx_dev->config.lock, flags); + + return ret; +} + +static void alpx_configure_close(struct alpx_device *alpx_dev) +{ + unsigned long flags; + + spin_lock_irqsave(&alpx_dev->config.lock, flags); + + alpx_dev->config.users--; + + spin_unlock_irqrestore(&alpx_dev->config.lock, flags); +} + +/* Pipe */ + +static int alpx_pipe_start(struct alpx_pipe *pipe, struct snd_pcm_substream *substream) +{ + struct alpx_device *alpx_dev = snd_pcm_substream_chip(substream); + + dev_dbg( alpx_dev->dev, "%s starting\n", pipe->xdma_write ? "Playback" : "Capture"); + + if (pipe->status != ALPX_PIPE_STATUS_IDLE && + pipe->status != ALPX_PIPE_STATUS_STOPPED) { + dev_warn(alpx_dev->dev, "%s pipe is busy!\n", + pipe->xdma_write ? "playback" : "capture"); + return -EBUSY; + } + + if (alpx_is_madi(alpx_dev)) + alpmadi_set_led_state(alpx_dev, true); + + snd_dmaengine_pcm_trigger(substream, SNDRV_PCM_TRIGGER_START); + pipe->period_qty_on_start = alpx_get_samples_counter(alpx_dev); + + dev_dbg( alpx_dev->dev, "%s Period:%u\n", pipe->xdma_write ? "Playback" : "Capture", pipe->period_qty_on_start); + + return 0; +} + +static int alpx_pipe_open(struct alpx_pipe *pipe, + struct snd_pcm_substream *substream) +{ + struct alpx_device *alpx_dev = substream->pcm->private_data; + struct dma_chan *chan; + + /* Check */ + if (!alpx_dev) { + printk(KERN_ERR"%s() : alpx_dev is NULL\n",__func__); + return -EINVAL; + } + + if (!alpx_dev->dev) { + printk(KERN_ERR"%s() : alpx_dev->dev is NULL\n",__func__); + return -EINVAL; + } + + dev_dbg(alpx_dev->dev, "%s(): CALLED\n", __func__); + + dev_dbg(alpx_dev->dev, "%s: matching with dev [%s]\n", __func__, dev_name(alpx_dev->dev)); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + chan = dma_request_chan(alpx_dev->dev, "h2c-0"); + else + chan = dma_request_chan(alpx_dev->dev, "c2h-0"); + + if (IS_ERR(chan)) { + dev_err(alpx_dev->dev, "%s() : Error %ld when requesting DMA channel\n", + __func__, PTR_ERR(chan)); + return PTR_ERR(chan); + } + + pipe->substream = substream; + + return snd_dmaengine_pcm_open(substream, chan); + +} + +static int alpx_pipe_stop(struct alpx_pipe *pipe, struct snd_pcm_substream *substream) +{ + struct alpx_device *alpx_dev = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + unsigned int samples_counter, card_samples_qty; + + /* Retrieve the samples counter as soon as possible */ + samples_counter = alpx_get_samples_counter(alpx_dev); + snd_dmaengine_pcm_trigger(substream, SNDRV_PCM_TRIGGER_STOP); + + if (alpx_is_madi(alpx_dev)) + alpmadi_set_led_state(alpx_dev, false); + + /* + * Since we are under stream lock here and the transfer done callback + * also needs to grab stream lock, we cannot have a sync wait for the + * completion. As a result, we request a stop with the stopping status. + */ + card_samples_qty = samples_counter - pipe->period_qty_on_start; + dev_dbg(alpx_dev->dev, "%s stopped after %u samples (%u bytes)\n", + pipe->xdma_write ? "Playback" : "Capture", card_samples_qty, + runtime->hw.channels_max * ALPX_SAMPLE_CONTAINER_SIZE * card_samples_qty); + + if (pipe->status == ALPX_PIPE_STATUS_RUNNING) + pipe->status = ALPX_PIPE_STATUS_STOPPING; + else + pipe->status = ALPX_PIPE_STATUS_STOPPED; + + return 0; +} + +static int alpx_pipe_configure(struct alpx_pipe *pipe, + struct snd_pcm_hw_params *hw_params) +{ + struct alpx_device *alpx_dev = pipe->substream->pcm->private_data; + unsigned int rate = params_rate(hw_params); + int ret; + + dev_dbg(alpx_dev->dev, "%s hardware parameters:\n", + pipe->substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? "Playback" : "Capture"); + dev_dbg(alpx_dev->dev, "* channels: %d\n", params_channels(hw_params)); + dev_dbg(alpx_dev->dev, "* rate: %d\n", params_rate(hw_params)); + dev_dbg(alpx_dev->dev, "* periods: %d\n", params_periods(hw_params)); + dev_dbg(alpx_dev->dev, "* period size: %d frames\n", + params_period_size(hw_params)); + dev_dbg(alpx_dev->dev, "* period bytes: %d bytes\n", + params_period_size(hw_params) * params_channels(hw_params) * 4); + dev_dbg(alpx_dev->dev, "* buffer size: %d frames\n", + params_buffer_size(hw_params)); + dev_dbg(alpx_dev->dev, "* buffer bytes: %d bytes\n", + params_buffer_bytes(hw_params)); + + ret = alpx_configure(alpx_dev, rate); + if (ret) + return ret; + + pipe->configured = true; + + return 0; +} + +static void alpx_pipe_close(struct alpx_pipe *pipe) +{ + struct alpx_device *alpx_dev = pipe->substream->pcm->private_data; + + dev_dbg(alpx_dev->dev, "%s(): CALLED\n", __func__); + + snd_dmaengine_pcm_close_release_chan(pipe->substream); + + if (pipe->configured) { + alpx_configure_close(alpx_dev); + pipe->configured = false; + } +} + +int alpx_pipe_init(struct alpx_pipe *pipe, bool xdma_write) +{ + pipe->xdma_write = xdma_write; + + pipe->status = ALPX_PIPE_STATUS_IDLE; + + return 0; +} + +/* Playback */ + +int alpx_playback_open(struct snd_pcm_substream *substream) +{ + struct alpx_device *alpx_dev = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + int ret; + + //Add a break to avoid playback lock when chaining playbacks. This is required for AlpDANTE cards. Looks like the XDMA needs some time here. + msleep(200); + + dev_dbg(alpx_dev->dev, "CALLED\n"); + + ret = alpx_pipe_open(&alpx_dev->playback, substream); + if (!ret) + runtime->hw = *alpx_dev->variant->playback_hw; + + dev_dbg(alpx_dev->dev, "=> %u\n", ret); + return ret; +} + +int alpx_playback_close(struct snd_pcm_substream *substream) +{ + struct alpx_device *alpx_dev = snd_pcm_substream_chip(substream); + + alpx_pipe_close(&alpx_dev->playback); + return 0; +} + +int alpx_playback_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) +{ + struct alpx_device *alpx_dev = snd_pcm_substream_chip(substream); + int ret; + + ret = alpx_pipe_configure(&alpx_dev->playback, hw_params); + if (ret) + return ret; + +#if KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE + return 0; +#else + return snd_pcm_lib_malloc_pages(substream, + params_buffer_bytes(hw_params)); +#endif +} + +int alpx_playback_hw_free(struct snd_pcm_substream *substream) +{ + +#if KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE + return 0; +#else + return snd_pcm_lib_free_pages(substream); +#endif +} + +int alpx_playback_prepare(struct snd_pcm_substream *substream) +{ + return 0; +} + +int alpx_playback_trigger(struct snd_pcm_substream *substream, + int command) +{ + struct alpx_device *alpx_dev = snd_pcm_substream_chip(substream); + + dev_dbg(alpx_dev->dev, "CALLED\n"); + + switch (command) { + case SNDRV_PCM_TRIGGER_START: + alpx_pipe_start(&alpx_dev->playback, substream); + break; + case SNDRV_PCM_TRIGGER_STOP: + alpx_pipe_stop(&alpx_dev->playback, substream); + break; + default: + return -EINVAL; + } + + return 0; +} + +const struct snd_pcm_ops alpx_playback_ops = { + .open = alpx_playback_open, + .close = alpx_playback_close, +#if KERNEL_VERSION(5, 6, 0) > LINUX_VERSION_CODE + .ioctl = snd_pcm_lib_ioctl, +#endif + .hw_params = alpx_playback_hw_params, + .hw_free = alpx_playback_hw_free, + .prepare = alpx_playback_prepare, + .trigger = alpx_playback_trigger, + .pointer = snd_dmaengine_pcm_pointer, +}; + +/* Capture */ + +int alpx_capture_open(struct snd_pcm_substream *substream) +{ + struct alpx_device *alpx_dev = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + int ret; + + ret = alpx_pipe_open(&alpx_dev->capture, substream); + if (ret) + return ret; + + runtime->hw = *alpx_dev->variant->capture_hw; + + return 0; +} + +int alpx_capture_close(struct snd_pcm_substream *substream) +{ + struct alpx_device *alpx_dev = snd_pcm_substream_chip(substream); + + alpx_pipe_close(&alpx_dev->capture); + + return 0; +} + +int alpx_capture_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) +{ + struct alpx_device *alpx_dev = snd_pcm_substream_chip(substream); + int ret; + + ret = alpx_pipe_configure(&alpx_dev->capture, hw_params); + if (ret) + return ret; + +#if KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE + return 0; +#else + return snd_pcm_lib_malloc_pages(substream, + params_buffer_bytes(hw_params)); +#endif +} + +int alpx_capture_hw_free(struct snd_pcm_substream *substream) +{ +#if KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE + return 0; +#else + return snd_pcm_lib_free_pages(substream); +#endif +} + +int alpx_capture_prepare(struct snd_pcm_substream *substream) +{ + return 0; +} + +int alpx_capture_trigger(struct snd_pcm_substream *substream, + int command) +{ + struct alpx_device *alpx_dev = snd_pcm_substream_chip(substream); + + switch (command) { + case SNDRV_PCM_TRIGGER_START: + alpx_pipe_start(&alpx_dev->capture, substream); + break; + case SNDRV_PCM_TRIGGER_STOP: + alpx_pipe_stop(&alpx_dev->capture, substream); + break; + default: + return -EINVAL; + } + + return 0; +} + +const struct snd_pcm_ops alpx_capture_ops = { + .open = alpx_capture_open, + .close = alpx_capture_close, +#if KERNEL_VERSION(5, 6, 0) > LINUX_VERSION_CODE + .ioctl = snd_pcm_lib_ioctl, +#endif + .hw_params = alpx_capture_hw_params, + .hw_free = alpx_capture_hw_free, + .prepare = alpx_capture_prepare, + .trigger = alpx_capture_trigger, + .pointer = snd_dmaengine_pcm_pointer, +}; diff --git a/snd-alpx-dkms/snd-alpx/alpx_streams.h b/snd-alpx-dkms/snd-alpx/alpx_streams.h new file mode 100644 index 0000000..bb33554 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/alpx_streams.h @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* +* Support for Digigram AlpX PCI-e boards +* +* Copyright (c) 2024 Digigram Digital (info@digigram.com) +*/ +#ifndef _ALPX_STREAMS_EDF_H +#define _ALPX_STREAMS_EDF_H + +#include <sound/pcm.h> + +/* Structures */ + +enum alpx_pipe_status { + ALPX_PIPE_STATUS_IDLE = 0, + ALPX_PIPE_STATUS_RUNNING, + ALPX_PIPE_STATUS_STOPPING, + ALPX_PIPE_STATUS_STOPPED, +}; + +struct alpx_pipe { + u32 period_qty_on_start; /* 2^64-1 periods @ 192kHZ = 2M years ! , u32 => 0.2year , enough to debug*/ + struct snd_pcm_substream *substream; + + enum alpx_pipe_status status; + bool configured; + bool xdma_write; +}; + + +/* Pipe */ + +int alpx_pipe_init(struct alpx_pipe *pipe, bool xdma_write); + +/* Playback */ +extern const struct snd_pcm_ops alpx_playback_ops; + +int alpx_playback_open(struct snd_pcm_substream *substream); +int alpx_playback_close(struct snd_pcm_substream *substream); +int alpx_playback_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params); +int alpx_playback_hw_free(struct snd_pcm_substream *substream); +int alpx_playback_prepare(struct snd_pcm_substream *substream); +int alpx_playback_trigger(struct snd_pcm_substream *substream, + int command); +snd_pcm_uframes_t alpx_playback_pointer(struct snd_pcm_substream *substream); + +/* Capture */ + +extern const struct snd_pcm_ops alpx_capture_ops; + + +int alpx_capture_open(struct snd_pcm_substream *substream); +int alpx_capture_close(struct snd_pcm_substream *substream); +int alpx_capture_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params); +int alpx_capture_hw_free(struct snd_pcm_substream *substream); +int alpx_capture_prepare(struct snd_pcm_substream *substream); +int alpx_capture_trigger(struct snd_pcm_substream *substream, + int command); + +#endif diff --git a/snd-alpx-dkms/snd-alpx/alpx_variants_882_apps_preFW240.h b/snd-alpx-dkms/snd-alpx/alpx_variants_882_apps_preFW240.h new file mode 100644 index 0000000..713a3a4 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/alpx_variants_882_apps_preFW240.h @@ -0,0 +1,827 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* +* Support for Digigram AlpX PCI-e boards +* +* Copyright (c) 2024 Digigram Digital (info@digigram.com) +*/ + +#ifndef _ALPX_VARIANTS_882_APP_PREFW240H_ +#define _ALPX_VARIANTS_882_APP_PREFW240H_ + +#include "alpx.h" +#include "alpx_reg.h" + +#include <sound/tlv.h> +#include "alpx_variants_common.h" + + +/* 882 ONLY !!*/ +/* Alp882 Commons */ +/** Pre FW V240 for compatibility with OLD applications Translation tables FOR CLOCK sources !!*/ +static const char *alp882_app_preFW240_control_choice_clk_src_entries[ALP882_APP_PREFW240_CLK_MANAGER_CLK_SRC_QTY] = { + "Word Clk", + "AES Syn", + "AES Aud 1/2", + "AES Aud 3/4", + "AES Aud 5/6", + "AES Aud 7/8", + "Internal", +}; + +/* Index is application side index, items is the register ones*/ +static u32 alp882_app_preFW240_control_choice_clk_src_entries_values[ALP882_APP_PREFW240_CLK_MANAGER_CLK_SRC_QTY] = { + ALPMC_CLK_MANAGER_SOURCE_WCLK_IN, + ALPMC_CLK_MANAGER_SOURCE_AES_SYNC, + ALPMC_CLK_MANAGER_SOURCE_AES_AUDIO_12, + ALPMC_CLK_MANAGER_SOURCE_AES_AUDIO_34, + ALPMC_CLK_MANAGER_SOURCE_AES_AUDIO_56, + ALPMC_CLK_MANAGER_SOURCE_AES_AUDIO_78, + ALPMC_CLK_MANAGER_SOURCE_INTERNAL, +}; + +/* Indexed by the register => application side value */ +static u32 alp882_app_preFW240_to_apps_control_choice_clk_src_entries_values [ALP882_CLK_MANAGER_CONFIG_CLK_SRC_QTY] = { + ALP882_APP_PREFW240_CLK_MANAGER_SOURCE_INTERNAL, + ALP882_APP_PREFW240_CLK_MANAGER_SOURCE_INTERNAL, /* FORBIDDEN VALUE => INTERNAL !!*/ + ALP882_APP_PREFW240_CLK_MANAGER_SOURCE_WCLK_IN, + ALP882_APP_PREFW240_CLK_MANAGER_SOURCE_AES_SYNC, + ALP882_APP_PREFW240_CLK_MANAGER_SOURCE_AES_AUDIO_12, + ALP882_APP_PREFW240_CLK_MANAGER_SOURCE_AES_AUDIO_34, + ALP882_APP_PREFW240_CLK_MANAGER_SOURCE_AES_AUDIO_56, + ALP882_APP_PREFW240_CLK_MANAGER_SOURCE_AES_AUDIO_78, +}; + + +static struct snd_pcm_hardware alp882_app_preFW240_hardware_specs = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_RESUME, + .formats = SNDRV_PCM_FMTBIT_S32_LE, + .rates = SNDRV_PCM_RATE_CONTINUOUS | + SNDRV_PCM_RATE_8000_192000, + .rate_min = 8000, + .rate_max = 192000, + .channels_min = 16, + .channels_max = 16, + .buffer_bytes_max = 256 * SZ_1K * 4, /* period_bytes_max * periods_max */ + .period_bytes_min = 48, /* min latency 1ms */ + .period_bytes_max = 256 * SZ_1K, /* 20ms at 192kHz * nchans * 4B, rounded at 2^n */ + .periods_min = 1, + .periods_max = 4, +}; + + +/* Alp 882 LINE Variant definition */ + +static const DECLARE_TLV_DB_MINMAX_MUTE(alp882_app_preFW240_line_control_codec_gains_scale, ALPMC_LINE_ANALOG_GAIN_MIN_cdB, ALPMC_LINE_ANALOG_GAIN_MAX_cdB); + +static struct alpx_control_descriptor alp882_app_preFW240_line_control_descriptors[] = { + /* Gain */ + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALPMC_AMPLI_IN_BASE + + ALPMC_GAIN_TABLE_BASE(ALP882_CHANNELS_IN_DAW_OFFSET), + .prefix = "DAW Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP882_CHANNELS_DAW_COUNT, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALPMC_AMPLI_IN_BASE + + ALPMC_GAIN_TABLE_BASE(ALP882_CHANNELS_IN_ANALOG_OFFSET), + .prefix = "Ana Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP882_CHANNELS_ANALOG_COUNT, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALPMC_AMPLI_IN_BASE + + ALPMC_GAIN_TABLE_BASE(ALP882_CHANNELS_IN_AES_OFFSET), + .prefix = "AES Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP882_CHANNELS_AES_COUNT, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALPMC_AMPLI_OUT_BASE + + ALPMC_GAIN_TABLE_BASE(ALP882_CHANNELS_OUT_ANALOG_OFFSET), + .prefix = "Ana Playback", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP882_CHANNELS_ANALOG_COUNT, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALPMC_AMPLI_OUT_BASE + + ALPMC_GAIN_TABLE_BASE(ALP882_CHANNELS_OUT_AES_OFFSET), + .prefix = "AES Playback", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP882_CHANNELS_AES_COUNT, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALPMC_AMPLI_OUT_BASE + + ALPMC_GAIN_TABLE_BASE(ALP882_CHANNELS_OUT_DAW_OFFSET), + .prefix = "DAW Playback", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP882_CHANNELS_DAW_COUNT, + }, + }, + /* Mixer */ + { + .type = ALPX_CONTROL_TYPE_MIXER, + .base = ALPMC_MIXER_BASE, + .prefix = "Mxr", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.mixer = { + .lines_count = ALP882_MIXER_SIZE, + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + }, + }, + /* Clock sources Read Only */ + { + .type = ALPX_CONTROL_TYPE_TRANSLATED_CHOICE, + .base = ALPMC_CLK_MANAGER_BASE, + .prefix = "Clk Eff Src", + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .data.translated_choice = { + .offset = ALPMC_CLK_MANAGER_CONFIG_REG, + .mask = ALPMC_CLK_MANAGER_CONFIG_CLK_SRC_MASK, + .pos = ALPMC_CLK_MANAGER_CONFIG_CLK_SRC_POS, + .entries = alp882_app_preFW240_control_choice_clk_src_entries, + .entries_values = alp882_app_preFW240_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp882_app_preFW240_control_choice_clk_src_entries), + .card_entries_values = alp882_app_preFW240_to_apps_control_choice_clk_src_entries_values, + .card_entries_count = ARRAY_SIZE(alp882_app_preFW240_to_apps_control_choice_clk_src_entries_values) + }, + }, + /* Current Clock BASE Value Read Only */ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALPMC_CLK_MANAGER_BASE, + .prefix = "Clk Eff", + .access = SNDRV_CTL_ELEM_ACCESS_READ | + SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .data.choice = { + .offset = ALPMC_CLK_MANAGER_CONFIG_REG, + .mask = ALPMC_CLK_MANAGER_CONFIG_CLK_CURRENT_VALUE_MASK, + .pos = ALPMC_CLK_MANAGER_CONFIG_CLK_CURRENT_VALUE_POS, + .entries = alpxxx_control_choice_current_clk_values_entries, + .entries_values = alpxxx_control_choice_current_clk_values_entries_values, + .entries_count = ARRAY_SIZE(alpxxx_control_choice_current_clk_values_entries), + }, + }, + + /* Current Clock factor values Read Only, RESERVED to keep Ids order */ + { + .type = ALPX_CONTROL_RESERVED, + .base = ALPMC_CLK_MANAGER_BASE, + .prefix = "RESERVED", + .access = SNDRV_CTL_ELEM_ACCESS_READ, + }, + /* Clock UP on fail over enabled flag */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALP_PROC_BASE, + .prefix = "Clk Src Up", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALP_PROC_FWCONFIG_REG, + .mask = ALP_PROC_FWCONFIG_CLKSRC_UP_MASK, + .pos = ALP_PROC_FWCONFIG_CLKSRC_UP_POS, + }, + }, + /* Clock DOWN on fail over enabled flag */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALP_PROC_BASE, + .prefix = "Clk Src Down", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALP_PROC_FWCONFIG_REG, + .mask = ALP_PROC_FWCONFIG_CLKSRC_DOWN_MASK, + .pos = ALP_PROC_FWCONFIG_CLKSRC_DOWN_POS, + }, + }, + /* Clock Failover priority 0 TOP*/ + { + .type = ALPX_CONTROL_TYPE_TRANSLATED_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P0", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.translated_choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO0_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO0_POS, + .entries = alp882_app_preFW240_control_choice_clk_src_entries, + .entries_values = alp882_app_preFW240_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp882_app_preFW240_control_choice_clk_src_entries), + .card_entries_values = alp882_app_preFW240_to_apps_control_choice_clk_src_entries_values, + .card_entries_count = ARRAY_SIZE(alp882_app_preFW240_to_apps_control_choice_clk_src_entries_values) + }, + }, + /* Clock Failover priority 1 */ + { + .type = ALPX_CONTROL_TYPE_TRANSLATED_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P1", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.translated_choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO1_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO1_POS, + .entries = alp882_app_preFW240_control_choice_clk_src_entries, + .entries_values = alp882_app_preFW240_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp882_app_preFW240_control_choice_clk_src_entries), + .card_entries_values = alp882_app_preFW240_to_apps_control_choice_clk_src_entries_values, + .card_entries_count = ARRAY_SIZE(alp882_app_preFW240_to_apps_control_choice_clk_src_entries_values) + }, + }, + /* Clock Failover priority 2*/ + { + .type = ALPX_CONTROL_TYPE_TRANSLATED_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P2", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.translated_choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO2_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO2_POS, + .entries = alp882_app_preFW240_control_choice_clk_src_entries, + .entries_values = alp882_app_preFW240_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp882_app_preFW240_control_choice_clk_src_entries), + .card_entries_values = alp882_app_preFW240_to_apps_control_choice_clk_src_entries_values, + .card_entries_count = ARRAY_SIZE(alp882_app_preFW240_to_apps_control_choice_clk_src_entries_values) + }, + }, + /* Clock Failover priority 3*/ + { + .type = ALPX_CONTROL_TYPE_TRANSLATED_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P3", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.translated_choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO3_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO3_POS, + .entries = alp882_app_preFW240_control_choice_clk_src_entries, + .entries_values = alp882_app_preFW240_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp882_app_preFW240_control_choice_clk_src_entries), + .card_entries_values = alp882_app_preFW240_to_apps_control_choice_clk_src_entries_values, + .card_entries_count = ARRAY_SIZE(alp882_app_preFW240_to_apps_control_choice_clk_src_entries_values) + }, + }, + /* Auto AES SRC disable */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "AES SRC 1/2 Disable", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALPMC_CODEC_AES_SRC_CONTROL_REG, + .mask = ALPMC_CODEC_AES_SRC_1_2_MASK, + .pos = ALPMC_CODEC_AES_SRC_1_2_POS, + }, + }, + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "AES SRC 3/4 Disable", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALPMC_CODEC_AES_SRC_CONTROL_REG, + .mask = ALPMC_CODEC_AES_SRC_3_4_MASK, + .pos = ALPMC_CODEC_AES_SRC_3_4_POS, + }, + }, + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "AES SRC 5/6 Disable", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALPMC_CODEC_AES_SRC_CONTROL_REG, + .mask = ALPMC_CODEC_AES_SRC_5_6_MASK, + .pos = ALPMC_CODEC_AES_SRC_5_6_POS, + }, + }, + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "AES SRC 7/8 Disable", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALPMC_CODEC_AES_SRC_CONTROL_REG, + .mask = ALPMC_CODEC_AES_SRC_7_8_MASK, + .pos = ALPMC_CODEC_AES_SRC_7_8_POS, + }, + }, + /* Codec Input Gain for LINE Option*/ + { + .type = ALPX_CONTROL_TYPE_ANALOG_EQ, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "Codec Analog Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.codec = { + .offset = ALPMC_CODEC_PGA_REGS, + .gains_scale = alp882_app_preFW240_line_control_codec_gains_scale, + .reg_gain_min = ALPMC_LINE_ANALOG_GAIN_MIN_REG, + .reg_gain_max = ALPMC_LINE_ANALOG_GAIN_MAX_REG, + .lines_count = 8, + }, + }, +}; + +static struct alpx_variant alp882_app_preFW240_line_variant __attribute__((unused)) = { + .shortname = "Alp882e", + .longname = "Alp 882e", + .model = ALPX_VARIANT_MODEL_ALP882, + .mixername = "Alp882e_Mix", + .features = ALPX_VARIANT_FEATURE_GPIOS, + .control_descriptors = alp882_app_preFW240_line_control_descriptors, + .control_descriptors_count = ARRAY_SIZE(alp882_app_preFW240_line_control_descriptors), + + .capture_hw = &alp882_app_preFW240_hardware_specs, + .playback_hw = &alp882_app_preFW240_hardware_specs, + + .flash_golden_production_base = ALPxxx_FLASH_GOLDEN_PRODUCTION_BASE, + + .gpios = { + .base = ALPMC_GPIO_BASE, + .inputs_reg_offset = ALPMC_GPIO_INPUT_REG, + .inputs_qty = ALPMC_GPIO_INPUT_QTY, + .outputs_reg_offset = ALPMC_GPIO_OUTPUT_REG, + .outputs_qty = ALPMC_GPIO_OUTPUT_QTY, + }, + + .flash_partitions.partitions = alpx_mtd_partitions, + .flash_partitions.qty = ARRAY_SIZE(alpx_mtd_partitions), + .flash_partitions.qty_for_fw_update = 1, +}; + + +/* Alp 882 - MIC App preFW240 Variant definition */ + +static const DECLARE_TLV_DB_MINMAX_MUTE(alp882_app_preFW240_mic_control_codec_gains_scale, ALPMC_MIC_ANALOG_GAIN_MIN_cdB, ALPMC_MIC_ANALOG_GAIN_MAX_cdB); + +static struct alpx_control_descriptor alp882_app_preFW240_mic_control_descriptors[] = { + /* Gain */ + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALPMC_AMPLI_IN_BASE + + ALPMC_GAIN_TABLE_BASE(ALP882_CHANNELS_IN_DAW_OFFSET), + .prefix = "DAW Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP882_CHANNELS_DAW_COUNT, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALPMC_AMPLI_IN_BASE + + ALPMC_GAIN_TABLE_BASE(ALP882_CHANNELS_IN_ANALOG_OFFSET), + .prefix = "Ana Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP882_CHANNELS_ANALOG_COUNT, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALPMC_AMPLI_IN_BASE + + ALPMC_GAIN_TABLE_BASE(ALP882_CHANNELS_IN_AES_OFFSET), + .prefix = "AES Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP882_CHANNELS_AES_COUNT, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALPMC_AMPLI_OUT_BASE + + ALPMC_GAIN_TABLE_BASE(ALP882_CHANNELS_OUT_ANALOG_OFFSET), + .prefix = "Ana Playback", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP882_CHANNELS_ANALOG_COUNT, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALPMC_AMPLI_OUT_BASE + + ALPMC_GAIN_TABLE_BASE(ALP882_CHANNELS_OUT_AES_OFFSET), + .prefix = "AES Playback", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP882_CHANNELS_AES_COUNT, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALPMC_AMPLI_OUT_BASE + + ALPMC_GAIN_TABLE_BASE(ALP882_CHANNELS_OUT_DAW_OFFSET), + .prefix = "DAW Playback", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP882_CHANNELS_DAW_COUNT, + }, + }, + /* Mixer */ + { + .type = ALPX_CONTROL_TYPE_MIXER, + .base = ALPMC_MIXER_BASE, + .prefix = "Mxr", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.mixer = { + .lines_count = ALP882_MIXER_SIZE, + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + }, + }, + /* Clock sources Read Only */ + { + .type = ALPX_CONTROL_TYPE_TRANSLATED_CHOICE, + .base = ALPMC_CLK_MANAGER_BASE, + .prefix = "Clk Eff Src", + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .data.translated_choice= { + .offset = ALPMC_CLK_MANAGER_CONFIG_REG, + .mask = ALPMC_CLK_MANAGER_CONFIG_CLK_SRC_MASK, + .pos = ALPMC_CLK_MANAGER_CONFIG_CLK_SRC_POS, + .entries = alp882_app_preFW240_control_choice_clk_src_entries, + .entries_values = alp882_app_preFW240_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp882_app_preFW240_control_choice_clk_src_entries), + .card_entries_values = alp882_app_preFW240_to_apps_control_choice_clk_src_entries_values, + .card_entries_count = ARRAY_SIZE(alp882_app_preFW240_to_apps_control_choice_clk_src_entries_values) + }, + }, + /* Current Clock BASE Value Read Only */ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALPMC_CLK_MANAGER_BASE, + .prefix = "Clk Eff", + .access = SNDRV_CTL_ELEM_ACCESS_READ | + SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .data.choice = { + .offset = ALPMC_CLK_MANAGER_CONFIG_REG, + .mask = ALPMC_CLK_MANAGER_CONFIG_CLK_CURRENT_VALUE_MASK, + .pos = ALPMC_CLK_MANAGER_CONFIG_CLK_CURRENT_VALUE_POS, + .entries = alpxxx_control_choice_current_clk_values_entries, + .entries_values = alpxxx_control_choice_current_clk_values_entries_values, + .entries_count = ARRAY_SIZE(alpxxx_control_choice_current_clk_values_entries), + }, + }, + + /* Current Clock factor values Read Only, RESERVED now to keep ids order */ + { + .type = ALPX_CONTROL_RESERVED, + .base = ALPMC_CLK_MANAGER_BASE, + .prefix = "RESERVED", + .access = SNDRV_CTL_ELEM_ACCESS_READ, + }, + /* Clock UP on fail over enabled flag */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALP_PROC_BASE, + .prefix = "Clk Src Up", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALP_PROC_FWCONFIG_REG, + .mask = ALP_PROC_FWCONFIG_CLKSRC_UP_MASK, + .pos = ALP_PROC_FWCONFIG_CLKSRC_UP_POS, + }, + }, + /* Clock DOWN on fail over enabled flag */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALP_PROC_BASE, + .prefix = "Clk Src Down", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALP_PROC_FWCONFIG_REG, + .mask = ALP_PROC_FWCONFIG_CLKSRC_DOWN_MASK, + .pos = ALP_PROC_FWCONFIG_CLKSRC_DOWN_POS, + }, + }, + /* Clock Failover priority 0 TOP*/ + { + .type = ALPX_CONTROL_TYPE_TRANSLATED_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P0", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.translated_choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO0_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO0_POS, + .entries = alp882_app_preFW240_control_choice_clk_src_entries, + .entries_values = alp882_app_preFW240_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp882_app_preFW240_control_choice_clk_src_entries), + .card_entries_values = alp882_app_preFW240_to_apps_control_choice_clk_src_entries_values, + .card_entries_count = ARRAY_SIZE(alp882_app_preFW240_to_apps_control_choice_clk_src_entries_values) + }, + }, + /* Clock Failover priority 1 */ + { + .type = ALPX_CONTROL_TYPE_TRANSLATED_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P1", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.translated_choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO1_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO1_POS, + .entries = alp882_app_preFW240_control_choice_clk_src_entries, + .entries_values = alp882_app_preFW240_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp882_app_preFW240_control_choice_clk_src_entries), + .card_entries_values = alp882_app_preFW240_to_apps_control_choice_clk_src_entries_values, + .card_entries_count = ARRAY_SIZE(alp882_app_preFW240_to_apps_control_choice_clk_src_entries_values) + }, + }, + /* Clock Failover priority 2*/ + { + .type = ALPX_CONTROL_TYPE_TRANSLATED_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P2", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.translated_choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO2_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO2_POS, + .entries = alp882_app_preFW240_control_choice_clk_src_entries, + .entries_values = alp882_app_preFW240_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp882_app_preFW240_control_choice_clk_src_entries), + .card_entries_values = alp882_app_preFW240_to_apps_control_choice_clk_src_entries_values, + .card_entries_count = ARRAY_SIZE(alp882_app_preFW240_to_apps_control_choice_clk_src_entries_values) + }, + }, + /* Clock Failover priority 3*/ + { + .type = ALPX_CONTROL_TYPE_TRANSLATED_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P3", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.translated_choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO3_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO3_POS, + .entries = alp882_app_preFW240_control_choice_clk_src_entries, + .entries_values = alp882_app_preFW240_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp882_app_preFW240_control_choice_clk_src_entries), + .card_entries_values = alp882_app_preFW240_to_apps_control_choice_clk_src_entries_values, + .card_entries_count = ARRAY_SIZE(alp882_app_preFW240_to_apps_control_choice_clk_src_entries_values) + }, + }, + /* Auto AES SRC disable */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "AES SRC 1/2 Disable", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALPMC_CODEC_AES_SRC_CONTROL_REG, + .mask = ALPMC_CODEC_AES_SRC_1_2_MASK, + .pos = ALPMC_CODEC_AES_SRC_1_2_POS, + }, + }, + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "AES SRC 3/4 Disable", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALPMC_CODEC_AES_SRC_CONTROL_REG, + .mask = ALPMC_CODEC_AES_SRC_3_4_MASK, + .pos = ALPMC_CODEC_AES_SRC_3_4_POS, + }, + }, + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "AES SRC 5/6 Disable", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALPMC_CODEC_AES_SRC_CONTROL_REG, + .mask = ALPMC_CODEC_AES_SRC_5_6_MASK, + .pos = ALPMC_CODEC_AES_SRC_5_6_POS, + }, + }, + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "AES SRC 7/8 Disable", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALPMC_CODEC_AES_SRC_CONTROL_REG, + .mask = ALPMC_CODEC_AES_SRC_7_8_MASK, + .pos = ALPMC_CODEC_AES_SRC_7_8_POS, + }, + }, + /* Codec Input Gain for MIC Option*/ + { + .type = ALPX_CONTROL_TYPE_ANALOG_EQ, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "Codec MIC Analog Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.codec = { + .offset = ALPMC_CODEC_PGA_REGS, + .gains_scale = alp882_app_preFW240_mic_control_codec_gains_scale, + .reg_gain_min = ALPMC_MIC_ANALOG_GAIN_MIN_REG, + .reg_gain_max = ALPMC_MIC_ANALOG_GAIN_MAX_REG, + .lines_count = 8, + }, + }, + /** MIC Phantoms **/ + /* MIC Phantom 1 */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "McPh1", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.mic_flags = { + .offset = ALPMC_INPUT_PARAMS_REG, + .mask = ALPMC_MIC_INPUT_PH_1_MASK, + .pos = ALPMC_MIC_INPUT_PH_1_POS, + }, + }, + /* MIC Phantom 2 */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "McPh2", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.mic_flags = { + .offset = ALPMC_INPUT_PARAMS_REG, + .mask = ALPMC_MIC_INPUT_PH_2_MASK, + .pos = ALPMC_MIC_INPUT_PH_2_POS, + }, + }, + /* MIC Phantom 3 */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "McPh3", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.mic_flags = { + .offset = ALPMC_INPUT_PARAMS_REG, + .mask = ALPMC_MIC_INPUT_PH_3_MASK, + .pos = ALPMC_MIC_INPUT_PH_3_POS, + }, + }, + /* MIC Phantom 4 */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "McPh4", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.mic_flags = { + .offset = ALPMC_INPUT_PARAMS_REG, + .mask = ALPMC_MIC_INPUT_PH_4_MASK, + .pos = ALPMC_MIC_INPUT_PH_4_POS, + }, + }, + /* MIC Phantom 5 */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "McPh5", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.mic_flags = { + .offset = ALPMC_INPUT_PARAMS_REG, + .mask = ALPMC_MIC_INPUT_PH_5_MASK, + .pos = ALPMC_MIC_INPUT_PH_5_POS, + }, + }, + /* MIC Phantom 6 */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "McPh6", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.mic_flags = { + .offset = ALPMC_INPUT_PARAMS_REG, + .mask = ALPMC_MIC_INPUT_PH_6_MASK, + .pos = ALPMC_MIC_INPUT_PH_6_POS, + }, + }, + /* MIC Phantom 7 */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "McPh7", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.mic_flags = { + .offset = ALPMC_INPUT_PARAMS_REG, + .mask = ALPMC_MIC_INPUT_PH_7_MASK, + .pos = ALPMC_MIC_INPUT_PH_7_POS, + }, + }, + /* MIC Phantom 8 */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "McPh8", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.mic_flags = { + .offset = ALPMC_INPUT_PARAMS_REG, + .mask = ALPMC_MIC_INPUT_PH_8_MASK, + .pos = ALPMC_MIC_INPUT_PH_8_POS, + }, + }, +}; + + +static struct alpx_variant alp882_app_preFW240_mic_variant __attribute__((unused)) = { + .shortname = "Alp882e-MIC", + .longname = "Alp 882e MIC", + .model = ALPX_VARIANT_MODEL_ALP882_MIC, + .mixername = "Alp882e_MIC_Mix", + .features = ALPX_VARIANT_FEATURE_GPIOS, + .control_descriptors = alp882_app_preFW240_mic_control_descriptors, + .control_descriptors_count = ARRAY_SIZE(alp882_app_preFW240_mic_control_descriptors), + + .capture_hw = &alp882_app_preFW240_hardware_specs, + .playback_hw = &alp882_app_preFW240_hardware_specs, + + .flash_golden_production_base = ALPxxx_FLASH_GOLDEN_PRODUCTION_BASE, + + .gpios = { + .base = ALPMC_GPIO_BASE, + .inputs_reg_offset = ALPMC_GPIO_INPUT_REG, + .inputs_qty = ALPMC_GPIO_INPUT_QTY, + .outputs_reg_offset = ALPMC_GPIO_OUTPUT_REG, + .outputs_qty = ALPMC_GPIO_OUTPUT_QTY, + }, + + .flash_partitions.partitions = alpx_mtd_partitions, + .flash_partitions.qty = ARRAY_SIZE(alpx_mtd_partitions), + .flash_partitions.qty_for_fw_update = 1, +}; + +#endif /* _ALPX_VARIANTS_882_APP_PREFW240H_ */ diff --git a/snd-alpx-dkms/snd-alpx/alpx_variants_common.h b/snd-alpx-dkms/snd-alpx/alpx_variants_common.h new file mode 100644 index 0000000..ef33e55 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/alpx_variants_common.h @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* +* Support for Digigram AlpX PCI-e boards +* +* Copyright (c) 2024 Digigram Digital (info@digigram.com) +*/ + +#ifndef _ALPX_VARIANTS_COMMON_H_ +#define _ALPX_VARIANTS_COMMON_H_ + +#include "alpx.h" +#include "alpx_reg.h" + +#include <sound/tlv.h> +#include <linux/sizes.h> + +/** Common parts **/ + +/* Flash Partitions with USER access mode rules*/ +static struct mtd_partition alpx_mtd_partitions[ALPX_FLASH_PARTITION_QTY] __attribute__((unused)) = { + /* golden */ + { + .name = "golden", + .offset = 0x000000, + .size = 0x400000, + }, + /* user firmware */ + { + .name = "fw-user-updatable", + .offset = 0x400000, + .size = 0x218000, + }, + /* initial configuration */ + { + .name = "init-config", + .offset = 0x400000 + 0x218000, + .size = 0x008000, + }, + /* user configuration */ + { + .name = "user-config", + .offset = 0x400000 + 0x218000 + 0x008000, + .size = 0x008000, + }, + /* PRODUCTION : last area on flash, but keep it here to be the one before last partition*/ + { + .name = "production", + .offset = 0x400000 + 0x218000 + 0x008000 + 0x008000, + .size = 0x008000, /* Limited size : this is enough instead of remaining Flash which is 0x1D8000 bytes*/ + } +}; + +static struct mtd_partition alpx_dead_mtd_partitions[ALPX_DEAD_FLASH_PARTITION_QTY] __attribute__((unused)) = { + /* GOLDEN Prod */ + { + .name = "golden-prod", + .offset = ALPxxx_FLASH_GOLDEN_PRODUCTION_BASE, + .size = 0x008000, + }, + /* PRODUCTION : last area on flash, but keep it here to be the one before last partition*/ + { + .name = "production", + .offset = 0x400000 + 0x218000 + 0x008000 + 0x008000, + .size = 0x008000, /* Limited size : this is enough instead of remaining Flash which is 0x1D8000 bytes*/ + } +}; + +/* Common clock controls */ +static const char* alpxxx_control_choice_current_clk_values_entries[ALPxxx_CLK_MANAGER_CLK_VALUES_QTY] __attribute__((unused)) = { + "8kHz", "11.025kHz", "16kHz","22.05kHz", "24kHz", "32kHz", "44.1kHz", "48kHz", "64kHz", "88.2kHz", + "96kHz", "128kHz", "176,4kHz","192kHz" +}; +/* Same order than the constant values above */ +static u32 alpxxx_control_choice_current_clk_values_entries_values[ALPxxx_CLK_MANAGER_CLK_VALUES_QTY] __attribute__((unused)) = { +ALPxxx_CLK_MANAGER_CLK_VALUE_8K, +ALPxxx_CLK_MANAGER_CLK_VALUE_11_025K, +ALPxxx_CLK_MANAGER_CLK_VALUE_16K, +ALPxxx_CLK_MANAGER_CLK_VALUE_22_05K, +ALPxxx_CLK_MANAGER_CLK_VALUE_24K, +ALPxxx_CLK_MANAGER_CLK_VALUE_32K, +ALPxxx_CLK_MANAGER_CLK_VALUE_44_1K, +ALPxxx_CLK_MANAGER_CLK_VALUE_48K, +ALPxxx_CLK_MANAGER_CLK_VALUE_64K, +ALPxxx_CLK_MANAGER_CLK_VALUE_88_2K, +ALPxxx_CLK_MANAGER_CLK_VALUE_96K, +ALPxxx_CLK_MANAGER_CLK_VALUE_128K, +ALPxxx_CLK_MANAGER_CLK_VALUE_176_4K, +ALPxxx_CLK_MANAGER_CLK_VALUE_192K , +}; + +/* Digital channels gains scale */ + +static const DECLARE_TLV_DB_MINMAX_MUTE(alpxxx_line_digital_gains_scale, + ALP_AMPLIFIER_GAIN_MIN_cdB, ALP_AMPLIFIER_GAIN_MAX_cdB); + + +#endif /* _ALPX_VARIANTS_COMMON_H_ */ diff --git a/snd-alpx-dkms/snd-alpx/alpx_variants_dante.h b/snd-alpx-dkms/snd-alpx/alpx_variants_dante.h new file mode 100644 index 0000000..41a5c82 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/alpx_variants_dante.h @@ -0,0 +1,227 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* +* Support for Digigram AlpX PCI-e boards +* +* Copyright (c) 2024 Digigram Digital (info@digigram.com) +*/ + +#ifndef _ALPX_VARIANTS_DANTE_H_ +#define _ALPX_VARIANTS_DANTE_H_ + +#include "alpx.h" +#include "alpx_reg.h" + +#include <sound/tlv.h> +#include "alpx_variants_common.h" +#include "alpx_axcmem.h" +#include "alpx_controls.h" + +/* DANTE card */ + +#define ALPDANTE_DEFAULT_FS 48000 + + +static struct snd_pcm_hardware alpdante_hardware_specs = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_RESUME, + .formats = SNDRV_PCM_FMTBIT_S32_LE, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = ALPDANTE_DEFAULT_FS, + .rate_max = ALPDANTE_DEFAULT_FS, + .channels_min = 64, + .channels_max = 64, + .buffer_bytes_max = SZ_1M * 4, /* period_bytes_max * periods_max */ + .period_bytes_min = 48, /* min latency 1ms */ + .period_bytes_max = SZ_1M, /* 20ms at 192kHz * nchans * 4B, rounded at 2^n */ + .periods_min = 1, + .periods_max = 4, +}; + + +/* FFPR Support */ + +/* FPPR Parameters */ +static const u32 ALPDANTE_FLASH_UNLOCK = 1; +static const u32 ALPDANTE_FLASH_WAIT_STEP_TIME = 10; +static const u32 ALPDANTE_FLASH_LOCK_ACCESS_TRY_QTY = 1; +static const u32 ALPDANTE_FPPR_SAVE_REGS_CMD_COMPLETION_WAIT_STEPS_QTY = 200; +static const u32 ALPDANTE_FPPR_NOPE_CMD_ID = 0; +static const u32 ALPDANTE_FPPR_SAVE_REGISTERS_CMD_ID = 6; +static const u32 ALPDANTE_FCAR_STATUS_MASK = 0xFFFFFF; +static const u32 ALPDANTE_SMALAR_AVAILABLE = 0; +static const u32 ALPDANTE_SMALAR_IN_USE = 1; + +/* PROD TEST Parameters */ +static const u32 ALPDANTE_PROD_TEST_LOOPBACK = BIT(1); + +/* FPPR Macros */ +#define ALPDANTE_FPPR_CMD_STATUS(reg_val) ((reg_val) & ALPDANTE_FCAR_STATUS_MASK) + +/* AXCmem Registers locations */ + +static const struct alpx_axcmem_loc ALPDANTE_FIR_LOC = {1,0,2}; +static const struct alpx_axcmem_loc ALPDANTE_CSPPR_LOC = {1,3,2}; + +static const struct alpx_axcmem_loc ALPDANTE_CLKPR_LOC = {1,3,1}; +#define DEF_ALPDANTE_CLKPR_LOC {1,3,1} + +static const struct alpx_axcmem_loc ALPDANTE_FPPR_LOC = {1,4,0}; +static const struct alpx_axcmem_loc ALPDANTE_ERRTST_LOC = {1,4,3}; + + +static const struct alpx_axcmem_loc ALPDANTE_UBLAZE_VERSION_LOC = {3,1,2}; +static const struct alpx_axcmem_loc ALPDANTE_DESIGN_BLOC_VERSION_LOC = {3,1,0}; +static const struct alpx_axcmem_loc ALPDANTE_LOW_SERIAL_NUM_LOC = {3,2,0}; +static const struct alpx_axcmem_loc ALPDANTE_HIGH_SERIAL_NUM_LOC = {3,3,0}; + +static const struct alpx_axcmem_loc ALPDANTE_SRConfig_LOC = {0,6,2}; +static const struct alpx_axcmem_loc ALPDANTE_Frequency_Measure_LOC = {0,6,0}; +#define DEF_ALPDANTE_Frequency_Measure_LOC {0,6,0} + +static const struct alpx_axcmem_loc ALPDANTE_Clock_Status_LOC = {0,3,0}; +#define DEF_ALPDANTE_Clock_Status_LOC {0,3,0} +static const struct alpx_axcmem_loc ALPDANTE_CLCSR_LOC = {1,1,0}; + +static const struct alpx_axcmem_loc ALPDANTE_FSDR_LOC = {0,1,1}; +static const struct alpx_axcmem_loc ALPDANTE_FCR_LOC = {0,5,3}; +static const struct alpx_axcmem_loc ALPDANTE_FCAR_LOC = {0,6,0}; +static const struct alpx_axcmem_loc ALPDANTE_SMALAR_LOC = {0,4,0}; + +static const struct alpx_axcmem_loc ALPDANTE_CNAMPR_LOC = {1,3,3}; +static const struct alpx_axcmem_loc ALPDANTE_NAME_LOC = {0,1,0}; + +static const struct alpx_axcmem_loc ALPDANTE_SAMPLE_COUNT_LOC = {3,0,0}; + +static const struct alpx_axcmem_loc ALPDANTE_PROD_TEST_LOC = {1,0,0}; + + +/* NETWORK NAME support */ + +#define ALPDANTE_NETWORK_NAME_LENGTH 29 + +/* Controls support */ + +/* Clk controls support */ +#define ALPDANTE_CLK_MANAGER_CONFIG_CLK_SRC_QTY 2 +#define ALPDANTE_CLK_MANAGER_SOURCE_INTERNAL 0 +#define ALPDANTE_CLK_MANAGER_SOURCE_SIC 1 + +static const char* alpdante_control_choice_clk_src_entries[ALPDANTE_CLK_MANAGER_CONFIG_CLK_SRC_QTY] __attribute__((unused)) = { + "Internal", /* Only this one at the moment */ + "SIC" +}; + +/* Same order than the constants values */ +static u32 alpdante_control_choice_clk_src_entries_values[ALPDANTE_CLK_MANAGER_CONFIG_CLK_SRC_QTY] __attribute__((unused)) = { + ALPDANTE_CLK_MANAGER_SOURCE_INTERNAL, /* Only this one at the moment */ + ALPDANTE_CLK_MANAGER_SOURCE_SIC, +}; + + +#if 0 +#define ALPDANTE_CLK_MANAGER_CLK_VALUES_QTY 6 +static const char* alpdante_control_choice_current_clk_values_entries[ALPDANTE_CLK_MANAGER_CLK_VALUES_QTY] __attribute__((unused)) = { + "44.1kHz", "48kHz", + "88.2kHz", "96kHz", + "176,4kHz","192kHz" +}; +/* Same order than the constant values above */ +static u32 alpdante_control_choice_current_clk_values_entries_values[ALPDANTE_CLK_MANAGER_CLK_VALUES_QTY] __attribute__((unused)) = { +ALPDANTE_CLK_MANAGER_CLK_VALUE_44_1K, +ALPDANTE_CLK_MANAGER_CLK_VALUE_48K, + +ALPDANTE_CLK_MANAGER_CLK_VALUE_88_2K, +ALPDANTE_CLK_MANAGER_CLK_VALUE_96K, + +ALPDANTE_CLK_MANAGER_CLK_VALUE_176_4K, +ALPDANTE_CLK_MANAGER_CLK_VALUE_192K , +}; +#endif + +/* Clock source register access */ +#define ALPDANTE_Clock_Status_CLK_SRC_MASK GENMASK(2, 2) +#define ALPDANTE_Clock_Status_CLK_SRC_POS 2 + +#define ALPDANTE_Clock_Status_Sample_Rate_MASK GENMASK(5,7) +#define ALPDANTE_Clock_Status_Sample_Rate_POS 5 + +static struct alpx_control_descriptor alpdante_control_descriptors[] = { + /* Clock sources Read Only */ + { + .type = ALPX_CONTROL_TYPE_AXCMEM_REL_CHOICE, + .base = 0, + .prefix = "Clk Eff Src", + .access = SNDRV_CTL_ELEM_ACCESS_READ | + SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .data.axcmem_rel_choice = { + .base_loc = DEF_ALPDANTE_CLKPR_LOC, + .reg_loc = DEF_ALPDANTE_Clock_Status_LOC, + .mask = ALPDANTE_Clock_Status_CLK_SRC_MASK, + .pos = ALPDANTE_Clock_Status_CLK_SRC_POS, + .getter = alpx_axcmem_getRegU8Value_ptr, + .setter = NULL, + .entries = alpdante_control_choice_clk_src_entries, + .entries_values = alpdante_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alpdante_control_choice_clk_src_entries), + }, + }, + /* Read Measured Frequency Current Value Read Only */ + { + .type = ALPX_CONTROL_TYPE_AXCMEM_REL_VALUE, + .base = 0, + .prefix = "Clk Eff", + .access = SNDRV_CTL_ELEM_ACCESS_READ | + SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .data.axcmem_rel_value = { + .base_loc = DEF_ALPDANTE_CLKPR_LOC, + .reg_loc = DEF_ALPDANTE_Frequency_Measure_LOC, + .mask = 0xFF, + .pos = 0, + .min = 0, + .max = 192, + .getter = alpx_axcmem_getRegU8Value_ptr, + .setter = NULL, + }, + }, +/* Clock Fail over priority 0 TOP : a constant since no failover yet */ + { + .type = ALPX_CONTROL_TYPE_CONSTANT, + .base = 0, + .prefix = "Clk P0", + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .data.constant = { + .value = ALPDANTE_CLK_MANAGER_SOURCE_INTERNAL, + }, + }, +}; + +/* Alp DANTE Variant */ +static struct alpx_variant alpx_dante_variant __attribute__((unused)) = { + .shortname = "AlpDANTE", + .longname = "Alp DANTE", + .model = ALPX_VARIANT_MODEL_ALPDANTE, + .mixername = "AlpX-DANTE_Mix", + .capture_hw = &alpdante_hardware_specs, + .playback_hw = &alpdante_hardware_specs, + .gpios = { + .base = 0, + .inputs_reg_offset = 0, + .inputs_qty = 0, + .outputs_reg_offset = 0, + .outputs_qty = 0, + }, + + .flash_golden_production_base = ALPxxx_FLASH_GOLDEN_PRODUCTION_BASE, + + .flash_partitions.partitions = NULL, + .flash_partitions.qty = 0, + .flash_partitions.qty_for_fw_update = 0, + .control_descriptors = alpdante_control_descriptors, + .control_descriptors_count = ARRAY_SIZE(alpdante_control_descriptors), +}; + + +#endif /* _ALPX_VARIANTS_DANTE_H_ */ diff --git a/snd-alpx-dkms/snd-alpx/alpx_variants_dead.h b/snd-alpx-dkms/snd-alpx/alpx_variants_dead.h new file mode 100644 index 0000000..ad7ee87 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/alpx_variants_dead.h @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* +* Support for Digigram AlpX PCI-e boards +* +* Copyright (c) 2024 Digigram Digital (info@digigram.com) +*/ + +#ifndef _ALPX_VARIANTS_DEAD_H_ +#define _ALPX_VARIANTS_DEAD_H_ + +#include "alpx.h" +#include "alpx_reg.h" + +#include <sound/tlv.h> +#include "alpx_variants_common.h" + + +/* DEAD Variant : used for DEAD cards : invalid production zones in Flash */ +static const struct alpx_variant alpx_dead_variant = { + .shortname = "AlpDEAD", + .longname = "Alp DEAD", + .model = ALPX_VARIANT_DEAD, + .mixername = "Alp DEAD_Mix", + .features = 0, + .control_descriptors = NULL, + .control_descriptors_count = 0, + + .capture_hw = NULL, + .playback_hw = NULL, + + .flash_golden_production_base = ALPxxx_FLASH_GOLDEN_PRODUCTION_BASE, + + .gpios = { + .base = 0, + .inputs_reg_offset = 0, + .inputs_qty = 0, + .outputs_reg_offset = 0, + .outputs_qty = 0, + }, + + .flash_partitions.partitions = alpx_dead_mtd_partitions, + .flash_partitions.qty = ARRAY_SIZE(alpx_dead_mtd_partitions), +}; + +#endif /* _ALPX_VARIANTS_DEAD_H_ */ diff --git a/snd-alpx-dkms/snd-alpx/alpx_variants_madi.h b/snd-alpx-dkms/snd-alpx/alpx_variants_madi.h new file mode 100644 index 0000000..d269e9f --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/alpx_variants_madi.h @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* +* Support for Digigram AlpX PCI-e boards +* +* Copyright (c) 2024 Digigram Digital (info@digigram.com) +*/ + +#ifndef _ALPX_VARIANTS_MADI_H_ +#define _ALPX_VARIANTS_MADI_H_ + +#include "alpx.h" +#include "alpx_reg.h" + +#include <sound/tlv.h> +#include "alpx_variants_common.h" + +/* MADI */ +static struct snd_pcm_hardware alpmadi_hardware_specs = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_RESUME, + .formats = SNDRV_PCM_FMTBIT_S32_LE, + .rates = SNDRV_PCM_RATE_CONTINUOUS | + SNDRV_PCM_RATE_8000_192000, + .rate_min = 8000, + .rate_max = 192000, + .channels_min = 64, + .channels_max = 64, + .buffer_bytes_max = SZ_1M * 4, /* period_bytes_max * periods_max */ + .period_bytes_min = 48, /* min latency 1ms */ + .period_bytes_max = SZ_1M, /* 20ms at 192kHz * nchans * 4B, rounded at 2^n */ + .periods_min = 1, + .periods_max = 4, +}; + + +/* Alp MADI Variant */ +static struct alpx_variant alpx_madi_variant __attribute__((unused)) = { + .shortname = "AlpMADI", + .longname = "Alp MADI", + .model = ALPX_VARIANT_MODEL_MADI, + .mixername = "AlpX-MADI_Mix", + .capture_hw = &alpmadi_hardware_specs, + .playback_hw = &alpmadi_hardware_specs, + .gpios = { + .base = 0, + .inputs_reg_offset = 0, + .inputs_qty = 0, + .outputs_reg_offset = 0, + .outputs_qty = 0, + }, + + .flash_golden_production_base = ALPxxx_FLASH_GOLDEN_PRODUCTION_BASE, + + .flash_partitions.partitions = alpx_mtd_partitions, + .flash_partitions.qty = ARRAY_SIZE(alpx_mtd_partitions), + .flash_partitions.qty_for_fw_update = 1, +}; + + +/* Alp MADI Loopback */ + +static struct alpx_variant alpx_madi_loopback_variant __attribute__((unused)) = { + .shortname = "AlpLoopback", + .longname = "Alp Loopback", + .model = ALPX_VARIANT_MODEL_MADI_LOOPBACK, + .mixername = "AlpX-MADI-Loopback_Mix", + .capture_hw = &alpmadi_hardware_specs, + .playback_hw = &alpmadi_hardware_specs, + + .flash_golden_production_base = ALPxxx_FLASH_GOLDEN_PRODUCTION_BASE, + + .gpios = { + .base = 0, + .inputs_reg_offset = 0, + .inputs_qty = 0, + .outputs_reg_offset = 0, + .outputs_qty = 0, + }, + + .flash_partitions.partitions = alpx_mtd_partitions, + .flash_partitions.qty = ARRAY_SIZE(alpx_mtd_partitions), + .flash_partitions.qty_for_fw_update = 1, +}; + + +#endif /* _ALPX_VARIANTS_MADI_H_ */ diff --git a/snd-alpx-dkms/snd-alpx/alpx_variants_mc.h b/snd-alpx-dkms/snd-alpx/alpx_variants_mc.h new file mode 100644 index 0000000..aa32035 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/alpx_variants_mc.h @@ -0,0 +1,1475 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* +* Support for Digigram AlpX PCI-e boards +* +* Copyright (c) 2024 Digigram Digital (info@digigram.com) +*/ + +#ifndef _ALPX_VARIANTS_MC_H_ +#define _ALPX_VARIANTS_MC_H_ + +#include "alpx.h" +#include "alpx_reg.h" + +#include <sound/tlv.h> +#include "alpx_variants_common.h" + + +/* 882 */ +/* Alp882 Commons */ +static const char *alp882_control_choice_clk_src_entries[ALP882_CLK_MANAGER_CONFIG_CLK_SRC_QTY] = { + "Internal", + "SIC", + "Word Clk", + "AES Syn", + "AES Aud 1/2", + "AES Aud 3/4", + "AES Aud 5/6", + "AES Aud 7/8", +}; + +/* Same order than the constants values */ +static u32 alp882_control_choice_clk_src_entries_values[ALP882_CLK_MANAGER_CONFIG_CLK_SRC_QTY] = { + ALPMC_CLK_MANAGER_SOURCE_INTERNAL, + ALPMC_CLK_MANAGER_SOURCE_SIC, + ALPMC_CLK_MANAGER_SOURCE_WCLK_IN, + ALPMC_CLK_MANAGER_SOURCE_AES_SYNC, + ALPMC_CLK_MANAGER_SOURCE_AES_AUDIO_12, + ALPMC_CLK_MANAGER_SOURCE_AES_AUDIO_34, + ALPMC_CLK_MANAGER_SOURCE_AES_AUDIO_56, + ALPMC_CLK_MANAGER_SOURCE_AES_AUDIO_78, +}; + +static struct snd_pcm_hardware alp882_hardware_specs = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_RESUME, + .formats = SNDRV_PCM_FMTBIT_S32_LE, + .rates = SNDRV_PCM_RATE_CONTINUOUS | + SNDRV_PCM_RATE_8000_192000, + .rate_min = 8000, + .rate_max = 192000, + .channels_min = 16, + .channels_max = 16, + .buffer_bytes_max = 256 * SZ_1K * 4, /* period_bytes_max * periods_max */ + .period_bytes_min = 48, /* min latency 1ms */ + .period_bytes_max = 256 * SZ_1K, /* 20ms at 192kHz * nchans * 4B, rounded at 2^n */ + .periods_min = 1, + .periods_max = 4, +}; + + +/* Alp 882 LINE Variant definition */ + +static const DECLARE_TLV_DB_MINMAX_MUTE(alpmc_line_control_codec_gains_scale, ALPMC_LINE_ANALOG_GAIN_MIN_cdB, ALPMC_LINE_ANALOG_GAIN_MAX_cdB); + +static struct alpx_control_descriptor alp882_line_control_descriptors[] = { + /* Gain */ + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALPMC_AMPLI_IN_BASE + + ALPMC_GAIN_TABLE_BASE(ALP882_CHANNELS_IN_DAW_OFFSET), + .prefix = "DAW Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP882_CHANNELS_DAW_COUNT, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALPMC_AMPLI_IN_BASE + + ALPMC_GAIN_TABLE_BASE(ALP882_CHANNELS_IN_ANALOG_OFFSET), + .prefix = "Ana Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP882_CHANNELS_ANALOG_COUNT, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALPMC_AMPLI_IN_BASE + + ALPMC_GAIN_TABLE_BASE(ALP882_CHANNELS_IN_AES_OFFSET), + .prefix = "AES Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP882_CHANNELS_AES_COUNT, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALPMC_AMPLI_OUT_BASE + + ALPMC_GAIN_TABLE_BASE(ALP882_CHANNELS_OUT_ANALOG_OFFSET), + .prefix = "Ana Playback", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP882_CHANNELS_ANALOG_COUNT, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALPMC_AMPLI_OUT_BASE + + ALPMC_GAIN_TABLE_BASE(ALP882_CHANNELS_OUT_AES_OFFSET), + .prefix = "AES Playback", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP882_CHANNELS_AES_COUNT, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALPMC_AMPLI_OUT_BASE + + ALPMC_GAIN_TABLE_BASE(ALP882_CHANNELS_OUT_DAW_OFFSET), + .prefix = "DAW Playback", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP882_CHANNELS_DAW_COUNT, + }, + }, + /* Mixer */ + { + .type = ALPX_CONTROL_TYPE_MIXER, + .base = ALPMC_MIXER_BASE, + .prefix = "Mxr", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.mixer = { + .lines_count = ALP882_MIXER_SIZE, + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + }, + }, + /* Clock sources Read Only */ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALPMC_CLK_MANAGER_BASE, + .prefix = "Clk Eff Src", + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .data.choice = { + .offset = ALPMC_CLK_MANAGER_CONFIG_REG, + .mask = ALPMC_CLK_MANAGER_CONFIG_CLK_SRC_MASK, + .pos = ALPMC_CLK_MANAGER_CONFIG_CLK_SRC_POS, + .entries = alp882_control_choice_clk_src_entries, + .entries_values = alp882_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp882_control_choice_clk_src_entries), + }, + }, + /* Current Clock BASE Value Read Only */ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALPMC_CLK_MANAGER_BASE, + .prefix = "Clk Eff", + .access = SNDRV_CTL_ELEM_ACCESS_READ | + SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .data.choice = { + .offset = ALPMC_CLK_MANAGER_CONFIG_REG, + .mask = ALPMC_CLK_MANAGER_CONFIG_CLK_CURRENT_VALUE_MASK, + .pos = ALPMC_CLK_MANAGER_CONFIG_CLK_CURRENT_VALUE_POS, + .entries = alpxxx_control_choice_current_clk_values_entries, + .entries_values = alpxxx_control_choice_current_clk_values_entries_values, + .entries_count = ARRAY_SIZE(alpxxx_control_choice_current_clk_values_entries), + }, + }, + + /* Current Clock factor values Read Only, RESERVED to keep Ids order */ + { + .type = ALPX_CONTROL_RESERVED, + .base = ALPMC_CLK_MANAGER_BASE, + .prefix = "RESERVED", + .access = SNDRV_CTL_ELEM_ACCESS_READ, + }, + /* Clock UP on fail over enabled flag */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALP_PROC_BASE, + .prefix = "Clk Src Up", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALP_PROC_FWCONFIG_REG, + .mask = ALP_PROC_FWCONFIG_CLKSRC_UP_MASK, + .pos = ALP_PROC_FWCONFIG_CLKSRC_UP_POS, + }, + }, + /* Clock DOWN on fail over enabled flag */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALP_PROC_BASE, + .prefix = "Clk Src Down", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALP_PROC_FWCONFIG_REG, + .mask = ALP_PROC_FWCONFIG_CLKSRC_DOWN_MASK, + .pos = ALP_PROC_FWCONFIG_CLKSRC_DOWN_POS, + }, + }, + /* Clock Failover priority 0 TOP*/ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P0", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO0_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO0_POS, + .entries = alp882_control_choice_clk_src_entries, + .entries_values = alp882_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp882_control_choice_clk_src_entries), + }, + }, + /* Clock Failover priority 1 */ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P1", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO1_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO1_POS, + .entries = alp882_control_choice_clk_src_entries, + .entries_values = alp882_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp882_control_choice_clk_src_entries), + }, + }, + /* Clock Failover priority 2*/ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P2", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO2_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO2_POS, + .entries = alp882_control_choice_clk_src_entries, + .entries_values = alp882_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp882_control_choice_clk_src_entries), + }, + }, + /* Clock Failover priority 3*/ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P3", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO3_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO3_POS, + .entries = alp882_control_choice_clk_src_entries, + .entries_values = alp882_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp882_control_choice_clk_src_entries), + }, + }, + /* Auto AES SRC disable */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "AES SRC 1/2 Disable", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALPMC_CODEC_AES_SRC_CONTROL_REG, + .mask = ALPMC_CODEC_AES_SRC_1_2_MASK, + .pos = ALPMC_CODEC_AES_SRC_1_2_POS, + }, + }, + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "AES SRC 3/4 Disable", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALPMC_CODEC_AES_SRC_CONTROL_REG, + .mask = ALPMC_CODEC_AES_SRC_3_4_MASK, + .pos = ALPMC_CODEC_AES_SRC_3_4_POS, + }, + }, + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "AES SRC 5/6 Disable", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALPMC_CODEC_AES_SRC_CONTROL_REG, + .mask = ALPMC_CODEC_AES_SRC_5_6_MASK, + .pos = ALPMC_CODEC_AES_SRC_5_6_POS, + }, + }, + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "AES SRC 7/8 Disable", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALPMC_CODEC_AES_SRC_CONTROL_REG, + .mask = ALPMC_CODEC_AES_SRC_7_8_MASK, + .pos = ALPMC_CODEC_AES_SRC_7_8_POS, + }, + }, + /* Codec Input Gain for LINE Option*/ + { + .type = ALPX_CONTROL_TYPE_ANALOG_EQ, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "Codec Analog Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.codec = { + .offset = ALPMC_CODEC_PGA_REGS, + .gains_scale = alpmc_line_control_codec_gains_scale, + .reg_gain_min = ALPMC_LINE_ANALOG_GAIN_MIN_REG, + .reg_gain_max = ALPMC_LINE_ANALOG_GAIN_MAX_REG, + .lines_count = 8, + }, + }, +}; + +static struct alpx_variant alp882_line_variant __attribute__((unused)) = { + .shortname = "Alp882e", + .longname = "Alp 882e", + .model = ALPX_VARIANT_MODEL_ALP882, + .mixername = "Alp882e_Mix", + .features = ALPX_VARIANT_FEATURE_GPIOS, + .control_descriptors = alp882_line_control_descriptors, + .control_descriptors_count = ARRAY_SIZE(alp882_line_control_descriptors), + + .capture_hw = &alp882_hardware_specs, + .playback_hw = &alp882_hardware_specs, + + .flash_golden_production_base = ALPxxx_FLASH_GOLDEN_PRODUCTION_BASE, + + .gpios = { + .base = ALPMC_GPIO_BASE, + .inputs_reg_offset = ALPMC_GPIO_INPUT_REG, + .inputs_qty = ALPMC_GPIO_INPUT_QTY, + .outputs_reg_offset = ALPMC_GPIO_OUTPUT_REG, + .outputs_qty = ALPMC_GPIO_OUTPUT_QTY, + }, + + .flash_partitions.partitions = alpx_mtd_partitions, + .flash_partitions.qty = ARRAY_SIZE(alpx_mtd_partitions), + .flash_partitions.qty_for_fw_update = 1, +}; + + +/* Alp 882 - MIC Variant definition */ + +static const DECLARE_TLV_DB_MINMAX_MUTE(alpmc_mic_control_codec_gains_scale, ALPMC_MIC_ANALOG_GAIN_MIN_cdB, ALPMC_MIC_ANALOG_GAIN_MAX_cdB); + +static struct alpx_control_descriptor alp882_mic_control_descriptors[] = { + /* Gain */ + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALPMC_AMPLI_IN_BASE + + ALPMC_GAIN_TABLE_BASE(ALP882_CHANNELS_IN_DAW_OFFSET), + .prefix = "DAW Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP882_CHANNELS_DAW_COUNT, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALPMC_AMPLI_IN_BASE + + ALPMC_GAIN_TABLE_BASE(ALP882_CHANNELS_IN_ANALOG_OFFSET), + .prefix = "Ana Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP882_CHANNELS_ANALOG_COUNT, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALPMC_AMPLI_IN_BASE + + ALPMC_GAIN_TABLE_BASE(ALP882_CHANNELS_IN_AES_OFFSET), + .prefix = "AES Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP882_CHANNELS_AES_COUNT, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALPMC_AMPLI_OUT_BASE + + ALPMC_GAIN_TABLE_BASE(ALP882_CHANNELS_OUT_ANALOG_OFFSET), + .prefix = "Ana Playback", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP882_CHANNELS_ANALOG_COUNT, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALPMC_AMPLI_OUT_BASE + + ALPMC_GAIN_TABLE_BASE(ALP882_CHANNELS_OUT_AES_OFFSET), + .prefix = "AES Playback", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP882_CHANNELS_AES_COUNT, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALPMC_AMPLI_OUT_BASE + + ALPMC_GAIN_TABLE_BASE(ALP882_CHANNELS_OUT_DAW_OFFSET), + .prefix = "DAW Playback", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP882_CHANNELS_DAW_COUNT, + }, + }, + /* Mixer */ + { + .type = ALPX_CONTROL_TYPE_MIXER, + .base = ALPMC_MIXER_BASE, + .prefix = "Mxr", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.mixer = { + .lines_count = ALP882_MIXER_SIZE, + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + }, + }, + /* Clock sources Read Only */ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALPMC_CLK_MANAGER_BASE, + .prefix = "Clk Eff Src", + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .data.choice = { + .offset = ALPMC_CLK_MANAGER_CONFIG_REG, + .mask = ALPMC_CLK_MANAGER_CONFIG_CLK_SRC_MASK, + .pos = ALPMC_CLK_MANAGER_CONFIG_CLK_SRC_POS, + .entries = alp882_control_choice_clk_src_entries, + .entries_values = alp882_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp882_control_choice_clk_src_entries), + }, + }, + /* Current Clock BASE Value Read Only */ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALPMC_CLK_MANAGER_BASE, + .prefix = "Clk Eff", + .access = SNDRV_CTL_ELEM_ACCESS_READ | + SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .data.choice = { + .offset = ALPMC_CLK_MANAGER_CONFIG_REG, + .mask = ALPMC_CLK_MANAGER_CONFIG_CLK_CURRENT_VALUE_MASK, + .pos = ALPMC_CLK_MANAGER_CONFIG_CLK_CURRENT_VALUE_POS, + .entries = alpxxx_control_choice_current_clk_values_entries, + .entries_values = alpxxx_control_choice_current_clk_values_entries_values, + .entries_count = ARRAY_SIZE(alpxxx_control_choice_current_clk_values_entries), + }, + }, + + /* Current Clock factor values Read Only, RESERVED now to keep ids order */ + { + .type = ALPX_CONTROL_RESERVED, + .base = ALPMC_CLK_MANAGER_BASE, + .prefix = "RESERVED", + .access = SNDRV_CTL_ELEM_ACCESS_READ, + }, + /* Clock UP on fail over enabled flag */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALP_PROC_BASE, + .prefix = "Clk Src Up", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALP_PROC_FWCONFIG_REG, + .mask = ALP_PROC_FWCONFIG_CLKSRC_UP_MASK, + .pos = ALP_PROC_FWCONFIG_CLKSRC_UP_POS, + }, + }, + /* Clock DOWN on fail over enabled flag */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALP_PROC_BASE, + .prefix = "Clk Src Down", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALP_PROC_FWCONFIG_REG, + .mask = ALP_PROC_FWCONFIG_CLKSRC_DOWN_MASK, + .pos = ALP_PROC_FWCONFIG_CLKSRC_DOWN_POS, + }, + }, + /* Clock Failover priority 0 TOP*/ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P0", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO0_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO0_POS, + .entries = alp882_control_choice_clk_src_entries, + .entries_values = alp882_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp882_control_choice_clk_src_entries), + }, + }, + /* Clock Failover priority 1 */ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P1", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO1_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO1_POS, + .entries = alp882_control_choice_clk_src_entries, + .entries_values = alp882_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp882_control_choice_clk_src_entries), + }, + }, + /* Clock Failover priority 2*/ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P2", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO2_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO2_POS, + .entries = alp882_control_choice_clk_src_entries, + .entries_values = alp882_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp882_control_choice_clk_src_entries), + }, + }, + /* Clock Failover priority 3*/ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P3", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO3_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO3_POS, + .entries = alp882_control_choice_clk_src_entries, + .entries_values = alp882_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp882_control_choice_clk_src_entries), + }, + }, + /* Auto AES SRC disable */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "AES SRC 1/2 Disable", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALPMC_CODEC_AES_SRC_CONTROL_REG, + .mask = ALPMC_CODEC_AES_SRC_1_2_MASK, + .pos = ALPMC_CODEC_AES_SRC_1_2_POS, + }, + }, + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "AES SRC 3/4 Disable", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALPMC_CODEC_AES_SRC_CONTROL_REG, + .mask = ALPMC_CODEC_AES_SRC_3_4_MASK, + .pos = ALPMC_CODEC_AES_SRC_3_4_POS, + }, + }, + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "AES SRC 5/6 Disable", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALPMC_CODEC_AES_SRC_CONTROL_REG, + .mask = ALPMC_CODEC_AES_SRC_5_6_MASK, + .pos = ALPMC_CODEC_AES_SRC_5_6_POS, + }, + }, + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "AES SRC 7/8 Disable", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALPMC_CODEC_AES_SRC_CONTROL_REG, + .mask = ALPMC_CODEC_AES_SRC_7_8_MASK, + .pos = ALPMC_CODEC_AES_SRC_7_8_POS, + }, + }, + /* Codec Input Gain for MIC Option*/ + { + .type = ALPX_CONTROL_TYPE_ANALOG_EQ, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "Codec MIC Analog Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.codec = { + .offset = ALPMC_CODEC_PGA_REGS, + .gains_scale = alpmc_mic_control_codec_gains_scale, + .reg_gain_min = ALPMC_MIC_ANALOG_GAIN_MIN_REG, + .reg_gain_max = ALPMC_MIC_ANALOG_GAIN_MAX_REG, + .lines_count = 8, + }, + }, + /** MIC Phantoms **/ + /* MIC Phantom 1 */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "McPh1", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.mic_flags = { + .offset = ALPMC_INPUT_PARAMS_REG, + .mask = ALPMC_MIC_INPUT_PH_1_MASK, + .pos = ALPMC_MIC_INPUT_PH_1_POS, + }, + }, + /* MIC Phantom 2 */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "McPh2", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.mic_flags = { + .offset = ALPMC_INPUT_PARAMS_REG, + .mask = ALPMC_MIC_INPUT_PH_2_MASK, + .pos = ALPMC_MIC_INPUT_PH_2_POS, + }, + }, + /* MIC Phantom 3 */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "McPh3", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.mic_flags = { + .offset = ALPMC_INPUT_PARAMS_REG, + .mask = ALPMC_MIC_INPUT_PH_3_MASK, + .pos = ALPMC_MIC_INPUT_PH_3_POS, + }, + }, + /* MIC Phantom 4 */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "McPh4", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.mic_flags = { + .offset = ALPMC_INPUT_PARAMS_REG, + .mask = ALPMC_MIC_INPUT_PH_4_MASK, + .pos = ALPMC_MIC_INPUT_PH_4_POS, + }, + }, + /* MIC Phantom 5 */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "McPh5", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.mic_flags = { + .offset = ALPMC_INPUT_PARAMS_REG, + .mask = ALPMC_MIC_INPUT_PH_5_MASK, + .pos = ALPMC_MIC_INPUT_PH_5_POS, + }, + }, + /* MIC Phantom 6 */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "McPh6", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.mic_flags = { + .offset = ALPMC_INPUT_PARAMS_REG, + .mask = ALPMC_MIC_INPUT_PH_6_MASK, + .pos = ALPMC_MIC_INPUT_PH_6_POS, + }, + }, + /* MIC Phantom 7 */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "McPh7", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.mic_flags = { + .offset = ALPMC_INPUT_PARAMS_REG, + .mask = ALPMC_MIC_INPUT_PH_7_MASK, + .pos = ALPMC_MIC_INPUT_PH_7_POS, + }, + }, + /* MIC Phantom 8 */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "McPh8", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.mic_flags = { + .offset = ALPMC_INPUT_PARAMS_REG, + .mask = ALPMC_MIC_INPUT_PH_8_MASK, + .pos = ALPMC_MIC_INPUT_PH_8_POS, + }, + }, +}; + + +static struct alpx_variant alp882_mic_variant __attribute__((unused)) = { + .shortname = "Alp882e-MIC", + .longname = "Alp 882e MIC", + .model = ALPX_VARIANT_MODEL_ALP882_MIC, + .mixername = "Alp882e_MIC_Mix", + .features = ALPX_VARIANT_FEATURE_GPIOS, + .control_descriptors = alp882_mic_control_descriptors, + .control_descriptors_count = ARRAY_SIZE(alp882_mic_control_descriptors), + + .capture_hw = &alp882_hardware_specs, + .playback_hw = &alp882_hardware_specs, + + .flash_golden_production_base = ALPxxx_FLASH_GOLDEN_PRODUCTION_BASE, + + .gpios = { + .base = ALPMC_GPIO_BASE, + .inputs_reg_offset = ALPMC_GPIO_INPUT_REG, + .inputs_qty = ALPMC_GPIO_INPUT_QTY, + .outputs_reg_offset = ALPMC_GPIO_OUTPUT_REG, + .outputs_qty = ALPMC_GPIO_OUTPUT_QTY, + }, + + .flash_partitions.partitions = alpx_mtd_partitions, + .flash_partitions.qty = ARRAY_SIZE(alpx_mtd_partitions), + .flash_partitions.qty_for_fw_update = 1, +}; + +/* 442 */ +/* Commons clock sources : WARNING : Sme as 882 for the moment */ +static const char *alp442_control_choice_clk_src_entries[ALP442_CLK_MANAGER_CONFIG_CLK_SRC_QTY] = { + "Internal", + "SIC", + "Word Clk", + "AES Syn", + "AES Aud 1/2", + "AES Aud 3/4", +}; + +/* Same order than the constants values */ +static u32 alp442_control_choice_clk_src_entries_values[ALP442_CLK_MANAGER_CONFIG_CLK_SRC_QTY] = { + ALPMC_CLK_MANAGER_SOURCE_INTERNAL, + ALPMC_CLK_MANAGER_SOURCE_SIC, + ALPMC_CLK_MANAGER_SOURCE_WCLK_IN, + ALPMC_CLK_MANAGER_SOURCE_AES_SYNC, + ALPMC_CLK_MANAGER_SOURCE_AES_AUDIO_12, + ALPMC_CLK_MANAGER_SOURCE_AES_AUDIO_34 +}; + +static struct snd_pcm_hardware alp442_hardware_specs = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_RESUME, + .formats = SNDRV_PCM_FMTBIT_S32_LE, + .rates = SNDRV_PCM_RATE_CONTINUOUS | + SNDRV_PCM_RATE_8000_192000, + .rate_min = 8000, + .rate_max = 192000, + .channels_min = ALP442_CHANNELS_DAW_COUNT, + .channels_max = ALP442_CHANNELS_DAW_COUNT, + .buffer_bytes_max = 128 * SZ_1K * 4, /* period_bytes_max * periods_max */ + .period_bytes_min = 48, /* min latency 1ms */ + .period_bytes_max = 128 * SZ_1K, /* 20ms at 192kHz * nchans * 4B, rounded at 2^n */ + .periods_min = 1, + .periods_max = 4, +}; + + +/* Alp 442 LINE Variant definition */ + + +static struct alpx_control_descriptor alp442_line_control_descriptors[] = { + /* Gain */ + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALPMC_AMPLI_IN_BASE + + ALPMC_GAIN_TABLE_BASE(ALP442_CHANNELS_IN_DAW_OFFSET), + .prefix = "DAW Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP442_CHANNELS_DAW_COUNT, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALPMC_AMPLI_IN_BASE + + ALPMC_GAIN_TABLE_BASE(ALP442_CHANNELS_IN_ANALOG_OFFSET), + .prefix = "Ana Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP442_CHANNELS_ANALOG_COUNT, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALPMC_AMPLI_IN_BASE + + ALPMC_GAIN_TABLE_BASE(ALP442_CHANNELS_IN_AES_OFFSET), + .prefix = "AES Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP442_CHANNELS_AES_COUNT, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALPMC_AMPLI_OUT_BASE + + ALPMC_GAIN_TABLE_BASE(ALP442_CHANNELS_OUT_ANALOG_OFFSET), + .prefix = "Ana Playback", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP442_CHANNELS_ANALOG_COUNT, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALPMC_AMPLI_OUT_BASE + + ALPMC_GAIN_TABLE_BASE(ALP442_CHANNELS_OUT_AES_OFFSET), + .prefix = "AES Playback", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP442_CHANNELS_AES_COUNT, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALPMC_AMPLI_OUT_BASE + + ALPMC_GAIN_TABLE_BASE(ALP442_CHANNELS_OUT_DAW_OFFSET), + .prefix = "DAW Playback", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP442_CHANNELS_DAW_COUNT, + }, + }, + /* Mixer */ + { + .type = ALPX_CONTROL_TYPE_MIXER, + .base = ALPMC_MIXER_BASE, + .prefix = "Mxr", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.mixer = { + .lines_count = ALP442_MIXER_SIZE, + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + }, + }, + /* Clock sources Read Only */ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALPMC_CLK_MANAGER_BASE, + .prefix = "Clk Eff Src", + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .data.choice = { + .offset = ALPMC_CLK_MANAGER_CONFIG_REG, + .mask = ALPMC_CLK_MANAGER_CONFIG_CLK_SRC_MASK, + .pos = ALPMC_CLK_MANAGER_CONFIG_CLK_SRC_POS, + .entries = alp442_control_choice_clk_src_entries, + .entries_values = alp442_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp442_control_choice_clk_src_entries), + }, + }, + + /* Current Clock BASE Value Read Only */ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALPMC_CLK_MANAGER_BASE, + .prefix = "Clk Eff", + .access = SNDRV_CTL_ELEM_ACCESS_READ | + SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .data.choice = { + .offset = ALPMC_CLK_MANAGER_CONFIG_REG, + .mask = ALPMC_CLK_MANAGER_CONFIG_CLK_CURRENT_VALUE_MASK, + .pos = ALPMC_CLK_MANAGER_CONFIG_CLK_CURRENT_VALUE_POS, + .entries = alpxxx_control_choice_current_clk_values_entries, + .entries_values = alpxxx_control_choice_current_clk_values_entries_values, + .entries_count = ARRAY_SIZE(alpxxx_control_choice_current_clk_values_entries), + }, + }, + + /* Current Clock factor values Read Only, RESERVED to keep Ids order */ + { + .type = ALPX_CONTROL_RESERVED, + .base = ALPMC_CLK_MANAGER_BASE, + .prefix = "RESERVED", + .access = SNDRV_CTL_ELEM_ACCESS_READ, + }, + /* Clock UP on fail over enabled flag */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALP_PROC_BASE, + .prefix = "Clk Src Up", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALP_PROC_FWCONFIG_REG, + .mask = ALP_PROC_FWCONFIG_CLKSRC_UP_MASK, + .pos = ALP_PROC_FWCONFIG_CLKSRC_UP_POS, + }, + }, + /* Clock DOWN on fail over enabled flag */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALP_PROC_BASE, + .prefix = "Clk Src Down", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALP_PROC_FWCONFIG_REG, + .mask = ALP_PROC_FWCONFIG_CLKSRC_DOWN_MASK, + .pos = ALP_PROC_FWCONFIG_CLKSRC_DOWN_POS, + }, + }, + /* Clock Failover priority 0 TOP*/ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P0", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO0_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO0_POS, + .entries = alp442_control_choice_clk_src_entries, + .entries_values = alp442_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp442_control_choice_clk_src_entries), + }, + }, + /* Clock Failover priority 1 */ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P1", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO1_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO1_POS, + .entries = alp442_control_choice_clk_src_entries, + .entries_values = alp442_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp442_control_choice_clk_src_entries), + }, + }, + /* Clock Failover priority 2*/ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P2", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO2_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO2_POS, + .entries = alp442_control_choice_clk_src_entries, + .entries_values = alp442_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp442_control_choice_clk_src_entries), + }, + }, + /* Clock Failover priority 3*/ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P3", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO3_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO3_POS, + .entries = alp442_control_choice_clk_src_entries, + .entries_values = alp442_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp442_control_choice_clk_src_entries), + }, + }, + /* Auto AES SRC disable */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "AES SRC 1/2 Disable", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALPMC_CODEC_AES_SRC_CONTROL_REG, + .mask = ALPMC_CODEC_AES_SRC_1_2_MASK, + .pos = ALPMC_CODEC_AES_SRC_1_2_POS, + }, + }, + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "AES SRC 3/4 Disable", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALPMC_CODEC_AES_SRC_CONTROL_REG, + .mask = ALPMC_CODEC_AES_SRC_3_4_MASK, + .pos = ALPMC_CODEC_AES_SRC_3_4_POS, + }, + }, + /* Codec Input Gain for LINE Option*/ + { + .type = ALPX_CONTROL_TYPE_ANALOG_EQ, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "Codec Analog Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.codec = { + .offset = ALPMC_CODEC_PGA_REGS, + .gains_scale = alpmc_line_control_codec_gains_scale, + .reg_gain_min = ALPMC_LINE_ANALOG_GAIN_MIN_REG, + .reg_gain_max = ALPMC_LINE_ANALOG_GAIN_MAX_REG, + .lines_count = ALP442_CHANNELS_ANALOG_COUNT, + }, + }, +}; + +static struct alpx_variant alp442_line_variant __attribute__((unused)) = { + .shortname = "Alp442e", + .longname = "Alp 442e", + .model = ALPX_VARIANT_MODEL_ALP442, + .mixername = "Alp442e_Mix", + .features = ALPX_VARIANT_FEATURE_GPIOS, + .control_descriptors = alp442_line_control_descriptors, + .control_descriptors_count = ARRAY_SIZE(alp442_line_control_descriptors), + + .capture_hw = &alp442_hardware_specs, + .playback_hw = &alp442_hardware_specs, + + .flash_golden_production_base = ALPxxx_FLASH_GOLDEN_PRODUCTION_BASE, + + .gpios = {/*Same as Alp882*/ + .base = ALPMC_GPIO_BASE, + .inputs_reg_offset = ALPMC_GPIO_INPUT_REG, + .inputs_qty = ALPMC_GPIO_INPUT_QTY, + .outputs_reg_offset = ALPMC_GPIO_OUTPUT_REG, + .outputs_qty = ALPMC_GPIO_OUTPUT_QTY, + }, + + .flash_partitions.partitions = alpx_mtd_partitions, + .flash_partitions.qty = ARRAY_SIZE(alpx_mtd_partitions), + .flash_partitions.qty_for_fw_update = 1, +}; + + +/* Alp 442 - MIC Variant definition */ + +static struct alpx_control_descriptor alp442_mic_control_descriptors[] = { + /* Gain */ + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALPMC_AMPLI_IN_BASE + + ALPMC_GAIN_TABLE_BASE(ALP442_CHANNELS_IN_DAW_OFFSET), + .prefix = "DAW Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP442_CHANNELS_DAW_COUNT, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALPMC_AMPLI_IN_BASE + + ALPMC_GAIN_TABLE_BASE(ALP442_CHANNELS_IN_ANALOG_OFFSET), + .prefix = "Ana Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP442_CHANNELS_ANALOG_COUNT, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALPMC_AMPLI_IN_BASE + + ALPMC_GAIN_TABLE_BASE(ALP442_CHANNELS_IN_AES_OFFSET), + .prefix = "AES Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP442_CHANNELS_AES_COUNT, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALPMC_AMPLI_OUT_BASE + + ALPMC_GAIN_TABLE_BASE(ALP442_CHANNELS_OUT_ANALOG_OFFSET), + .prefix = "Ana Playback", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP442_CHANNELS_ANALOG_COUNT, + }, + }, + {/*a 882 with halved QTY*/ + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALPMC_AMPLI_OUT_BASE + + ALPMC_GAIN_TABLE_BASE(ALP442_CHANNELS_OUT_AES_OFFSET), + .prefix = "AES Playback", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP442_CHANNELS_AES_COUNT, + }, + }, + {/*a 882 with halved QTY*/ + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALPMC_AMPLI_OUT_BASE + + ALPMC_GAIN_TABLE_BASE(ALP442_CHANNELS_OUT_DAW_OFFSET), + .prefix = "DAW Playback", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP442_CHANNELS_DAW_COUNT, + }, + }, + /* Mixer a 882 with halved QTY Mixer : square*/ + { + .type = ALPX_CONTROL_TYPE_MIXER, + .base = ALPMC_MIXER_BASE, + .prefix = "Mxr", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.mixer = { + .lines_count = ALP442_MIXER_SIZE, + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + }, + }, + /* Clock sources Read Only As 882 except for AES due to 4 entries only */ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALPMC_CLK_MANAGER_BASE, + .prefix = "Clk Eff Src", + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .data.choice = { + .offset = ALPMC_CLK_MANAGER_CONFIG_REG, + .mask = ALPMC_CLK_MANAGER_CONFIG_CLK_SRC_MASK, + .pos = ALPMC_CLK_MANAGER_CONFIG_CLK_SRC_POS, + .entries = alp442_control_choice_clk_src_entries, + .entries_values = alp442_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp442_control_choice_clk_src_entries), + }, + }, + /* Current Clock Value Read Only */ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALPMC_CLK_MANAGER_BASE, + .prefix = "Clk Eff", + .access = SNDRV_CTL_ELEM_ACCESS_READ | + SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .data.choice = { + .offset = ALPMC_CLK_MANAGER_CONFIG_REG, + .mask = ALPMC_CLK_MANAGER_CONFIG_CLK_CURRENT_VALUE_MASK, + .pos = ALPMC_CLK_MANAGER_CONFIG_CLK_CURRENT_VALUE_POS, + .entries = alpxxx_control_choice_current_clk_values_entries, + .entries_values = alpxxx_control_choice_current_clk_values_entries_values, + .entries_count = ARRAY_SIZE(alpxxx_control_choice_current_clk_values_entries), + }, + }, + + /* Current Clock factor values Read Only, RESERVED now to keep ids order */ + { + .type = ALPX_CONTROL_RESERVED, + .base = ALPMC_CLK_MANAGER_BASE, + .prefix = "RESERVED", + .access = SNDRV_CTL_ELEM_ACCESS_READ, + }, + /* Clock UP on fail over enabled flag */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALP_PROC_BASE, + .prefix = "Clk Src Up", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALP_PROC_FWCONFIG_REG, + .mask = ALP_PROC_FWCONFIG_CLKSRC_UP_MASK, + .pos = ALP_PROC_FWCONFIG_CLKSRC_UP_POS, + }, + }, + /* Clock DOWN on fail over enabled flag */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALP_PROC_BASE, + .prefix = "Clk Src Down", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALP_PROC_FWCONFIG_REG, + .mask = ALP_PROC_FWCONFIG_CLKSRC_DOWN_MASK, + .pos = ALP_PROC_FWCONFIG_CLKSRC_DOWN_POS, + }, + }, + /* Clock Failover priority 0 TOP*/ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P0", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO0_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO0_POS, + .entries = alp442_control_choice_clk_src_entries, + .entries_values = alp442_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp442_control_choice_clk_src_entries), + }, + }, + /* Clock Failover priority 1 */ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P1", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO1_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO1_POS, + .entries = alp442_control_choice_clk_src_entries, + .entries_values = alp442_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp442_control_choice_clk_src_entries), + }, + }, + /* Clock Failover priority 2*/ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P2", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO2_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO2_POS, + .entries = alp442_control_choice_clk_src_entries, + .entries_values = alp442_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp442_control_choice_clk_src_entries), + }, + }, + /* Clock Failover priority 3*/ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P3", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO3_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO3_POS, + .entries = alp442_control_choice_clk_src_entries, + .entries_values = alp442_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp442_control_choice_clk_src_entries), + }, + }, + /* Auto AES SRC disable SAME as Alp882 except for qty*/ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "AES SRC 1/2 Disable", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALPMC_CODEC_AES_SRC_CONTROL_REG, + .mask = ALPMC_CODEC_AES_SRC_1_2_MASK, + .pos = ALPMC_CODEC_AES_SRC_1_2_POS, + }, + }, + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "AES SRC 3/4 Disable", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALPMC_CODEC_AES_SRC_CONTROL_REG, + .mask = ALPMC_CODEC_AES_SRC_3_4_MASK, + .pos = ALPMC_CODEC_AES_SRC_3_4_POS, + }, + }, + /* Codec Input Gain for MIC Option SAME as 882 execpt for qty*/ + { + .type = ALPX_CONTROL_TYPE_ANALOG_EQ, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "Codec MIC Analog Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.codec = { + .offset = ALPMC_CODEC_PGA_REGS, + .gains_scale = alpmc_mic_control_codec_gains_scale, + .reg_gain_min = ALPMC_MIC_ANALOG_GAIN_MIN_REG, + .reg_gain_max = ALPMC_MIC_ANALOG_GAIN_MAX_REG, + .lines_count = ALP442_CHANNELS_ANALOG_COUNT, + }, + }, + /** MIC Phantoms SAME as 882 except for qty **/ + /* MIC Phantom 1 */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "McPh1", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.mic_flags = { + .offset = ALPMC_INPUT_PARAMS_REG, + .mask = ALPMC_MIC_INPUT_PH_1_MASK, + .pos = ALPMC_MIC_INPUT_PH_1_POS, + }, + }, + /* MIC Phantom 2 */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "McPh2", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.mic_flags = { + .offset = ALPMC_INPUT_PARAMS_REG, + .mask = ALPMC_MIC_INPUT_PH_2_MASK, + .pos = ALPMC_MIC_INPUT_PH_2_POS, + }, + }, + /* MIC Phantom 3 */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "McPh3", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.mic_flags = { + .offset = ALPMC_INPUT_PARAMS_REG, + .mask = ALPMC_MIC_INPUT_PH_3_MASK, + .pos = ALPMC_MIC_INPUT_PH_3_POS, + }, + }, + /* MIC Phantom 4 */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALPMC_CODEC_CTRL_BASE, + .prefix = "McPh4", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.mic_flags = { + .offset = ALPMC_INPUT_PARAMS_REG, + .mask = ALPMC_MIC_INPUT_PH_4_MASK, + .pos = ALPMC_MIC_INPUT_PH_4_POS, + }, + }, +}; + + +static struct alpx_variant alp442_mic_variant __attribute__((unused)) = { + .shortname = "Alp442e-MIC", + .longname = "Alp 442e MIC", + .model = ALPX_VARIANT_MODEL_ALP442_MIC, + .mixername = "Alp442e_MIC_Mix", + .features = ALPX_VARIANT_FEATURE_GPIOS, + .control_descriptors = alp442_mic_control_descriptors, + .control_descriptors_count = ARRAY_SIZE(alp442_mic_control_descriptors), + + .capture_hw = &alp442_hardware_specs, + .playback_hw = &alp442_hardware_specs, + + .flash_golden_production_base = ALPxxx_FLASH_GOLDEN_PRODUCTION_BASE, + + .gpios = {/* Same as 882 */ + .base = ALPMC_GPIO_BASE, + .inputs_reg_offset = ALPMC_GPIO_INPUT_REG, + .inputs_qty = ALPMC_GPIO_INPUT_QTY, + .outputs_reg_offset = ALPMC_GPIO_OUTPUT_REG, + .outputs_qty = ALPMC_GPIO_OUTPUT_QTY, + }, + + .flash_partitions.partitions = alpx_mtd_partitions, + .flash_partitions.qty = ARRAY_SIZE(alpx_mtd_partitions), + .flash_partitions.qty_for_fw_update = 1, +}; + + +#endif /* _ALPX_VARIANTS_MC_H_ */ diff --git a/snd-alpx-dkms/snd-alpx/alpx_variants_stereo.h b/snd-alpx-dkms/snd-alpx/alpx_variants_stereo.h new file mode 100644 index 0000000..aae4120 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/alpx_variants_stereo.h @@ -0,0 +1,709 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* +* Support for Digigram AlpX PCI-e boards +* +* Copyright (c) 2024 Digigram Digital (info@digigram.com) +*/ + +#ifndef _ALPX_VARIANTS_STEREO_H_ +#define _ALPX_VARIANTS_STEREO_H_ + +#include "alpx.h" +#include "alpx_reg.h" + +#include <sound/tlv.h> +#include "alpx_variants_common.h" + +/* Specifications of stereo cards */ + +/* Alp222 clock controls */ +static const char *alp222_control_choice_clk_src_entries[ALP222_CLK_MANAGER_CLK_SRC_QTY] = { + "Internal","SIC","Word Clk", "AES Syn", "AES Aud", +}; + +/* Same order than the constants values */ +static u32 alp222_control_choice_clk_src_entries_values[ALP222_CLK_MANAGER_CLK_SRC_QTY] = { + ALP222_CLK_MANAGER_CLK_SRC_INTERNAL, + ALP222_CLK_MANAGER_CLK_SRC_SIC, + ALP222_CLK_MANAGER_CLK_SRC_WCLK, + ALP222_CLK_MANAGER_CLK_SRC_AES_SYNC, + ALP222_CLK_MANAGER_CLK_SRC_AES_AUDIO, +}; + + +/** 222 **/ +static struct snd_pcm_hardware alp222_hardware_specs = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_RESUME, + .formats = SNDRV_PCM_FMTBIT_S32_LE, + .rates = SNDRV_PCM_RATE_CONTINUOUS | + SNDRV_PCM_RATE_8000_192000, + .rate_min = 8000, + .rate_max = 192000, + .channels_min = 4, + .channels_max = 4, + .buffer_bytes_max = 64 * SZ_1K * 4, /* period_bytes_max * periods_max */ + .period_bytes_min = 48, /* min latency 1ms */ + .period_bytes_max = 64 * SZ_1K, /* 20ms at 192kHz * nchans * 4B, rounded at 2^n */ + .periods_min = 1, + .periods_max = 4, +}; + + +/* Alp 222e LINE */ + +static const DECLARE_TLV_DB_MINMAX_MUTE(alp222_line_analog_gains_scale, + ALP222_ANALOG_EQ_GAIN_MIN_cdB, + ALP222_ANALOG_EQ_GAIN_MAX_cdB); + +/* Note : use ALPX_GAIN_REG(0) to jump to the actual parameters's registers */ +static struct alpx_control_descriptor alp222_control_descriptors[] = { + /* INPUT Amplification */ + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALP222_ANALOG_CAPTURE_AMPLI_BASE, + .prefix = "Ana Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP222_ANALOG_QTY, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALP222_AES3_CAPTURE_AMPLI_BASE, + .prefix = "AES Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP222_AES3_QTY, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALP222_DAW_PLAYBACK_AMPLI_BASE, + .prefix = "DAW Playback", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP222_DAW_QTY, + }, + }, + /* OUTPUT Amplification*/ + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALP222_ANALOG_PLAYBACK_AMPLI_BASE, + .prefix = "Ana Playback", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP222_ANALOG_QTY, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALP222_AES3_PLAYBACK_AMPLI_BASE, + .prefix = "AES Playback", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP222_AES3_QTY, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALP222_DAW_CAPTURE_AMPLI_BASE , + .prefix = "DAW Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP222_DAW_QTY, + }, + }, + + /* Analog Eq */ +{ + .type = ALPX_CONTROL_TYPE_ANALOG_EQ, + .base = ALP222_CODEC_CTRL_BASE, + .prefix = "Codec Analog Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.codec = { + .offset = ALP222_CODEC_PGA_REGS, + .gains_scale = alp222_line_analog_gains_scale, + .reg_gain_min = ALP222_ANALOG_EQ_GAIN_MIN_REG, + .reg_gain_max = ALP222_ANALOG_EQ_GAIN_MAX_REG, + .lines_count = ALP222_ANALOG_QTY, + }, +}, + /* Mixer */ + { + .type = ALPX_CONTROL_TYPE_MIXER, + .base = ALP222_MIXER_BASE, + .prefix = "Mxr", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE| + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.mixer = { + .lines_count = ALP222_MIXER_SIZE, + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + }, + }, + + /* Clock sources Read Only */ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALP222_CLK_MANAGER_BASE, + .prefix = "Clk Src", + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .data.choice = { + .offset = ALP222_CLK_MANAGER_CONFIG_REG, + .mask = ALP222_CLK_MANAGER_CLK_SRC_MASK, + .pos = ALP222_CLK_MANAGER_CLK_SRC_POS, + .entries = alp222_control_choice_clk_src_entries, + .entries_values = alp222_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp222_control_choice_clk_src_entries), + }, + }, + /* Current Clock BASE Value Read Only */ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALP222_CLK_MANAGER_BASE, + .prefix = "Clk Eff", + .access = SNDRV_CTL_ELEM_ACCESS_READ | + SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .data.choice = { + .offset = ALP222_CLK_MANAGER_CONFIG_REG, + .mask = ALP222_CLK_MANAGER_CONFIG_CLK_CURRENT_VALUE_MASK, + .pos = ALP222_CLK_MANAGER_CONFIG_CLK_CURRENT_VALUE_POS, + .entries = alpxxx_control_choice_current_clk_values_entries, + .entries_values = alpxxx_control_choice_current_clk_values_entries_values, + .entries_count = ARRAY_SIZE(alpxxx_control_choice_current_clk_values_entries), + }, + }, + /* Current Clock factor values Read Only : RESERVED to keep id order*/ + { + .type = ALPX_CONTROL_RESERVED, + .base = ALP222_CLK_MANAGER_BASE, + .prefix = "RESERVED", + .access = SNDRV_CTL_ELEM_ACCESS_READ, + }, + /* AES SRC */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALP222_CODEC_CTRL_BASE, + .prefix = "AES SRC Disable", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALP222_CODEC_CTRL_ASRC_REG, + .mask = ALP222_CODEC_CTRL_ASRC_MASK, + .pos = ALP222_CODEC_CTRL_ASRC_POS, + }, + }, + /* Clock UP on fail over enabled flag */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALP_PROC_BASE, + .prefix = "CkSc Up", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALP_PROC_FWCONFIG_REG, + .mask = ALP_PROC_FWCONFIG_CLKSRC_UP_MASK, + .pos = ALP_PROC_FWCONFIG_CLKSRC_UP_POS, + }, + }, + /* Clock DOWN on fail over enabled flag */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALP_PROC_BASE, + .prefix = "CkSc Down", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALP_PROC_FWCONFIG_REG, + .mask = ALP_PROC_FWCONFIG_CLKSRC_DOWN_MASK, + .pos = ALP_PROC_FWCONFIG_CLKSRC_DOWN_POS, + }, + }, + /* Clock Failover priority 0 TOP*/ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P0", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO0_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO0_POS, + .entries = alp222_control_choice_clk_src_entries, + .entries_values = alp222_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp222_control_choice_clk_src_entries), + }, + }, + /* Clock Failover priority 1 */ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P1", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO1_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO1_POS, + .entries = alp222_control_choice_clk_src_entries, + .entries_values = alp222_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp222_control_choice_clk_src_entries), + }, + }, + /* Clock Failover priority 2*/ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P2", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO2_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO2_POS, + .entries = alp222_control_choice_clk_src_entries, + .entries_values = alp222_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp222_control_choice_clk_src_entries), + }, + }, + /* Clock Failover priority 3 Bottom*/ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P3", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO3_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO3_POS, + .entries = alp222_control_choice_clk_src_entries, + .entries_values = alp222_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp222_control_choice_clk_src_entries), + }, + }, +}; + +static struct alpx_variant alp222_variant __attribute__((unused)) = { + .shortname = "Alp222e", + .longname = "Alp 222e", + .model = ALPX_VARIANT_MODEL_ALP222, + .mixername = "Alp222e_Mix", + .features = ALPX_VARIANT_FEATURE_GPIOS, + .control_descriptors = alp222_control_descriptors, + .control_descriptors_count = ARRAY_SIZE(alp222_control_descriptors), + + .capture_hw = &alp222_hardware_specs, + .playback_hw = &alp222_hardware_specs, + + .flash_golden_production_base = ALPxxx_FLASH_GOLDEN_PRODUCTION_BASE, + + .gpios = { + .base = ALP222_GPIO_BASE, + .inputs_reg_offset = ALP222_GPIO_INPUT_REG, + .inputs_qty = ALP222_GPIO_INPUT_QTY, + .outputs_reg_offset = ALP222_GPIO_OUTPUT_REG, + .outputs_qty = ALP222_GPIO_OUTPUT_QTY, + }, + + .flash_partitions.partitions = alpx_mtd_partitions, + .flash_partitions.qty = ARRAY_SIZE(alpx_mtd_partitions), + .flash_partitions.qty_for_fw_update = 1, +}; + + +/* Alp 222e-MIC Variant definition */ + +static const DECLARE_TLV_DB_MINMAX_MUTE(alp222_mic_control_scale, + ALP222_MIC_GAIN_MIN_cdB, + ALP222_MIC_GAIN_MAX_cdB); + +/* Alp222 MIC controls : superset of Alp222 controls. Don't know how to embed an array into antother as first items ? */ +/* So I've copied the items !! */ +static struct alpx_control_descriptor alp222_mic_control_descriptors[] = { + /* INPUT Amplification */ + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALP222_ANALOG_CAPTURE_AMPLI_BASE, + .prefix = "Ana Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP222_ANALOG_QTY, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALP222_AES3_CAPTURE_AMPLI_BASE, + .prefix = "AES Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP222_AES3_QTY, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALP222_DAW_PLAYBACK_AMPLI_BASE, + .prefix = "DAW Playback", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP222_DAW_QTY, + }, + }, + /* OUTPUT Amplification*/ + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALP222_ANALOG_PLAYBACK_AMPLI_BASE, + .prefix = "Ana Playback", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP222_ANALOG_QTY, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALP222_AES3_PLAYBACK_AMPLI_BASE, + .prefix = "AES Playback", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP222_AES3_QTY, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALP222_DAW_CAPTURE_AMPLI_BASE , + .prefix = "DAW Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP222_DAW_QTY, + }, + }, + + /* Analog Eq */ +{ + .type = ALPX_CONTROL_TYPE_ANALOG_EQ, + .base = ALP222_CODEC_CTRL_BASE, + .prefix = "Codec Analog Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.codec = { + .offset = ALP222_CODEC_PGA_REGS, + .gains_scale = alp222_line_analog_gains_scale, + .reg_gain_min = ALP222_ANALOG_EQ_GAIN_MIN_REG, + .reg_gain_max = ALP222_ANALOG_EQ_GAIN_MAX_REG, + .lines_count = ALP222_ANALOG_QTY, + }, +}, + /* Mixer */ + { + .type = ALPX_CONTROL_TYPE_MIXER, + .base = ALP222_MIXER_BASE, + .prefix = "Mxr", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.mixer = { + .lines_count = ALP222_MIXER_SIZE, + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + }, + }, + + /* Clock sources Read Only */ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALP222_CLK_MANAGER_BASE, + .prefix = "Clk Src", + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .data.choice = { + .offset = ALP222_CLK_MANAGER_CONFIG_REG, + .mask = ALP222_CLK_MANAGER_CLK_SRC_MASK, + .pos = ALP222_CLK_MANAGER_CLK_SRC_POS, + .entries = alp222_control_choice_clk_src_entries, + .entries_values = alp222_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp222_control_choice_clk_src_entries), + }, + }, + /* Current Clock BASE Value Read Only */ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALP222_CLK_MANAGER_BASE, + .prefix = "Clk Eff", + .access = SNDRV_CTL_ELEM_ACCESS_READ | + SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .data.choice = { + .offset = ALP222_CLK_MANAGER_CONFIG_REG, + .mask = ALP222_CLK_MANAGER_CONFIG_CLK_CURRENT_VALUE_MASK, + .pos = ALP222_CLK_MANAGER_CONFIG_CLK_CURRENT_VALUE_POS, + .entries = alpxxx_control_choice_current_clk_values_entries, + .entries_values = alpxxx_control_choice_current_clk_values_entries_values, + .entries_count = ARRAY_SIZE(alpxxx_control_choice_current_clk_values_entries), + }, + }, + /* Current Clock factor values Read Only RESERVED to keep id order */ + { + .type = ALPX_CONTROL_RESERVED, + .base = ALP222_CLK_MANAGER_BASE, + .prefix = "RESERVED", + .access = SNDRV_CTL_ELEM_ACCESS_READ, + }, + /* AES SRC */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALP222_CODEC_CTRL_BASE, + .prefix = "AES SRC", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALP222_CODEC_CTRL_ASRC_REG, + .mask = ALP222_CODEC_CTRL_ASRC_MASK, + .pos = ALP222_CODEC_CTRL_ASRC_POS, + }, + }, + + /* Clock UP on fail over enabled flag */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALP_PROC_BASE, + .prefix = "CkSc Up", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALP_PROC_FWCONFIG_REG, + .mask = ALP_PROC_FWCONFIG_CLKSRC_UP_MASK, + .pos = ALP_PROC_FWCONFIG_CLKSRC_UP_POS, + }, + }, + /* Clock DOWN on fail over enabled flag */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALP_PROC_BASE, + .prefix = "CkSc Down", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALP_PROC_FWCONFIG_REG, + .mask = ALP_PROC_FWCONFIG_CLKSRC_DOWN_MASK, + .pos = ALP_PROC_FWCONFIG_CLKSRC_DOWN_POS, + }, + }, + /* Clock Failover priority 0 TOP*/ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P0", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO0_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO0_POS, + .entries = alp222_control_choice_clk_src_entries, + .entries_values = alp222_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp222_control_choice_clk_src_entries), + }, + }, + /* Clock Failover priority 1 */ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P1", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO1_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO1_POS, + .entries = alp222_control_choice_clk_src_entries, + .entries_values = alp222_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp222_control_choice_clk_src_entries), + }, + }, + /* Clock Failover priority 2*/ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P2", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO2_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO2_POS, + .entries = alp222_control_choice_clk_src_entries, + .entries_values = alp222_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp222_control_choice_clk_src_entries), + }, + }, + /* Clock Failover priority 3 Bottom*/ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P3", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO3_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO3_POS, + .entries = alp222_control_choice_clk_src_entries, + .entries_values = alp222_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp222_control_choice_clk_src_entries), + }, + }, +/* MIC INPUT Amplification (the gains MUST BE KEPT FIRST, control initialization)*/ + { + .type = ALPX_CONTROL_TYPE_GAINS_EMBEDDED, + .base = ALP222_CONTROL_BASE, + .prefix = "McGaL Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.mic_gains = { + .min = ALP222_MIC_GAINS_MIN_REG_VAL, + .max = ALP222_MIC_GAINS_MAX_REG_VAL, + .lines_count = 1, /* Only one line per mic side on 222e*/ + .offset = ALP222_MIC_CONTROL_REG, + .mask = ALP222_MIC_GAIN_L_MASK, + .pos = ALP222_MIC_GAIN_L_POS, + .width = ALP222_MIC_GAIN_WIDTH, + .gains_scale = alp222_mic_control_scale, + }, + }, + { + .type = ALPX_CONTROL_TYPE_GAINS_EMBEDDED, + .base = ALP222_CONTROL_BASE, + .prefix = "McGaR Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.mic_gains = { + .min = ALP222_MIC_GAINS_MIN_REG_VAL, + .max = ALP222_MIC_GAINS_MAX_REG_VAL, + .lines_count = 1, /* Only one line per mic side on 222e*/ + .offset = ALP222_MIC_CONTROL_REG, + .mask = ALP222_MIC_GAIN_R_MASK, + .pos = ALP222_MIC_GAIN_R_POS, + .width = ALP222_MIC_GAIN_WIDTH, + .gains_scale = alp222_mic_control_scale, + }, + }, + /* MIC Phantom */ + { + .type = ALPX_CONTROL_TYPE_FLAGS_EMBEDDED, + .base = ALP222_CONTROL_BASE, + .prefix = "McPhL", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.mic_flags = { + .offset = ALP222_MIC_CONTROL_REG, + .mask = ALP222_MIC_PH_L_MASK, + .pos = ALP222_MIC_PH_L_POS, + .lines_count = 1, // Should be if control items[i] was Ok : ALP222_ANALOG_QTY, + }, + }, + { + .type = ALPX_CONTROL_TYPE_FLAGS_EMBEDDED, + .base = ALP222_CONTROL_BASE, + .prefix = "McPhR", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.mic_flags = { + .offset = ALP222_MIC_CONTROL_REG, + .mask = ALP222_MIC_PH_R_MASK, + .pos = ALP222_MIC_PH_R_POS, + .lines_count = 1, // Should be if control items[i] was Ok : ALP222_ANALOG_QTY, + }, + }, + /* MIC Enable*/ + { + .type = ALPX_CONTROL_TYPE_FLAGS_EMBEDDED, + .base = ALP222_CONTROL_BASE, + .prefix = "McEnL", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.mic_flags = { + .offset = ALP222_MIC_CONTROL_REG, + .mask = ALP222_MIC_EN_L_MASK, + .pos = ALP222_MIC_EN_L_POS, + .lines_count = 1, // Should be if control items[i] was Ok : ALP222_ANALOG_QTY, + }, + }, + { + .type = ALPX_CONTROL_TYPE_FLAGS_EMBEDDED, + .base = ALP222_CONTROL_BASE, + .prefix = "McEnR", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.mic_flags = { + .offset = ALP222_MIC_CONTROL_REG, + .mask = ALP222_MIC_EN_R_MASK, + .pos = ALP222_MIC_EN_R_POS, + .lines_count = 1, // Should be if control items[i] was Ok : ALP222_ANALOG_QTY, + }, + }, +}; + + +static struct alpx_variant alp222_mic_variant __attribute__((unused)) = { + .shortname = "Alp222e-MIC", + .longname = "Alp 222e-MIC", + .model = ALPX_VARIANT_MODEL_ALP222_MIC, + .mixername = "Alp222e_MIC_Mix", + .features = ALPX_VARIANT_FEATURE_GPIOS, + .control_descriptors = alp222_mic_control_descriptors, + .control_descriptors_count = ARRAY_SIZE(alp222_mic_control_descriptors), + + .capture_hw = &alp222_hardware_specs, + .playback_hw = &alp222_hardware_specs, + + .flash_golden_production_base = ALPxxx_FLASH_GOLDEN_PRODUCTION_BASE, + + .gpios = { + .base = ALP222_GPIO_BASE, + .inputs_reg_offset = ALP222_GPIO_INPUT_REG, + .inputs_qty = ALP222_GPIO_INPUT_QTY, + .outputs_reg_offset = ALP222_GPIO_OUTPUT_REG, + .outputs_qty = ALP222_GPIO_OUTPUT_QTY, + }, + + .flash_partitions.partitions = alpx_mtd_partitions, + .flash_partitions.qty = ARRAY_SIZE(alpx_mtd_partitions), + .flash_partitions.qty_for_fw_update = 1, +}; + +#endif /* _ALPX_VARIANTS_STEREO_H_ */ diff --git a/snd-alpx-dkms/snd-alpx/alpx_variants_stereo_apps_preFW283.h b/snd-alpx-dkms/snd-alpx/alpx_variants_stereo_apps_preFW283.h new file mode 100644 index 0000000..d5019f9 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/alpx_variants_stereo_apps_preFW283.h @@ -0,0 +1,737 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* +* Support for Digigram AlpX PCI-e boards +* +* Copyright (c) 2024 Digigram Digital (info@digigram.com) +*/ + +#ifndef _ALPX_VARIANTS_STEREO_APP_PREFW283_H_ +#define _ALPX_VARIANTS_STEREO_APP_PREFW283_H_ + +#include "alpx.h" +#include "alpx_reg.h" + +#include <sound/tlv.h> +#include "alpx_variants_common.h" + +/* Specifications of stereo cards */ +/** Pre FW V283 for compatibility with OLD applications Translation tables FOR CLOCK sources !!*/ + +/* Alp222 clock controls */ +static const char *alp222_app_preFW283_control_choice_clk_src_entries[ALP222_APPS_PREFW283_CLK_MANAGER_CLK_SRC_QTY] = { + "Word Clk", "AES Syn", "AES Aud", "Internal", +}; + +/* Index is application side index, items is the register ones*/ +static u32 alp222_app_preFW283_control_choice_clk_src_entries_values[ALP222_APPS_PREFW283_CLK_MANAGER_CLK_SRC_QTY] = { + ALP222_CLK_MANAGER_CLK_SRC_WCLK, + ALP222_CLK_MANAGER_CLK_SRC_AES_SYNC, + ALP222_CLK_MANAGER_CLK_SRC_AES_AUDIO, + ALP222_CLK_MANAGER_CLK_SRC_INTERNAL, +}; + +/* Indexed by the register => application side value */ +static u32 alp222_app_preFW283_to_apps_control_choice_clk_src_entries_values [ALP222_CLK_MANAGER_CLK_SRC_QTY] = { + ALP222_CLK_MANAGER_APPSPREFW283_CLK_SRC_INTERNAL, + ALP222_CLK_MANAGER_APPSPREFW283_CLK_SRC_INTERNAL, /* FORBIDDEN VALUE => INTERNAL !!*/ + ALP222_CLK_MANAGER_APPSPREFW283_CLK_SRC_WCLK, + ALP222_CLK_MANAGER_APPSPREFW283_CLK_SRC_AES_SYNC, + ALP222_CLK_MANAGER_APPSPREFW283_CLK_SRC_AES_AUDIO, +}; + +/** 222 **/ +static struct snd_pcm_hardware alp222_app_preFW283_hardware_specs = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_RESUME, + .formats = SNDRV_PCM_FMTBIT_S32_LE, + .rates = SNDRV_PCM_RATE_CONTINUOUS | + SNDRV_PCM_RATE_8000_192000, + .rate_min = 8000, + .rate_max = 192000, + .channels_min = 4, + .channels_max = 4, + .buffer_bytes_max = 64 * SZ_1K * 4, /* period_bytes_max * periods_max */ + .period_bytes_min = 48, /* min latency 1ms */ + .period_bytes_max = 64 * SZ_1K, /* 20ms at 192kHz * nchans * 4B, rounded at 2^n */ + .periods_min = 1, + .periods_max = 4, +}; + + +/* Alp 222e LINE */ + +static const DECLARE_TLV_DB_MINMAX_MUTE(alp222_app_preFW283_line_analog_gains_scale, + ALP222_ANALOG_EQ_GAIN_MIN_cdB, + ALP222_ANALOG_EQ_GAIN_MAX_cdB); + +/* Note : use ALPX_GAIN_REG(0) to jump to the actual parameters's registers */ +static struct alpx_control_descriptor alp222_app_preFW283_line_control_descriptors[] = { + /* INPUT Amplification */ + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALP222_ANALOG_CAPTURE_AMPLI_BASE, + .prefix = "Ana Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP222_ANALOG_QTY, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALP222_AES3_CAPTURE_AMPLI_BASE, + .prefix = "AES Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP222_AES3_QTY, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALP222_DAW_PLAYBACK_AMPLI_BASE, + .prefix = "DAW Playback", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP222_DAW_QTY, + }, + }, + /* OUTPUT Amplification*/ + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALP222_ANALOG_PLAYBACK_AMPLI_BASE, + .prefix = "Ana Playback", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP222_ANALOG_QTY, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALP222_AES3_PLAYBACK_AMPLI_BASE, + .prefix = "AES Playback", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP222_AES3_QTY, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALP222_DAW_CAPTURE_AMPLI_BASE , + .prefix = "DAW Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP222_DAW_QTY, + }, + }, + + /* Analog Eq */ +{ + .type = ALPX_CONTROL_TYPE_ANALOG_EQ, + .base = ALP222_CODEC_CTRL_BASE, + .prefix = "Codec Analog Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.codec = { + .offset = ALP222_CODEC_PGA_REGS, + .gains_scale = alp222_app_preFW283_line_analog_gains_scale, + .reg_gain_min = ALP222_ANALOG_EQ_GAIN_MIN_REG, + .reg_gain_max = ALP222_ANALOG_EQ_GAIN_MAX_REG, + .lines_count = ALP222_ANALOG_QTY, + }, +}, + /* Mixer */ + { + .type = ALPX_CONTROL_TYPE_MIXER, + .base = ALP222_MIXER_BASE, + .prefix = "Mxr", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE| + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.mixer = { + .lines_count = ALP222_MIXER_SIZE, + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + }, + }, + + /* Clock sources Read Only */ + { + .type = ALPX_CONTROL_TYPE_TRANSLATED_CHOICE, + .base = ALP222_CLK_MANAGER_BASE, + .prefix = "Clk Src", + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .data.translated_choice = { + .offset = ALP222_CLK_MANAGER_CONFIG_REG, + .mask = ALP222_CLK_MANAGER_CLK_SRC_MASK, + .pos = ALP222_CLK_MANAGER_CLK_SRC_POS, + .entries = alp222_app_preFW283_control_choice_clk_src_entries, + .entries_values = alp222_app_preFW283_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp222_app_preFW283_control_choice_clk_src_entries), + .card_entries_values = alp222_app_preFW283_to_apps_control_choice_clk_src_entries_values, + .card_entries_count = ARRAY_SIZE(alp222_app_preFW283_to_apps_control_choice_clk_src_entries_values) + }, + }, + /* Current Clock BASE Value Read Only */ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALP222_CLK_MANAGER_BASE, + .prefix = "Clk Eff", + .access = SNDRV_CTL_ELEM_ACCESS_READ | + SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .data.choice = { + .offset = ALP222_CLK_MANAGER_CONFIG_REG, + .mask = ALP222_CLK_MANAGER_CONFIG_CLK_CURRENT_VALUE_MASK, + .pos = ALP222_CLK_MANAGER_CONFIG_CLK_CURRENT_VALUE_POS, + .entries = alpxxx_control_choice_current_clk_values_entries, + .entries_values = alpxxx_control_choice_current_clk_values_entries_values, + .entries_count = ARRAY_SIZE(alpxxx_control_choice_current_clk_values_entries), + }, + }, + /* Current Clock factor values Read Only : RESERVED to keep id order*/ + { + .type = ALPX_CONTROL_RESERVED, + .base = ALP222_CLK_MANAGER_BASE, + .prefix = "RESERVED", + .access = SNDRV_CTL_ELEM_ACCESS_READ, + }, + /* AES SRC */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALP222_CODEC_CTRL_BASE, + .prefix = "AES SRC Disable", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALP222_CODEC_CTRL_ASRC_REG, + .mask = ALP222_CODEC_CTRL_ASRC_MASK, + .pos = ALP222_CODEC_CTRL_ASRC_POS, + }, + }, + /* Clock UP on fail over enabled flag */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALP_PROC_BASE, + .prefix = "CkSc Up", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALP_PROC_FWCONFIG_REG, + .mask = ALP_PROC_FWCONFIG_CLKSRC_UP_MASK, + .pos = ALP_PROC_FWCONFIG_CLKSRC_UP_POS, + }, + }, + /* Clock DOWN on fail over enabled flag */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALP_PROC_BASE, + .prefix = "CkSc Down", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALP_PROC_FWCONFIG_REG, + .mask = ALP_PROC_FWCONFIG_CLKSRC_DOWN_MASK, + .pos = ALP_PROC_FWCONFIG_CLKSRC_DOWN_POS, + }, + }, + /* Clock Failover priority 0 TOP*/ + { + .type = ALPX_CONTROL_TYPE_TRANSLATED_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P0", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.translated_choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO0_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO0_POS, + .entries = alp222_app_preFW283_control_choice_clk_src_entries, + .entries_values = alp222_app_preFW283_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp222_app_preFW283_control_choice_clk_src_entries), + .card_entries_values = alp222_app_preFW283_to_apps_control_choice_clk_src_entries_values, + .card_entries_count = ARRAY_SIZE(alp222_app_preFW283_to_apps_control_choice_clk_src_entries_values) + }, + }, + /* Clock Failover priority 1 */ + { + .type = ALPX_CONTROL_TYPE_TRANSLATED_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P1", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.translated_choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO1_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO1_POS, + .entries = alp222_app_preFW283_control_choice_clk_src_entries, + .entries_values = alp222_app_preFW283_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp222_app_preFW283_control_choice_clk_src_entries), + .card_entries_values = alp222_app_preFW283_to_apps_control_choice_clk_src_entries_values, + .card_entries_count = ARRAY_SIZE(alp222_app_preFW283_to_apps_control_choice_clk_src_entries_values) + }, + }, + /* Clock Failover priority 2*/ + { + .type = ALPX_CONTROL_TYPE_TRANSLATED_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P2", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.translated_choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO2_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO2_POS, + .entries = alp222_app_preFW283_control_choice_clk_src_entries, + .entries_values = alp222_app_preFW283_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp222_app_preFW283_control_choice_clk_src_entries), + .card_entries_values = alp222_app_preFW283_to_apps_control_choice_clk_src_entries_values, + .card_entries_count = ARRAY_SIZE(alp222_app_preFW283_to_apps_control_choice_clk_src_entries_values) + }, + }, + /* Clock Failover priority 3 Bottom*/ + { + .type = ALPX_CONTROL_TYPE_TRANSLATED_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P3", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.translated_choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO3_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO3_POS, + .entries = alp222_app_preFW283_control_choice_clk_src_entries, + .entries_values = alp222_app_preFW283_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp222_app_preFW283_control_choice_clk_src_entries), + .card_entries_values = alp222_app_preFW283_to_apps_control_choice_clk_src_entries_values, + .card_entries_count = ARRAY_SIZE(alp222_app_preFW283_to_apps_control_choice_clk_src_entries_values) + }, + }, +}; + +static struct alpx_variant alp222_app_preFW283_variant __attribute__((unused)) = { + .shortname = "Alp222e", + .longname = "Alp 222e-comp", + .model = ALPX_VARIANT_MODEL_ALP222, + .mixername = "Alp222e_Mix", + .features = ALPX_VARIANT_FEATURE_GPIOS, + .control_descriptors = alp222_app_preFW283_line_control_descriptors, + .control_descriptors_count = ARRAY_SIZE(alp222_app_preFW283_line_control_descriptors), + + .capture_hw = &alp222_app_preFW283_hardware_specs, + .playback_hw = &alp222_app_preFW283_hardware_specs, + + .flash_golden_production_base = ALPxxx_FLASH_GOLDEN_PRODUCTION_BASE, + + .gpios = { + .base = ALP222_GPIO_BASE, + .inputs_reg_offset = ALP222_GPIO_INPUT_REG, + .inputs_qty = ALP222_GPIO_INPUT_QTY, + .outputs_reg_offset = ALP222_GPIO_OUTPUT_REG, + .outputs_qty = ALP222_GPIO_OUTPUT_QTY, + }, + + .flash_partitions.partitions = alpx_mtd_partitions, + .flash_partitions.qty = ARRAY_SIZE(alpx_mtd_partitions), + .flash_partitions.qty_for_fw_update = 1, +}; + + +/* Alp 222e-MIC Variant definition */ + +static const DECLARE_TLV_DB_MINMAX_MUTE(alp222_app_preFW283_mic_control_scale, + ALP222_MIC_GAIN_MIN_cdB, + ALP222_MIC_GAIN_MAX_cdB); + +/* Alp222 MIC controls : superset of Alp222 controls. Don't know how to embed an array into antother as first items ? */ +/* So I've copied the items !! */ +static struct alpx_control_descriptor alp222_app_preFW283_mic_control_descriptors[] = { + /* INPUT Amplification */ + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALP222_ANALOG_CAPTURE_AMPLI_BASE, + .prefix = "Ana Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP222_ANALOG_QTY, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALP222_AES3_CAPTURE_AMPLI_BASE, + .prefix = "AES Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP222_AES3_QTY, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALP222_DAW_PLAYBACK_AMPLI_BASE, + .prefix = "DAW Playback", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP222_DAW_QTY, + }, + }, + /* OUTPUT Amplification*/ + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALP222_ANALOG_PLAYBACK_AMPLI_BASE, + .prefix = "Ana Playback", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP222_ANALOG_QTY, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALP222_AES3_PLAYBACK_AMPLI_BASE, + .prefix = "AES Playback", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP222_AES3_QTY, + }, + }, + { + .type = ALPX_CONTROL_TYPE_AMPLIFIER, + .base = ALP222_DAW_CAPTURE_AMPLI_BASE , + .prefix = "DAW Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.ampli = { + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + .lines_count = ALP222_DAW_QTY, + }, + }, + + /* Analog Eq */ +{ + .type = ALPX_CONTROL_TYPE_ANALOG_EQ, + .base = ALP222_CODEC_CTRL_BASE, + .prefix = "Codec Analog Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.codec = { + .offset = ALP222_CODEC_PGA_REGS, + .gains_scale = alp222_app_preFW283_line_analog_gains_scale, + .reg_gain_min = ALP222_ANALOG_EQ_GAIN_MIN_REG, + .reg_gain_max = ALP222_ANALOG_EQ_GAIN_MAX_REG, + .lines_count = ALP222_ANALOG_QTY, + }, +}, + /* Mixer */ + { + .type = ALPX_CONTROL_TYPE_MIXER, + .base = ALP222_MIXER_BASE, + .prefix = "Mxr", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.mixer = { + .lines_count = ALP222_MIXER_SIZE, + .gains_scale = alpxxx_line_digital_gains_scale, + .reg_gain_min = ALP_AMPLIFIER_GAIN_MIN_REG, + .reg_gain_max = ALP_AMPLIFIER_GAIN_MAX_REG, + }, + }, + + /* Clock sources Read Only */ + { + .type = ALPX_CONTROL_TYPE_TRANSLATED_CHOICE, + .base = ALP222_CLK_MANAGER_BASE, + .prefix = "Clk Src", + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .data.translated_choice = { + .offset = ALP222_CLK_MANAGER_CONFIG_REG, + .mask = ALP222_CLK_MANAGER_CLK_SRC_MASK, + .pos = ALP222_CLK_MANAGER_CLK_SRC_POS, + .entries = alp222_app_preFW283_control_choice_clk_src_entries, + .entries_values = alp222_app_preFW283_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp222_app_preFW283_control_choice_clk_src_entries), + .card_entries_values = alp222_app_preFW283_to_apps_control_choice_clk_src_entries_values, + .card_entries_count = ARRAY_SIZE(alp222_app_preFW283_to_apps_control_choice_clk_src_entries_values) + }, + }, + /* Current Clock BASE Value Read Only */ + { + .type = ALPX_CONTROL_TYPE_CHOICE, + .base = ALP222_CLK_MANAGER_BASE, + .prefix = "Clk Eff", + .access = SNDRV_CTL_ELEM_ACCESS_READ | + SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .data.choice = { + .offset = ALP222_CLK_MANAGER_CONFIG_REG, + .mask = ALP222_CLK_MANAGER_CONFIG_CLK_CURRENT_VALUE_MASK, + .pos = ALP222_CLK_MANAGER_CONFIG_CLK_CURRENT_VALUE_POS, + .entries = alpxxx_control_choice_current_clk_values_entries, + .entries_values = alpxxx_control_choice_current_clk_values_entries_values, + .entries_count = ARRAY_SIZE(alpxxx_control_choice_current_clk_values_entries), + }, + }, + /* Current Clock factor values Read Only RESERVED to keep id order */ + { + .type = ALPX_CONTROL_RESERVED, + .base = ALP222_CLK_MANAGER_BASE, + .prefix = "RESERVED", + .access = SNDRV_CTL_ELEM_ACCESS_READ, + }, + /* AES SRC */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALP222_CODEC_CTRL_BASE, + .prefix = "AES SRC", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALP222_CODEC_CTRL_ASRC_REG, + .mask = ALP222_CODEC_CTRL_ASRC_MASK, + .pos = ALP222_CODEC_CTRL_ASRC_POS, + }, + }, + + /* Clock UP on fail over enabled flag */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALP_PROC_BASE, + .prefix = "CkSc Up", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALP_PROC_FWCONFIG_REG, + .mask = ALP_PROC_FWCONFIG_CLKSRC_UP_MASK, + .pos = ALP_PROC_FWCONFIG_CLKSRC_UP_POS, + }, + }, + /* Clock DOWN on fail over enabled flag */ + { + .type = ALPX_CONTROL_TYPE_FLAG, + .base = ALP_PROC_BASE, + .prefix = "CkSc Down", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.flag = { + .offset = ALP_PROC_FWCONFIG_REG, + .mask = ALP_PROC_FWCONFIG_CLKSRC_DOWN_MASK, + .pos = ALP_PROC_FWCONFIG_CLKSRC_DOWN_POS, + }, + }, + /* Clock Failover priority 0 TOP*/ + { + .type = ALPX_CONTROL_TYPE_TRANSLATED_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P0", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.translated_choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO0_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO0_POS, + .entries = alp222_app_preFW283_control_choice_clk_src_entries, + .entries_values = alp222_app_preFW283_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp222_app_preFW283_control_choice_clk_src_entries), + .card_entries_values = alp222_app_preFW283_to_apps_control_choice_clk_src_entries_values, + .card_entries_count = ARRAY_SIZE(alp222_app_preFW283_to_apps_control_choice_clk_src_entries_values) + }, + }, + /* Clock Failover priority 1 */ + { + .type = ALPX_CONTROL_TYPE_TRANSLATED_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P1", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.translated_choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO1_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO1_POS, + .entries = alp222_app_preFW283_control_choice_clk_src_entries, + .entries_values = alp222_app_preFW283_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp222_app_preFW283_control_choice_clk_src_entries), + .card_entries_values = alp222_app_preFW283_to_apps_control_choice_clk_src_entries_values, + .card_entries_count = ARRAY_SIZE(alp222_app_preFW283_to_apps_control_choice_clk_src_entries_values) + }, + }, + /* Clock Failover priority 2*/ + { + .type = ALPX_CONTROL_TYPE_TRANSLATED_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P2", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.translated_choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO2_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO2_POS, + .entries = alp222_app_preFW283_control_choice_clk_src_entries, + .entries_values = alp222_app_preFW283_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp222_app_preFW283_control_choice_clk_src_entries), + .card_entries_values = alp222_app_preFW283_to_apps_control_choice_clk_src_entries_values, + .card_entries_count = ARRAY_SIZE(alp222_app_preFW283_to_apps_control_choice_clk_src_entries_values) + }, + }, + /* Clock Failover priority 3 Bottom*/ + { + .type = ALPX_CONTROL_TYPE_TRANSLATED_CHOICE, + .base = ALP_PROC_BASE, + .prefix = "Clk P3", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.translated_choice = { + .offset = ALP_PROC_CLK_SOURCE_PRIO_REG, + .mask = ALP_PROC_CLK_SOURCE_PRIO3_MASK, + .pos = ALP_PROC_CLK_SOURCE_PRIO3_POS, + .entries = alp222_app_preFW283_control_choice_clk_src_entries, + .entries_values = alp222_app_preFW283_control_choice_clk_src_entries_values, + .entries_count = ARRAY_SIZE(alp222_app_preFW283_control_choice_clk_src_entries), + .card_entries_values = alp222_app_preFW283_to_apps_control_choice_clk_src_entries_values, + .card_entries_count = ARRAY_SIZE(alp222_app_preFW283_to_apps_control_choice_clk_src_entries_values) + }, + }, +/* MIC INPUT Amplification (the gains MUST BE KEPT FIRST, control initialization)*/ + { + .type = ALPX_CONTROL_TYPE_GAINS_EMBEDDED, + .base = ALP222_CONTROL_BASE, + .prefix = "McGaL Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.mic_gains = { + .min = ALP222_MIC_GAINS_MIN_REG_VAL, + .max = ALP222_MIC_GAINS_MAX_REG_VAL, + .lines_count = 1, /* Only one line per mic side on 222e*/ + .offset = ALP222_MIC_CONTROL_REG, + .mask = ALP222_MIC_GAIN_L_MASK, + .pos = ALP222_MIC_GAIN_L_POS, + .width = ALP222_MIC_GAIN_WIDTH, + .gains_scale = alp222_app_preFW283_mic_control_scale, + }, + }, + { + .type = ALPX_CONTROL_TYPE_GAINS_EMBEDDED, + .base = ALP222_CONTROL_BASE, + .prefix = "McGaR Capture", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .data.mic_gains = { + .min = ALP222_MIC_GAINS_MIN_REG_VAL, + .max = ALP222_MIC_GAINS_MAX_REG_VAL, + .lines_count = 1, /* Only one line per mic side on 222e*/ + .offset = ALP222_MIC_CONTROL_REG, + .mask = ALP222_MIC_GAIN_R_MASK, + .pos = ALP222_MIC_GAIN_R_POS, + .width = ALP222_MIC_GAIN_WIDTH, + .gains_scale = alp222_app_preFW283_mic_control_scale, + }, + }, + /* MIC Phantom */ + { + .type = ALPX_CONTROL_TYPE_FLAGS_EMBEDDED, + .base = ALP222_CONTROL_BASE, + .prefix = "McPhL", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.mic_flags = { + .offset = ALP222_MIC_CONTROL_REG, + .mask = ALP222_MIC_PH_L_MASK, + .pos = ALP222_MIC_PH_L_POS, + .lines_count = 1, // Should be if control items[i] was Ok : ALP222_ANALOG_QTY, + }, + }, + { + .type = ALPX_CONTROL_TYPE_FLAGS_EMBEDDED, + .base = ALP222_CONTROL_BASE, + .prefix = "McPhR", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.mic_flags = { + .offset = ALP222_MIC_CONTROL_REG, + .mask = ALP222_MIC_PH_R_MASK, + .pos = ALP222_MIC_PH_R_POS, + .lines_count = 1, // Should be if control items[i] was Ok : ALP222_ANALOG_QTY, + }, + }, + /* MIC Enable*/ + { + .type = ALPX_CONTROL_TYPE_FLAGS_EMBEDDED, + .base = ALP222_CONTROL_BASE, + .prefix = "McEnL", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.mic_flags = { + .offset = ALP222_MIC_CONTROL_REG, + .mask = ALP222_MIC_EN_L_MASK, + .pos = ALP222_MIC_EN_L_POS, + .lines_count = 1, // Should be if control items[i] was Ok : ALP222_ANALOG_QTY, + }, + }, + { + .type = ALPX_CONTROL_TYPE_FLAGS_EMBEDDED, + .base = ALP222_CONTROL_BASE, + .prefix = "McEnR", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .data.mic_flags = { + .offset = ALP222_MIC_CONTROL_REG, + .mask = ALP222_MIC_EN_R_MASK, + .pos = ALP222_MIC_EN_R_POS, + .lines_count = 1, // Should be if control items[i] was Ok : ALP222_ANALOG_QTY, + }, + }, +}; + + +static struct alpx_variant alp222_app_preFW283_mic_variant __attribute__((unused)) = { + .shortname = "Alp222e-MIC", + .longname = "Alp 222e-MIC-comp", + .model = ALPX_VARIANT_MODEL_ALP222_MIC, + .mixername = "Alp222e_MIC_Mix", + .features = ALPX_VARIANT_FEATURE_GPIOS, + .control_descriptors = alp222_app_preFW283_mic_control_descriptors, + .control_descriptors_count = ARRAY_SIZE(alp222_app_preFW283_mic_control_descriptors), + + .capture_hw = &alp222_app_preFW283_hardware_specs, + .playback_hw = &alp222_app_preFW283_hardware_specs, + + .flash_golden_production_base = ALPxxx_FLASH_GOLDEN_PRODUCTION_BASE, + + .gpios = { + .base = ALP222_GPIO_BASE, + .inputs_reg_offset = ALP222_GPIO_INPUT_REG, + .inputs_qty = ALP222_GPIO_INPUT_QTY, + .outputs_reg_offset = ALP222_GPIO_OUTPUT_REG, + .outputs_qty = ALP222_GPIO_OUTPUT_QTY, + }, + + .flash_partitions.partitions = alpx_mtd_partitions, + .flash_partitions.qty = ARRAY_SIZE(alpx_mtd_partitions), + .flash_partitions.qty_for_fw_update = 1, +}; + +#endif /* _ALPX_VARIANTS_STEREO_APP_PREFW283_H_ */ diff --git a/snd-alpx-dkms/snd-alpx/alpx_version.h b/snd-alpx-dkms/snd-alpx/alpx_version.h new file mode 100644 index 0000000..511e092 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/alpx_version.h @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* +* Support for Digigram AlpX PCI-e boards +* +* Copyright (c) 2024 Digigram Digital (info@digigram.com) +*/ + +/* Driver version definition */ +#define ALPX_MODULE_VERSION "3.4.3" diff --git a/snd-alpx-dkms/snd-alpx/alpx_xdma.c b/snd-alpx-dkms/snd-alpx/alpx_xdma.c new file mode 100644 index 0000000..c6b4bf2 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/alpx_xdma.c @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* +* Support for Digigram AlpX PCI-e boards +* +* Copyright (c) 2024 Digigram Digital (info@digigram.com) +*/ + +#include <linux/version.h> + +#include "alpx_xdma.h" + + +#if KERNEL_VERSION(6, 7, 0) > LINUX_VERSION_CODE +#include "core/generic/6.3/amd_xdma.h" +#include "include/6.3/amd_xdma.h" +#else +#include <linux/platform_data/amd_xdma.h> +#include <linux/dma/amd_xdma.h> +#endif + + +static struct xdma_chan_info alpx_xdma_chan_info[2] = { + [0].dir = DMA_MEM_TO_DEV, + [1].dir = DMA_DEV_TO_MEM, +}; + +struct alpx_xdma_platform_data { + struct resource resources[2]; + struct dma_slave_map map[2]; + struct xdma_platdata platdata; +}; + +struct platform_device *alpx_xdma_register(struct pci_dev *pci_dev) +{ + struct alpx_xdma_platform_data *data; + struct platform_device *xdma_pdev; + int nvectors, vector, ret; + + data = devm_kzalloc(&pci_dev->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return NULL; + + xdma_pdev = platform_device_alloc("xdma", PLATFORM_DEVID_AUTO); + if (!xdma_pdev) + return NULL; + + data->resources[0].start = pci_resource_start(pci_dev, 2); + data->resources[0].end = pci_resource_end(pci_dev, 2); + data->resources[0].flags = IORESOURCE_MEM; + + nvectors = pci_alloc_irq_vectors(pci_dev, 2, 2, + PCI_IRQ_MSIX | PCI_IRQ_MSI | PCI_IRQ_LEGACY); + if (nvectors < 0) + goto put_pdev; + + vector = pci_irq_vector(pci_dev, 0); + data->resources[1].start = vector; + data->resources[1].end = vector + nvectors - 1; + data->resources[1].flags = IORESOURCE_IRQ; + + ret = platform_device_add_resources(xdma_pdev, data->resources, + ARRAY_SIZE(data->resources)); + if (ret) + goto free_irq_vectors; + + data->map[0].devname = pci_name(pci_dev); + data->map[0].slave = "h2c-0"; + data->map[0].param = &alpx_xdma_chan_info[0]; + + data->map[1].devname = pci_name(pci_dev); + data->map[1].slave = "c2h-0"; + data->map[1].param = &alpx_xdma_chan_info[1]; + + data->platdata.max_dma_channels = 4; + data->platdata.device_map = data->map; + data->platdata.device_map_cnt = ARRAY_SIZE(data->map); + + ret = platform_device_add_data(xdma_pdev, &data->platdata, sizeof(data->platdata)); + if (ret) + goto free_irq_vectors; + + xdma_pdev->dev.parent = &pci_dev->dev; + + ret = platform_device_add(xdma_pdev); + if (ret) + goto free_irq_vectors; + + return xdma_pdev; + +free_irq_vectors: + pci_free_irq_vectors(pci_dev); +put_pdev: + platform_device_put(xdma_pdev); + + return NULL; +} + +void alpx_xdma_unregister(struct pci_dev *pci_dev, + struct platform_device *xdma_pdev) +{ + platform_device_unregister(xdma_pdev); + pci_free_irq_vectors(pci_dev); +} diff --git a/snd-alpx-dkms/snd-alpx/alpx_xdma.h b/snd-alpx-dkms/snd-alpx/alpx_xdma.h new file mode 100644 index 0000000..3bb34c5 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/alpx_xdma.h @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* +* Support for Digigram AlpX PCI-e boards +* +* Copyright (c) 2024 Digigram Digital (info@digigram.com) +*/ +#ifndef _ALPX_XDMA_H_ +#define _ALPX_XDMA_H_ + + +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/platform_device.h> + + +struct platform_device *alpx_xdma_register(struct pci_dev *pci_dev); + +void alpx_xdma_unregister(struct pci_dev *pci_dev, + struct platform_device *xdma_pdev); + +#endif /*_ALPX_XDMA_H_*/ diff --git a/snd-alpx-dkms/snd-alpx/alsa_conf/asound-stereo_alp882.conf b/snd-alpx-dkms/snd-alpx/alsa_conf/asound-stereo_alp882.conf new file mode 100644 index 0000000..3fee8af --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/alsa_conf/asound-stereo_alp882.conf @@ -0,0 +1,154 @@ +pcm_slave.ins { + pcm "hw:CARD=Alp882e,DEV=0" + channels 16 +} + +pcm.mic0 { + type dsnoop + ipc_key 0x414c5043 + slave ins + bindings.0 0 + bindings.1 1 + hint.description "Emulated analog Alp222 #0 in" +} + +pcm.mic1 { + type dsnoop + ipc_key 0x414c5043 + slave ins + bindings.0 2 + bindings.1 3 + hint.description "Emulated analog Alp222 #1 in" +} + +pcm.mic2 { + type dsnoop + ipc_key 0x414c5043 + slave ins + bindings.0 4 + bindings.1 5 + hint.description "Emulated analog Alp222 #2 in" +} + +pcm.mic3 { + type dsnoop + ipc_key 0x414c5043 + slave ins + bindings.0 6 + bindings.1 7 + hint.description "Emulated analog Alp222 #3 in" +} + +pcm.mic4 { + type dsnoop + ipc_key 0x414c5043 + slave ins + bindings.0 8 + bindings.1 9 + hint.description "Emulated digital Alp222 #0 in" +} + +pcm.mic5 { + type dsnoop + ipc_key 0x414c5043 + slave ins + bindings.0 10 + bindings.1 11 + hint.description "Emulated digital Alp222 #1 in" +} + +pcm.mic6 { + type dsnoop + ipc_key 0x414c5043 + slave ins + bindings.0 12 + bindings.1 13 + hint.description "Emulated digital Alp222 #2 in" +} + +pcm.mic7 { + type dsnoop + ipc_key 0x414c5043 + slave ins + bindings.0 14 + bindings.1 15 + hint.description "Emulated digital Alp222 #3 in" +} + +pcm_slave.outs { + pcm "hw:CARD=Alp882e,DEV=0" + channels 16 +} + + +pcm.out0 { + type dshare + ipc_key 0x414c5050 + slave outs + bindings.0 0 + bindings.1 1 + hint.description "Emulated analog Alp222 #0 out" +} + +pcm.out1 { + type dshare + ipc_key 0x414c5050 + slave outs + bindings.0 2 + bindings.1 3 + hint.description "Emulated analog Alp222 #1 out" +} + +pcm.out2 { + type dshare + ipc_key 0x414c5050 + slave outs + bindings.0 4 + bindings.1 5 + hint.description "Emulated analog Alp222 #2 out" +} + +pcm.out3 { + type dshare + ipc_key 0x414c5050 + slave outs + bindings.0 6 + bindings.1 7 + hint.description "Emulated analog Alp222 #3 out" +} + +pcm.out4 { + type dshare + ipc_key 0x414c5050 + slave outs + bindings.0 8 + bindings.1 9 + hint.description "Emulated digital Alp222 #0 out" +} + +pcm.out5 { + type dshare + ipc_key 0x414c5050 + slave outs + bindings.0 10 + bindings.1 11 + hint.description "Emulated digital Alp222 #1 out" +} + +pcm.out6 { + type dshare + ipc_key 0x414c5050 + slave outs + bindings.0 12 + bindings.1 13 + hint.description "Emulated digital Alp222 #2 out" +} + +pcm.out7 { + type dshare + ipc_key 0x414c5050 + slave outs + bindings.0 14 + bindings.1 15 + hint.description "Emulated digital Alp222 #3 out" +} diff --git a/snd-alpx-dkms/snd-alpx/cdev_sgdma.h b/snd-alpx-dkms/snd-alpx/cdev_sgdma.h new file mode 100644 index 0000000..f1437ed --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/cdev_sgdma.h @@ -0,0 +1,72 @@ +/* + * This file is part of the Xilinx DMA IP Core driver for Linux + * + * Copyright (c) 2016-present, Xilinx, Inc. + * All rights reserved. + * + * This source code is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + */ + +#ifndef _XDMA_IOCALLS_POSIX_H_ +#define _XDMA_IOCALLS_POSIX_H_ + +#include <linux/ioctl.h> + + +#define IOCTL_XDMA_PERF_V1 (1) +#define XDMA_ADDRMODE_MEMORY (0) +#define XDMA_ADDRMODE_FIXED (1) + +/* + * S means "Set" through a ptr, + * T means "Tell" directly with the argument value + * G means "Get": reply by setting through a pointer + * Q means "Query": response is on the return value + * X means "eXchange": switch G and S atomically + * H means "sHift": switch T and Q atomically + * + * _IO(type,nr) no arguments + * _IOR(type,nr,datatype) read data from driver + * _IOW(type,nr.datatype) write data to driver + * _IORW(type,nr,datatype) read/write data + * + * _IOC_DIR(nr) returns direction + * _IOC_TYPE(nr) returns magic + * _IOC_NR(nr) returns number + * _IOC_SIZE(nr) returns size + */ + +struct xdma_performance_ioctl { + /* IOCTL_XDMA_IOCTL_Vx */ + uint32_t version; + uint32_t transfer_size; + /* measurement */ + uint32_t stopped; + uint32_t iterations; + uint64_t clock_cycle_count; + uint64_t data_cycle_count; + uint64_t pending_count; +}; + + + +/* IOCTL codes */ + +#define IOCTL_XDMA_PERF_START _IOW('q', 1, struct xdma_performance_ioctl *) +#define IOCTL_XDMA_PERF_STOP _IOW('q', 2, struct xdma_performance_ioctl *) +#define IOCTL_XDMA_PERF_GET _IOR('q', 3, struct xdma_performance_ioctl *) +#define IOCTL_XDMA_ADDRMODE_SET _IOW('q', 4, int) +#define IOCTL_XDMA_ADDRMODE_GET _IOR('q', 5, int) +#define IOCTL_XDMA_ALIGN_GET _IOR('q', 6, int) + +#endif /* _XDMA_IOCALLS_POSIX_H_ */ diff --git a/snd-alpx-dkms/snd-alpx/core/RedHat/4.18/dmaengine_pcm.h b/snd-alpx-dkms/snd-alpx/core/RedHat/4.18/dmaengine_pcm.h new file mode 100755 index 0000000..2df54cf --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/core/RedHat/4.18/dmaengine_pcm.h @@ -0,0 +1,180 @@ +/* SPDX-License-Identifier: GPL-2.0+ + * + * Copyright (C) 2012, Analog Devices Inc. + * Author: Lars-Peter Clausen <lars@metafoo.de> + */ + +#ifndef __SOUND_DMAENGINE_PCM_H__ +#define __SOUND_DMAENGINE_PCM_H__ + +#include <sound/pcm.h> +#include <sound/soc.h> +#include <linux/dmaengine.h> + +/** + * snd_pcm_substream_to_dma_direction - Get dma_transfer_direction for a PCM + * substream + * @substream: PCM substream + * + * Return: DMA transfer direction + */ +static inline enum dma_transfer_direction +snd_pcm_substream_to_dma_direction(const struct snd_pcm_substream *substream) +{ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + return DMA_MEM_TO_DEV; + else + return DMA_DEV_TO_MEM; +} + +int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream, + const struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config); +int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd); +snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream); +snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream *substream); + +int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, + struct dma_chan *chan); +int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream); + +int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream, + dma_filter_fn filter_fn, void *filter_data); +int snd_dmaengine_pcm_close_release_chan(struct snd_pcm_substream *substream); + +struct dma_chan *snd_dmaengine_pcm_request_channel(dma_filter_fn filter_fn, + void *filter_data); +struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream); + +/* + * The DAI supports packed transfers, eg 2 16-bit samples in a 32-bit word. + * If this flag is set the dmaengine driver won't put any restriction on + * the supported sample formats and set the DMA transfer size to undefined. + * The DAI driver is responsible to disable any unsupported formats in it's + * configuration and catch corner cases that are not already handled in + * the ALSA core. + */ +#define SND_DMAENGINE_PCM_DAI_FLAG_PACK BIT(0) + +/** + * struct snd_dmaengine_dai_dma_data - DAI DMA configuration data + * @addr: Address of the DAI data source or destination register. + * @addr_width: Width of the DAI data source or destination register. + * @maxburst: Maximum number of words(note: words, as in units of the + * src_addr_width member, not bytes) that can be send to or received from the + * DAI in one burst. + * @filter_data: Custom DMA channel filter data, this will usually be used when + * requesting the DMA channel. + * @chan_name: Custom channel name to use when requesting DMA channel. + * @fifo_size: FIFO size of the DAI controller in bytes + * @flags: PCM_DAI flags, only SND_DMAENGINE_PCM_DAI_FLAG_PACK for now + * @peripheral_config: peripheral configuration for programming peripheral + * for dmaengine transfer + * @peripheral_size: peripheral configuration buffer size + */ +struct snd_dmaengine_dai_dma_data { + dma_addr_t addr; + enum dma_slave_buswidth addr_width; + u32 maxburst; + void *filter_data; + const char *chan_name; + unsigned int fifo_size; + unsigned int flags; + void *peripheral_config; + size_t peripheral_size; +}; + +void snd_dmaengine_pcm_set_config_from_dai_data( + const struct snd_pcm_substream *substream, + const struct snd_dmaengine_dai_dma_data *dma_data, + struct dma_slave_config *config); + +int snd_dmaengine_pcm_refine_runtime_hwparams( + struct snd_pcm_substream *substream, + struct snd_dmaengine_dai_dma_data *dma_data, + struct snd_pcm_hardware *hw, + struct dma_chan *chan); + +/* + * Try to request the DMA channel using compat_request_channel or + * compat_filter_fn if it couldn't be requested through devicetree. + */ +#define SND_DMAENGINE_PCM_FLAG_COMPAT BIT(0) +/* + * Don't try to request the DMA channels through devicetree. This flag only + * makes sense if SND_DMAENGINE_PCM_FLAG_COMPAT is set as well. + */ +#define SND_DMAENGINE_PCM_FLAG_NO_DT BIT(1) +/* + * The PCM is half duplex and the DMA channel is shared between capture and + * playback. + */ +#define SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX BIT(3) + +/** + * struct snd_dmaengine_pcm_config - Configuration data for dmaengine based PCM + * @prepare_slave_config: Callback used to fill in the DMA slave_config for a + * PCM substream. Will be called from the PCM drivers hwparams callback. + * @compat_request_channel: Callback to request a DMA channel for platforms + * which do not use devicetree. + * @process: Callback used to apply processing on samples transferred from/to + * user space. + * @compat_filter_fn: Will be used as the filter function when requesting a + * channel for platforms which do not use devicetree. The filter parameter + * will be the DAI's DMA data. + * @dma_dev: If set, request DMA channel on this device rather than the DAI + * device. + * @chan_names: If set, these custom DMA channel names will be requested at + * registration time. + * @pcm_hardware: snd_pcm_hardware struct to be used for the PCM. + * @prealloc_buffer_size: Size of the preallocated audio buffer. + * + * Note: If both compat_request_channel and compat_filter_fn are set + * compat_request_channel will be used to request the channel and + * compat_filter_fn will be ignored. Otherwise the channel will be requested + * using dma_request_channel with compat_filter_fn as the filter function. + */ +struct snd_dmaengine_pcm_config { + int (*prepare_slave_config)(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct dma_slave_config *slave_config); + struct dma_chan *(*compat_request_channel)( + struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_substream *substream); + int (*process)(struct snd_pcm_substream *substream, + int channel, unsigned long hwoff, + void *buf, unsigned long bytes); + dma_filter_fn compat_filter_fn; + struct device *dma_dev; + const char *chan_names[SNDRV_PCM_STREAM_LAST + 1]; + + const struct snd_pcm_hardware *pcm_hardware; + unsigned int prealloc_buffer_size; +}; + +int snd_dmaengine_pcm_register(struct device *dev, + const struct snd_dmaengine_pcm_config *config, + unsigned int flags); +void snd_dmaengine_pcm_unregister(struct device *dev); + +int devm_snd_dmaengine_pcm_register(struct device *dev, + const struct snd_dmaengine_pcm_config *config, + unsigned int flags); + +int snd_dmaengine_pcm_prepare_slave_config(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct dma_slave_config *slave_config); + +#define SND_DMAENGINE_PCM_DRV_NAME "snd_dmaengine_pcm" + +struct dmaengine_pcm { + struct dma_chan *chan[SNDRV_PCM_STREAM_LAST + 1]; + const struct snd_dmaengine_pcm_config *config; + struct snd_soc_component component; + unsigned int flags; +}; + +static inline struct dmaengine_pcm *soc_component_to_pcm(struct snd_soc_component *p) +{ + return container_of(p, struct dmaengine_pcm, component); +} +#endif diff --git a/snd-alpx-dkms/snd-alpx/core/RedHat/4.18/pcm_dmaengine.c b/snd-alpx-dkms/snd-alpx/core/RedHat/4.18/pcm_dmaengine.c new file mode 100755 index 0000000..494ec0c --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/core/RedHat/4.18/pcm_dmaengine.c @@ -0,0 +1,473 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2012, Analog Devices Inc. + * Author: Lars-Peter Clausen <lars@metafoo.de> + * + * Based on: + * imx-pcm-dma-mx2.c, Copyright 2009 Sascha Hauer <s.hauer@pengutronix.de> + * mxs-pcm.c, Copyright (C) 2011 Freescale Semiconductor, Inc. + * ep93xx-pcm.c, Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> + * Copyright (C) 2006 Applied Data Systems + */ +#include <linux/module.h> +#include <linux/init.h> +#include <linux/dmaengine.h> +#include <linux/slab.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> + +#include <sound/dmaengine_pcm.h> + +struct dmaengine_pcm_runtime_data { + struct dma_chan *dma_chan; + dma_cookie_t cookie; + + unsigned int pos; +}; + +static inline struct dmaengine_pcm_runtime_data *substream_to_prtd( + const struct snd_pcm_substream *substream) +{ + return substream->runtime->private_data; +} + +struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + return prtd->dma_chan; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_get_chan); + +/** + * snd_hwparams_to_dma_slave_config - Convert hw_params to dma_slave_config + * @substream: PCM substream + * @params: hw_params + * @slave_config: DMA slave config + * + * This function can be used to initialize a dma_slave_config from a substream + * and hw_params in a dmaengine based PCM driver implementation. + * + * Return: zero if successful, or a negative error code + */ +int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream, + const struct snd_pcm_hw_params *params, + struct dma_slave_config *slave_config) +{ + enum dma_slave_buswidth buswidth; + int bits; + + bits = params_physical_width(params); + if (bits < 8 || bits > 64) + return -EINVAL; + else if (bits == 8) + buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE; + else if (bits == 16) + buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; + else if (bits == 24) + buswidth = DMA_SLAVE_BUSWIDTH_3_BYTES; + else if (bits <= 32) + buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES; + else + buswidth = DMA_SLAVE_BUSWIDTH_8_BYTES; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + slave_config->direction = DMA_MEM_TO_DEV; + slave_config->dst_addr_width = buswidth; + } else { + slave_config->direction = DMA_DEV_TO_MEM; + slave_config->src_addr_width = buswidth; + } + + slave_config->device_fc = false; + + return 0; +} +EXPORT_SYMBOL_GPL(snd_hwparams_to_dma_slave_config); + +/** + * snd_dmaengine_pcm_set_config_from_dai_data() - Initializes a dma slave config + * using DAI DMA data. + * @substream: PCM substream + * @dma_data: DAI DMA data + * @slave_config: DMA slave configuration + * + * Initializes the {dst,src}_addr, {dst,src}_maxburst, {dst,src}_addr_width + * fields of the DMA slave config from the same fields of the DAI DMA + * data struct. The src and dst fields will be initialized depending on the + * direction of the substream. If the substream is a playback stream the dst + * fields will be initialized, if it is a capture stream the src fields will be + * initialized. The {dst,src}_addr_width field will only be initialized if the + * SND_DMAENGINE_PCM_DAI_FLAG_PACK flag is set or if the addr_width field of + * the DAI DMA data struct is not equal to DMA_SLAVE_BUSWIDTH_UNDEFINED. If + * both conditions are met the latter takes priority. + */ +void snd_dmaengine_pcm_set_config_from_dai_data( + const struct snd_pcm_substream *substream, + const struct snd_dmaengine_dai_dma_data *dma_data, + struct dma_slave_config *slave_config) +{ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + slave_config->dst_addr = dma_data->addr; + slave_config->dst_maxburst = dma_data->maxburst; + if (dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK) + slave_config->dst_addr_width = + DMA_SLAVE_BUSWIDTH_UNDEFINED; + if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED) + slave_config->dst_addr_width = dma_data->addr_width; + } else { + slave_config->src_addr = dma_data->addr; + slave_config->src_maxburst = dma_data->maxburst; + if (dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK) + slave_config->src_addr_width = + DMA_SLAVE_BUSWIDTH_UNDEFINED; + if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED) + slave_config->src_addr_width = dma_data->addr_width; + } + + slave_config->peripheral_config = dma_data->peripheral_config; + slave_config->peripheral_size = dma_data->peripheral_size; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_config_from_dai_data); + +static void dmaengine_pcm_dma_complete(void *arg) +{ + unsigned int new_pos; + struct snd_pcm_substream *substream = arg; + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + new_pos = prtd->pos + snd_pcm_lib_period_bytes(substream); + if (new_pos >= snd_pcm_lib_buffer_bytes(substream)) + new_pos = 0; + prtd->pos = new_pos; + + snd_pcm_period_elapsed(substream); +} + +static int dmaengine_pcm_prepare_and_submit(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + struct dma_chan *chan = prtd->dma_chan; + struct dma_async_tx_descriptor *desc; + enum dma_transfer_direction direction; + unsigned long flags = DMA_CTRL_ACK; + + direction = snd_pcm_substream_to_dma_direction(substream); + + if (!substream->runtime->no_period_wakeup) + flags |= DMA_PREP_INTERRUPT; + + prtd->pos = 0; + desc = dmaengine_prep_dma_cyclic(chan, + substream->runtime->dma_addr, + snd_pcm_lib_buffer_bytes(substream), + snd_pcm_lib_period_bytes(substream), direction, flags); + + if (!desc) + return -ENOMEM; + + desc->callback = dmaengine_pcm_dma_complete; + desc->callback_param = substream; + prtd->cookie = dmaengine_submit(desc); + + return 0; +} + +/** + * snd_dmaengine_pcm_trigger - dmaengine based PCM trigger implementation + * @substream: PCM substream + * @cmd: Trigger command + * + * This function can be used as the PCM trigger callback for dmaengine based PCM + * driver implementations. + * + * Return: 0 on success, a negative error code otherwise + */ +int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + int ret; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + ret = dmaengine_pcm_prepare_and_submit(substream); + if (ret) + return ret; + dma_async_issue_pending(prtd->dma_chan); + break; + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + dmaengine_resume(prtd->dma_chan); + break; + case SNDRV_PCM_TRIGGER_SUSPEND: + if (runtime->info & SNDRV_PCM_INFO_PAUSE) + dmaengine_pause(prtd->dma_chan); + else + dmaengine_terminate_async(prtd->dma_chan); + break; + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + dmaengine_pause(prtd->dma_chan); + break; + case SNDRV_PCM_TRIGGER_STOP: + dmaengine_terminate_async(prtd->dma_chan); + break; + default: + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_trigger); + +/** + * snd_dmaengine_pcm_pointer_no_residue - dmaengine based PCM pointer implementation + * @substream: PCM substream + * + * This function is deprecated and should not be used by new drivers, as its + * results may be unreliable. + * + * Return: PCM position in frames + */ +snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + return bytes_to_frames(substream->runtime, prtd->pos); +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer_no_residue); + +/** + * snd_dmaengine_pcm_pointer - dmaengine based PCM pointer implementation + * @substream: PCM substream + * + * This function can be used as the PCM pointer callback for dmaengine based PCM + * driver implementations. + * + * Return: PCM position in frames + */ +snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + struct dma_tx_state state; + enum dma_status status; + unsigned int buf_size; + unsigned int pos = 0; + + status = dmaengine_tx_status(prtd->dma_chan, prtd->cookie, &state); + if (status == DMA_IN_PROGRESS || status == DMA_PAUSED) { + buf_size = snd_pcm_lib_buffer_bytes(substream); + if (state.residue > 0 && state.residue <= buf_size) + pos = buf_size - state.residue; + + runtime->delay = bytes_to_frames(runtime, + state.in_flight_bytes); + } + + return bytes_to_frames(runtime, pos); +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer); + +/** + * snd_dmaengine_pcm_request_channel - Request channel for the dmaengine PCM + * @filter_fn: Filter function used to request the DMA channel + * @filter_data: Data passed to the DMA filter function + * + * This function request a DMA channel for usage with dmaengine PCM. + * + * Return: NULL or the requested DMA channel + */ +struct dma_chan *snd_dmaengine_pcm_request_channel(dma_filter_fn filter_fn, + void *filter_data) +{ + dma_cap_mask_t mask; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + dma_cap_set(DMA_CYCLIC, mask); + + return dma_request_channel(mask, filter_fn, filter_data); +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_request_channel); + +/** + * snd_dmaengine_pcm_open - Open a dmaengine based PCM substream + * @substream: PCM substream + * @chan: DMA channel to use for data transfers + * + * The function should usually be called from the pcm open callback. Note that + * this function will use private_data field of the substream's runtime. So it + * is not available to your pcm driver implementation. + * + * Return: 0 on success, a negative error code otherwise + */ +int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, + struct dma_chan *chan) +{ + struct dmaengine_pcm_runtime_data *prtd; + int ret; + + if (!chan) + return -ENXIO; + + ret = snd_pcm_hw_constraint_integer(substream->runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + if (ret < 0) + return ret; + + prtd = kzalloc(sizeof(*prtd), GFP_KERNEL); + if (!prtd) + return -ENOMEM; + + prtd->dma_chan = chan; + + substream->runtime->private_data = prtd; + + return 0; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open); + +/** + * snd_dmaengine_pcm_open_request_chan - Open a dmaengine based PCM substream and request channel + * @substream: PCM substream + * @filter_fn: Filter function used to request the DMA channel + * @filter_data: Data passed to the DMA filter function + * + * This function will request a DMA channel using the passed filter function and + * data. The function should usually be called from the pcm open callback. Note + * that this function will use private_data field of the substream's runtime. So + * it is not available to your pcm driver implementation. + * + * Return: 0 on success, a negative error code otherwise + */ +int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream, + dma_filter_fn filter_fn, void *filter_data) +{ + return snd_dmaengine_pcm_open(substream, + snd_dmaengine_pcm_request_channel(filter_fn, filter_data)); +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open_request_chan); + +/** + * snd_dmaengine_pcm_close - Close a dmaengine based PCM substream + * @substream: PCM substream + * + * Return: 0 on success, a negative error code otherwise + */ +int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + dmaengine_synchronize(prtd->dma_chan); + kfree(prtd); + + return 0; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close); + +/** + * snd_dmaengine_pcm_close_release_chan - Close a dmaengine based PCM + * substream and release channel + * @substream: PCM substream + * + * Releases the DMA channel associated with the PCM substream. + * + * Return: zero if successful, or a negative error code + */ +int snd_dmaengine_pcm_close_release_chan(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + dmaengine_synchronize(prtd->dma_chan); + dma_release_channel(prtd->dma_chan); + kfree(prtd); + + return 0; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close_release_chan); + +/** + * snd_dmaengine_pcm_refine_runtime_hwparams - Refine runtime hw params + * @substream: PCM substream + * @dma_data: DAI DMA data + * @hw: PCM hw params + * @chan: DMA channel to use for data transfers + * + * This function will query DMA capability, then refine the pcm hardware + * parameters. + * + * Return: 0 on success, a negative error code otherwise + */ +int snd_dmaengine_pcm_refine_runtime_hwparams( + struct snd_pcm_substream *substream, + struct snd_dmaengine_dai_dma_data *dma_data, + struct snd_pcm_hardware *hw, + struct dma_chan *chan) +{ + struct dma_slave_caps dma_caps; + u32 addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | + BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | + BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); + snd_pcm_format_t i; + int ret = 0; + + if (!hw || !chan || !dma_data) + return -EINVAL; + + ret = dma_get_slave_caps(chan, &dma_caps); + if (ret == 0) { + if (dma_caps.cmd_pause && dma_caps.cmd_resume) + hw->info |= SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME; + if (dma_caps.residue_granularity <= DMA_RESIDUE_GRANULARITY_SEGMENT) + hw->info |= SNDRV_PCM_INFO_BATCH; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + addr_widths = dma_caps.dst_addr_widths; + else + addr_widths = dma_caps.src_addr_widths; + } + + /* + * If SND_DMAENGINE_PCM_DAI_FLAG_PACK is set keep + * hw.formats set to 0, meaning no restrictions are in place. + * In this case it's the responsibility of the DAI driver to + * provide the supported format information. + */ + if (!(dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK)) + /* + * Prepare formats mask for valid/allowed sample types. If the + * dma does not have support for the given physical word size, + * it needs to be masked out so user space can not use the + * format which produces corrupted audio. + * In case the dma driver does not implement the slave_caps the + * default assumption is that it supports 1, 2 and 4 bytes + * widths. + */ + pcm_for_each_format(i) { + int bits = snd_pcm_format_physical_width(i); + + /* + * Enable only samples with DMA supported physical + * widths + */ + switch (bits) { + case 8: + case 16: + case 24: + case 32: + case 64: + if (addr_widths & (1 << (bits / 8))) + hw->formats |= pcm_format_to_bits(i); + break; + default: + /* Unsupported types */ + break; + } + } + + return ret; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_refine_runtime_hwparams); + +MODULE_LICENSE("GPL"); diff --git a/snd-alpx-dkms/snd-alpx/core/RedHat/5.14/dmaengine_pcm.h b/snd-alpx-dkms/snd-alpx/core/RedHat/5.14/dmaengine_pcm.h new file mode 100755 index 0000000..2df54cf --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/core/RedHat/5.14/dmaengine_pcm.h @@ -0,0 +1,180 @@ +/* SPDX-License-Identifier: GPL-2.0+ + * + * Copyright (C) 2012, Analog Devices Inc. + * Author: Lars-Peter Clausen <lars@metafoo.de> + */ + +#ifndef __SOUND_DMAENGINE_PCM_H__ +#define __SOUND_DMAENGINE_PCM_H__ + +#include <sound/pcm.h> +#include <sound/soc.h> +#include <linux/dmaengine.h> + +/** + * snd_pcm_substream_to_dma_direction - Get dma_transfer_direction for a PCM + * substream + * @substream: PCM substream + * + * Return: DMA transfer direction + */ +static inline enum dma_transfer_direction +snd_pcm_substream_to_dma_direction(const struct snd_pcm_substream *substream) +{ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + return DMA_MEM_TO_DEV; + else + return DMA_DEV_TO_MEM; +} + +int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream, + const struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config); +int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd); +snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream); +snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream *substream); + +int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, + struct dma_chan *chan); +int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream); + +int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream, + dma_filter_fn filter_fn, void *filter_data); +int snd_dmaengine_pcm_close_release_chan(struct snd_pcm_substream *substream); + +struct dma_chan *snd_dmaengine_pcm_request_channel(dma_filter_fn filter_fn, + void *filter_data); +struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream); + +/* + * The DAI supports packed transfers, eg 2 16-bit samples in a 32-bit word. + * If this flag is set the dmaengine driver won't put any restriction on + * the supported sample formats and set the DMA transfer size to undefined. + * The DAI driver is responsible to disable any unsupported formats in it's + * configuration and catch corner cases that are not already handled in + * the ALSA core. + */ +#define SND_DMAENGINE_PCM_DAI_FLAG_PACK BIT(0) + +/** + * struct snd_dmaengine_dai_dma_data - DAI DMA configuration data + * @addr: Address of the DAI data source or destination register. + * @addr_width: Width of the DAI data source or destination register. + * @maxburst: Maximum number of words(note: words, as in units of the + * src_addr_width member, not bytes) that can be send to or received from the + * DAI in one burst. + * @filter_data: Custom DMA channel filter data, this will usually be used when + * requesting the DMA channel. + * @chan_name: Custom channel name to use when requesting DMA channel. + * @fifo_size: FIFO size of the DAI controller in bytes + * @flags: PCM_DAI flags, only SND_DMAENGINE_PCM_DAI_FLAG_PACK for now + * @peripheral_config: peripheral configuration for programming peripheral + * for dmaengine transfer + * @peripheral_size: peripheral configuration buffer size + */ +struct snd_dmaengine_dai_dma_data { + dma_addr_t addr; + enum dma_slave_buswidth addr_width; + u32 maxburst; + void *filter_data; + const char *chan_name; + unsigned int fifo_size; + unsigned int flags; + void *peripheral_config; + size_t peripheral_size; +}; + +void snd_dmaengine_pcm_set_config_from_dai_data( + const struct snd_pcm_substream *substream, + const struct snd_dmaengine_dai_dma_data *dma_data, + struct dma_slave_config *config); + +int snd_dmaengine_pcm_refine_runtime_hwparams( + struct snd_pcm_substream *substream, + struct snd_dmaengine_dai_dma_data *dma_data, + struct snd_pcm_hardware *hw, + struct dma_chan *chan); + +/* + * Try to request the DMA channel using compat_request_channel or + * compat_filter_fn if it couldn't be requested through devicetree. + */ +#define SND_DMAENGINE_PCM_FLAG_COMPAT BIT(0) +/* + * Don't try to request the DMA channels through devicetree. This flag only + * makes sense if SND_DMAENGINE_PCM_FLAG_COMPAT is set as well. + */ +#define SND_DMAENGINE_PCM_FLAG_NO_DT BIT(1) +/* + * The PCM is half duplex and the DMA channel is shared between capture and + * playback. + */ +#define SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX BIT(3) + +/** + * struct snd_dmaengine_pcm_config - Configuration data for dmaengine based PCM + * @prepare_slave_config: Callback used to fill in the DMA slave_config for a + * PCM substream. Will be called from the PCM drivers hwparams callback. + * @compat_request_channel: Callback to request a DMA channel for platforms + * which do not use devicetree. + * @process: Callback used to apply processing on samples transferred from/to + * user space. + * @compat_filter_fn: Will be used as the filter function when requesting a + * channel for platforms which do not use devicetree. The filter parameter + * will be the DAI's DMA data. + * @dma_dev: If set, request DMA channel on this device rather than the DAI + * device. + * @chan_names: If set, these custom DMA channel names will be requested at + * registration time. + * @pcm_hardware: snd_pcm_hardware struct to be used for the PCM. + * @prealloc_buffer_size: Size of the preallocated audio buffer. + * + * Note: If both compat_request_channel and compat_filter_fn are set + * compat_request_channel will be used to request the channel and + * compat_filter_fn will be ignored. Otherwise the channel will be requested + * using dma_request_channel with compat_filter_fn as the filter function. + */ +struct snd_dmaengine_pcm_config { + int (*prepare_slave_config)(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct dma_slave_config *slave_config); + struct dma_chan *(*compat_request_channel)( + struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_substream *substream); + int (*process)(struct snd_pcm_substream *substream, + int channel, unsigned long hwoff, + void *buf, unsigned long bytes); + dma_filter_fn compat_filter_fn; + struct device *dma_dev; + const char *chan_names[SNDRV_PCM_STREAM_LAST + 1]; + + const struct snd_pcm_hardware *pcm_hardware; + unsigned int prealloc_buffer_size; +}; + +int snd_dmaengine_pcm_register(struct device *dev, + const struct snd_dmaengine_pcm_config *config, + unsigned int flags); +void snd_dmaengine_pcm_unregister(struct device *dev); + +int devm_snd_dmaengine_pcm_register(struct device *dev, + const struct snd_dmaengine_pcm_config *config, + unsigned int flags); + +int snd_dmaengine_pcm_prepare_slave_config(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct dma_slave_config *slave_config); + +#define SND_DMAENGINE_PCM_DRV_NAME "snd_dmaengine_pcm" + +struct dmaengine_pcm { + struct dma_chan *chan[SNDRV_PCM_STREAM_LAST + 1]; + const struct snd_dmaengine_pcm_config *config; + struct snd_soc_component component; + unsigned int flags; +}; + +static inline struct dmaengine_pcm *soc_component_to_pcm(struct snd_soc_component *p) +{ + return container_of(p, struct dmaengine_pcm, component); +} +#endif diff --git a/snd-alpx-dkms/snd-alpx/core/RedHat/5.14/pcm_dmaengine.c b/snd-alpx-dkms/snd-alpx/core/RedHat/5.14/pcm_dmaengine.c new file mode 100755 index 0000000..494ec0c --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/core/RedHat/5.14/pcm_dmaengine.c @@ -0,0 +1,473 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2012, Analog Devices Inc. + * Author: Lars-Peter Clausen <lars@metafoo.de> + * + * Based on: + * imx-pcm-dma-mx2.c, Copyright 2009 Sascha Hauer <s.hauer@pengutronix.de> + * mxs-pcm.c, Copyright (C) 2011 Freescale Semiconductor, Inc. + * ep93xx-pcm.c, Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> + * Copyright (C) 2006 Applied Data Systems + */ +#include <linux/module.h> +#include <linux/init.h> +#include <linux/dmaengine.h> +#include <linux/slab.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> + +#include <sound/dmaengine_pcm.h> + +struct dmaengine_pcm_runtime_data { + struct dma_chan *dma_chan; + dma_cookie_t cookie; + + unsigned int pos; +}; + +static inline struct dmaengine_pcm_runtime_data *substream_to_prtd( + const struct snd_pcm_substream *substream) +{ + return substream->runtime->private_data; +} + +struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + return prtd->dma_chan; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_get_chan); + +/** + * snd_hwparams_to_dma_slave_config - Convert hw_params to dma_slave_config + * @substream: PCM substream + * @params: hw_params + * @slave_config: DMA slave config + * + * This function can be used to initialize a dma_slave_config from a substream + * and hw_params in a dmaengine based PCM driver implementation. + * + * Return: zero if successful, or a negative error code + */ +int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream, + const struct snd_pcm_hw_params *params, + struct dma_slave_config *slave_config) +{ + enum dma_slave_buswidth buswidth; + int bits; + + bits = params_physical_width(params); + if (bits < 8 || bits > 64) + return -EINVAL; + else if (bits == 8) + buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE; + else if (bits == 16) + buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; + else if (bits == 24) + buswidth = DMA_SLAVE_BUSWIDTH_3_BYTES; + else if (bits <= 32) + buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES; + else + buswidth = DMA_SLAVE_BUSWIDTH_8_BYTES; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + slave_config->direction = DMA_MEM_TO_DEV; + slave_config->dst_addr_width = buswidth; + } else { + slave_config->direction = DMA_DEV_TO_MEM; + slave_config->src_addr_width = buswidth; + } + + slave_config->device_fc = false; + + return 0; +} +EXPORT_SYMBOL_GPL(snd_hwparams_to_dma_slave_config); + +/** + * snd_dmaengine_pcm_set_config_from_dai_data() - Initializes a dma slave config + * using DAI DMA data. + * @substream: PCM substream + * @dma_data: DAI DMA data + * @slave_config: DMA slave configuration + * + * Initializes the {dst,src}_addr, {dst,src}_maxburst, {dst,src}_addr_width + * fields of the DMA slave config from the same fields of the DAI DMA + * data struct. The src and dst fields will be initialized depending on the + * direction of the substream. If the substream is a playback stream the dst + * fields will be initialized, if it is a capture stream the src fields will be + * initialized. The {dst,src}_addr_width field will only be initialized if the + * SND_DMAENGINE_PCM_DAI_FLAG_PACK flag is set or if the addr_width field of + * the DAI DMA data struct is not equal to DMA_SLAVE_BUSWIDTH_UNDEFINED. If + * both conditions are met the latter takes priority. + */ +void snd_dmaengine_pcm_set_config_from_dai_data( + const struct snd_pcm_substream *substream, + const struct snd_dmaengine_dai_dma_data *dma_data, + struct dma_slave_config *slave_config) +{ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + slave_config->dst_addr = dma_data->addr; + slave_config->dst_maxburst = dma_data->maxburst; + if (dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK) + slave_config->dst_addr_width = + DMA_SLAVE_BUSWIDTH_UNDEFINED; + if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED) + slave_config->dst_addr_width = dma_data->addr_width; + } else { + slave_config->src_addr = dma_data->addr; + slave_config->src_maxburst = dma_data->maxburst; + if (dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK) + slave_config->src_addr_width = + DMA_SLAVE_BUSWIDTH_UNDEFINED; + if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED) + slave_config->src_addr_width = dma_data->addr_width; + } + + slave_config->peripheral_config = dma_data->peripheral_config; + slave_config->peripheral_size = dma_data->peripheral_size; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_config_from_dai_data); + +static void dmaengine_pcm_dma_complete(void *arg) +{ + unsigned int new_pos; + struct snd_pcm_substream *substream = arg; + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + new_pos = prtd->pos + snd_pcm_lib_period_bytes(substream); + if (new_pos >= snd_pcm_lib_buffer_bytes(substream)) + new_pos = 0; + prtd->pos = new_pos; + + snd_pcm_period_elapsed(substream); +} + +static int dmaengine_pcm_prepare_and_submit(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + struct dma_chan *chan = prtd->dma_chan; + struct dma_async_tx_descriptor *desc; + enum dma_transfer_direction direction; + unsigned long flags = DMA_CTRL_ACK; + + direction = snd_pcm_substream_to_dma_direction(substream); + + if (!substream->runtime->no_period_wakeup) + flags |= DMA_PREP_INTERRUPT; + + prtd->pos = 0; + desc = dmaengine_prep_dma_cyclic(chan, + substream->runtime->dma_addr, + snd_pcm_lib_buffer_bytes(substream), + snd_pcm_lib_period_bytes(substream), direction, flags); + + if (!desc) + return -ENOMEM; + + desc->callback = dmaengine_pcm_dma_complete; + desc->callback_param = substream; + prtd->cookie = dmaengine_submit(desc); + + return 0; +} + +/** + * snd_dmaengine_pcm_trigger - dmaengine based PCM trigger implementation + * @substream: PCM substream + * @cmd: Trigger command + * + * This function can be used as the PCM trigger callback for dmaengine based PCM + * driver implementations. + * + * Return: 0 on success, a negative error code otherwise + */ +int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + int ret; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + ret = dmaengine_pcm_prepare_and_submit(substream); + if (ret) + return ret; + dma_async_issue_pending(prtd->dma_chan); + break; + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + dmaengine_resume(prtd->dma_chan); + break; + case SNDRV_PCM_TRIGGER_SUSPEND: + if (runtime->info & SNDRV_PCM_INFO_PAUSE) + dmaengine_pause(prtd->dma_chan); + else + dmaengine_terminate_async(prtd->dma_chan); + break; + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + dmaengine_pause(prtd->dma_chan); + break; + case SNDRV_PCM_TRIGGER_STOP: + dmaengine_terminate_async(prtd->dma_chan); + break; + default: + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_trigger); + +/** + * snd_dmaengine_pcm_pointer_no_residue - dmaengine based PCM pointer implementation + * @substream: PCM substream + * + * This function is deprecated and should not be used by new drivers, as its + * results may be unreliable. + * + * Return: PCM position in frames + */ +snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + return bytes_to_frames(substream->runtime, prtd->pos); +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer_no_residue); + +/** + * snd_dmaengine_pcm_pointer - dmaengine based PCM pointer implementation + * @substream: PCM substream + * + * This function can be used as the PCM pointer callback for dmaengine based PCM + * driver implementations. + * + * Return: PCM position in frames + */ +snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + struct dma_tx_state state; + enum dma_status status; + unsigned int buf_size; + unsigned int pos = 0; + + status = dmaengine_tx_status(prtd->dma_chan, prtd->cookie, &state); + if (status == DMA_IN_PROGRESS || status == DMA_PAUSED) { + buf_size = snd_pcm_lib_buffer_bytes(substream); + if (state.residue > 0 && state.residue <= buf_size) + pos = buf_size - state.residue; + + runtime->delay = bytes_to_frames(runtime, + state.in_flight_bytes); + } + + return bytes_to_frames(runtime, pos); +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer); + +/** + * snd_dmaengine_pcm_request_channel - Request channel for the dmaengine PCM + * @filter_fn: Filter function used to request the DMA channel + * @filter_data: Data passed to the DMA filter function + * + * This function request a DMA channel for usage with dmaengine PCM. + * + * Return: NULL or the requested DMA channel + */ +struct dma_chan *snd_dmaengine_pcm_request_channel(dma_filter_fn filter_fn, + void *filter_data) +{ + dma_cap_mask_t mask; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + dma_cap_set(DMA_CYCLIC, mask); + + return dma_request_channel(mask, filter_fn, filter_data); +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_request_channel); + +/** + * snd_dmaengine_pcm_open - Open a dmaengine based PCM substream + * @substream: PCM substream + * @chan: DMA channel to use for data transfers + * + * The function should usually be called from the pcm open callback. Note that + * this function will use private_data field of the substream's runtime. So it + * is not available to your pcm driver implementation. + * + * Return: 0 on success, a negative error code otherwise + */ +int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, + struct dma_chan *chan) +{ + struct dmaengine_pcm_runtime_data *prtd; + int ret; + + if (!chan) + return -ENXIO; + + ret = snd_pcm_hw_constraint_integer(substream->runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + if (ret < 0) + return ret; + + prtd = kzalloc(sizeof(*prtd), GFP_KERNEL); + if (!prtd) + return -ENOMEM; + + prtd->dma_chan = chan; + + substream->runtime->private_data = prtd; + + return 0; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open); + +/** + * snd_dmaengine_pcm_open_request_chan - Open a dmaengine based PCM substream and request channel + * @substream: PCM substream + * @filter_fn: Filter function used to request the DMA channel + * @filter_data: Data passed to the DMA filter function + * + * This function will request a DMA channel using the passed filter function and + * data. The function should usually be called from the pcm open callback. Note + * that this function will use private_data field of the substream's runtime. So + * it is not available to your pcm driver implementation. + * + * Return: 0 on success, a negative error code otherwise + */ +int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream, + dma_filter_fn filter_fn, void *filter_data) +{ + return snd_dmaengine_pcm_open(substream, + snd_dmaengine_pcm_request_channel(filter_fn, filter_data)); +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open_request_chan); + +/** + * snd_dmaengine_pcm_close - Close a dmaengine based PCM substream + * @substream: PCM substream + * + * Return: 0 on success, a negative error code otherwise + */ +int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + dmaengine_synchronize(prtd->dma_chan); + kfree(prtd); + + return 0; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close); + +/** + * snd_dmaengine_pcm_close_release_chan - Close a dmaengine based PCM + * substream and release channel + * @substream: PCM substream + * + * Releases the DMA channel associated with the PCM substream. + * + * Return: zero if successful, or a negative error code + */ +int snd_dmaengine_pcm_close_release_chan(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + dmaengine_synchronize(prtd->dma_chan); + dma_release_channel(prtd->dma_chan); + kfree(prtd); + + return 0; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close_release_chan); + +/** + * snd_dmaengine_pcm_refine_runtime_hwparams - Refine runtime hw params + * @substream: PCM substream + * @dma_data: DAI DMA data + * @hw: PCM hw params + * @chan: DMA channel to use for data transfers + * + * This function will query DMA capability, then refine the pcm hardware + * parameters. + * + * Return: 0 on success, a negative error code otherwise + */ +int snd_dmaengine_pcm_refine_runtime_hwparams( + struct snd_pcm_substream *substream, + struct snd_dmaengine_dai_dma_data *dma_data, + struct snd_pcm_hardware *hw, + struct dma_chan *chan) +{ + struct dma_slave_caps dma_caps; + u32 addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | + BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | + BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); + snd_pcm_format_t i; + int ret = 0; + + if (!hw || !chan || !dma_data) + return -EINVAL; + + ret = dma_get_slave_caps(chan, &dma_caps); + if (ret == 0) { + if (dma_caps.cmd_pause && dma_caps.cmd_resume) + hw->info |= SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME; + if (dma_caps.residue_granularity <= DMA_RESIDUE_GRANULARITY_SEGMENT) + hw->info |= SNDRV_PCM_INFO_BATCH; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + addr_widths = dma_caps.dst_addr_widths; + else + addr_widths = dma_caps.src_addr_widths; + } + + /* + * If SND_DMAENGINE_PCM_DAI_FLAG_PACK is set keep + * hw.formats set to 0, meaning no restrictions are in place. + * In this case it's the responsibility of the DAI driver to + * provide the supported format information. + */ + if (!(dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK)) + /* + * Prepare formats mask for valid/allowed sample types. If the + * dma does not have support for the given physical word size, + * it needs to be masked out so user space can not use the + * format which produces corrupted audio. + * In case the dma driver does not implement the slave_caps the + * default assumption is that it supports 1, 2 and 4 bytes + * widths. + */ + pcm_for_each_format(i) { + int bits = snd_pcm_format_physical_width(i); + + /* + * Enable only samples with DMA supported physical + * widths + */ + switch (bits) { + case 8: + case 16: + case 24: + case 32: + case 64: + if (addr_widths & (1 << (bits / 8))) + hw->formats |= pcm_format_to_bits(i); + break; + default: + /* Unsupported types */ + break; + } + } + + return ret; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_refine_runtime_hwparams); + +MODULE_LICENSE("GPL"); diff --git a/snd-alpx-dkms/snd-alpx/core/generic/4.19/dmaengine_pcm.h b/snd-alpx-dkms/snd-alpx/core/generic/4.19/dmaengine_pcm.h new file mode 100755 index 0000000..2c4cfaa --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/core/generic/4.19/dmaengine_pcm.h @@ -0,0 +1,163 @@ +/* SPDX-License-Identifier: GPL-2.0+ + * + * Copyright (C) 2012, Analog Devices Inc. + * Author: Lars-Peter Clausen <lars@metafoo.de> + */ + +#ifndef __SOUND_DMAENGINE_PCM_H__ +#define __SOUND_DMAENGINE_PCM_H__ + +#include <sound/pcm.h> +#include <sound/soc.h> +#include <linux/dmaengine.h> + +/** + * snd_pcm_substream_to_dma_direction - Get dma_transfer_direction for a PCM + * substream + * @substream: PCM substream + */ +static inline enum dma_transfer_direction +snd_pcm_substream_to_dma_direction(const struct snd_pcm_substream *substream) +{ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + return DMA_MEM_TO_DEV; + else + return DMA_DEV_TO_MEM; +} + +int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream, + const struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config); +int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd); +snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream); +snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream *substream); + +int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, + struct dma_chan *chan); +int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream); + +int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream, + dma_filter_fn filter_fn, void *filter_data); +int snd_dmaengine_pcm_close_release_chan(struct snd_pcm_substream *substream); + +struct dma_chan *snd_dmaengine_pcm_request_channel(dma_filter_fn filter_fn, + void *filter_data); +struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream); + +/* + * The DAI supports packed transfers, eg 2 16-bit samples in a 32-bit word. + * If this flag is set the dmaengine driver won't put any restriction on + * the supported sample formats and set the DMA transfer size to undefined. + * The DAI driver is responsible to disable any unsupported formats in it's + * configuration and catch corner cases that are not already handled in + * the ALSA core. + */ +#define SND_DMAENGINE_PCM_DAI_FLAG_PACK BIT(0) + +/** + * struct snd_dmaengine_dai_dma_data - DAI DMA configuration data + * @addr: Address of the DAI data source or destination register. + * @addr_width: Width of the DAI data source or destination register. + * @maxburst: Maximum number of words(note: words, as in units of the + * src_addr_width member, not bytes) that can be send to or received from the + * DAI in one burst. + * @slave_id: Slave requester id for the DMA channel. + * @filter_data: Custom DMA channel filter data, this will usually be used when + * requesting the DMA channel. + * @chan_name: Custom channel name to use when requesting DMA channel. + * @fifo_size: FIFO size of the DAI controller in bytes + * @flags: PCM_DAI flags, only SND_DMAENGINE_PCM_DAI_FLAG_PACK for now + */ +struct snd_dmaengine_dai_dma_data { + dma_addr_t addr; + enum dma_slave_buswidth addr_width; + u32 maxburst; + unsigned int slave_id; + void *filter_data; + const char *chan_name; + unsigned int fifo_size; + unsigned int flags; +}; + +void snd_dmaengine_pcm_set_config_from_dai_data( + const struct snd_pcm_substream *substream, + const struct snd_dmaengine_dai_dma_data *dma_data, + struct dma_slave_config *config); + + +/* + * Try to request the DMA channel using compat_request_channel or + * compat_filter_fn if it couldn't be requested through devicetree. + */ +#define SND_DMAENGINE_PCM_FLAG_COMPAT BIT(0) +/* + * Don't try to request the DMA channels through devicetree. This flag only + * makes sense if SND_DMAENGINE_PCM_FLAG_COMPAT is set as well. + */ +#define SND_DMAENGINE_PCM_FLAG_NO_DT BIT(1) +/* + * The PCM is half duplex and the DMA channel is shared between capture and + * playback. + */ +#define SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX BIT(3) +/* + * The PCM streams have custom channel names specified. + */ +#define SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME BIT(4) + +/** + * struct snd_dmaengine_pcm_config - Configuration data for dmaengine based PCM + * @prepare_slave_config: Callback used to fill in the DMA slave_config for a + * PCM substream. Will be called from the PCM drivers hwparams callback. + * @compat_request_channel: Callback to request a DMA channel for platforms + * which do not use devicetree. + * @process: Callback used to apply processing on samples transferred from/to + * user space. + * @compat_filter_fn: Will be used as the filter function when requesting a + * channel for platforms which do not use devicetree. The filter parameter + * will be the DAI's DMA data. + * @dma_dev: If set, request DMA channel on this device rather than the DAI + * device. + * @chan_names: If set, these custom DMA channel names will be requested at + * registration time. + * @pcm_hardware: snd_pcm_hardware struct to be used for the PCM. + * @prealloc_buffer_size: Size of the preallocated audio buffer. + * + * Note: If both compat_request_channel and compat_filter_fn are set + * compat_request_channel will be used to request the channel and + * compat_filter_fn will be ignored. Otherwise the channel will be requested + * using dma_request_channel with compat_filter_fn as the filter function. + */ +struct snd_dmaengine_pcm_config { + int (*prepare_slave_config)(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct dma_slave_config *slave_config); + struct dma_chan *(*compat_request_channel)( + struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_substream *substream); + int (*process)(struct snd_pcm_substream *substream, + int channel, unsigned long hwoff, + void *buf, unsigned long bytes); + dma_filter_fn compat_filter_fn; + struct device *dma_dev; + const char *chan_names[SNDRV_PCM_STREAM_LAST + 1]; + + const struct snd_pcm_hardware *pcm_hardware; + unsigned int prealloc_buffer_size; +}; + +int snd_dmaengine_pcm_register(struct device *dev, + const struct snd_dmaengine_pcm_config *config, + unsigned int flags); +void snd_dmaengine_pcm_unregister(struct device *dev); + +int devm_snd_dmaengine_pcm_register(struct device *dev, + const struct snd_dmaengine_pcm_config *config, + unsigned int flags); + +int snd_dmaengine_pcm_prepare_slave_config(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct dma_slave_config *slave_config); + +#define SND_DMAENGINE_PCM_DRV_NAME "snd_dmaengine_pcm" + +#endif diff --git a/snd-alpx-dkms/snd-alpx/core/generic/4.19/internal.h b/snd-alpx-dkms/snd-alpx/core/generic/4.19/internal.h new file mode 100644 index 0000000..a6bf34d --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/core/generic/4.19/internal.h @@ -0,0 +1,297 @@ +/* + * Register map access API internal header + * + * Copyright 2011 Wolfson Microelectronics plc + * + * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _REGMAP_INTERNAL_H +#define _REGMAP_INTERNAL_H + +#include <linux/device.h> +#include <linux/regmap.h> +#include <linux/fs.h> +#include <linux/list.h> +#include <linux/wait.h> + +struct regmap; +struct regcache_ops; + +struct regmap_debugfs_off_cache { + struct list_head list; + off_t min; + off_t max; + unsigned int base_reg; + unsigned int max_reg; +}; + +struct regmap_format { + size_t buf_size; + size_t reg_bytes; + size_t pad_bytes; + size_t val_bytes; + void (*format_write)(struct regmap *map, + unsigned int reg, unsigned int val); + void (*format_reg)(void *buf, unsigned int reg, unsigned int shift); + void (*format_val)(void *buf, unsigned int val, unsigned int shift); + unsigned int (*parse_val)(const void *buf); + void (*parse_inplace)(void *buf); +}; + +struct regmap_async { + struct list_head list; + struct regmap *map; + void *work_buf; +}; + +struct regmap { + union { + struct mutex mutex; + struct { + spinlock_t spinlock; + unsigned long spinlock_flags; + }; + }; + regmap_lock lock; + regmap_unlock unlock; + void *lock_arg; /* This is passed to lock/unlock functions */ + gfp_t alloc_flags; + + struct device *dev; /* Device we do I/O on */ + void *work_buf; /* Scratch buffer used to format I/O */ + struct regmap_format format; /* Buffer format */ + const struct regmap_bus *bus; + void *bus_context; + const char *name; + + bool async; + spinlock_t async_lock; + wait_queue_head_t async_waitq; + struct list_head async_list; + struct list_head async_free; + int async_ret; + +#ifdef CONFIG_DEBUG_FS + bool debugfs_disable; + struct dentry *debugfs; + const char *debugfs_name; + + unsigned int debugfs_reg_len; + unsigned int debugfs_val_len; + unsigned int debugfs_tot_len; + + struct list_head debugfs_off_cache; + struct mutex cache_lock; +#endif + + unsigned int max_register; + bool (*writeable_reg)(struct device *dev, unsigned int reg); + bool (*readable_reg)(struct device *dev, unsigned int reg); + bool (*volatile_reg)(struct device *dev, unsigned int reg); + bool (*precious_reg)(struct device *dev, unsigned int reg); + bool (*readable_noinc_reg)(struct device *dev, unsigned int reg); + const struct regmap_access_table *wr_table; + const struct regmap_access_table *rd_table; + const struct regmap_access_table *volatile_table; + const struct regmap_access_table *precious_table; + const struct regmap_access_table *rd_noinc_table; + + int (*reg_read)(void *context, unsigned int reg, unsigned int *val); + int (*reg_write)(void *context, unsigned int reg, unsigned int val); + int (*reg_update_bits)(void *context, unsigned int reg, + unsigned int mask, unsigned int val); + + bool defer_caching; + + unsigned long read_flag_mask; + unsigned long write_flag_mask; + + /* number of bits to (left) shift the reg value when formatting*/ + int reg_shift; + int reg_stride; + int reg_stride_order; + + /* regcache specific members */ + const struct regcache_ops *cache_ops; + enum regcache_type cache_type; + + /* number of bytes in reg_defaults_raw */ + unsigned int cache_size_raw; + /* number of bytes per word in reg_defaults_raw */ + unsigned int cache_word_size; + /* number of entries in reg_defaults */ + unsigned int num_reg_defaults; + /* number of entries in reg_defaults_raw */ + unsigned int num_reg_defaults_raw; + + /* if set, only the cache is modified not the HW */ + bool cache_only; + /* if set, only the HW is modified not the cache */ + bool cache_bypass; + /* if set, remember to free reg_defaults_raw */ + bool cache_free; + + struct reg_default *reg_defaults; + const void *reg_defaults_raw; + void *cache; + /* if set, the cache contains newer data than the HW */ + bool cache_dirty; + /* if set, the HW registers are known to match map->reg_defaults */ + bool no_sync_defaults; + + struct reg_sequence *patch; + int patch_regs; + + /* if set, converts bulk read to single read */ + bool use_single_read; + /* if set, converts bulk read to single read */ + bool use_single_write; + /* if set, the device supports multi write mode */ + bool can_multi_write; + + /* if set, raw reads/writes are limited to this size */ + size_t max_raw_read; + size_t max_raw_write; + + struct rb_root range_tree; + void *selector_work_buf; /* Scratch buffer used for selector */ + + struct hwspinlock *hwlock; +}; + +struct regcache_ops { + const char *name; + enum regcache_type type; + int (*init)(struct regmap *map); + int (*exit)(struct regmap *map); +#ifdef CONFIG_DEBUG_FS + void (*debugfs_init)(struct regmap *map); +#endif + int (*read)(struct regmap *map, unsigned int reg, unsigned int *value); + int (*write)(struct regmap *map, unsigned int reg, unsigned int value); + int (*sync)(struct regmap *map, unsigned int min, unsigned int max); + int (*drop)(struct regmap *map, unsigned int min, unsigned int max); +}; + +bool regmap_cached(struct regmap *map, unsigned int reg); +bool regmap_writeable(struct regmap *map, unsigned int reg); +bool regmap_readable(struct regmap *map, unsigned int reg); +bool regmap_volatile(struct regmap *map, unsigned int reg); +bool regmap_precious(struct regmap *map, unsigned int reg); +bool regmap_readable_noinc(struct regmap *map, unsigned int reg); + +int _regmap_write(struct regmap *map, unsigned int reg, + unsigned int val); + +struct regmap_range_node { + struct rb_node node; + const char *name; + struct regmap *map; + + unsigned int range_min; + unsigned int range_max; + + unsigned int selector_reg; + unsigned int selector_mask; + int selector_shift; + + unsigned int window_start; + unsigned int window_len; +}; + +struct regmap_field { + struct regmap *regmap; + unsigned int mask; + /* lsb */ + unsigned int shift; + unsigned int reg; + + unsigned int id_size; + unsigned int id_offset; +}; + +#ifdef CONFIG_DEBUG_FS +extern void regmap_debugfs_initcall(void); +extern void regmap_debugfs_init(struct regmap *map, const char *name); +extern void regmap_debugfs_exit(struct regmap *map); + +static inline void regmap_debugfs_disable(struct regmap *map) +{ + map->debugfs_disable = true; +} + +#else +static inline void regmap_debugfs_initcall(void) { } +static inline void regmap_debugfs_init(struct regmap *map, const char *name) { } +static inline void regmap_debugfs_exit(struct regmap *map) { } +static inline void regmap_debugfs_disable(struct regmap *map) { } +#endif + +/* regcache core declarations */ +int regcache_init(struct regmap *map, const struct regmap_config *config); +void regcache_exit(struct regmap *map); +int regcache_read(struct regmap *map, + unsigned int reg, unsigned int *value); +int regcache_write(struct regmap *map, + unsigned int reg, unsigned int value); +int regcache_sync(struct regmap *map); +int regcache_sync_block(struct regmap *map, void *block, + unsigned long *cache_present, + unsigned int block_base, unsigned int start, + unsigned int end); + +static inline const void *regcache_get_val_addr(struct regmap *map, + const void *base, + unsigned int idx) +{ + return base + (map->cache_word_size * idx); +} + +unsigned int regcache_get_val(struct regmap *map, const void *base, + unsigned int idx); +bool regcache_set_val(struct regmap *map, void *base, unsigned int idx, + unsigned int val); +int regcache_lookup_reg(struct regmap *map, unsigned int reg); + +int _regmap_raw_write(struct regmap *map, unsigned int reg, + const void *val, size_t val_len); + +void regmap_async_complete_cb(struct regmap_async *async, int ret); + +enum regmap_endian regmap_get_val_endian(struct device *dev, + const struct regmap_bus *bus, + const struct regmap_config *config); + +extern struct regcache_ops regcache_rbtree_ops; +extern struct regcache_ops regcache_lzo_ops; +extern struct regcache_ops regcache_flat_ops; + +static inline const char *regmap_name(const struct regmap *map) +{ + if (map->dev) + return dev_name(map->dev); + + return map->name; +} + +static inline unsigned int regmap_get_offset(const struct regmap *map, + unsigned int index) +{ + if (map->reg_stride_order >= 0) + return index << map->reg_stride_order; + else + return index * map->reg_stride; +} + +static inline unsigned int regcache_get_index_by_order(const struct regmap *map, + unsigned int reg) +{ + return reg >> map->reg_stride_order; +} + +#endif diff --git a/snd-alpx-dkms/snd-alpx/core/generic/4.19/pcm_dmaengine.c b/snd-alpx-dkms/snd-alpx/core/generic/4.19/pcm_dmaengine.c new file mode 100755 index 0000000..6f6da11 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/core/generic/4.19/pcm_dmaengine.c @@ -0,0 +1,383 @@ +/* + * Copyright (C) 2012, Analog Devices Inc. + * Author: Lars-Peter Clausen <lars@metafoo.de> + * + * Based on: + * imx-pcm-dma-mx2.c, Copyright 2009 Sascha Hauer <s.hauer@pengutronix.de> + * mxs-pcm.c, Copyright (C) 2011 Freescale Semiconductor, Inc. + * ep93xx-pcm.c, Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> + * Copyright (C) 2006 Applied Data Systems + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#include <linux/module.h> +#include <linux/init.h> +#include <linux/dmaengine.h> +#include <linux/slab.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> + +#include <sound/dmaengine_pcm.h> + +struct dmaengine_pcm_runtime_data { + struct dma_chan *dma_chan; + dma_cookie_t cookie; + + unsigned int pos; +}; + +static inline struct dmaengine_pcm_runtime_data *substream_to_prtd( + const struct snd_pcm_substream *substream) +{ + return substream->runtime->private_data; +} + +struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + return prtd->dma_chan; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_get_chan); + +/** + * snd_hwparams_to_dma_slave_config - Convert hw_params to dma_slave_config + * @substream: PCM substream + * @params: hw_params + * @slave_config: DMA slave config + * + * This function can be used to initialize a dma_slave_config from a substream + * and hw_params in a dmaengine based PCM driver implementation. + */ +int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream, + const struct snd_pcm_hw_params *params, + struct dma_slave_config *slave_config) +{ + enum dma_slave_buswidth buswidth; + int bits; + + bits = params_physical_width(params); + if (bits < 8 || bits > 64) + return -EINVAL; + else if (bits == 8) + buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE; + else if (bits == 16) + buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; + else if (bits == 24) + buswidth = DMA_SLAVE_BUSWIDTH_3_BYTES; + else if (bits <= 32) + buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES; + else + buswidth = DMA_SLAVE_BUSWIDTH_8_BYTES; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + slave_config->direction = DMA_MEM_TO_DEV; + slave_config->dst_addr_width = buswidth; + } else { + slave_config->direction = DMA_DEV_TO_MEM; + slave_config->src_addr_width = buswidth; + } + + slave_config->device_fc = false; + + return 0; +} +EXPORT_SYMBOL_GPL(snd_hwparams_to_dma_slave_config); + +/** + * snd_dmaengine_pcm_set_config_from_dai_data() - Initializes a dma slave config + * using DAI DMA data. + * @substream: PCM substream + * @dma_data: DAI DMA data + * @slave_config: DMA slave configuration + * + * Initializes the {dst,src}_addr, {dst,src}_maxburst, {dst,src}_addr_width and + * slave_id fields of the DMA slave config from the same fields of the DAI DMA + * data struct. The src and dst fields will be initialized depending on the + * direction of the substream. If the substream is a playback stream the dst + * fields will be initialized, if it is a capture stream the src fields will be + * initialized. The {dst,src}_addr_width field will only be initialized if the + * SND_DMAENGINE_PCM_DAI_FLAG_PACK flag is set or if the addr_width field of + * the DAI DMA data struct is not equal to DMA_SLAVE_BUSWIDTH_UNDEFINED. If + * both conditions are met the latter takes priority. + */ +void snd_dmaengine_pcm_set_config_from_dai_data( + const struct snd_pcm_substream *substream, + const struct snd_dmaengine_dai_dma_data *dma_data, + struct dma_slave_config *slave_config) +{ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + slave_config->dst_addr = dma_data->addr; + slave_config->dst_maxburst = dma_data->maxburst; + if (dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK) + slave_config->dst_addr_width = + DMA_SLAVE_BUSWIDTH_UNDEFINED; + if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED) + slave_config->dst_addr_width = dma_data->addr_width; + } else { + slave_config->src_addr = dma_data->addr; + slave_config->src_maxburst = dma_data->maxburst; + if (dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK) + slave_config->src_addr_width = + DMA_SLAVE_BUSWIDTH_UNDEFINED; + if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED) + slave_config->src_addr_width = dma_data->addr_width; + } + + slave_config->slave_id = dma_data->slave_id; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_config_from_dai_data); + +static void dmaengine_pcm_dma_complete(void *arg) +{ + unsigned int new_pos; + struct snd_pcm_substream *substream = arg; + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + new_pos = prtd->pos + snd_pcm_lib_period_bytes(substream); + if (new_pos >= snd_pcm_lib_buffer_bytes(substream)) + new_pos = 0; + prtd->pos = new_pos; + + snd_pcm_period_elapsed(substream); +} + +static int dmaengine_pcm_prepare_and_submit(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + struct dma_chan *chan = prtd->dma_chan; + struct dma_async_tx_descriptor *desc; + enum dma_transfer_direction direction; + unsigned long flags = DMA_CTRL_ACK; + + direction = snd_pcm_substream_to_dma_direction(substream); + + if (!substream->runtime->no_period_wakeup) + flags |= DMA_PREP_INTERRUPT; + + prtd->pos = 0; + desc = dmaengine_prep_dma_cyclic(chan, + substream->runtime->dma_addr, + snd_pcm_lib_buffer_bytes(substream), + snd_pcm_lib_period_bytes(substream), direction, flags); + + if (!desc) + return -ENOMEM; + + desc->callback = dmaengine_pcm_dma_complete; + desc->callback_param = substream; + prtd->cookie = dmaengine_submit(desc); + + return 0; +} + +/** + * snd_dmaengine_pcm_trigger - dmaengine based PCM trigger implementation + * @substream: PCM substream + * @cmd: Trigger command + * + * Returns 0 on success, a negative error code otherwise. + * + * This function can be used as the PCM trigger callback for dmaengine based PCM + * driver implementations. + */ +int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + int ret; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + ret = dmaengine_pcm_prepare_and_submit(substream); + if (ret) + return ret; + dma_async_issue_pending(prtd->dma_chan); + break; + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + dmaengine_resume(prtd->dma_chan); + break; + case SNDRV_PCM_TRIGGER_SUSPEND: + if (runtime->info & SNDRV_PCM_INFO_PAUSE) + dmaengine_pause(prtd->dma_chan); + else + dmaengine_terminate_async(prtd->dma_chan); + break; + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + dmaengine_pause(prtd->dma_chan); + break; + case SNDRV_PCM_TRIGGER_STOP: + dmaengine_terminate_async(prtd->dma_chan); + break; + default: + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_trigger); + +/** + * snd_dmaengine_pcm_pointer_no_residue - dmaengine based PCM pointer implementation + * @substream: PCM substream + * + * This function is deprecated and should not be used by new drivers, as its + * results may be unreliable. + */ +snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + return bytes_to_frames(substream->runtime, prtd->pos); +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer_no_residue); + +/** + * snd_dmaengine_pcm_pointer - dmaengine based PCM pointer implementation + * @substream: PCM substream + * + * This function can be used as the PCM pointer callback for dmaengine based PCM + * driver implementations. + */ +snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + struct dma_tx_state state; + enum dma_status status; + unsigned int buf_size; + unsigned int pos = 0; + + status = dmaengine_tx_status(prtd->dma_chan, prtd->cookie, &state); + if (status == DMA_IN_PROGRESS || status == DMA_PAUSED) { + buf_size = snd_pcm_lib_buffer_bytes(substream); + if (state.residue > 0 && state.residue <= buf_size) + pos = buf_size - state.residue; + } + + return bytes_to_frames(substream->runtime, pos); +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer); + +/** + * snd_dmaengine_pcm_request_channel - Request channel for the dmaengine PCM + * @filter_fn: Filter function used to request the DMA channel + * @filter_data: Data passed to the DMA filter function + * + * Returns NULL or the requested DMA channel. + * + * This function request a DMA channel for usage with dmaengine PCM. + */ +struct dma_chan *snd_dmaengine_pcm_request_channel(dma_filter_fn filter_fn, + void *filter_data) +{ + dma_cap_mask_t mask; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + dma_cap_set(DMA_CYCLIC, mask); + + return dma_request_channel(mask, filter_fn, filter_data); +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_request_channel); + +/** + * snd_dmaengine_pcm_open - Open a dmaengine based PCM substream + * @substream: PCM substream + * @chan: DMA channel to use for data transfers + * + * Returns 0 on success, a negative error code otherwise. + * + * The function should usually be called from the pcm open callback. Note that + * this function will use private_data field of the substream's runtime. So it + * is not available to your pcm driver implementation. + */ +int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, + struct dma_chan *chan) +{ + struct dmaengine_pcm_runtime_data *prtd; + int ret; + + if (!chan) + return -ENXIO; + + ret = snd_pcm_hw_constraint_integer(substream->runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + if (ret < 0) + return ret; + + prtd = kzalloc(sizeof(*prtd), GFP_KERNEL); + if (!prtd) + return -ENOMEM; + + prtd->dma_chan = chan; + + substream->runtime->private_data = prtd; + + return 0; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open); + +/** + * snd_dmaengine_pcm_open_request_chan - Open a dmaengine based PCM substream and request channel + * @substream: PCM substream + * @filter_fn: Filter function used to request the DMA channel + * @filter_data: Data passed to the DMA filter function + * + * Returns 0 on success, a negative error code otherwise. + * + * This function will request a DMA channel using the passed filter function and + * data. The function should usually be called from the pcm open callback. Note + * that this function will use private_data field of the substream's runtime. So + * it is not available to your pcm driver implementation. + */ +int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream, + dma_filter_fn filter_fn, void *filter_data) +{ + return snd_dmaengine_pcm_open(substream, + snd_dmaengine_pcm_request_channel(filter_fn, filter_data)); +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open_request_chan); + +/** + * snd_dmaengine_pcm_close - Close a dmaengine based PCM substream + * @substream: PCM substream + */ +int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + dmaengine_synchronize(prtd->dma_chan); + kfree(prtd); + + return 0; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close); + +/** + * snd_dmaengine_pcm_release_chan_close - Close a dmaengine based PCM substream and release channel + * @substream: PCM substream + * + * Releases the DMA channel associated with the PCM substream. + */ +int snd_dmaengine_pcm_close_release_chan(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + dmaengine_synchronize(prtd->dma_chan); + dma_release_channel(prtd->dma_chan); + kfree(prtd); + + return 0; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close_release_chan); + +MODULE_LICENSE("GPL"); diff --git a/snd-alpx-dkms/snd-alpx/core/generic/4.19/regmap-mmio.c b/snd-alpx-dkms/snd-alpx/core/generic/4.19/regmap-mmio.c new file mode 100644 index 0000000..d524815 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/core/generic/4.19/regmap-mmio.c @@ -0,0 +1,399 @@ +/* + * Register map access API - MMIO support + * + * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* Simple patch to embed this file in its user module */ +/* DISABLE the EXPORT_SYMBOL() macros */ +#undef CONFIG_MODULES +#include <linux/export.h> +/* Then re-enable the module support to include modle.h */ +#define CONFIG_MODULES + + +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/regmap.h> +#include <linux/slab.h> + +#include "internal.h" + +struct regmap_mmio_context { + void __iomem *regs; + unsigned val_bytes; + + bool attached_clk; + struct clk *clk; + + void (*reg_write)(struct regmap_mmio_context *ctx, + unsigned int reg, unsigned int val); + unsigned int (*reg_read)(struct regmap_mmio_context *ctx, + unsigned int reg); +}; + +static int regmap_mmio_regbits_check(size_t reg_bits) +{ + switch (reg_bits) { + case 8: + case 16: + case 32: +#ifdef CONFIG_64BIT + case 64: +#endif + return 0; + default: + return -EINVAL; + } +} + +static int regmap_mmio_get_min_stride(size_t val_bits) +{ + int min_stride; + + switch (val_bits) { + case 8: + /* The core treats 0 as 1 */ + min_stride = 0; + return 0; + case 16: + min_stride = 2; + break; + case 32: + min_stride = 4; + break; +#ifdef CONFIG_64BIT + case 64: + min_stride = 8; + break; +#endif + default: + return -EINVAL; + } + + return min_stride; +} + +static void regmap_mmio_write8(struct regmap_mmio_context *ctx, + unsigned int reg, + unsigned int val) +{ + writeb(val, ctx->regs + reg); +} + +static void regmap_mmio_write16le(struct regmap_mmio_context *ctx, + unsigned int reg, + unsigned int val) +{ + writew(val, ctx->regs + reg); +} + +static void regmap_mmio_write16be(struct regmap_mmio_context *ctx, + unsigned int reg, + unsigned int val) +{ + iowrite16be(val, ctx->regs + reg); +} + +static void regmap_mmio_write32le(struct regmap_mmio_context *ctx, + unsigned int reg, + unsigned int val) +{ + writel(val, ctx->regs + reg); +} + +static void regmap_mmio_write32be(struct regmap_mmio_context *ctx, + unsigned int reg, + unsigned int val) +{ + iowrite32be(val, ctx->regs + reg); +} + +#ifdef CONFIG_64BIT +static void regmap_mmio_write64le(struct regmap_mmio_context *ctx, + unsigned int reg, + unsigned int val) +{ + writeq(val, ctx->regs + reg); +} +#endif + +static int regmap_mmio_write(void *context, unsigned int reg, unsigned int val) +{ + struct regmap_mmio_context *ctx = context; + int ret; + + if (!IS_ERR(ctx->clk)) { + ret = clk_enable(ctx->clk); + if (ret < 0) + return ret; + } + + ctx->reg_write(ctx, reg, val); + + if (!IS_ERR(ctx->clk)) + clk_disable(ctx->clk); + + return 0; +} + +static unsigned int regmap_mmio_read8(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return readb(ctx->regs + reg); +} + +static unsigned int regmap_mmio_read16le(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return readw(ctx->regs + reg); +} + +static unsigned int regmap_mmio_read16be(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return ioread16be(ctx->regs + reg); +} + +static unsigned int regmap_mmio_read32le(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return readl(ctx->regs + reg); +} + +static unsigned int regmap_mmio_read32be(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return ioread32be(ctx->regs + reg); +} + +#ifdef CONFIG_64BIT +static unsigned int regmap_mmio_read64le(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return readq(ctx->regs + reg); +} +#endif + +static int regmap_mmio_read(void *context, unsigned int reg, unsigned int *val) +{ + struct regmap_mmio_context *ctx = context; + int ret; + + if (!IS_ERR(ctx->clk)) { + ret = clk_enable(ctx->clk); + if (ret < 0) + return ret; + } + + *val = ctx->reg_read(ctx, reg); + + if (!IS_ERR(ctx->clk)) + clk_disable(ctx->clk); + + return 0; +} + +static void regmap_mmio_free_context(void *context) +{ + struct regmap_mmio_context *ctx = context; + + if (!IS_ERR(ctx->clk)) { + clk_unprepare(ctx->clk); + if (!ctx->attached_clk) + clk_put(ctx->clk); + } + kfree(context); +} + +static const struct regmap_bus regmap_mmio = { + .fast_io = true, + .reg_write = regmap_mmio_write, + .reg_read = regmap_mmio_read, + .free_context = regmap_mmio_free_context, + .val_format_endian_default = REGMAP_ENDIAN_LITTLE, +}; + +static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev, + const char *clk_id, + void __iomem *regs, + const struct regmap_config *config) +{ + struct regmap_mmio_context *ctx; + int min_stride; + int ret; + + ret = regmap_mmio_regbits_check(config->reg_bits); + if (ret) + return ERR_PTR(ret); + + if (config->pad_bits) + return ERR_PTR(-EINVAL); + + min_stride = regmap_mmio_get_min_stride(config->val_bits); + if (min_stride < 0) + return ERR_PTR(min_stride); + + if (config->reg_stride < min_stride) + return ERR_PTR(-EINVAL); + + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return ERR_PTR(-ENOMEM); + + ctx->regs = regs; + ctx->val_bytes = config->val_bits / 8; + ctx->clk = ERR_PTR(-ENODEV); + + switch (regmap_get_val_endian(dev, ®map_mmio, config)) { + case REGMAP_ENDIAN_DEFAULT: + case REGMAP_ENDIAN_LITTLE: +#ifdef __LITTLE_ENDIAN + case REGMAP_ENDIAN_NATIVE: +#endif + switch (config->val_bits) { + case 8: + ctx->reg_read = regmap_mmio_read8; + ctx->reg_write = regmap_mmio_write8; + break; + case 16: + ctx->reg_read = regmap_mmio_read16le; + ctx->reg_write = regmap_mmio_write16le; + break; + case 32: + ctx->reg_read = regmap_mmio_read32le; + ctx->reg_write = regmap_mmio_write32le; + break; +#ifdef CONFIG_64BIT + case 64: + ctx->reg_read = regmap_mmio_read64le; + ctx->reg_write = regmap_mmio_write64le; + break; +#endif + default: + ret = -EINVAL; + goto err_free; + } + break; + case REGMAP_ENDIAN_BIG: +#ifdef __BIG_ENDIAN + case REGMAP_ENDIAN_NATIVE: +#endif + switch (config->val_bits) { + case 8: + ctx->reg_read = regmap_mmio_read8; + ctx->reg_write = regmap_mmio_write8; + break; + case 16: + ctx->reg_read = regmap_mmio_read16be; + ctx->reg_write = regmap_mmio_write16be; + break; + case 32: + ctx->reg_read = regmap_mmio_read32be; + ctx->reg_write = regmap_mmio_write32be; + break; + default: + ret = -EINVAL; + goto err_free; + } + break; + default: + ret = -EINVAL; + goto err_free; + } + + if (clk_id == NULL) + return ctx; + + ctx->clk = clk_get(dev, clk_id); + if (IS_ERR(ctx->clk)) { + ret = PTR_ERR(ctx->clk); + goto err_free; + } + + ret = clk_prepare(ctx->clk); + if (ret < 0) { + clk_put(ctx->clk); + goto err_free; + } + + return ctx; + +err_free: + kfree(ctx); + + return ERR_PTR(ret); +} + +struct regmap *__regmap_init_mmio_clk(struct device *dev, const char *clk_id, + void __iomem *regs, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name) +{ + struct regmap_mmio_context *ctx; + + ctx = regmap_mmio_gen_context(dev, clk_id, regs, config); + if (IS_ERR(ctx)) + return ERR_CAST(ctx); + + return __regmap_init(dev, ®map_mmio, ctx, config, + lock_key, lock_name); +} +EXPORT_SYMBOL_GPL(__regmap_init_mmio_clk); + +struct regmap *__devm_regmap_init_mmio_clk(struct device *dev, + const char *clk_id, + void __iomem *regs, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name) +{ + struct regmap_mmio_context *ctx; + + ctx = regmap_mmio_gen_context(dev, clk_id, regs, config); + if (IS_ERR(ctx)) + return ERR_CAST(ctx); + + return __devm_regmap_init(dev, ®map_mmio, ctx, config, + lock_key, lock_name); +} +EXPORT_SYMBOL_GPL(__devm_regmap_init_mmio_clk); + +int regmap_mmio_attach_clk(struct regmap *map, struct clk *clk) +{ + struct regmap_mmio_context *ctx = map->bus_context; + + ctx->clk = clk; + ctx->attached_clk = true; + + return clk_prepare(ctx->clk); +} +EXPORT_SYMBOL_GPL(regmap_mmio_attach_clk); + +void regmap_mmio_detach_clk(struct regmap *map) +{ + struct regmap_mmio_context *ctx = map->bus_context; + + clk_unprepare(ctx->clk); + + ctx->attached_clk = false; + ctx->clk = NULL; +} +EXPORT_SYMBOL_GPL(regmap_mmio_detach_clk); + +MODULE_LICENSE("GPL v2"); diff --git a/snd-alpx-dkms/snd-alpx/core/generic/5.12/dmaengine_pcm.h b/snd-alpx-dkms/snd-alpx/core/generic/5.12/dmaengine_pcm.h new file mode 100644 index 0000000..96666ef --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/core/generic/5.12/dmaengine_pcm.h @@ -0,0 +1,180 @@ +/* SPDX-License-Identifier: GPL-2.0+ + * + * Copyright (C) 2012, Analog Devices Inc. + * Author: Lars-Peter Clausen <lars@metafoo.de> + */ + +#ifndef __SOUND_DMAENGINE_PCM_H__ +#define __SOUND_DMAENGINE_PCM_H__ + +#include <sound/pcm.h> +#include <sound/soc.h> +#include <linux/dmaengine.h> + +/** + * snd_pcm_substream_to_dma_direction - Get dma_transfer_direction for a PCM + * substream + * @substream: PCM substream + */ +static inline enum dma_transfer_direction +snd_pcm_substream_to_dma_direction(const struct snd_pcm_substream *substream) +{ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + return DMA_MEM_TO_DEV; + else + return DMA_DEV_TO_MEM; +} + +int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream, + const struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config); +int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd); +snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream); +snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream *substream); + +int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, + struct dma_chan *chan); +int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream); + +int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream, + dma_filter_fn filter_fn, void *filter_data); +int snd_dmaengine_pcm_close_release_chan(struct snd_pcm_substream *substream); + +struct dma_chan *snd_dmaengine_pcm_request_channel(dma_filter_fn filter_fn, + void *filter_data); +struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream); + +/* + * The DAI supports packed transfers, eg 2 16-bit samples in a 32-bit word. + * If this flag is set the dmaengine driver won't put any restriction on + * the supported sample formats and set the DMA transfer size to undefined. + * The DAI driver is responsible to disable any unsupported formats in it's + * configuration and catch corner cases that are not already handled in + * the ALSA core. + */ +#define SND_DMAENGINE_PCM_DAI_FLAG_PACK BIT(0) + +/** + * struct snd_dmaengine_dai_dma_data - DAI DMA configuration data + * @addr: Address of the DAI data source or destination register. + * @addr_width: Width of the DAI data source or destination register. + * @maxburst: Maximum number of words(note: words, as in units of the + * src_addr_width member, not bytes) that can be send to or received from the + * DAI in one burst. + * @slave_id: Slave requester id for the DMA channel. + * @filter_data: Custom DMA channel filter data, this will usually be used when + * requesting the DMA channel. + * @chan_name: Custom channel name to use when requesting DMA channel. + * @fifo_size: FIFO size of the DAI controller in bytes + * @flags: PCM_DAI flags, only SND_DMAENGINE_PCM_DAI_FLAG_PACK for now + * @peripheral_config: peripheral configuration for programming peripheral + * for dmaengine transfer + * @peripheral_size: peripheral configuration buffer size + */ +struct snd_dmaengine_dai_dma_data { + dma_addr_t addr; + enum dma_slave_buswidth addr_width; + u32 maxburst; + unsigned int slave_id; + void *filter_data; + const char *chan_name; + unsigned int fifo_size; + unsigned int flags; + void *peripheral_config; + size_t peripheral_size; +}; + +void snd_dmaengine_pcm_set_config_from_dai_data( + const struct snd_pcm_substream *substream, + const struct snd_dmaengine_dai_dma_data *dma_data, + struct dma_slave_config *config); + +int snd_dmaengine_pcm_refine_runtime_hwparams( + struct snd_pcm_substream *substream, + struct snd_dmaengine_dai_dma_data *dma_data, + struct snd_pcm_hardware *hw, + struct dma_chan *chan); + +/* + * Try to request the DMA channel using compat_request_channel or + * compat_filter_fn if it couldn't be requested through devicetree. + */ +#define SND_DMAENGINE_PCM_FLAG_COMPAT BIT(0) +/* + * Don't try to request the DMA channels through devicetree. This flag only + * makes sense if SND_DMAENGINE_PCM_FLAG_COMPAT is set as well. + */ +#define SND_DMAENGINE_PCM_FLAG_NO_DT BIT(1) +/* + * The PCM is half duplex and the DMA channel is shared between capture and + * playback. + */ +#define SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX BIT(3) + +/** + * struct snd_dmaengine_pcm_config - Configuration data for dmaengine based PCM + * @prepare_slave_config: Callback used to fill in the DMA slave_config for a + * PCM substream. Will be called from the PCM drivers hwparams callback. + * @compat_request_channel: Callback to request a DMA channel for platforms + * which do not use devicetree. + * @process: Callback used to apply processing on samples transferred from/to + * user space. + * @compat_filter_fn: Will be used as the filter function when requesting a + * channel for platforms which do not use devicetree. The filter parameter + * will be the DAI's DMA data. + * @dma_dev: If set, request DMA channel on this device rather than the DAI + * device. + * @chan_names: If set, these custom DMA channel names will be requested at + * registration time. + * @pcm_hardware: snd_pcm_hardware struct to be used for the PCM. + * @prealloc_buffer_size: Size of the preallocated audio buffer. + * + * Note: If both compat_request_channel and compat_filter_fn are set + * compat_request_channel will be used to request the channel and + * compat_filter_fn will be ignored. Otherwise the channel will be requested + * using dma_request_channel with compat_filter_fn as the filter function. + */ +struct snd_dmaengine_pcm_config { + int (*prepare_slave_config)(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct dma_slave_config *slave_config); + struct dma_chan *(*compat_request_channel)( + struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_substream *substream); + int (*process)(struct snd_pcm_substream *substream, + int channel, unsigned long hwoff, + void *buf, unsigned long bytes); + dma_filter_fn compat_filter_fn; + struct device *dma_dev; + const char *chan_names[SNDRV_PCM_STREAM_LAST + 1]; + + const struct snd_pcm_hardware *pcm_hardware; + unsigned int prealloc_buffer_size; +}; + +int snd_dmaengine_pcm_register(struct device *dev, + const struct snd_dmaengine_pcm_config *config, + unsigned int flags); +void snd_dmaengine_pcm_unregister(struct device *dev); + +int devm_snd_dmaengine_pcm_register(struct device *dev, + const struct snd_dmaengine_pcm_config *config, + unsigned int flags); + +int snd_dmaengine_pcm_prepare_slave_config(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct dma_slave_config *slave_config); + +#define SND_DMAENGINE_PCM_DRV_NAME "snd_dmaengine_pcm" + +struct dmaengine_pcm { + struct dma_chan *chan[SNDRV_PCM_STREAM_LAST + 1]; + const struct snd_dmaengine_pcm_config *config; + struct snd_soc_component component; + unsigned int flags; +}; + +static inline struct dmaengine_pcm *soc_component_to_pcm(struct snd_soc_component *p) +{ + return container_of(p, struct dmaengine_pcm, component); +} +#endif diff --git a/snd-alpx-dkms/snd-alpx/core/generic/5.12/pcm_dmaengine.c b/snd-alpx-dkms/snd-alpx/core/generic/5.12/pcm_dmaengine.c new file mode 100644 index 0000000..1fc2fa0 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/core/generic/5.12/pcm_dmaengine.c @@ -0,0 +1,462 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2012, Analog Devices Inc. + * Author: Lars-Peter Clausen <lars@metafoo.de> + * + * Based on: + * imx-pcm-dma-mx2.c, Copyright 2009 Sascha Hauer <s.hauer@pengutronix.de> + * mxs-pcm.c, Copyright (C) 2011 Freescale Semiconductor, Inc. + * ep93xx-pcm.c, Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> + * Copyright (C) 2006 Applied Data Systems + */ +#include <linux/module.h> +#include <linux/init.h> +#include <linux/dmaengine.h> +#include <linux/slab.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> + +#include <sound/dmaengine_pcm.h> + +struct dmaengine_pcm_runtime_data { + struct dma_chan *dma_chan; + dma_cookie_t cookie; + + unsigned int pos; +}; + +static inline struct dmaengine_pcm_runtime_data *substream_to_prtd( + const struct snd_pcm_substream *substream) +{ + return substream->runtime->private_data; +} + +struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + return prtd->dma_chan; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_get_chan); + +/** + * snd_hwparams_to_dma_slave_config - Convert hw_params to dma_slave_config + * @substream: PCM substream + * @params: hw_params + * @slave_config: DMA slave config + * + * This function can be used to initialize a dma_slave_config from a substream + * and hw_params in a dmaengine based PCM driver implementation. + */ +int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream, + const struct snd_pcm_hw_params *params, + struct dma_slave_config *slave_config) +{ + enum dma_slave_buswidth buswidth; + int bits; + + bits = params_physical_width(params); + if (bits < 8 || bits > 64) + return -EINVAL; + else if (bits == 8) + buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE; + else if (bits == 16) + buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; + else if (bits == 24) + buswidth = DMA_SLAVE_BUSWIDTH_3_BYTES; + else if (bits <= 32) + buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES; + else + buswidth = DMA_SLAVE_BUSWIDTH_8_BYTES; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + slave_config->direction = DMA_MEM_TO_DEV; + slave_config->dst_addr_width = buswidth; + } else { + slave_config->direction = DMA_DEV_TO_MEM; + slave_config->src_addr_width = buswidth; + } + + slave_config->device_fc = false; + + return 0; +} +EXPORT_SYMBOL_GPL(snd_hwparams_to_dma_slave_config); + +/** + * snd_dmaengine_pcm_set_config_from_dai_data() - Initializes a dma slave config + * using DAI DMA data. + * @substream: PCM substream + * @dma_data: DAI DMA data + * @slave_config: DMA slave configuration + * + * Initializes the {dst,src}_addr, {dst,src}_maxburst, {dst,src}_addr_width and + * slave_id fields of the DMA slave config from the same fields of the DAI DMA + * data struct. The src and dst fields will be initialized depending on the + * direction of the substream. If the substream is a playback stream the dst + * fields will be initialized, if it is a capture stream the src fields will be + * initialized. The {dst,src}_addr_width field will only be initialized if the + * SND_DMAENGINE_PCM_DAI_FLAG_PACK flag is set or if the addr_width field of + * the DAI DMA data struct is not equal to DMA_SLAVE_BUSWIDTH_UNDEFINED. If + * both conditions are met the latter takes priority. + */ +void snd_dmaengine_pcm_set_config_from_dai_data( + const struct snd_pcm_substream *substream, + const struct snd_dmaengine_dai_dma_data *dma_data, + struct dma_slave_config *slave_config) +{ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + slave_config->dst_addr = dma_data->addr; + slave_config->dst_maxburst = dma_data->maxburst; + if (dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK) + slave_config->dst_addr_width = + DMA_SLAVE_BUSWIDTH_UNDEFINED; + if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED) + slave_config->dst_addr_width = dma_data->addr_width; + } else { + slave_config->src_addr = dma_data->addr; + slave_config->src_maxburst = dma_data->maxburst; + if (dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK) + slave_config->src_addr_width = + DMA_SLAVE_BUSWIDTH_UNDEFINED; + if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED) + slave_config->src_addr_width = dma_data->addr_width; + } + + slave_config->slave_id = dma_data->slave_id; + slave_config->peripheral_config = dma_data->peripheral_config; + slave_config->peripheral_size = dma_data->peripheral_size; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_config_from_dai_data); + +static void dmaengine_pcm_dma_complete(void *arg) +{ + struct snd_pcm_substream *substream = arg; + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + prtd->pos += snd_pcm_lib_period_bytes(substream); + if (prtd->pos >= snd_pcm_lib_buffer_bytes(substream)) + prtd->pos = 0; + + snd_pcm_period_elapsed(substream); +} + +static int dmaengine_pcm_prepare_and_submit(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + struct dma_chan *chan = prtd->dma_chan; + struct dma_async_tx_descriptor *desc; + enum dma_transfer_direction direction; + unsigned long flags = DMA_CTRL_ACK; + + direction = snd_pcm_substream_to_dma_direction(substream); + + if (!substream->runtime->no_period_wakeup) + flags |= DMA_PREP_INTERRUPT; + + prtd->pos = 0; + desc = dmaengine_prep_dma_cyclic(chan, + substream->runtime->dma_addr, + snd_pcm_lib_buffer_bytes(substream), + snd_pcm_lib_period_bytes(substream), direction, flags); + + if (!desc) + return -ENOMEM; + + desc->callback = dmaengine_pcm_dma_complete; + desc->callback_param = substream; + prtd->cookie = dmaengine_submit(desc); + + return 0; +} + +/** + * snd_dmaengine_pcm_trigger - dmaengine based PCM trigger implementation + * @substream: PCM substream + * @cmd: Trigger command + * + * Returns 0 on success, a negative error code otherwise. + * + * This function can be used as the PCM trigger callback for dmaengine based PCM + * driver implementations. + */ +int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + int ret; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + ret = dmaengine_pcm_prepare_and_submit(substream); + if (ret) + return ret; + dma_async_issue_pending(prtd->dma_chan); + break; + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + dmaengine_resume(prtd->dma_chan); + break; + case SNDRV_PCM_TRIGGER_SUSPEND: + if (runtime->info & SNDRV_PCM_INFO_PAUSE) + dmaengine_pause(prtd->dma_chan); + else + dmaengine_terminate_async(prtd->dma_chan); + break; + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + dmaengine_pause(prtd->dma_chan); + break; + case SNDRV_PCM_TRIGGER_STOP: + dmaengine_terminate_async(prtd->dma_chan); + break; + default: + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_trigger); + +/** + * snd_dmaengine_pcm_pointer_no_residue - dmaengine based PCM pointer implementation + * @substream: PCM substream + * + * This function is deprecated and should not be used by new drivers, as its + * results may be unreliable. + */ +snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + return bytes_to_frames(substream->runtime, prtd->pos); +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer_no_residue); + +/** + * snd_dmaengine_pcm_pointer - dmaengine based PCM pointer implementation + * @substream: PCM substream + * + * This function can be used as the PCM pointer callback for dmaengine based PCM + * driver implementations. + */ +snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + struct dma_tx_state state; + enum dma_status status; + unsigned int buf_size; + unsigned int pos = 0; + + status = dmaengine_tx_status(prtd->dma_chan, prtd->cookie, &state); + if (status == DMA_IN_PROGRESS || status == DMA_PAUSED) { + buf_size = snd_pcm_lib_buffer_bytes(substream); + if (state.residue > 0 && state.residue <= buf_size) + pos = buf_size - state.residue; + + runtime->delay = bytes_to_frames(runtime, + state.in_flight_bytes); + } + + return bytes_to_frames(runtime, pos); +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer); + +/** + * snd_dmaengine_pcm_request_channel - Request channel for the dmaengine PCM + * @filter_fn: Filter function used to request the DMA channel + * @filter_data: Data passed to the DMA filter function + * + * Returns NULL or the requested DMA channel. + * + * This function request a DMA channel for usage with dmaengine PCM. + */ +struct dma_chan *snd_dmaengine_pcm_request_channel(dma_filter_fn filter_fn, + void *filter_data) +{ + dma_cap_mask_t mask; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + dma_cap_set(DMA_CYCLIC, mask); + + return dma_request_channel(mask, filter_fn, filter_data); +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_request_channel); + +/** + * snd_dmaengine_pcm_open - Open a dmaengine based PCM substream + * @substream: PCM substream + * @chan: DMA channel to use for data transfers + * + * Returns 0 on success, a negative error code otherwise. + * + * The function should usually be called from the pcm open callback. Note that + * this function will use private_data field of the substream's runtime. So it + * is not available to your pcm driver implementation. + */ +int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, + struct dma_chan *chan) +{ + struct dmaengine_pcm_runtime_data *prtd; + int ret; + + if (!chan) + return -ENXIO; + + ret = snd_pcm_hw_constraint_integer(substream->runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + if (ret < 0) + return ret; + + prtd = kzalloc(sizeof(*prtd), GFP_KERNEL); + if (!prtd) + return -ENOMEM; + + prtd->dma_chan = chan; + + substream->runtime->private_data = prtd; + + return 0; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open); + +/** + * snd_dmaengine_pcm_open_request_chan - Open a dmaengine based PCM substream and request channel + * @substream: PCM substream + * @filter_fn: Filter function used to request the DMA channel + * @filter_data: Data passed to the DMA filter function + * + * Returns 0 on success, a negative error code otherwise. + * + * This function will request a DMA channel using the passed filter function and + * data. The function should usually be called from the pcm open callback. Note + * that this function will use private_data field of the substream's runtime. So + * it is not available to your pcm driver implementation. + */ +int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream, + dma_filter_fn filter_fn, void *filter_data) +{ + return snd_dmaengine_pcm_open(substream, + snd_dmaengine_pcm_request_channel(filter_fn, filter_data)); +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open_request_chan); + +/** + * snd_dmaengine_pcm_close - Close a dmaengine based PCM substream + * @substream: PCM substream + */ +int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + dmaengine_synchronize(prtd->dma_chan); + kfree(prtd); + + return 0; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close); + +/** + * snd_dmaengine_pcm_close_release_chan - Close a dmaengine based PCM + * substream and release channel + * @substream: PCM substream + * + * Releases the DMA channel associated with the PCM substream. + */ +int snd_dmaengine_pcm_close_release_chan(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + dmaengine_synchronize(prtd->dma_chan); + dma_release_channel(prtd->dma_chan); + kfree(prtd); + + return 0; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close_release_chan); + +/** + * snd_dmaengine_pcm_refine_runtime_hwparams - Refine runtime hw params + * @substream: PCM substream + * @dma_data: DAI DMA data + * @hw: PCM hw params + * @chan: DMA channel to use for data transfers + * + * Returns 0 on success, a negative error code otherwise. + * + * This function will query DMA capability, then refine the pcm hardware + * parameters. + */ +int snd_dmaengine_pcm_refine_runtime_hwparams( + struct snd_pcm_substream *substream, + struct snd_dmaengine_dai_dma_data *dma_data, + struct snd_pcm_hardware *hw, + struct dma_chan *chan) +{ + struct dma_slave_caps dma_caps; + u32 addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | + BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | + BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); + snd_pcm_format_t i; + int ret = 0; + + if (!hw || !chan || !dma_data) + return -EINVAL; + + ret = dma_get_slave_caps(chan, &dma_caps); + if (ret == 0) { + if (dma_caps.cmd_pause && dma_caps.cmd_resume) + hw->info |= SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME; + if (dma_caps.residue_granularity <= DMA_RESIDUE_GRANULARITY_SEGMENT) + hw->info |= SNDRV_PCM_INFO_BATCH; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + addr_widths = dma_caps.dst_addr_widths; + else + addr_widths = dma_caps.src_addr_widths; + } + + /* + * If SND_DMAENGINE_PCM_DAI_FLAG_PACK is set keep + * hw.formats set to 0, meaning no restrictions are in place. + * In this case it's the responsibility of the DAI driver to + * provide the supported format information. + */ + if (!(dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK)) + /* + * Prepare formats mask for valid/allowed sample types. If the + * dma does not have support for the given physical word size, + * it needs to be masked out so user space can not use the + * format which produces corrupted audio. + * In case the dma driver does not implement the slave_caps the + * default assumption is that it supports 1, 2 and 4 bytes + * widths. + */ + pcm_for_each_format(i) { + int bits = snd_pcm_format_physical_width(i); + + /* + * Enable only samples with DMA supported physical + * widths + */ + switch (bits) { + case 8: + case 16: + case 24: + case 32: + case 64: + if (addr_widths & (1 << (bits / 8))) + hw->formats |= pcm_format_to_bits(i); + break; + default: + /* Unsupported types */ + break; + } + } + + return ret; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_refine_runtime_hwparams); + +MODULE_LICENSE("GPL"); diff --git a/snd-alpx-dkms/snd-alpx/core/generic/5.14/internal.h b/snd-alpx-dkms/snd-alpx/core/generic/5.14/internal.h new file mode 100644 index 0000000..37dfbdf --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/core/generic/5.14/internal.h @@ -0,0 +1,340 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Register map access API internal header + * + * Copyright 2011 Wolfson Microelectronics plc + * + * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> + */ + +#ifndef _REGMAP_INTERNAL_H +#define _REGMAP_INTERNAL_H + +#include <linux/device.h> +#include <linux/regmap.h> +#include <linux/fs.h> +#include <linux/list.h> +#include <linux/wait.h> + +struct regmap; +struct regcache_ops; + +struct regmap_debugfs_off_cache { + struct list_head list; + off_t min; + off_t max; + unsigned int base_reg; + unsigned int max_reg; +}; + +struct regmap_format { + size_t buf_size; + size_t reg_bytes; + size_t pad_bytes; + size_t val_bytes; + s8 reg_shift; + void (*format_write)(struct regmap *map, + unsigned int reg, unsigned int val); + void (*format_reg)(void *buf, unsigned int reg, unsigned int shift); + void (*format_val)(void *buf, unsigned int val, unsigned int shift); + unsigned int (*parse_val)(const void *buf); + void (*parse_inplace)(void *buf); +}; + +struct regmap_async { + struct list_head list; + struct regmap *map; + void *work_buf; +}; + +struct regmap { + union { + struct mutex mutex; + struct { + spinlock_t spinlock; + unsigned long spinlock_flags; + }; + struct { + raw_spinlock_t raw_spinlock; + unsigned long raw_spinlock_flags; + }; + }; + regmap_lock lock; + regmap_unlock unlock; + void *lock_arg; /* This is passed to lock/unlock functions */ + gfp_t alloc_flags; + unsigned int reg_base; + + struct device *dev; /* Device we do I/O on */ + void *work_buf; /* Scratch buffer used to format I/O */ + struct regmap_format format; /* Buffer format */ + const struct regmap_bus *bus; + void *bus_context; + const char *name; + + bool async; + spinlock_t async_lock; + wait_queue_head_t async_waitq; + struct list_head async_list; + struct list_head async_free; + int async_ret; + +#ifdef CONFIG_DEBUG_FS + bool debugfs_disable; + struct dentry *debugfs; + const char *debugfs_name; + + unsigned int debugfs_reg_len; + unsigned int debugfs_val_len; + unsigned int debugfs_tot_len; + + struct list_head debugfs_off_cache; + struct mutex cache_lock; +#endif + + unsigned int max_register; + bool (*writeable_reg)(struct device *dev, unsigned int reg); + bool (*readable_reg)(struct device *dev, unsigned int reg); + bool (*volatile_reg)(struct device *dev, unsigned int reg); + bool (*precious_reg)(struct device *dev, unsigned int reg); + bool (*writeable_noinc_reg)(struct device *dev, unsigned int reg); + bool (*readable_noinc_reg)(struct device *dev, unsigned int reg); + const struct regmap_access_table *wr_table; + const struct regmap_access_table *rd_table; + const struct regmap_access_table *volatile_table; + const struct regmap_access_table *precious_table; + const struct regmap_access_table *wr_noinc_table; + const struct regmap_access_table *rd_noinc_table; + + int (*reg_read)(void *context, unsigned int reg, unsigned int *val); + int (*reg_write)(void *context, unsigned int reg, unsigned int val); + int (*reg_update_bits)(void *context, unsigned int reg, + unsigned int mask, unsigned int val); + /* Bulk read/write */ + int (*read)(void *context, const void *reg_buf, size_t reg_size, + void *val_buf, size_t val_size); + int (*write)(void *context, const void *data, size_t count); + + bool defer_caching; + + unsigned long read_flag_mask; + unsigned long write_flag_mask; + + /* number of bits to (left) shift the reg value when formatting*/ + int reg_shift; + int reg_stride; + int reg_stride_order; + + /* regcache specific members */ + const struct regcache_ops *cache_ops; + enum regcache_type cache_type; + + /* number of bytes in reg_defaults_raw */ + unsigned int cache_size_raw; + /* number of bytes per word in reg_defaults_raw */ + unsigned int cache_word_size; + /* number of entries in reg_defaults */ + unsigned int num_reg_defaults; + /* number of entries in reg_defaults_raw */ + unsigned int num_reg_defaults_raw; + + /* if set, only the cache is modified not the HW */ + bool cache_only; + /* if set, only the HW is modified not the cache */ + bool cache_bypass; + /* if set, remember to free reg_defaults_raw */ + bool cache_free; + + struct reg_default *reg_defaults; + const void *reg_defaults_raw; + void *cache; + /* if set, the cache contains newer data than the HW */ + bool cache_dirty; + /* if set, the HW registers are known to match map->reg_defaults */ + bool no_sync_defaults; + + struct reg_sequence *patch; + int patch_regs; + + /* if set, converts bulk read to single read */ + bool use_single_read; + /* if set, converts bulk write to single write */ + bool use_single_write; + /* if set, the device supports multi write mode */ + bool can_multi_write; + + /* if set, raw reads/writes are limited to this size */ + size_t max_raw_read; + size_t max_raw_write; + + struct rb_root range_tree; + void *selector_work_buf; /* Scratch buffer used for selector */ + + struct hwspinlock *hwlock; + + /* if set, the regmap core can sleep */ + bool can_sleep; +}; + +struct regcache_ops { + const char *name; + enum regcache_type type; + int (*init)(struct regmap *map); + int (*exit)(struct regmap *map); +#ifdef CONFIG_DEBUG_FS + void (*debugfs_init)(struct regmap *map); +#endif + int (*read)(struct regmap *map, unsigned int reg, unsigned int *value); + int (*write)(struct regmap *map, unsigned int reg, unsigned int value); + int (*sync)(struct regmap *map, unsigned int min, unsigned int max); + int (*drop)(struct regmap *map, unsigned int min, unsigned int max); +}; + +bool regmap_cached(struct regmap *map, unsigned int reg); +bool regmap_writeable(struct regmap *map, unsigned int reg); +bool regmap_readable(struct regmap *map, unsigned int reg); +bool regmap_volatile(struct regmap *map, unsigned int reg); +bool regmap_precious(struct regmap *map, unsigned int reg); +bool regmap_writeable_noinc(struct regmap *map, unsigned int reg); +bool regmap_readable_noinc(struct regmap *map, unsigned int reg); + +int _regmap_write(struct regmap *map, unsigned int reg, + unsigned int val); + +struct regmap_range_node { + struct rb_node node; + const char *name; + struct regmap *map; + + unsigned int range_min; + unsigned int range_max; + + unsigned int selector_reg; + unsigned int selector_mask; + int selector_shift; + + unsigned int window_start; + unsigned int window_len; +}; + +struct regmap_field { + struct regmap *regmap; + unsigned int mask; + /* lsb */ + unsigned int shift; + unsigned int reg; + + unsigned int id_size; + unsigned int id_offset; +}; + +#ifdef CONFIG_DEBUG_FS +extern void regmap_debugfs_initcall(void); +extern void regmap_debugfs_init(struct regmap *map); +extern void regmap_debugfs_exit(struct regmap *map); + +static inline void regmap_debugfs_disable(struct regmap *map) +{ + map->debugfs_disable = true; +} + +#else +static inline void regmap_debugfs_initcall(void) { } +static inline void regmap_debugfs_init(struct regmap *map) { } +static inline void regmap_debugfs_exit(struct regmap *map) { } +static inline void regmap_debugfs_disable(struct regmap *map) { } +#endif + +/* regcache core declarations */ +int regcache_init(struct regmap *map, const struct regmap_config *config); +void regcache_exit(struct regmap *map); +int regcache_read(struct regmap *map, + unsigned int reg, unsigned int *value); +int regcache_write(struct regmap *map, + unsigned int reg, unsigned int value); +int regcache_sync(struct regmap *map); +int regcache_sync_block(struct regmap *map, void *block, + unsigned long *cache_present, + unsigned int block_base, unsigned int start, + unsigned int end); +bool regcache_reg_needs_sync(struct regmap *map, unsigned int reg, + unsigned int val); + +static inline const void *regcache_get_val_addr(struct regmap *map, + const void *base, + unsigned int idx) +{ + return base + (map->cache_word_size * idx); +} + +unsigned int regcache_get_val(struct regmap *map, const void *base, + unsigned int idx); +bool regcache_set_val(struct regmap *map, void *base, unsigned int idx, + unsigned int val); +int regcache_lookup_reg(struct regmap *map, unsigned int reg); +int regcache_sync_val(struct regmap *map, unsigned int reg, unsigned int val); + +int _regmap_raw_write(struct regmap *map, unsigned int reg, + const void *val, size_t val_len, bool noinc); + +void regmap_async_complete_cb(struct regmap_async *async, int ret); + +enum regmap_endian regmap_get_val_endian(struct device *dev, + const struct regmap_bus *bus, + const struct regmap_config *config); + +extern struct regcache_ops regcache_rbtree_ops; +extern struct regcache_ops regcache_maple_ops; +extern struct regcache_ops regcache_flat_ops; + +static inline const char *regmap_name(const struct regmap *map) +{ + if (map->dev) + return dev_name(map->dev); + + return map->name; +} + +static inline unsigned int regmap_get_offset(const struct regmap *map, + unsigned int index) +{ + if (map->reg_stride_order >= 0) + return index << map->reg_stride_order; + else + return index * map->reg_stride; +} + +static inline unsigned int regcache_get_index_by_order(const struct regmap *map, + unsigned int reg) +{ + return reg >> map->reg_stride_order; +} + +struct regmap_ram_data { + unsigned int *vals; /* Allocatd by caller */ + bool *read; + bool *written; + enum regmap_endian reg_endian; +}; + +/* + * Create a test register map with data stored in RAM, not intended + * for practical use. + */ +struct regmap *__regmap_init_ram(const struct regmap_config *config, + struct regmap_ram_data *data, + struct lock_class_key *lock_key, + const char *lock_name); + +#define regmap_init_ram(config, data) \ + __regmap_lockdep_wrapper(__regmap_init_ram, #config, config, data) + +struct regmap *__regmap_init_raw_ram(const struct regmap_config *config, + struct regmap_ram_data *data, + struct lock_class_key *lock_key, + const char *lock_name); + +#define regmap_init_raw_ram(config, data) \ + __regmap_lockdep_wrapper(__regmap_init_raw_ram, #config, config, data) + +#endif diff --git a/snd-alpx-dkms/snd-alpx/core/generic/5.14/regmap-mmio.c b/snd-alpx-dkms/snd-alpx/core/generic/5.14/regmap-mmio.c new file mode 100644 index 0000000..3ccdd86 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/core/generic/5.14/regmap-mmio.c @@ -0,0 +1,636 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Register map access API - MMIO support +// +// Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/regmap.h> +#include <linux/slab.h> +#include <linux/swab.h> + +#include "internal.h" + +struct regmap_mmio_context { + void __iomem *regs; + unsigned int val_bytes; + bool big_endian; + + bool attached_clk; + struct clk *clk; + + void (*reg_write)(struct regmap_mmio_context *ctx, + unsigned int reg, unsigned int val); + unsigned int (*reg_read)(struct regmap_mmio_context *ctx, + unsigned int reg); +}; + +static int regmap_mmio_regbits_check(size_t reg_bits) +{ + switch (reg_bits) { + case 8: + case 16: + case 32: + return 0; + default: + return -EINVAL; + } +} + +static int regmap_mmio_get_min_stride(size_t val_bits) +{ + int min_stride; + + switch (val_bits) { + case 8: + /* The core treats 0 as 1 */ + min_stride = 0; + break; + case 16: + min_stride = 2; + break; + case 32: + min_stride = 4; + break; + default: + return -EINVAL; + } + + return min_stride; +} + +static void regmap_mmio_write8(struct regmap_mmio_context *ctx, + unsigned int reg, + unsigned int val) +{ + writeb(val, ctx->regs + reg); +} + +static void regmap_mmio_write8_relaxed(struct regmap_mmio_context *ctx, + unsigned int reg, + unsigned int val) +{ + writeb_relaxed(val, ctx->regs + reg); +} + +static void regmap_mmio_iowrite8(struct regmap_mmio_context *ctx, + unsigned int reg, unsigned int val) +{ + iowrite8(val, ctx->regs + reg); +} + +static void regmap_mmio_write16le(struct regmap_mmio_context *ctx, + unsigned int reg, + unsigned int val) +{ + writew(val, ctx->regs + reg); +} + +static void regmap_mmio_write16le_relaxed(struct regmap_mmio_context *ctx, + unsigned int reg, + unsigned int val) +{ + writew_relaxed(val, ctx->regs + reg); +} + +static void regmap_mmio_iowrite16le(struct regmap_mmio_context *ctx, + unsigned int reg, unsigned int val) +{ + iowrite16(val, ctx->regs + reg); +} + +static void regmap_mmio_write16be(struct regmap_mmio_context *ctx, + unsigned int reg, + unsigned int val) +{ + writew(swab16(val), ctx->regs + reg); +} + +static void regmap_mmio_iowrite16be(struct regmap_mmio_context *ctx, + unsigned int reg, unsigned int val) +{ + iowrite16be(val, ctx->regs + reg); +} + +static void regmap_mmio_write32le(struct regmap_mmio_context *ctx, + unsigned int reg, + unsigned int val) +{ + writel(val, ctx->regs + reg); +} + +static void regmap_mmio_write32le_relaxed(struct regmap_mmio_context *ctx, + unsigned int reg, + unsigned int val) +{ + writel_relaxed(val, ctx->regs + reg); +} + +static void regmap_mmio_iowrite32le(struct regmap_mmio_context *ctx, + unsigned int reg, unsigned int val) +{ + iowrite32(val, ctx->regs + reg); +} + +static void regmap_mmio_write32be(struct regmap_mmio_context *ctx, + unsigned int reg, + unsigned int val) +{ + writel(swab32(val), ctx->regs + reg); +} + +static void regmap_mmio_iowrite32be(struct regmap_mmio_context *ctx, + unsigned int reg, unsigned int val) +{ + iowrite32be(val, ctx->regs + reg); +} + +static int regmap_mmio_write(void *context, unsigned int reg, unsigned int val) +{ + struct regmap_mmio_context *ctx = context; + int ret; + + if (!IS_ERR(ctx->clk)) { + ret = clk_enable(ctx->clk); + if (ret < 0) + return ret; + } + + ctx->reg_write(ctx, reg, val); + + if (!IS_ERR(ctx->clk)) + clk_disable(ctx->clk); + + return 0; +} + +static int regmap_mmio_noinc_write(void *context, unsigned int reg, + const void *val, size_t val_count) +{ + struct regmap_mmio_context *ctx = context; + int ret = 0; + int i; + + if (!IS_ERR(ctx->clk)) { + ret = clk_enable(ctx->clk); + if (ret < 0) + return ret; + } + + /* + * There are no native, assembly-optimized write single register + * operations for big endian, so fall back to emulation if this + * is needed. (Single bytes are fine, they are not affected by + * endianness.) + */ + if (ctx->big_endian && (ctx->val_bytes > 1)) { + switch (ctx->val_bytes) { + case 2: + { + const u16 *valp = (const u16 *)val; + for (i = 0; i < val_count; i++) + writew(swab16(valp[i]), ctx->regs + reg); + goto out_clk; + } + case 4: + { + const u32 *valp = (const u32 *)val; + for (i = 0; i < val_count; i++) + writel(swab32(valp[i]), ctx->regs + reg); + goto out_clk; + } +#ifdef CONFIG_64BIT + case 8: + { + const u64 *valp = (const u64 *)val; + for (i = 0; i < val_count; i++) + writeq(swab64(valp[i]), ctx->regs + reg); + goto out_clk; + } +#endif + default: + ret = -EINVAL; + goto out_clk; + } + } + + switch (ctx->val_bytes) { + case 1: + writesb(ctx->regs + reg, (const u8 *)val, val_count); + break; + case 2: + writesw(ctx->regs + reg, (const u16 *)val, val_count); + break; + case 4: + writesl(ctx->regs + reg, (const u32 *)val, val_count); + break; +#ifdef CONFIG_64BIT + case 8: + writesq(ctx->regs + reg, (const u64 *)val, val_count); + break; +#endif + default: + ret = -EINVAL; + break; + } + +out_clk: + if (!IS_ERR(ctx->clk)) + clk_disable(ctx->clk); + + return ret; +} + +static unsigned int regmap_mmio_read8(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return readb(ctx->regs + reg); +} + +static unsigned int regmap_mmio_read8_relaxed(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return readb_relaxed(ctx->regs + reg); +} + +static unsigned int regmap_mmio_ioread8(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return ioread8(ctx->regs + reg); +} + +static unsigned int regmap_mmio_read16le(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return readw(ctx->regs + reg); +} + +static unsigned int regmap_mmio_read16le_relaxed(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return readw_relaxed(ctx->regs + reg); +} + +static unsigned int regmap_mmio_ioread16le(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return ioread16(ctx->regs + reg); +} + +static unsigned int regmap_mmio_read16be(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return swab16(readw(ctx->regs + reg)); +} + +static unsigned int regmap_mmio_ioread16be(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return ioread16be(ctx->regs + reg); +} + +static unsigned int regmap_mmio_read32le(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return readl(ctx->regs + reg); +} + +static unsigned int regmap_mmio_read32le_relaxed(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return readl_relaxed(ctx->regs + reg); +} + +static unsigned int regmap_mmio_ioread32le(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return ioread32(ctx->regs + reg); +} + +static unsigned int regmap_mmio_read32be(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return swab32(readl(ctx->regs + reg)); +} + +static unsigned int regmap_mmio_ioread32be(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return ioread32be(ctx->regs + reg); +} + +static int regmap_mmio_read(void *context, unsigned int reg, unsigned int *val) +{ + struct regmap_mmio_context *ctx = context; + int ret; + + if (!IS_ERR(ctx->clk)) { + ret = clk_enable(ctx->clk); + if (ret < 0) + return ret; + } + + *val = ctx->reg_read(ctx, reg); + + if (!IS_ERR(ctx->clk)) + clk_disable(ctx->clk); + + return 0; +} + +static int regmap_mmio_noinc_read(void *context, unsigned int reg, + void *val, size_t val_count) +{ + struct regmap_mmio_context *ctx = context; + int ret = 0; + + if (!IS_ERR(ctx->clk)) { + ret = clk_enable(ctx->clk); + if (ret < 0) + return ret; + } + + switch (ctx->val_bytes) { + case 1: + readsb(ctx->regs + reg, (u8 *)val, val_count); + break; + case 2: + readsw(ctx->regs + reg, (u16 *)val, val_count); + break; + case 4: + readsl(ctx->regs + reg, (u32 *)val, val_count); + break; +#ifdef CONFIG_64BIT + case 8: + readsq(ctx->regs + reg, (u64 *)val, val_count); + break; +#endif + default: + ret = -EINVAL; + goto out_clk; + } + + /* + * There are no native, assembly-optimized write single register + * operations for big endian, so fall back to emulation if this + * is needed. (Single bytes are fine, they are not affected by + * endianness.) + */ + if (ctx->big_endian && (ctx->val_bytes > 1)) { + switch (ctx->val_bytes) { + case 2: + swab16_array(val, val_count); + break; + case 4: + swab32_array(val, val_count); + break; +#ifdef CONFIG_64BIT + case 8: + swab64_array(val, val_count); + break; +#endif + default: + ret = -EINVAL; + break; + } + } + +out_clk: + if (!IS_ERR(ctx->clk)) + clk_disable(ctx->clk); + + return ret; +} + + +static void regmap_mmio_free_context(void *context) +{ + struct regmap_mmio_context *ctx = context; + + if (!IS_ERR(ctx->clk)) { + clk_unprepare(ctx->clk); + if (!ctx->attached_clk) + clk_put(ctx->clk); + } + kfree(context); +} + +static const struct regmap_bus regmap_mmio = { + .fast_io = true, + .reg_write = regmap_mmio_write, + .reg_read = regmap_mmio_read, + .reg_noinc_write = regmap_mmio_noinc_write, + .reg_noinc_read = regmap_mmio_noinc_read, + .free_context = regmap_mmio_free_context, + .val_format_endian_default = REGMAP_ENDIAN_LITTLE, +}; + +static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev, + const char *clk_id, + void __iomem *regs, + const struct regmap_config *config) +{ + struct regmap_mmio_context *ctx; + int min_stride; + int ret; + + ret = regmap_mmio_regbits_check(config->reg_bits); + if (ret) + return ERR_PTR(ret); + + if (config->pad_bits) + return ERR_PTR(-EINVAL); + + min_stride = regmap_mmio_get_min_stride(config->val_bits); + if (min_stride < 0) + return ERR_PTR(min_stride); + + if (config->reg_stride < min_stride) + return ERR_PTR(-EINVAL); + + if (config->use_relaxed_mmio && config->io_port) + return ERR_PTR(-EINVAL); + + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return ERR_PTR(-ENOMEM); + + ctx->regs = regs; + ctx->val_bytes = config->val_bits / 8; + ctx->clk = ERR_PTR(-ENODEV); + + switch (regmap_get_val_endian(dev, ®map_mmio, config)) { + case REGMAP_ENDIAN_DEFAULT: + case REGMAP_ENDIAN_LITTLE: +#ifdef __LITTLE_ENDIAN + case REGMAP_ENDIAN_NATIVE: +#endif + switch (config->val_bits) { + case 8: + if (config->io_port) { + ctx->reg_read = regmap_mmio_ioread8; + ctx->reg_write = regmap_mmio_iowrite8; + } else if (config->use_relaxed_mmio) { + ctx->reg_read = regmap_mmio_read8_relaxed; + ctx->reg_write = regmap_mmio_write8_relaxed; + } else { + ctx->reg_read = regmap_mmio_read8; + ctx->reg_write = regmap_mmio_write8; + } + break; + case 16: + if (config->io_port) { + ctx->reg_read = regmap_mmio_ioread16le; + ctx->reg_write = regmap_mmio_iowrite16le; + } else if (config->use_relaxed_mmio) { + ctx->reg_read = regmap_mmio_read16le_relaxed; + ctx->reg_write = regmap_mmio_write16le_relaxed; + } else { + ctx->reg_read = regmap_mmio_read16le; + ctx->reg_write = regmap_mmio_write16le; + } + break; + case 32: + if (config->io_port) { + ctx->reg_read = regmap_mmio_ioread32le; + ctx->reg_write = regmap_mmio_iowrite32le; + } else if (config->use_relaxed_mmio) { + ctx->reg_read = regmap_mmio_read32le_relaxed; + ctx->reg_write = regmap_mmio_write32le_relaxed; + } else { + ctx->reg_read = regmap_mmio_read32le; + ctx->reg_write = regmap_mmio_write32le; + } + break; + default: + ret = -EINVAL; + goto err_free; + } + break; + case REGMAP_ENDIAN_BIG: +#ifdef __BIG_ENDIAN + case REGMAP_ENDIAN_NATIVE: +#endif + ctx->big_endian = true; + switch (config->val_bits) { + case 8: + if (config->io_port) { + ctx->reg_read = regmap_mmio_ioread8; + ctx->reg_write = regmap_mmio_iowrite8; + } else { + ctx->reg_read = regmap_mmio_read8; + ctx->reg_write = regmap_mmio_write8; + } + break; + case 16: + if (config->io_port) { + ctx->reg_read = regmap_mmio_ioread16be; + ctx->reg_write = regmap_mmio_iowrite16be; + } else { + ctx->reg_read = regmap_mmio_read16be; + ctx->reg_write = regmap_mmio_write16be; + } + break; + case 32: + if (config->io_port) { + ctx->reg_read = regmap_mmio_ioread32be; + ctx->reg_write = regmap_mmio_iowrite32be; + } else { + ctx->reg_read = regmap_mmio_read32be; + ctx->reg_write = regmap_mmio_write32be; + } + break; + default: + ret = -EINVAL; + goto err_free; + } + break; + default: + ret = -EINVAL; + goto err_free; + } + + if (clk_id == NULL) + return ctx; + + ctx->clk = clk_get(dev, clk_id); + if (IS_ERR(ctx->clk)) { + ret = PTR_ERR(ctx->clk); + goto err_free; + } + + ret = clk_prepare(ctx->clk); + if (ret < 0) { + clk_put(ctx->clk); + goto err_free; + } + + return ctx; + +err_free: + kfree(ctx); + + return ERR_PTR(ret); +} + +struct regmap *__regmap_init_mmio_clk(struct device *dev, const char *clk_id, + void __iomem *regs, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name) +{ + struct regmap_mmio_context *ctx; + + ctx = regmap_mmio_gen_context(dev, clk_id, regs, config); + if (IS_ERR(ctx)) + return ERR_CAST(ctx); + + return __regmap_init(dev, ®map_mmio, ctx, config, + lock_key, lock_name); +} +EXPORT_SYMBOL_GPL(__regmap_init_mmio_clk); + +struct regmap *__devm_regmap_init_mmio_clk(struct device *dev, + const char *clk_id, + void __iomem *regs, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name) +{ + struct regmap_mmio_context *ctx; + + ctx = regmap_mmio_gen_context(dev, clk_id, regs, config); + if (IS_ERR(ctx)) + return ERR_CAST(ctx); + + return __devm_regmap_init(dev, ®map_mmio, ctx, config, + lock_key, lock_name); +} +EXPORT_SYMBOL_GPL(__devm_regmap_init_mmio_clk); + +int regmap_mmio_attach_clk(struct regmap *map, struct clk *clk) +{ + struct regmap_mmio_context *ctx = map->bus_context; + + ctx->clk = clk; + ctx->attached_clk = true; + + return clk_prepare(ctx->clk); +} +EXPORT_SYMBOL_GPL(regmap_mmio_attach_clk); + +void regmap_mmio_detach_clk(struct regmap *map) +{ + struct regmap_mmio_context *ctx = map->bus_context; + + clk_unprepare(ctx->clk); + + ctx->attached_clk = false; + ctx->clk = NULL; +} +EXPORT_SYMBOL_GPL(regmap_mmio_detach_clk); + +MODULE_LICENSE("GPL v2"); diff --git a/snd-alpx-dkms/snd-alpx/core/generic/5.17/dmaengine_pcm.h b/snd-alpx-dkms/snd-alpx/core/generic/5.17/dmaengine_pcm.h new file mode 100644 index 0000000..38ea046 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/core/generic/5.17/dmaengine_pcm.h @@ -0,0 +1,178 @@ +/* SPDX-License-Identifier: GPL-2.0+ + * + * Copyright (C) 2012, Analog Devices Inc. + * Author: Lars-Peter Clausen <lars@metafoo.de> + */ + +#ifndef __SOUND_DMAENGINE_PCM_H__ +#define __SOUND_DMAENGINE_PCM_H__ + +#include <sound/pcm.h> +#include <sound/soc.h> +#include <linux/dmaengine.h> + +/** + * snd_pcm_substream_to_dma_direction - Get dma_transfer_direction for a PCM + * substream + * @substream: PCM substream + */ +static inline enum dma_transfer_direction +snd_pcm_substream_to_dma_direction(const struct snd_pcm_substream *substream) +{ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + return DMA_MEM_TO_DEV; + else + return DMA_DEV_TO_MEM; +} + +int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream, + const struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config); +int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd); +snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream); +snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream *substream); + +int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, + struct dma_chan *chan); +int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream); + +int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream, + dma_filter_fn filter_fn, void *filter_data); +int snd_dmaengine_pcm_close_release_chan(struct snd_pcm_substream *substream); + +struct dma_chan *snd_dmaengine_pcm_request_channel(dma_filter_fn filter_fn, + void *filter_data); +struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream); + +/* + * The DAI supports packed transfers, eg 2 16-bit samples in a 32-bit word. + * If this flag is set the dmaengine driver won't put any restriction on + * the supported sample formats and set the DMA transfer size to undefined. + * The DAI driver is responsible to disable any unsupported formats in it's + * configuration and catch corner cases that are not already handled in + * the ALSA core. + */ +#define SND_DMAENGINE_PCM_DAI_FLAG_PACK BIT(0) + +/** + * struct snd_dmaengine_dai_dma_data - DAI DMA configuration data + * @addr: Address of the DAI data source or destination register. + * @addr_width: Width of the DAI data source or destination register. + * @maxburst: Maximum number of words(note: words, as in units of the + * src_addr_width member, not bytes) that can be send to or received from the + * DAI in one burst. + * @filter_data: Custom DMA channel filter data, this will usually be used when + * requesting the DMA channel. + * @chan_name: Custom channel name to use when requesting DMA channel. + * @fifo_size: FIFO size of the DAI controller in bytes + * @flags: PCM_DAI flags, only SND_DMAENGINE_PCM_DAI_FLAG_PACK for now + * @peripheral_config: peripheral configuration for programming peripheral + * for dmaengine transfer + * @peripheral_size: peripheral configuration buffer size + */ +struct snd_dmaengine_dai_dma_data { + dma_addr_t addr; + enum dma_slave_buswidth addr_width; + u32 maxburst; + void *filter_data; + const char *chan_name; + unsigned int fifo_size; + unsigned int flags; + void *peripheral_config; + size_t peripheral_size; +}; + +void snd_dmaengine_pcm_set_config_from_dai_data( + const struct snd_pcm_substream *substream, + const struct snd_dmaengine_dai_dma_data *dma_data, + struct dma_slave_config *config); + +int snd_dmaengine_pcm_refine_runtime_hwparams( + struct snd_pcm_substream *substream, + struct snd_dmaengine_dai_dma_data *dma_data, + struct snd_pcm_hardware *hw, + struct dma_chan *chan); + +/* + * Try to request the DMA channel using compat_request_channel or + * compat_filter_fn if it couldn't be requested through devicetree. + */ +#define SND_DMAENGINE_PCM_FLAG_COMPAT BIT(0) +/* + * Don't try to request the DMA channels through devicetree. This flag only + * makes sense if SND_DMAENGINE_PCM_FLAG_COMPAT is set as well. + */ +#define SND_DMAENGINE_PCM_FLAG_NO_DT BIT(1) +/* + * The PCM is half duplex and the DMA channel is shared between capture and + * playback. + */ +#define SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX BIT(3) + +/** + * struct snd_dmaengine_pcm_config - Configuration data for dmaengine based PCM + * @prepare_slave_config: Callback used to fill in the DMA slave_config for a + * PCM substream. Will be called from the PCM drivers hwparams callback. + * @compat_request_channel: Callback to request a DMA channel for platforms + * which do not use devicetree. + * @process: Callback used to apply processing on samples transferred from/to + * user space. + * @compat_filter_fn: Will be used as the filter function when requesting a + * channel for platforms which do not use devicetree. The filter parameter + * will be the DAI's DMA data. + * @dma_dev: If set, request DMA channel on this device rather than the DAI + * device. + * @chan_names: If set, these custom DMA channel names will be requested at + * registration time. + * @pcm_hardware: snd_pcm_hardware struct to be used for the PCM. + * @prealloc_buffer_size: Size of the preallocated audio buffer. + * + * Note: If both compat_request_channel and compat_filter_fn are set + * compat_request_channel will be used to request the channel and + * compat_filter_fn will be ignored. Otherwise the channel will be requested + * using dma_request_channel with compat_filter_fn as the filter function. + */ +struct snd_dmaengine_pcm_config { + int (*prepare_slave_config)(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct dma_slave_config *slave_config); + struct dma_chan *(*compat_request_channel)( + struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_substream *substream); + int (*process)(struct snd_pcm_substream *substream, + int channel, unsigned long hwoff, + void *buf, unsigned long bytes); + dma_filter_fn compat_filter_fn; + struct device *dma_dev; + const char *chan_names[SNDRV_PCM_STREAM_LAST + 1]; + + const struct snd_pcm_hardware *pcm_hardware; + unsigned int prealloc_buffer_size; +}; + +int snd_dmaengine_pcm_register(struct device *dev, + const struct snd_dmaengine_pcm_config *config, + unsigned int flags); +void snd_dmaengine_pcm_unregister(struct device *dev); + +int devm_snd_dmaengine_pcm_register(struct device *dev, + const struct snd_dmaengine_pcm_config *config, + unsigned int flags); + +int snd_dmaengine_pcm_prepare_slave_config(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct dma_slave_config *slave_config); + +#define SND_DMAENGINE_PCM_DRV_NAME "snd_dmaengine_pcm" + +struct dmaengine_pcm { + struct dma_chan *chan[SNDRV_PCM_STREAM_LAST + 1]; + const struct snd_dmaengine_pcm_config *config; + struct snd_soc_component component; + unsigned int flags; +}; + +static inline struct dmaengine_pcm *soc_component_to_pcm(struct snd_soc_component *p) +{ + return container_of(p, struct dmaengine_pcm, component); +} +#endif diff --git a/snd-alpx-dkms/snd-alpx/core/generic/5.17/pcm_dmaengine.c b/snd-alpx-dkms/snd-alpx/core/generic/5.17/pcm_dmaengine.c new file mode 100644 index 0000000..af6f717 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/core/generic/5.17/pcm_dmaengine.c @@ -0,0 +1,461 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2012, Analog Devices Inc. + * Author: Lars-Peter Clausen <lars@metafoo.de> + * + * Based on: + * imx-pcm-dma-mx2.c, Copyright 2009 Sascha Hauer <s.hauer@pengutronix.de> + * mxs-pcm.c, Copyright (C) 2011 Freescale Semiconductor, Inc. + * ep93xx-pcm.c, Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> + * Copyright (C) 2006 Applied Data Systems + */ +#include <linux/module.h> +#include <linux/init.h> +#include <linux/dmaengine.h> +#include <linux/slab.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> + +#include <sound/dmaengine_pcm.h> + +struct dmaengine_pcm_runtime_data { + struct dma_chan *dma_chan; + dma_cookie_t cookie; + + unsigned int pos; +}; + +static inline struct dmaengine_pcm_runtime_data *substream_to_prtd( + const struct snd_pcm_substream *substream) +{ + return substream->runtime->private_data; +} + +struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + return prtd->dma_chan; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_get_chan); + +/** + * snd_hwparams_to_dma_slave_config - Convert hw_params to dma_slave_config + * @substream: PCM substream + * @params: hw_params + * @slave_config: DMA slave config + * + * This function can be used to initialize a dma_slave_config from a substream + * and hw_params in a dmaengine based PCM driver implementation. + */ +int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream, + const struct snd_pcm_hw_params *params, + struct dma_slave_config *slave_config) +{ + enum dma_slave_buswidth buswidth; + int bits; + + bits = params_physical_width(params); + if (bits < 8 || bits > 64) + return -EINVAL; + else if (bits == 8) + buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE; + else if (bits == 16) + buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; + else if (bits == 24) + buswidth = DMA_SLAVE_BUSWIDTH_3_BYTES; + else if (bits <= 32) + buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES; + else + buswidth = DMA_SLAVE_BUSWIDTH_8_BYTES; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + slave_config->direction = DMA_MEM_TO_DEV; + slave_config->dst_addr_width = buswidth; + } else { + slave_config->direction = DMA_DEV_TO_MEM; + slave_config->src_addr_width = buswidth; + } + + slave_config->device_fc = false; + + return 0; +} +EXPORT_SYMBOL_GPL(snd_hwparams_to_dma_slave_config); + +/** + * snd_dmaengine_pcm_set_config_from_dai_data() - Initializes a dma slave config + * using DAI DMA data. + * @substream: PCM substream + * @dma_data: DAI DMA data + * @slave_config: DMA slave configuration + * + * Initializes the {dst,src}_addr, {dst,src}_maxburst, {dst,src}_addr_width + * fields of the DMA slave config from the same fields of the DAI DMA + * data struct. The src and dst fields will be initialized depending on the + * direction of the substream. If the substream is a playback stream the dst + * fields will be initialized, if it is a capture stream the src fields will be + * initialized. The {dst,src}_addr_width field will only be initialized if the + * SND_DMAENGINE_PCM_DAI_FLAG_PACK flag is set or if the addr_width field of + * the DAI DMA data struct is not equal to DMA_SLAVE_BUSWIDTH_UNDEFINED. If + * both conditions are met the latter takes priority. + */ +void snd_dmaengine_pcm_set_config_from_dai_data( + const struct snd_pcm_substream *substream, + const struct snd_dmaengine_dai_dma_data *dma_data, + struct dma_slave_config *slave_config) +{ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + slave_config->dst_addr = dma_data->addr; + slave_config->dst_maxburst = dma_data->maxburst; + if (dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK) + slave_config->dst_addr_width = + DMA_SLAVE_BUSWIDTH_UNDEFINED; + if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED) + slave_config->dst_addr_width = dma_data->addr_width; + } else { + slave_config->src_addr = dma_data->addr; + slave_config->src_maxburst = dma_data->maxburst; + if (dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK) + slave_config->src_addr_width = + DMA_SLAVE_BUSWIDTH_UNDEFINED; + if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED) + slave_config->src_addr_width = dma_data->addr_width; + } + + slave_config->peripheral_config = dma_data->peripheral_config; + slave_config->peripheral_size = dma_data->peripheral_size; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_config_from_dai_data); + +static void dmaengine_pcm_dma_complete(void *arg) +{ + struct snd_pcm_substream *substream = arg; + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + prtd->pos += snd_pcm_lib_period_bytes(substream); + if (prtd->pos >= snd_pcm_lib_buffer_bytes(substream)) + prtd->pos = 0; + + snd_pcm_period_elapsed(substream); +} + +static int dmaengine_pcm_prepare_and_submit(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + struct dma_chan *chan = prtd->dma_chan; + struct dma_async_tx_descriptor *desc; + enum dma_transfer_direction direction; + unsigned long flags = DMA_CTRL_ACK; + + direction = snd_pcm_substream_to_dma_direction(substream); + + if (!substream->runtime->no_period_wakeup) + flags |= DMA_PREP_INTERRUPT; + + prtd->pos = 0; + desc = dmaengine_prep_dma_cyclic(chan, + substream->runtime->dma_addr, + snd_pcm_lib_buffer_bytes(substream), + snd_pcm_lib_period_bytes(substream), direction, flags); + + if (!desc) + return -ENOMEM; + + desc->callback = dmaengine_pcm_dma_complete; + desc->callback_param = substream; + prtd->cookie = dmaengine_submit(desc); + + return 0; +} + +/** + * snd_dmaengine_pcm_trigger - dmaengine based PCM trigger implementation + * @substream: PCM substream + * @cmd: Trigger command + * + * Returns 0 on success, a negative error code otherwise. + * + * This function can be used as the PCM trigger callback for dmaengine based PCM + * driver implementations. + */ +int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + int ret; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + ret = dmaengine_pcm_prepare_and_submit(substream); + if (ret) + return ret; + dma_async_issue_pending(prtd->dma_chan); + break; + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + dmaengine_resume(prtd->dma_chan); + break; + case SNDRV_PCM_TRIGGER_SUSPEND: + if (runtime->info & SNDRV_PCM_INFO_PAUSE) + dmaengine_pause(prtd->dma_chan); + else + dmaengine_terminate_async(prtd->dma_chan); + break; + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + dmaengine_pause(prtd->dma_chan); + break; + case SNDRV_PCM_TRIGGER_STOP: + dmaengine_terminate_async(prtd->dma_chan); + break; + default: + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_trigger); + +/** + * snd_dmaengine_pcm_pointer_no_residue - dmaengine based PCM pointer implementation + * @substream: PCM substream + * + * This function is deprecated and should not be used by new drivers, as its + * results may be unreliable. + */ +snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + return bytes_to_frames(substream->runtime, prtd->pos); +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer_no_residue); + +/** + * snd_dmaengine_pcm_pointer - dmaengine based PCM pointer implementation + * @substream: PCM substream + * + * This function can be used as the PCM pointer callback for dmaengine based PCM + * driver implementations. + */ +snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + struct dma_tx_state state; + enum dma_status status; + unsigned int buf_size; + unsigned int pos = 0; + + status = dmaengine_tx_status(prtd->dma_chan, prtd->cookie, &state); + if (status == DMA_IN_PROGRESS || status == DMA_PAUSED) { + buf_size = snd_pcm_lib_buffer_bytes(substream); + if (state.residue > 0 && state.residue <= buf_size) + pos = buf_size - state.residue; + + runtime->delay = bytes_to_frames(runtime, + state.in_flight_bytes); + } + + return bytes_to_frames(runtime, pos); +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer); + +/** + * snd_dmaengine_pcm_request_channel - Request channel for the dmaengine PCM + * @filter_fn: Filter function used to request the DMA channel + * @filter_data: Data passed to the DMA filter function + * + * Returns NULL or the requested DMA channel. + * + * This function request a DMA channel for usage with dmaengine PCM. + */ +struct dma_chan *snd_dmaengine_pcm_request_channel(dma_filter_fn filter_fn, + void *filter_data) +{ + dma_cap_mask_t mask; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + dma_cap_set(DMA_CYCLIC, mask); + + return dma_request_channel(mask, filter_fn, filter_data); +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_request_channel); + +/** + * snd_dmaengine_pcm_open - Open a dmaengine based PCM substream + * @substream: PCM substream + * @chan: DMA channel to use for data transfers + * + * Returns 0 on success, a negative error code otherwise. + * + * The function should usually be called from the pcm open callback. Note that + * this function will use private_data field of the substream's runtime. So it + * is not available to your pcm driver implementation. + */ +int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, + struct dma_chan *chan) +{ + struct dmaengine_pcm_runtime_data *prtd; + int ret; + + if (!chan) + return -ENXIO; + + ret = snd_pcm_hw_constraint_integer(substream->runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + if (ret < 0) + return ret; + + prtd = kzalloc(sizeof(*prtd), GFP_KERNEL); + if (!prtd) + return -ENOMEM; + + prtd->dma_chan = chan; + + substream->runtime->private_data = prtd; + + return 0; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open); + +/** + * snd_dmaengine_pcm_open_request_chan - Open a dmaengine based PCM substream and request channel + * @substream: PCM substream + * @filter_fn: Filter function used to request the DMA channel + * @filter_data: Data passed to the DMA filter function + * + * Returns 0 on success, a negative error code otherwise. + * + * This function will request a DMA channel using the passed filter function and + * data. The function should usually be called from the pcm open callback. Note + * that this function will use private_data field of the substream's runtime. So + * it is not available to your pcm driver implementation. + */ +int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream, + dma_filter_fn filter_fn, void *filter_data) +{ + return snd_dmaengine_pcm_open(substream, + snd_dmaengine_pcm_request_channel(filter_fn, filter_data)); +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open_request_chan); + +/** + * snd_dmaengine_pcm_close - Close a dmaengine based PCM substream + * @substream: PCM substream + */ +int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + dmaengine_synchronize(prtd->dma_chan); + kfree(prtd); + + return 0; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close); + +/** + * snd_dmaengine_pcm_close_release_chan - Close a dmaengine based PCM + * substream and release channel + * @substream: PCM substream + * + * Releases the DMA channel associated with the PCM substream. + */ +int snd_dmaengine_pcm_close_release_chan(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + dmaengine_synchronize(prtd->dma_chan); + dma_release_channel(prtd->dma_chan); + kfree(prtd); + + return 0; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close_release_chan); + +/** + * snd_dmaengine_pcm_refine_runtime_hwparams - Refine runtime hw params + * @substream: PCM substream + * @dma_data: DAI DMA data + * @hw: PCM hw params + * @chan: DMA channel to use for data transfers + * + * Returns 0 on success, a negative error code otherwise. + * + * This function will query DMA capability, then refine the pcm hardware + * parameters. + */ +int snd_dmaengine_pcm_refine_runtime_hwparams( + struct snd_pcm_substream *substream, + struct snd_dmaengine_dai_dma_data *dma_data, + struct snd_pcm_hardware *hw, + struct dma_chan *chan) +{ + struct dma_slave_caps dma_caps; + u32 addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | + BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | + BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); + snd_pcm_format_t i; + int ret = 0; + + if (!hw || !chan || !dma_data) + return -EINVAL; + + ret = dma_get_slave_caps(chan, &dma_caps); + if (ret == 0) { + if (dma_caps.cmd_pause && dma_caps.cmd_resume) + hw->info |= SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME; + if (dma_caps.residue_granularity <= DMA_RESIDUE_GRANULARITY_SEGMENT) + hw->info |= SNDRV_PCM_INFO_BATCH; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + addr_widths = dma_caps.dst_addr_widths; + else + addr_widths = dma_caps.src_addr_widths; + } + + /* + * If SND_DMAENGINE_PCM_DAI_FLAG_PACK is set keep + * hw.formats set to 0, meaning no restrictions are in place. + * In this case it's the responsibility of the DAI driver to + * provide the supported format information. + */ + if (!(dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK)) + /* + * Prepare formats mask for valid/allowed sample types. If the + * dma does not have support for the given physical word size, + * it needs to be masked out so user space can not use the + * format which produces corrupted audio. + * In case the dma driver does not implement the slave_caps the + * default assumption is that it supports 1, 2 and 4 bytes + * widths. + */ + pcm_for_each_format(i) { + int bits = snd_pcm_format_physical_width(i); + + /* + * Enable only samples with DMA supported physical + * widths + */ + switch (bits) { + case 8: + case 16: + case 24: + case 32: + case 64: + if (addr_widths & (1 << (bits / 8))) + hw->formats |= pcm_format_to_bits(i); + break; + default: + /* Unsupported types */ + break; + } + } + + return ret; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_refine_runtime_hwparams); + +MODULE_LICENSE("GPL"); diff --git a/snd-alpx-dkms/snd-alpx/core/generic/5.2/dmaengine_pcm.h b/snd-alpx-dkms/snd-alpx/core/generic/5.2/dmaengine_pcm.h new file mode 100644 index 0000000..c679f61 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/core/generic/5.2/dmaengine_pcm.h @@ -0,0 +1,159 @@ +/* SPDX-License-Identifier: GPL-2.0+ + * + * Copyright (C) 2012, Analog Devices Inc. + * Author: Lars-Peter Clausen <lars@metafoo.de> + */ + +#ifndef __SOUND_DMAENGINE_PCM_H__ +#define __SOUND_DMAENGINE_PCM_H__ + +#include <sound/pcm.h> +#include <sound/soc.h> +#include <linux/dmaengine.h> + +/** + * snd_pcm_substream_to_dma_direction - Get dma_transfer_direction for a PCM + * substream + * @substream: PCM substream + */ +static inline enum dma_transfer_direction +snd_pcm_substream_to_dma_direction(const struct snd_pcm_substream *substream) +{ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + return DMA_MEM_TO_DEV; + else + return DMA_DEV_TO_MEM; +} + +int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream, + const struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config); +int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd); +snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream); +snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream *substream); + +int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, + struct dma_chan *chan); +int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream); + +int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream, + dma_filter_fn filter_fn, void *filter_data); +int snd_dmaengine_pcm_close_release_chan(struct snd_pcm_substream *substream); + +struct dma_chan *snd_dmaengine_pcm_request_channel(dma_filter_fn filter_fn, + void *filter_data); +struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream); + +/* + * The DAI supports packed transfers, eg 2 16-bit samples in a 32-bit word. + * If this flag is set the dmaengine driver won't put any restriction on + * the supported sample formats and set the DMA transfer size to undefined. + * The DAI driver is responsible to disable any unsupported formats in it's + * configuration and catch corner cases that are not already handled in + * the ALSA core. + */ +#define SND_DMAENGINE_PCM_DAI_FLAG_PACK BIT(0) + +/** + * struct snd_dmaengine_dai_dma_data - DAI DMA configuration data + * @addr: Address of the DAI data source or destination register. + * @addr_width: Width of the DAI data source or destination register. + * @maxburst: Maximum number of words(note: words, as in units of the + * src_addr_width member, not bytes) that can be send to or received from the + * DAI in one burst. + * @slave_id: Slave requester id for the DMA channel. + * @filter_data: Custom DMA channel filter data, this will usually be used when + * requesting the DMA channel. + * @chan_name: Custom channel name to use when requesting DMA channel. + * @fifo_size: FIFO size of the DAI controller in bytes + * @flags: PCM_DAI flags, only SND_DMAENGINE_PCM_DAI_FLAG_PACK for now + */ +struct snd_dmaengine_dai_dma_data { + dma_addr_t addr; + enum dma_slave_buswidth addr_width; + u32 maxburst; + unsigned int slave_id; + void *filter_data; + const char *chan_name; + unsigned int fifo_size; + unsigned int flags; +}; + +void snd_dmaengine_pcm_set_config_from_dai_data( + const struct snd_pcm_substream *substream, + const struct snd_dmaengine_dai_dma_data *dma_data, + struct dma_slave_config *config); + + +/* + * Try to request the DMA channel using compat_request_channel or + * compat_filter_fn if it couldn't be requested through devicetree. + */ +#define SND_DMAENGINE_PCM_FLAG_COMPAT BIT(0) +/* + * Don't try to request the DMA channels through devicetree. This flag only + * makes sense if SND_DMAENGINE_PCM_FLAG_COMPAT is set as well. + */ +#define SND_DMAENGINE_PCM_FLAG_NO_DT BIT(1) +/* + * The PCM is half duplex and the DMA channel is shared between capture and + * playback. + */ +#define SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX BIT(3) + +/** + * struct snd_dmaengine_pcm_config - Configuration data for dmaengine based PCM + * @prepare_slave_config: Callback used to fill in the DMA slave_config for a + * PCM substream. Will be called from the PCM drivers hwparams callback. + * @compat_request_channel: Callback to request a DMA channel for platforms + * which do not use devicetree. + * @process: Callback used to apply processing on samples transferred from/to + * user space. + * @compat_filter_fn: Will be used as the filter function when requesting a + * channel for platforms which do not use devicetree. The filter parameter + * will be the DAI's DMA data. + * @dma_dev: If set, request DMA channel on this device rather than the DAI + * device. + * @chan_names: If set, these custom DMA channel names will be requested at + * registration time. + * @pcm_hardware: snd_pcm_hardware struct to be used for the PCM. + * @prealloc_buffer_size: Size of the preallocated audio buffer. + * + * Note: If both compat_request_channel and compat_filter_fn are set + * compat_request_channel will be used to request the channel and + * compat_filter_fn will be ignored. Otherwise the channel will be requested + * using dma_request_channel with compat_filter_fn as the filter function. + */ +struct snd_dmaengine_pcm_config { + int (*prepare_slave_config)(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct dma_slave_config *slave_config); + struct dma_chan *(*compat_request_channel)( + struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_substream *substream); + int (*process)(struct snd_pcm_substream *substream, + int channel, unsigned long hwoff, + void *buf, unsigned long bytes); + dma_filter_fn compat_filter_fn; + struct device *dma_dev; + const char *chan_names[SNDRV_PCM_STREAM_LAST + 1]; + + const struct snd_pcm_hardware *pcm_hardware; + unsigned int prealloc_buffer_size; +}; + +int snd_dmaengine_pcm_register(struct device *dev, + const struct snd_dmaengine_pcm_config *config, + unsigned int flags); +void snd_dmaengine_pcm_unregister(struct device *dev); + +int devm_snd_dmaengine_pcm_register(struct device *dev, + const struct snd_dmaengine_pcm_config *config, + unsigned int flags); + +int snd_dmaengine_pcm_prepare_slave_config(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct dma_slave_config *slave_config); + +#define SND_DMAENGINE_PCM_DRV_NAME "snd_dmaengine_pcm" + +#endif diff --git a/snd-alpx-dkms/snd-alpx/core/generic/5.2/pcm_dmaengine.c b/snd-alpx-dkms/snd-alpx/core/generic/5.2/pcm_dmaengine.c new file mode 100644 index 0000000..89a0592 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/core/generic/5.2/pcm_dmaengine.c @@ -0,0 +1,372 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2012, Analog Devices Inc. + * Author: Lars-Peter Clausen <lars@metafoo.de> + * + * Based on: + * imx-pcm-dma-mx2.c, Copyright 2009 Sascha Hauer <s.hauer@pengutronix.de> + * mxs-pcm.c, Copyright (C) 2011 Freescale Semiconductor, Inc. + * ep93xx-pcm.c, Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> + * Copyright (C) 2006 Applied Data Systems + */ +#include <linux/module.h> +#include <linux/init.h> +#include <linux/dmaengine.h> +#include <linux/slab.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> + +#include <sound/dmaengine_pcm.h> + +struct dmaengine_pcm_runtime_data { + struct dma_chan *dma_chan; + dma_cookie_t cookie; + + unsigned int pos; +}; + +static inline struct dmaengine_pcm_runtime_data *substream_to_prtd( + const struct snd_pcm_substream *substream) +{ + return substream->runtime->private_data; +} + +struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + return prtd->dma_chan; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_get_chan); + +/** + * snd_hwparams_to_dma_slave_config - Convert hw_params to dma_slave_config + * @substream: PCM substream + * @params: hw_params + * @slave_config: DMA slave config + * + * This function can be used to initialize a dma_slave_config from a substream + * and hw_params in a dmaengine based PCM driver implementation. + */ +int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream, + const struct snd_pcm_hw_params *params, + struct dma_slave_config *slave_config) +{ + enum dma_slave_buswidth buswidth; + int bits; + + bits = params_physical_width(params); + if (bits < 8 || bits > 64) + return -EINVAL; + else if (bits == 8) + buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE; + else if (bits == 16) + buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; + else if (bits == 24) + buswidth = DMA_SLAVE_BUSWIDTH_3_BYTES; + else if (bits <= 32) + buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES; + else + buswidth = DMA_SLAVE_BUSWIDTH_8_BYTES; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + slave_config->direction = DMA_MEM_TO_DEV; + slave_config->dst_addr_width = buswidth; + } else { + slave_config->direction = DMA_DEV_TO_MEM; + slave_config->src_addr_width = buswidth; + } + + slave_config->device_fc = false; + + return 0; +} +EXPORT_SYMBOL_GPL(snd_hwparams_to_dma_slave_config); + +/** + * snd_dmaengine_pcm_set_config_from_dai_data() - Initializes a dma slave config + * using DAI DMA data. + * @substream: PCM substream + * @dma_data: DAI DMA data + * @slave_config: DMA slave configuration + * + * Initializes the {dst,src}_addr, {dst,src}_maxburst, {dst,src}_addr_width and + * slave_id fields of the DMA slave config from the same fields of the DAI DMA + * data struct. The src and dst fields will be initialized depending on the + * direction of the substream. If the substream is a playback stream the dst + * fields will be initialized, if it is a capture stream the src fields will be + * initialized. The {dst,src}_addr_width field will only be initialized if the + * SND_DMAENGINE_PCM_DAI_FLAG_PACK flag is set or if the addr_width field of + * the DAI DMA data struct is not equal to DMA_SLAVE_BUSWIDTH_UNDEFINED. If + * both conditions are met the latter takes priority. + */ +void snd_dmaengine_pcm_set_config_from_dai_data( + const struct snd_pcm_substream *substream, + const struct snd_dmaengine_dai_dma_data *dma_data, + struct dma_slave_config *slave_config) +{ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + slave_config->dst_addr = dma_data->addr; + slave_config->dst_maxburst = dma_data->maxburst; + if (dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK) + slave_config->dst_addr_width = + DMA_SLAVE_BUSWIDTH_UNDEFINED; + if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED) + slave_config->dst_addr_width = dma_data->addr_width; + } else { + slave_config->src_addr = dma_data->addr; + slave_config->src_maxburst = dma_data->maxburst; + if (dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK) + slave_config->src_addr_width = + DMA_SLAVE_BUSWIDTH_UNDEFINED; + if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED) + slave_config->src_addr_width = dma_data->addr_width; + } + + slave_config->slave_id = dma_data->slave_id; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_config_from_dai_data); + +static void dmaengine_pcm_dma_complete(void *arg) +{ + struct snd_pcm_substream *substream = arg; + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + prtd->pos += snd_pcm_lib_period_bytes(substream); + if (prtd->pos >= snd_pcm_lib_buffer_bytes(substream)) + prtd->pos = 0; + + snd_pcm_period_elapsed(substream); +} + +static int dmaengine_pcm_prepare_and_submit(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + struct dma_chan *chan = prtd->dma_chan; + struct dma_async_tx_descriptor *desc; + enum dma_transfer_direction direction; + unsigned long flags = DMA_CTRL_ACK; + + direction = snd_pcm_substream_to_dma_direction(substream); + + if (!substream->runtime->no_period_wakeup) + flags |= DMA_PREP_INTERRUPT; + + prtd->pos = 0; + desc = dmaengine_prep_dma_cyclic(chan, + substream->runtime->dma_addr, + snd_pcm_lib_buffer_bytes(substream), + snd_pcm_lib_period_bytes(substream), direction, flags); + + if (!desc) + return -ENOMEM; + + desc->callback = dmaengine_pcm_dma_complete; + desc->callback_param = substream; + prtd->cookie = dmaengine_submit(desc); + + return 0; +} + +/** + * snd_dmaengine_pcm_trigger - dmaengine based PCM trigger implementation + * @substream: PCM substream + * @cmd: Trigger command + * + * Returns 0 on success, a negative error code otherwise. + * + * This function can be used as the PCM trigger callback for dmaengine based PCM + * driver implementations. + */ +int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + int ret; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + ret = dmaengine_pcm_prepare_and_submit(substream); + if (ret) + return ret; + dma_async_issue_pending(prtd->dma_chan); + break; + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + dmaengine_resume(prtd->dma_chan); + break; + case SNDRV_PCM_TRIGGER_SUSPEND: + if (runtime->info & SNDRV_PCM_INFO_PAUSE) + dmaengine_pause(prtd->dma_chan); + else + dmaengine_terminate_async(prtd->dma_chan); + break; + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + dmaengine_pause(prtd->dma_chan); + break; + case SNDRV_PCM_TRIGGER_STOP: + dmaengine_terminate_async(prtd->dma_chan); + break; + default: + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_trigger); + +/** + * snd_dmaengine_pcm_pointer_no_residue - dmaengine based PCM pointer implementation + * @substream: PCM substream + * + * This function is deprecated and should not be used by new drivers, as its + * results may be unreliable. + */ +snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + return bytes_to_frames(substream->runtime, prtd->pos); +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer_no_residue); + +/** + * snd_dmaengine_pcm_pointer - dmaengine based PCM pointer implementation + * @substream: PCM substream + * + * This function can be used as the PCM pointer callback for dmaengine based PCM + * driver implementations. + */ +snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + struct dma_tx_state state; + enum dma_status status; + unsigned int buf_size; + unsigned int pos = 0; + + status = dmaengine_tx_status(prtd->dma_chan, prtd->cookie, &state); + if (status == DMA_IN_PROGRESS || status == DMA_PAUSED) { + buf_size = snd_pcm_lib_buffer_bytes(substream); + if (state.residue > 0 && state.residue <= buf_size) + pos = buf_size - state.residue; + } + + return bytes_to_frames(substream->runtime, pos); +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer); + +/** + * snd_dmaengine_pcm_request_channel - Request channel for the dmaengine PCM + * @filter_fn: Filter function used to request the DMA channel + * @filter_data: Data passed to the DMA filter function + * + * Returns NULL or the requested DMA channel. + * + * This function request a DMA channel for usage with dmaengine PCM. + */ +struct dma_chan *snd_dmaengine_pcm_request_channel(dma_filter_fn filter_fn, + void *filter_data) +{ + dma_cap_mask_t mask; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + dma_cap_set(DMA_CYCLIC, mask); + + return dma_request_channel(mask, filter_fn, filter_data); +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_request_channel); + +/** + * snd_dmaengine_pcm_open - Open a dmaengine based PCM substream + * @substream: PCM substream + * @chan: DMA channel to use for data transfers + * + * Returns 0 on success, a negative error code otherwise. + * + * The function should usually be called from the pcm open callback. Note that + * this function will use private_data field of the substream's runtime. So it + * is not available to your pcm driver implementation. + */ +int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, + struct dma_chan *chan) +{ + struct dmaengine_pcm_runtime_data *prtd; + int ret; + + if (!chan) + return -ENXIO; + + ret = snd_pcm_hw_constraint_integer(substream->runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + if (ret < 0) + return ret; + + prtd = kzalloc(sizeof(*prtd), GFP_KERNEL); + if (!prtd) + return -ENOMEM; + + prtd->dma_chan = chan; + + substream->runtime->private_data = prtd; + + return 0; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open); + +/** + * snd_dmaengine_pcm_open_request_chan - Open a dmaengine based PCM substream and request channel + * @substream: PCM substream + * @filter_fn: Filter function used to request the DMA channel + * @filter_data: Data passed to the DMA filter function + * + * Returns 0 on success, a negative error code otherwise. + * + * This function will request a DMA channel using the passed filter function and + * data. The function should usually be called from the pcm open callback. Note + * that this function will use private_data field of the substream's runtime. So + * it is not available to your pcm driver implementation. + */ +int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream, + dma_filter_fn filter_fn, void *filter_data) +{ + return snd_dmaengine_pcm_open(substream, + snd_dmaengine_pcm_request_channel(filter_fn, filter_data)); +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open_request_chan); + +/** + * snd_dmaengine_pcm_close - Close a dmaengine based PCM substream + * @substream: PCM substream + */ +int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + dmaengine_synchronize(prtd->dma_chan); + kfree(prtd); + + return 0; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close); + +/** + * snd_dmaengine_pcm_release_chan_close - Close a dmaengine based PCM substream and release channel + * @substream: PCM substream + * + * Releases the DMA channel associated with the PCM substream. + */ +int snd_dmaengine_pcm_close_release_chan(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + dmaengine_synchronize(prtd->dma_chan); + dma_release_channel(prtd->dma_chan); + kfree(prtd); + + return 0; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close_release_chan); + +MODULE_LICENSE("GPL"); diff --git a/snd-alpx-dkms/snd-alpx/core/generic/5.5/dmaengine_pcm.h b/snd-alpx-dkms/snd-alpx/core/generic/5.5/dmaengine_pcm.h new file mode 100644 index 0000000..b652206 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/core/generic/5.5/dmaengine_pcm.h @@ -0,0 +1,164 @@ +/* SPDX-License-Identifier: GPL-2.0+ + * + * Copyright (C) 2012, Analog Devices Inc. + * Author: Lars-Peter Clausen <lars@metafoo.de> + */ + +#ifndef __SOUND_DMAENGINE_PCM_H__ +#define __SOUND_DMAENGINE_PCM_H__ + +#include <sound/pcm.h> +#include <sound/soc.h> +#include <linux/dmaengine.h> + +/** + * snd_pcm_substream_to_dma_direction - Get dma_transfer_direction for a PCM + * substream + * @substream: PCM substream + */ +static inline enum dma_transfer_direction +snd_pcm_substream_to_dma_direction(const struct snd_pcm_substream *substream) +{ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + return DMA_MEM_TO_DEV; + else + return DMA_DEV_TO_MEM; +} + +int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream, + const struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config); +int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd); +snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream); +snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream *substream); + +int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, + struct dma_chan *chan); +int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream); + +int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream, + dma_filter_fn filter_fn, void *filter_data); +int snd_dmaengine_pcm_close_release_chan(struct snd_pcm_substream *substream); + +struct dma_chan *snd_dmaengine_pcm_request_channel(dma_filter_fn filter_fn, + void *filter_data); +struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream); + +/* + * The DAI supports packed transfers, eg 2 16-bit samples in a 32-bit word. + * If this flag is set the dmaengine driver won't put any restriction on + * the supported sample formats and set the DMA transfer size to undefined. + * The DAI driver is responsible to disable any unsupported formats in it's + * configuration and catch corner cases that are not already handled in + * the ALSA core. + */ +#define SND_DMAENGINE_PCM_DAI_FLAG_PACK BIT(0) + +/** + * struct snd_dmaengine_dai_dma_data - DAI DMA configuration data + * @addr: Address of the DAI data source or destination register. + * @addr_width: Width of the DAI data source or destination register. + * @maxburst: Maximum number of words(note: words, as in units of the + * src_addr_width member, not bytes) that can be send to or received from the + * DAI in one burst. + * @slave_id: Slave requester id for the DMA channel. + * @filter_data: Custom DMA channel filter data, this will usually be used when + * requesting the DMA channel. + * @chan_name: Custom channel name to use when requesting DMA channel. + * @fifo_size: FIFO size of the DAI controller in bytes + * @flags: PCM_DAI flags, only SND_DMAENGINE_PCM_DAI_FLAG_PACK for now + */ +struct snd_dmaengine_dai_dma_data { + dma_addr_t addr; + enum dma_slave_buswidth addr_width; + u32 maxburst; + unsigned int slave_id; + void *filter_data; + const char *chan_name; + unsigned int fifo_size; + unsigned int flags; +}; + +void snd_dmaengine_pcm_set_config_from_dai_data( + const struct snd_pcm_substream *substream, + const struct snd_dmaengine_dai_dma_data *dma_data, + struct dma_slave_config *config); + +int snd_dmaengine_pcm_refine_runtime_hwparams( + struct snd_pcm_substream *substream, + struct snd_dmaengine_dai_dma_data *dma_data, + struct snd_pcm_hardware *hw, + struct dma_chan *chan); + +/* + * Try to request the DMA channel using compat_request_channel or + * compat_filter_fn if it couldn't be requested through devicetree. + */ +#define SND_DMAENGINE_PCM_FLAG_COMPAT BIT(0) +/* + * Don't try to request the DMA channels through devicetree. This flag only + * makes sense if SND_DMAENGINE_PCM_FLAG_COMPAT is set as well. + */ +#define SND_DMAENGINE_PCM_FLAG_NO_DT BIT(1) +/* + * The PCM is half duplex and the DMA channel is shared between capture and + * playback. + */ +#define SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX BIT(3) + +/** + * struct snd_dmaengine_pcm_config - Configuration data for dmaengine based PCM + * @prepare_slave_config: Callback used to fill in the DMA slave_config for a + * PCM substream. Will be called from the PCM drivers hwparams callback. + * @compat_request_channel: Callback to request a DMA channel for platforms + * which do not use devicetree. + * @process: Callback used to apply processing on samples transferred from/to + * user space. + * @compat_filter_fn: Will be used as the filter function when requesting a + * channel for platforms which do not use devicetree. The filter parameter + * will be the DAI's DMA data. + * @dma_dev: If set, request DMA channel on this device rather than the DAI + * device. + * @chan_names: If set, these custom DMA channel names will be requested at + * registration time. + * @pcm_hardware: snd_pcm_hardware struct to be used for the PCM. + * @prealloc_buffer_size: Size of the preallocated audio buffer. + * + * Note: If both compat_request_channel and compat_filter_fn are set + * compat_request_channel will be used to request the channel and + * compat_filter_fn will be ignored. Otherwise the channel will be requested + * using dma_request_channel with compat_filter_fn as the filter function. + */ +struct snd_dmaengine_pcm_config { + int (*prepare_slave_config)(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct dma_slave_config *slave_config); + struct dma_chan *(*compat_request_channel)( + struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_substream *substream); + int (*process)(struct snd_pcm_substream *substream, + int channel, unsigned long hwoff, + void *buf, unsigned long bytes); + dma_filter_fn compat_filter_fn; + struct device *dma_dev; + const char *chan_names[SNDRV_PCM_STREAM_LAST + 1]; + + const struct snd_pcm_hardware *pcm_hardware; + unsigned int prealloc_buffer_size; +}; + +int snd_dmaengine_pcm_register(struct device *dev, + const struct snd_dmaengine_pcm_config *config, + unsigned int flags); +void snd_dmaengine_pcm_unregister(struct device *dev); + +int devm_snd_dmaengine_pcm_register(struct device *dev, + const struct snd_dmaengine_pcm_config *config, + unsigned int flags); + +int snd_dmaengine_pcm_prepare_slave_config(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct dma_slave_config *slave_config); + +#define SND_DMAENGINE_PCM_DRV_NAME "snd_dmaengine_pcm" + +#endif diff --git a/snd-alpx-dkms/snd-alpx/core/generic/5.5/pcm_dmaengine.c b/snd-alpx-dkms/snd-alpx/core/generic/5.5/pcm_dmaengine.c new file mode 100644 index 0000000..5749a8a --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/core/generic/5.5/pcm_dmaengine.c @@ -0,0 +1,455 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2012, Analog Devices Inc. + * Author: Lars-Peter Clausen <lars@metafoo.de> + * + * Based on: + * imx-pcm-dma-mx2.c, Copyright 2009 Sascha Hauer <s.hauer@pengutronix.de> + * mxs-pcm.c, Copyright (C) 2011 Freescale Semiconductor, Inc. + * ep93xx-pcm.c, Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> + * Copyright (C) 2006 Applied Data Systems + */ +#include <linux/module.h> +#include <linux/init.h> +#include <linux/dmaengine.h> +#include <linux/slab.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> + +#include <sound/dmaengine_pcm.h> + +struct dmaengine_pcm_runtime_data { + struct dma_chan *dma_chan; + dma_cookie_t cookie; + + unsigned int pos; +}; + +static inline struct dmaengine_pcm_runtime_data *substream_to_prtd( + const struct snd_pcm_substream *substream) +{ + return substream->runtime->private_data; +} + +struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + return prtd->dma_chan; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_get_chan); + +/** + * snd_hwparams_to_dma_slave_config - Convert hw_params to dma_slave_config + * @substream: PCM substream + * @params: hw_params + * @slave_config: DMA slave config + * + * This function can be used to initialize a dma_slave_config from a substream + * and hw_params in a dmaengine based PCM driver implementation. + */ +int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream, + const struct snd_pcm_hw_params *params, + struct dma_slave_config *slave_config) +{ + enum dma_slave_buswidth buswidth; + int bits; + + bits = params_physical_width(params); + if (bits < 8 || bits > 64) + return -EINVAL; + else if (bits == 8) + buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE; + else if (bits == 16) + buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; + else if (bits == 24) + buswidth = DMA_SLAVE_BUSWIDTH_3_BYTES; + else if (bits <= 32) + buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES; + else + buswidth = DMA_SLAVE_BUSWIDTH_8_BYTES; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + slave_config->direction = DMA_MEM_TO_DEV; + slave_config->dst_addr_width = buswidth; + } else { + slave_config->direction = DMA_DEV_TO_MEM; + slave_config->src_addr_width = buswidth; + } + + slave_config->device_fc = false; + + return 0; +} +EXPORT_SYMBOL_GPL(snd_hwparams_to_dma_slave_config); + +/** + * snd_dmaengine_pcm_set_config_from_dai_data() - Initializes a dma slave config + * using DAI DMA data. + * @substream: PCM substream + * @dma_data: DAI DMA data + * @slave_config: DMA slave configuration + * + * Initializes the {dst,src}_addr, {dst,src}_maxburst, {dst,src}_addr_width and + * slave_id fields of the DMA slave config from the same fields of the DAI DMA + * data struct. The src and dst fields will be initialized depending on the + * direction of the substream. If the substream is a playback stream the dst + * fields will be initialized, if it is a capture stream the src fields will be + * initialized. The {dst,src}_addr_width field will only be initialized if the + * SND_DMAENGINE_PCM_DAI_FLAG_PACK flag is set or if the addr_width field of + * the DAI DMA data struct is not equal to DMA_SLAVE_BUSWIDTH_UNDEFINED. If + * both conditions are met the latter takes priority. + */ +void snd_dmaengine_pcm_set_config_from_dai_data( + const struct snd_pcm_substream *substream, + const struct snd_dmaengine_dai_dma_data *dma_data, + struct dma_slave_config *slave_config) +{ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + slave_config->dst_addr = dma_data->addr; + slave_config->dst_maxburst = dma_data->maxburst; + if (dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK) + slave_config->dst_addr_width = + DMA_SLAVE_BUSWIDTH_UNDEFINED; + if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED) + slave_config->dst_addr_width = dma_data->addr_width; + } else { + slave_config->src_addr = dma_data->addr; + slave_config->src_maxburst = dma_data->maxburst; + if (dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK) + slave_config->src_addr_width = + DMA_SLAVE_BUSWIDTH_UNDEFINED; + if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED) + slave_config->src_addr_width = dma_data->addr_width; + } + + slave_config->slave_id = dma_data->slave_id; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_config_from_dai_data); + +static void dmaengine_pcm_dma_complete(void *arg) +{ + struct snd_pcm_substream *substream = arg; + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + prtd->pos += snd_pcm_lib_period_bytes(substream); + if (prtd->pos >= snd_pcm_lib_buffer_bytes(substream)) + prtd->pos = 0; + + snd_pcm_period_elapsed(substream); +} + +static int dmaengine_pcm_prepare_and_submit(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + struct dma_chan *chan = prtd->dma_chan; + struct dma_async_tx_descriptor *desc; + enum dma_transfer_direction direction; + unsigned long flags = DMA_CTRL_ACK; + + direction = snd_pcm_substream_to_dma_direction(substream); + + if (!substream->runtime->no_period_wakeup) + flags |= DMA_PREP_INTERRUPT; + + prtd->pos = 0; + desc = dmaengine_prep_dma_cyclic(chan, + substream->runtime->dma_addr, + snd_pcm_lib_buffer_bytes(substream), + snd_pcm_lib_period_bytes(substream), direction, flags); + + if (!desc) + return -ENOMEM; + + desc->callback = dmaengine_pcm_dma_complete; + desc->callback_param = substream; + prtd->cookie = dmaengine_submit(desc); + + return 0; +} + +/** + * snd_dmaengine_pcm_trigger - dmaengine based PCM trigger implementation + * @substream: PCM substream + * @cmd: Trigger command + * + * Returns 0 on success, a negative error code otherwise. + * + * This function can be used as the PCM trigger callback for dmaengine based PCM + * driver implementations. + */ +int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + int ret; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + ret = dmaengine_pcm_prepare_and_submit(substream); + if (ret) + return ret; + dma_async_issue_pending(prtd->dma_chan); + break; + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + dmaengine_resume(prtd->dma_chan); + break; + case SNDRV_PCM_TRIGGER_SUSPEND: + if (runtime->info & SNDRV_PCM_INFO_PAUSE) + dmaengine_pause(prtd->dma_chan); + else + dmaengine_terminate_async(prtd->dma_chan); + break; + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + dmaengine_pause(prtd->dma_chan); + break; + case SNDRV_PCM_TRIGGER_STOP: + dmaengine_terminate_async(prtd->dma_chan); + break; + default: + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_trigger); + +/** + * snd_dmaengine_pcm_pointer_no_residue - dmaengine based PCM pointer implementation + * @substream: PCM substream + * + * This function is deprecated and should not be used by new drivers, as its + * results may be unreliable. + */ +snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + return bytes_to_frames(substream->runtime, prtd->pos); +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer_no_residue); + +/** + * snd_dmaengine_pcm_pointer - dmaengine based PCM pointer implementation + * @substream: PCM substream + * + * This function can be used as the PCM pointer callback for dmaengine based PCM + * driver implementations. + */ +snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + struct dma_tx_state state; + enum dma_status status; + unsigned int buf_size; + unsigned int pos = 0; + + status = dmaengine_tx_status(prtd->dma_chan, prtd->cookie, &state); + if (status == DMA_IN_PROGRESS || status == DMA_PAUSED) { + buf_size = snd_pcm_lib_buffer_bytes(substream); + if (state.residue > 0 && state.residue <= buf_size) + pos = buf_size - state.residue; + } + + return bytes_to_frames(substream->runtime, pos); +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer); + +/** + * snd_dmaengine_pcm_request_channel - Request channel for the dmaengine PCM + * @filter_fn: Filter function used to request the DMA channel + * @filter_data: Data passed to the DMA filter function + * + * Returns NULL or the requested DMA channel. + * + * This function request a DMA channel for usage with dmaengine PCM. + */ +struct dma_chan *snd_dmaengine_pcm_request_channel(dma_filter_fn filter_fn, + void *filter_data) +{ + dma_cap_mask_t mask; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + dma_cap_set(DMA_CYCLIC, mask); + + return dma_request_channel(mask, filter_fn, filter_data); +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_request_channel); + +/** + * snd_dmaengine_pcm_open - Open a dmaengine based PCM substream + * @substream: PCM substream + * @chan: DMA channel to use for data transfers + * + * Returns 0 on success, a negative error code otherwise. + * + * The function should usually be called from the pcm open callback. Note that + * this function will use private_data field of the substream's runtime. So it + * is not available to your pcm driver implementation. + */ +int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, + struct dma_chan *chan) +{ + struct dmaengine_pcm_runtime_data *prtd; + int ret; + + if (!chan) + return -ENXIO; + + ret = snd_pcm_hw_constraint_integer(substream->runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + if (ret < 0) + return ret; + + prtd = kzalloc(sizeof(*prtd), GFP_KERNEL); + if (!prtd) + return -ENOMEM; + + prtd->dma_chan = chan; + + substream->runtime->private_data = prtd; + + return 0; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open); + +/** + * snd_dmaengine_pcm_open_request_chan - Open a dmaengine based PCM substream and request channel + * @substream: PCM substream + * @filter_fn: Filter function used to request the DMA channel + * @filter_data: Data passed to the DMA filter function + * + * Returns 0 on success, a negative error code otherwise. + * + * This function will request a DMA channel using the passed filter function and + * data. The function should usually be called from the pcm open callback. Note + * that this function will use private_data field of the substream's runtime. So + * it is not available to your pcm driver implementation. + */ +int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream, + dma_filter_fn filter_fn, void *filter_data) +{ + return snd_dmaengine_pcm_open(substream, + snd_dmaengine_pcm_request_channel(filter_fn, filter_data)); +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open_request_chan); + +/** + * snd_dmaengine_pcm_close - Close a dmaengine based PCM substream + * @substream: PCM substream + */ +int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + dmaengine_synchronize(prtd->dma_chan); + kfree(prtd); + + return 0; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close); + +/** + * snd_dmaengine_pcm_release_chan_close - Close a dmaengine based PCM substream and release channel + * @substream: PCM substream + * + * Releases the DMA channel associated with the PCM substream. + */ +int snd_dmaengine_pcm_close_release_chan(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + dmaengine_synchronize(prtd->dma_chan); + dma_release_channel(prtd->dma_chan); + kfree(prtd); + + return 0; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close_release_chan); + +/** + * snd_dmaengine_pcm_refine_runtime_hwparams - Refine runtime hw params + * @substream: PCM substream + * @dma_data: DAI DMA data + * @hw: PCM hw params + * @chan: DMA channel to use for data transfers + * + * Returns 0 on success, a negative error code otherwise. + * + * This function will query DMA capability, then refine the pcm hardware + * parameters. + */ +int snd_dmaengine_pcm_refine_runtime_hwparams( + struct snd_pcm_substream *substream, + struct snd_dmaengine_dai_dma_data *dma_data, + struct snd_pcm_hardware *hw, + struct dma_chan *chan) +{ + struct dma_slave_caps dma_caps; + u32 addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | + BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | + BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); + snd_pcm_format_t i; + int ret = 0; + + if (!hw || !chan || !dma_data) + return -EINVAL; + + ret = dma_get_slave_caps(chan, &dma_caps); + if (ret == 0) { + if (dma_caps.cmd_pause && dma_caps.cmd_resume) + hw->info |= SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME; + if (dma_caps.residue_granularity <= DMA_RESIDUE_GRANULARITY_SEGMENT) + hw->info |= SNDRV_PCM_INFO_BATCH; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + addr_widths = dma_caps.dst_addr_widths; + else + addr_widths = dma_caps.src_addr_widths; + } + + /* + * If SND_DMAENGINE_PCM_DAI_FLAG_PACK is set keep + * hw.formats set to 0, meaning no restrictions are in place. + * In this case it's the responsibility of the DAI driver to + * provide the supported format information. + */ + if (!(dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK)) + /* + * Prepare formats mask for valid/allowed sample types. If the + * dma does not have support for the given physical word size, + * it needs to be masked out so user space can not use the + * format which produces corrupted audio. + * In case the dma driver does not implement the slave_caps the + * default assumption is that it supports 1, 2 and 4 bytes + * widths. + */ + for (i = SNDRV_PCM_FORMAT_FIRST; i <= SNDRV_PCM_FORMAT_LAST; i++) { + int bits = snd_pcm_format_physical_width(i); + + /* + * Enable only samples with DMA supported physical + * widths + */ + switch (bits) { + case 8: + case 16: + case 24: + case 32: + case 64: + if (addr_widths & (1 << (bits / 8))) + hw->formats |= pcm_format_to_bits(i); + break; + default: + /* Unsupported types */ + break; + } + } + + return ret; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_refine_runtime_hwparams); + +MODULE_LICENSE("GPL"); diff --git a/snd-alpx-dkms/snd-alpx/core/generic/5.7/dmaengine_pcm.h b/snd-alpx-dkms/snd-alpx/core/generic/5.7/dmaengine_pcm.h new file mode 100644 index 0000000..b652206 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/core/generic/5.7/dmaengine_pcm.h @@ -0,0 +1,164 @@ +/* SPDX-License-Identifier: GPL-2.0+ + * + * Copyright (C) 2012, Analog Devices Inc. + * Author: Lars-Peter Clausen <lars@metafoo.de> + */ + +#ifndef __SOUND_DMAENGINE_PCM_H__ +#define __SOUND_DMAENGINE_PCM_H__ + +#include <sound/pcm.h> +#include <sound/soc.h> +#include <linux/dmaengine.h> + +/** + * snd_pcm_substream_to_dma_direction - Get dma_transfer_direction for a PCM + * substream + * @substream: PCM substream + */ +static inline enum dma_transfer_direction +snd_pcm_substream_to_dma_direction(const struct snd_pcm_substream *substream) +{ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + return DMA_MEM_TO_DEV; + else + return DMA_DEV_TO_MEM; +} + +int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream, + const struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config); +int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd); +snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream); +snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream *substream); + +int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, + struct dma_chan *chan); +int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream); + +int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream, + dma_filter_fn filter_fn, void *filter_data); +int snd_dmaengine_pcm_close_release_chan(struct snd_pcm_substream *substream); + +struct dma_chan *snd_dmaengine_pcm_request_channel(dma_filter_fn filter_fn, + void *filter_data); +struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream); + +/* + * The DAI supports packed transfers, eg 2 16-bit samples in a 32-bit word. + * If this flag is set the dmaengine driver won't put any restriction on + * the supported sample formats and set the DMA transfer size to undefined. + * The DAI driver is responsible to disable any unsupported formats in it's + * configuration and catch corner cases that are not already handled in + * the ALSA core. + */ +#define SND_DMAENGINE_PCM_DAI_FLAG_PACK BIT(0) + +/** + * struct snd_dmaengine_dai_dma_data - DAI DMA configuration data + * @addr: Address of the DAI data source or destination register. + * @addr_width: Width of the DAI data source or destination register. + * @maxburst: Maximum number of words(note: words, as in units of the + * src_addr_width member, not bytes) that can be send to or received from the + * DAI in one burst. + * @slave_id: Slave requester id for the DMA channel. + * @filter_data: Custom DMA channel filter data, this will usually be used when + * requesting the DMA channel. + * @chan_name: Custom channel name to use when requesting DMA channel. + * @fifo_size: FIFO size of the DAI controller in bytes + * @flags: PCM_DAI flags, only SND_DMAENGINE_PCM_DAI_FLAG_PACK for now + */ +struct snd_dmaengine_dai_dma_data { + dma_addr_t addr; + enum dma_slave_buswidth addr_width; + u32 maxburst; + unsigned int slave_id; + void *filter_data; + const char *chan_name; + unsigned int fifo_size; + unsigned int flags; +}; + +void snd_dmaengine_pcm_set_config_from_dai_data( + const struct snd_pcm_substream *substream, + const struct snd_dmaengine_dai_dma_data *dma_data, + struct dma_slave_config *config); + +int snd_dmaengine_pcm_refine_runtime_hwparams( + struct snd_pcm_substream *substream, + struct snd_dmaengine_dai_dma_data *dma_data, + struct snd_pcm_hardware *hw, + struct dma_chan *chan); + +/* + * Try to request the DMA channel using compat_request_channel or + * compat_filter_fn if it couldn't be requested through devicetree. + */ +#define SND_DMAENGINE_PCM_FLAG_COMPAT BIT(0) +/* + * Don't try to request the DMA channels through devicetree. This flag only + * makes sense if SND_DMAENGINE_PCM_FLAG_COMPAT is set as well. + */ +#define SND_DMAENGINE_PCM_FLAG_NO_DT BIT(1) +/* + * The PCM is half duplex and the DMA channel is shared between capture and + * playback. + */ +#define SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX BIT(3) + +/** + * struct snd_dmaengine_pcm_config - Configuration data for dmaengine based PCM + * @prepare_slave_config: Callback used to fill in the DMA slave_config for a + * PCM substream. Will be called from the PCM drivers hwparams callback. + * @compat_request_channel: Callback to request a DMA channel for platforms + * which do not use devicetree. + * @process: Callback used to apply processing on samples transferred from/to + * user space. + * @compat_filter_fn: Will be used as the filter function when requesting a + * channel for platforms which do not use devicetree. The filter parameter + * will be the DAI's DMA data. + * @dma_dev: If set, request DMA channel on this device rather than the DAI + * device. + * @chan_names: If set, these custom DMA channel names will be requested at + * registration time. + * @pcm_hardware: snd_pcm_hardware struct to be used for the PCM. + * @prealloc_buffer_size: Size of the preallocated audio buffer. + * + * Note: If both compat_request_channel and compat_filter_fn are set + * compat_request_channel will be used to request the channel and + * compat_filter_fn will be ignored. Otherwise the channel will be requested + * using dma_request_channel with compat_filter_fn as the filter function. + */ +struct snd_dmaengine_pcm_config { + int (*prepare_slave_config)(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct dma_slave_config *slave_config); + struct dma_chan *(*compat_request_channel)( + struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_substream *substream); + int (*process)(struct snd_pcm_substream *substream, + int channel, unsigned long hwoff, + void *buf, unsigned long bytes); + dma_filter_fn compat_filter_fn; + struct device *dma_dev; + const char *chan_names[SNDRV_PCM_STREAM_LAST + 1]; + + const struct snd_pcm_hardware *pcm_hardware; + unsigned int prealloc_buffer_size; +}; + +int snd_dmaengine_pcm_register(struct device *dev, + const struct snd_dmaengine_pcm_config *config, + unsigned int flags); +void snd_dmaengine_pcm_unregister(struct device *dev); + +int devm_snd_dmaengine_pcm_register(struct device *dev, + const struct snd_dmaengine_pcm_config *config, + unsigned int flags); + +int snd_dmaengine_pcm_prepare_slave_config(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct dma_slave_config *slave_config); + +#define SND_DMAENGINE_PCM_DRV_NAME "snd_dmaengine_pcm" + +#endif diff --git a/snd-alpx-dkms/snd-alpx/core/generic/5.7/pcm_dmaengine.c b/snd-alpx-dkms/snd-alpx/core/generic/5.7/pcm_dmaengine.c new file mode 100644 index 0000000..4d059ff --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/core/generic/5.7/pcm_dmaengine.c @@ -0,0 +1,459 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2012, Analog Devices Inc. + * Author: Lars-Peter Clausen <lars@metafoo.de> + * + * Based on: + * imx-pcm-dma-mx2.c, Copyright 2009 Sascha Hauer <s.hauer@pengutronix.de> + * mxs-pcm.c, Copyright (C) 2011 Freescale Semiconductor, Inc. + * ep93xx-pcm.c, Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> + * Copyright (C) 2006 Applied Data Systems + */ +#include <linux/module.h> +#include <linux/init.h> +#include <linux/dmaengine.h> +#include <linux/slab.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> + +#include <sound/dmaengine_pcm.h> + +struct dmaengine_pcm_runtime_data { + struct dma_chan *dma_chan; + dma_cookie_t cookie; + + unsigned int pos; +}; + +static inline struct dmaengine_pcm_runtime_data *substream_to_prtd( + const struct snd_pcm_substream *substream) +{ + return substream->runtime->private_data; +} + +struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + return prtd->dma_chan; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_get_chan); + +/** + * snd_hwparams_to_dma_slave_config - Convert hw_params to dma_slave_config + * @substream: PCM substream + * @params: hw_params + * @slave_config: DMA slave config + * + * This function can be used to initialize a dma_slave_config from a substream + * and hw_params in a dmaengine based PCM driver implementation. + */ +int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream, + const struct snd_pcm_hw_params *params, + struct dma_slave_config *slave_config) +{ + enum dma_slave_buswidth buswidth; + int bits; + + bits = params_physical_width(params); + if (bits < 8 || bits > 64) + return -EINVAL; + else if (bits == 8) + buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE; + else if (bits == 16) + buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; + else if (bits == 24) + buswidth = DMA_SLAVE_BUSWIDTH_3_BYTES; + else if (bits <= 32) + buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES; + else + buswidth = DMA_SLAVE_BUSWIDTH_8_BYTES; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + slave_config->direction = DMA_MEM_TO_DEV; + slave_config->dst_addr_width = buswidth; + } else { + slave_config->direction = DMA_DEV_TO_MEM; + slave_config->src_addr_width = buswidth; + } + + slave_config->device_fc = false; + + return 0; +} +EXPORT_SYMBOL_GPL(snd_hwparams_to_dma_slave_config); + +/** + * snd_dmaengine_pcm_set_config_from_dai_data() - Initializes a dma slave config + * using DAI DMA data. + * @substream: PCM substream + * @dma_data: DAI DMA data + * @slave_config: DMA slave configuration + * + * Initializes the {dst,src}_addr, {dst,src}_maxburst, {dst,src}_addr_width and + * slave_id fields of the DMA slave config from the same fields of the DAI DMA + * data struct. The src and dst fields will be initialized depending on the + * direction of the substream. If the substream is a playback stream the dst + * fields will be initialized, if it is a capture stream the src fields will be + * initialized. The {dst,src}_addr_width field will only be initialized if the + * SND_DMAENGINE_PCM_DAI_FLAG_PACK flag is set or if the addr_width field of + * the DAI DMA data struct is not equal to DMA_SLAVE_BUSWIDTH_UNDEFINED. If + * both conditions are met the latter takes priority. + */ +void snd_dmaengine_pcm_set_config_from_dai_data( + const struct snd_pcm_substream *substream, + const struct snd_dmaengine_dai_dma_data *dma_data, + struct dma_slave_config *slave_config) +{ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + slave_config->dst_addr = dma_data->addr; + slave_config->dst_maxburst = dma_data->maxburst; + if (dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK) + slave_config->dst_addr_width = + DMA_SLAVE_BUSWIDTH_UNDEFINED; + if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED) + slave_config->dst_addr_width = dma_data->addr_width; + } else { + slave_config->src_addr = dma_data->addr; + slave_config->src_maxburst = dma_data->maxburst; + if (dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK) + slave_config->src_addr_width = + DMA_SLAVE_BUSWIDTH_UNDEFINED; + if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED) + slave_config->src_addr_width = dma_data->addr_width; + } + + slave_config->slave_id = dma_data->slave_id; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_config_from_dai_data); + +static void dmaengine_pcm_dma_complete(void *arg) +{ + struct snd_pcm_substream *substream = arg; + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + prtd->pos += snd_pcm_lib_period_bytes(substream); + if (prtd->pos >= snd_pcm_lib_buffer_bytes(substream)) + prtd->pos = 0; + + snd_pcm_period_elapsed(substream); +} + +static int dmaengine_pcm_prepare_and_submit(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + struct dma_chan *chan = prtd->dma_chan; + struct dma_async_tx_descriptor *desc; + enum dma_transfer_direction direction; + unsigned long flags = DMA_CTRL_ACK; + + direction = snd_pcm_substream_to_dma_direction(substream); + + if (!substream->runtime->no_period_wakeup) + flags |= DMA_PREP_INTERRUPT; + + prtd->pos = 0; + desc = dmaengine_prep_dma_cyclic(chan, + substream->runtime->dma_addr, + snd_pcm_lib_buffer_bytes(substream), + snd_pcm_lib_period_bytes(substream), direction, flags); + + if (!desc) + return -ENOMEM; + + desc->callback = dmaengine_pcm_dma_complete; + desc->callback_param = substream; + prtd->cookie = dmaengine_submit(desc); + + return 0; +} + +/** + * snd_dmaengine_pcm_trigger - dmaengine based PCM trigger implementation + * @substream: PCM substream + * @cmd: Trigger command + * + * Returns 0 on success, a negative error code otherwise. + * + * This function can be used as the PCM trigger callback for dmaengine based PCM + * driver implementations. + */ +int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + int ret; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + ret = dmaengine_pcm_prepare_and_submit(substream); + if (ret) + return ret; + dma_async_issue_pending(prtd->dma_chan); + break; + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + dmaengine_resume(prtd->dma_chan); + break; + case SNDRV_PCM_TRIGGER_SUSPEND: + if (runtime->info & SNDRV_PCM_INFO_PAUSE) + dmaengine_pause(prtd->dma_chan); + else + dmaengine_terminate_async(prtd->dma_chan); + break; + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + dmaengine_pause(prtd->dma_chan); + break; + case SNDRV_PCM_TRIGGER_STOP: + dmaengine_terminate_async(prtd->dma_chan); + break; + default: + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_trigger); + +/** + * snd_dmaengine_pcm_pointer_no_residue - dmaengine based PCM pointer implementation + * @substream: PCM substream + * + * This function is deprecated and should not be used by new drivers, as its + * results may be unreliable. + */ +snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + return bytes_to_frames(substream->runtime, prtd->pos); +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer_no_residue); + +/** + * snd_dmaengine_pcm_pointer - dmaengine based PCM pointer implementation + * @substream: PCM substream + * + * This function can be used as the PCM pointer callback for dmaengine based PCM + * driver implementations. + */ +snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + struct dma_tx_state state; + enum dma_status status; + unsigned int buf_size; + unsigned int pos = 0; + + status = dmaengine_tx_status(prtd->dma_chan, prtd->cookie, &state); + if (status == DMA_IN_PROGRESS || status == DMA_PAUSED) { + buf_size = snd_pcm_lib_buffer_bytes(substream); + if (state.residue > 0 && state.residue <= buf_size) + pos = buf_size - state.residue; + + runtime->delay = bytes_to_frames(runtime, + state.in_flight_bytes); + } + + return bytes_to_frames(runtime, pos); +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer); + +/** + * snd_dmaengine_pcm_request_channel - Request channel for the dmaengine PCM + * @filter_fn: Filter function used to request the DMA channel + * @filter_data: Data passed to the DMA filter function + * + * Returns NULL or the requested DMA channel. + * + * This function request a DMA channel for usage with dmaengine PCM. + */ +struct dma_chan *snd_dmaengine_pcm_request_channel(dma_filter_fn filter_fn, + void *filter_data) +{ + dma_cap_mask_t mask; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + dma_cap_set(DMA_CYCLIC, mask); + + return dma_request_channel(mask, filter_fn, filter_data); +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_request_channel); + +/** + * snd_dmaengine_pcm_open - Open a dmaengine based PCM substream + * @substream: PCM substream + * @chan: DMA channel to use for data transfers + * + * Returns 0 on success, a negative error code otherwise. + * + * The function should usually be called from the pcm open callback. Note that + * this function will use private_data field of the substream's runtime. So it + * is not available to your pcm driver implementation. + */ +int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, + struct dma_chan *chan) +{ + struct dmaengine_pcm_runtime_data *prtd; + int ret; + + if (!chan) + return -ENXIO; + + ret = snd_pcm_hw_constraint_integer(substream->runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + if (ret < 0) + return ret; + + prtd = kzalloc(sizeof(*prtd), GFP_KERNEL); + if (!prtd) + return -ENOMEM; + + prtd->dma_chan = chan; + + substream->runtime->private_data = prtd; + + return 0; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open); + +/** + * snd_dmaengine_pcm_open_request_chan - Open a dmaengine based PCM substream and request channel + * @substream: PCM substream + * @filter_fn: Filter function used to request the DMA channel + * @filter_data: Data passed to the DMA filter function + * + * Returns 0 on success, a negative error code otherwise. + * + * This function will request a DMA channel using the passed filter function and + * data. The function should usually be called from the pcm open callback. Note + * that this function will use private_data field of the substream's runtime. So + * it is not available to your pcm driver implementation. + */ +int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream, + dma_filter_fn filter_fn, void *filter_data) +{ + return snd_dmaengine_pcm_open(substream, + snd_dmaengine_pcm_request_channel(filter_fn, filter_data)); +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open_request_chan); + +/** + * snd_dmaengine_pcm_close - Close a dmaengine based PCM substream + * @substream: PCM substream + */ +int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + dmaengine_synchronize(prtd->dma_chan); + kfree(prtd); + + return 0; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close); + +/** + * snd_dmaengine_pcm_release_chan_close - Close a dmaengine based PCM substream and release channel + * @substream: PCM substream + * + * Releases the DMA channel associated with the PCM substream. + */ +int snd_dmaengine_pcm_close_release_chan(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + dmaengine_synchronize(prtd->dma_chan); + dma_release_channel(prtd->dma_chan); + kfree(prtd); + + return 0; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close_release_chan); + +/** + * snd_dmaengine_pcm_refine_runtime_hwparams - Refine runtime hw params + * @substream: PCM substream + * @dma_data: DAI DMA data + * @hw: PCM hw params + * @chan: DMA channel to use for data transfers + * + * Returns 0 on success, a negative error code otherwise. + * + * This function will query DMA capability, then refine the pcm hardware + * parameters. + */ +int snd_dmaengine_pcm_refine_runtime_hwparams( + struct snd_pcm_substream *substream, + struct snd_dmaengine_dai_dma_data *dma_data, + struct snd_pcm_hardware *hw, + struct dma_chan *chan) +{ + struct dma_slave_caps dma_caps; + u32 addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | + BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | + BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); + snd_pcm_format_t i; + int ret = 0; + + if (!hw || !chan || !dma_data) + return -EINVAL; + + ret = dma_get_slave_caps(chan, &dma_caps); + if (ret == 0) { + if (dma_caps.cmd_pause && dma_caps.cmd_resume) + hw->info |= SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME; + if (dma_caps.residue_granularity <= DMA_RESIDUE_GRANULARITY_SEGMENT) + hw->info |= SNDRV_PCM_INFO_BATCH; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + addr_widths = dma_caps.dst_addr_widths; + else + addr_widths = dma_caps.src_addr_widths; + } + + /* + * If SND_DMAENGINE_PCM_DAI_FLAG_PACK is set keep + * hw.formats set to 0, meaning no restrictions are in place. + * In this case it's the responsibility of the DAI driver to + * provide the supported format information. + */ + if (!(dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK)) + /* + * Prepare formats mask for valid/allowed sample types. If the + * dma does not have support for the given physical word size, + * it needs to be masked out so user space can not use the + * format which produces corrupted audio. + * In case the dma driver does not implement the slave_caps the + * default assumption is that it supports 1, 2 and 4 bytes + * widths. + */ + pcm_for_each_format(i) { + int bits = snd_pcm_format_physical_width(i); + + /* + * Enable only samples with DMA supported physical + * widths + */ + switch (bits) { + case 8: + case 16: + case 24: + case 32: + case 64: + if (addr_widths & (1 << (bits / 8))) + hw->formats |= pcm_format_to_bits(i); + break; + default: + /* Unsupported types */ + break; + } + } + + return ret; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_refine_runtime_hwparams); + +MODULE_LICENSE("GPL"); diff --git a/snd-alpx-dkms/snd-alpx/core/generic/6.2/amd_xdma.h b/snd-alpx-dkms/snd-alpx/core/generic/6.2/amd_xdma.h new file mode 100644 index 0000000..b5e23e1 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/core/generic/6.2/amd_xdma.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2022, Advanced Micro Devices, Inc. + */ + +#ifndef _PLATDATA_AMD_XDMA_H +#define _PLATDATA_AMD_XDMA_H + +#include <linux/dmaengine.h> + +/** + * struct xdma_chan_info - DMA channel information + * This information is used to match channel when request dma channel + * @dir: Channel transfer direction + */ +struct xdma_chan_info { + enum dma_transfer_direction dir; +}; + +#define XDMA_FILTER_PARAM(chan_info) ((void *)(chan_info)) + +struct dma_slave_map; + +/** + * struct xdma_platdata - platform specific data for XDMA engine + * @max_dma_channels: Maximum dma channels in each direction + */ +struct xdma_platdata { + u32 max_dma_channels; + u32 device_map_cnt; + struct dma_slave_map *device_map; +}; + +#endif /* _PLATDATA_AMD_XDMA_H */ diff --git a/snd-alpx-dkms/snd-alpx/core/generic/6.2/dmaengine.c b/snd-alpx-dkms/snd-alpx/core/generic/6.2/dmaengine.c new file mode 100644 index 0000000..8a6e6b6 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/core/generic/6.2/dmaengine.c @@ -0,0 +1,1652 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved. + */ + +/* + * This code implements the DMA subsystem. It provides a HW-neutral interface + * for other kernel code to use asynchronous memory copy capabilities, + * if present, and allows different HW DMA drivers to register as providing + * this capability. + * + * Due to the fact we are accelerating what is already a relatively fast + * operation, the code goes to great lengths to avoid additional overhead, + * such as locking. + * + * LOCKING: + * + * The subsystem keeps a global list of dma_device structs it is protected by a + * mutex, dma_list_mutex. + * + * A subsystem can get access to a channel by calling dmaengine_get() followed + * by dma_find_channel(), or if it has need for an exclusive channel it can call + * dma_request_channel(). Once a channel is allocated a reference is taken + * against its corresponding driver to disable removal. + * + * Each device has a channels list, which runs unlocked but is never modified + * once the device is registered, it's just setup by the driver. + * + * See Documentation/driver-api/dmaengine for more details + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/platform_device.h> +#include <linux/dma-mapping.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/mm.h> +#include <linux/device.h> +#include <linux/dmaengine.h> +#include <linux/hardirq.h> +#include <linux/spinlock.h> +#include <linux/percpu.h> +#include <linux/rcupdate.h> +#include <linux/mutex.h> +#include <linux/jiffies.h> +#include <linux/rculist.h> +#include <linux/idr.h> +#include <linux/slab.h> +#include <linux/acpi.h> +#include <linux/acpi_dma.h> +#include <linux/of_dma.h> +#include <linux/mempool.h> +#include <linux/numa.h> + +#include "dmaengine.h" + +static DEFINE_MUTEX(dma_list_mutex); +static DEFINE_IDA(dma_ida); +static LIST_HEAD(dma_device_list); +static long dmaengine_ref_count; + +/* --- debugfs implementation --- */ +#ifdef CONFIG_DEBUG_FS +#include <linux/debugfs.h> + +static struct dentry *rootdir; + +static void dmaengine_debug_register(struct dma_device *dma_dev) +{ + dma_dev->dbg_dev_root = debugfs_create_dir(dev_name(dma_dev->dev), + rootdir); + if (IS_ERR(dma_dev->dbg_dev_root)) + dma_dev->dbg_dev_root = NULL; +} + +static void dmaengine_debug_unregister(struct dma_device *dma_dev) +{ + debugfs_remove_recursive(dma_dev->dbg_dev_root); + dma_dev->dbg_dev_root = NULL; +} + +static void dmaengine_dbg_summary_show(struct seq_file *s, + struct dma_device *dma_dev) +{ + struct dma_chan *chan; + + list_for_each_entry(chan, &dma_dev->channels, device_node) { + if (chan->client_count) { + seq_printf(s, " %-13s| %s", dma_chan_name(chan), + chan->dbg_client_name ?: "in-use"); + + if (chan->router) + seq_printf(s, " (via router: %s)\n", + dev_name(chan->router->dev)); + else + seq_puts(s, "\n"); + } + } +} + +static int dmaengine_summary_show(struct seq_file *s, void *data) +{ + struct dma_device *dma_dev = NULL; + + mutex_lock(&dma_list_mutex); + list_for_each_entry(dma_dev, &dma_device_list, global_node) { + seq_printf(s, "dma%d (%s): number of channels: %u\n", + dma_dev->dev_id, dev_name(dma_dev->dev), + dma_dev->chancnt); + + if (dma_dev->dbg_summary_show) + dma_dev->dbg_summary_show(s, dma_dev); + else + dmaengine_dbg_summary_show(s, dma_dev); + + if (!list_is_last(&dma_dev->global_node, &dma_device_list)) + seq_puts(s, "\n"); + } + mutex_unlock(&dma_list_mutex); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(dmaengine_summary); + +static void __init dmaengine_debugfs_init(void) +{ + rootdir = debugfs_create_dir("dmaengine", NULL); + + /* /sys/kernel/debug/dmaengine/summary */ + debugfs_create_file("summary", 0444, rootdir, NULL, + &dmaengine_summary_fops); +} +#else +static inline void dmaengine_debugfs_init(void) { } +static inline int dmaengine_debug_register(struct dma_device *dma_dev) +{ + return 0; +} + +static inline void dmaengine_debug_unregister(struct dma_device *dma_dev) { } +#endif /* DEBUG_FS */ + +/* --- sysfs implementation --- */ + +#define DMA_SLAVE_NAME "slave" + +/** + * dev_to_dma_chan - convert a device pointer to its sysfs container object + * @dev: device node + * + * Must be called under dma_list_mutex. + */ +static struct dma_chan *dev_to_dma_chan(struct device *dev) +{ + struct dma_chan_dev *chan_dev; + + chan_dev = container_of(dev, typeof(*chan_dev), device); + return chan_dev->chan; +} + +static ssize_t memcpy_count_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct dma_chan *chan; + unsigned long count = 0; + int i; + int err; + + mutex_lock(&dma_list_mutex); + chan = dev_to_dma_chan(dev); + if (chan) { + for_each_possible_cpu(i) + count += per_cpu_ptr(chan->local, i)->memcpy_count; + err = sprintf(buf, "%lu\n", count); + } else + err = -ENODEV; + mutex_unlock(&dma_list_mutex); + + return err; +} +static DEVICE_ATTR_RO(memcpy_count); + +static ssize_t bytes_transferred_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct dma_chan *chan; + unsigned long count = 0; + int i; + int err; + + mutex_lock(&dma_list_mutex); + chan = dev_to_dma_chan(dev); + if (chan) { + for_each_possible_cpu(i) + count += per_cpu_ptr(chan->local, i)->bytes_transferred; + err = sprintf(buf, "%lu\n", count); + } else + err = -ENODEV; + mutex_unlock(&dma_list_mutex); + + return err; +} +static DEVICE_ATTR_RO(bytes_transferred); + +static ssize_t in_use_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct dma_chan *chan; + int err; + + mutex_lock(&dma_list_mutex); + chan = dev_to_dma_chan(dev); + if (chan) + err = sprintf(buf, "%d\n", chan->client_count); + else + err = -ENODEV; + mutex_unlock(&dma_list_mutex); + + return err; +} +static DEVICE_ATTR_RO(in_use); + +static struct attribute *dma_dev_attrs[] = { + &dev_attr_memcpy_count.attr, + &dev_attr_bytes_transferred.attr, + &dev_attr_in_use.attr, + NULL, +}; +ATTRIBUTE_GROUPS(dma_dev); + +static void chan_dev_release(struct device *dev) +{ + struct dma_chan_dev *chan_dev; + + chan_dev = container_of(dev, typeof(*chan_dev), device); + kfree(chan_dev); +} + +static struct class dma_devclass = { + .name = "dma", + .dev_groups = dma_dev_groups, + .dev_release = chan_dev_release, +}; + +/* --- client and device registration --- */ + +/* enable iteration over all operation types */ +static dma_cap_mask_t dma_cap_mask_all; + +/** + * struct dma_chan_tbl_ent - tracks channel allocations per core/operation + * @chan: associated channel for this entry + */ +struct dma_chan_tbl_ent { + struct dma_chan *chan; +}; + +/* percpu lookup table for memory-to-memory offload providers */ +static struct dma_chan_tbl_ent __percpu *channel_table[DMA_TX_TYPE_END]; + +static int __init dma_channel_table_init(void) +{ + enum dma_transaction_type cap; + int err = 0; + + bitmap_fill(dma_cap_mask_all.bits, DMA_TX_TYPE_END); + + /* 'interrupt', 'private', and 'slave' are channel capabilities, + * but are not associated with an operation so they do not need + * an entry in the channel_table + */ + clear_bit(DMA_INTERRUPT, dma_cap_mask_all.bits); + clear_bit(DMA_PRIVATE, dma_cap_mask_all.bits); + clear_bit(DMA_SLAVE, dma_cap_mask_all.bits); + + for_each_dma_cap_mask(cap, dma_cap_mask_all) { + channel_table[cap] = alloc_percpu(struct dma_chan_tbl_ent); + if (!channel_table[cap]) { + err = -ENOMEM; + break; + } + } + + if (err) { + pr_err("dmaengine dma_channel_table_init failure: %d\n", err); + for_each_dma_cap_mask(cap, dma_cap_mask_all) + free_percpu(channel_table[cap]); + } + + return err; +} +arch_initcall(dma_channel_table_init); + +/** + * dma_chan_is_local - checks if the channel is in the same NUMA-node as the CPU + * @chan: DMA channel to test + * @cpu: CPU index which the channel should be close to + * + * Returns true if the channel is in the same NUMA-node as the CPU. + */ +static bool dma_chan_is_local(struct dma_chan *chan, int cpu) +{ + int node = dev_to_node(chan->device->dev); + return node == NUMA_NO_NODE || + cpumask_test_cpu(cpu, cpumask_of_node(node)); +} + +/** + * min_chan - finds the channel with min count and in the same NUMA-node as the CPU + * @cap: capability to match + * @cpu: CPU index which the channel should be close to + * + * If some channels are close to the given CPU, the one with the lowest + * reference count is returned. Otherwise, CPU is ignored and only the + * reference count is taken into account. + * + * Must be called under dma_list_mutex. + */ +static struct dma_chan *min_chan(enum dma_transaction_type cap, int cpu) +{ + struct dma_device *device; + struct dma_chan *chan; + struct dma_chan *min = NULL; + struct dma_chan *localmin = NULL; + + list_for_each_entry(device, &dma_device_list, global_node) { + if (!dma_has_cap(cap, device->cap_mask) || + dma_has_cap(DMA_PRIVATE, device->cap_mask)) + continue; + list_for_each_entry(chan, &device->channels, device_node) { + if (!chan->client_count) + continue; + if (!min || chan->table_count < min->table_count) + min = chan; + + if (dma_chan_is_local(chan, cpu)) + if (!localmin || + chan->table_count < localmin->table_count) + localmin = chan; + } + } + + chan = localmin ? localmin : min; + + if (chan) + chan->table_count++; + + return chan; +} + +/** + * dma_channel_rebalance - redistribute the available channels + * + * Optimize for CPU isolation (each CPU gets a dedicated channel for an + * operation type) in the SMP case, and operation isolation (avoid + * multi-tasking channels) in the non-SMP case. + * + * Must be called under dma_list_mutex. + */ +static void dma_channel_rebalance(void) +{ + struct dma_chan *chan; + struct dma_device *device; + int cpu; + int cap; + + /* undo the last distribution */ + for_each_dma_cap_mask(cap, dma_cap_mask_all) + for_each_possible_cpu(cpu) + per_cpu_ptr(channel_table[cap], cpu)->chan = NULL; + + list_for_each_entry(device, &dma_device_list, global_node) { + if (dma_has_cap(DMA_PRIVATE, device->cap_mask)) + continue; + list_for_each_entry(chan, &device->channels, device_node) + chan->table_count = 0; + } + + /* don't populate the channel_table if no clients are available */ + if (!dmaengine_ref_count) + return; + + /* redistribute available channels */ + for_each_dma_cap_mask(cap, dma_cap_mask_all) + for_each_online_cpu(cpu) { + chan = min_chan(cap, cpu); + per_cpu_ptr(channel_table[cap], cpu)->chan = chan; + } +} + +static int dma_device_satisfies_mask(struct dma_device *device, + const dma_cap_mask_t *want) +{ + dma_cap_mask_t has; + + bitmap_and(has.bits, want->bits, device->cap_mask.bits, + DMA_TX_TYPE_END); + return bitmap_equal(want->bits, has.bits, DMA_TX_TYPE_END); +} + +static struct module *dma_chan_to_owner(struct dma_chan *chan) +{ + return chan->device->owner; +} + +/** + * balance_ref_count - catch up the channel reference count + * @chan: channel to balance ->client_count versus dmaengine_ref_count + * + * Must be called under dma_list_mutex. + */ +static void balance_ref_count(struct dma_chan *chan) +{ + struct module *owner = dma_chan_to_owner(chan); + + while (chan->client_count < dmaengine_ref_count) { + __module_get(owner); + chan->client_count++; + } +} + +static void dma_device_release(struct kref *ref) +{ + struct dma_device *device = container_of(ref, struct dma_device, ref); + + list_del_rcu(&device->global_node); + dma_channel_rebalance(); + + if (device->device_release) + device->device_release(device); +} + +static void dma_device_put(struct dma_device *device) +{ + lockdep_assert_held(&dma_list_mutex); + kref_put(&device->ref, dma_device_release); +} + +/** + * dma_chan_get - try to grab a DMA channel's parent driver module + * @chan: channel to grab + * + * Must be called under dma_list_mutex. + */ +static int dma_chan_get(struct dma_chan *chan) +{ + struct module *owner = dma_chan_to_owner(chan); + int ret; + + /* The channel is already in use, update client count */ + if (chan->client_count) { + __module_get(owner); + chan->client_count++; + return 0; + } + + if (!try_module_get(owner)) + return -ENODEV; + + ret = kref_get_unless_zero(&chan->device->ref); + if (!ret) { + ret = -ENODEV; + goto module_put_out; + } + + /* allocate upon first client reference */ + if (chan->device->device_alloc_chan_resources) { + ret = chan->device->device_alloc_chan_resources(chan); + if (ret < 0) + goto err_out; + } + + chan->client_count++; + + if (!dma_has_cap(DMA_PRIVATE, chan->device->cap_mask)) + balance_ref_count(chan); + + return 0; + +err_out: + dma_device_put(chan->device); +module_put_out: + module_put(owner); + return ret; +} + +/** + * dma_chan_put - drop a reference to a DMA channel's parent driver module + * @chan: channel to release + * + * Must be called under dma_list_mutex. + */ +static void dma_chan_put(struct dma_chan *chan) +{ + /* This channel is not in use, bail out */ + if (!chan->client_count) + return; + + chan->client_count--; + + /* This channel is not in use anymore, free it */ + if (!chan->client_count && chan->device->device_free_chan_resources) { + /* Make sure all operations have completed */ + dmaengine_synchronize(chan); + chan->device->device_free_chan_resources(chan); + } + + /* If the channel is used via a DMA request router, free the mapping */ + if (chan->router && chan->router->route_free) { + chan->router->route_free(chan->router->dev, chan->route_data); + chan->router = NULL; + chan->route_data = NULL; + } + + dma_device_put(chan->device); + module_put(dma_chan_to_owner(chan)); +} + +enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie) +{ + enum dma_status status; + unsigned long dma_sync_wait_timeout = jiffies + msecs_to_jiffies(5000); + + dma_async_issue_pending(chan); + do { + status = dma_async_is_tx_complete(chan, cookie, NULL, NULL); + if (time_after_eq(jiffies, dma_sync_wait_timeout)) { + dev_err(chan->device->dev, "%s: timeout!\n", __func__); + return DMA_ERROR; + } + if (status != DMA_IN_PROGRESS) + break; + cpu_relax(); + } while (1); + + return status; +} +EXPORT_SYMBOL(dma_sync_wait); + +/** + * dma_find_channel - find a channel to carry out the operation + * @tx_type: transaction type + */ +struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type) +{ + return this_cpu_read(channel_table[tx_type]->chan); +} +EXPORT_SYMBOL(dma_find_channel); + +/** + * dma_issue_pending_all - flush all pending operations across all channels + */ +void dma_issue_pending_all(void) +{ + struct dma_device *device; + struct dma_chan *chan; + + rcu_read_lock(); + list_for_each_entry_rcu(device, &dma_device_list, global_node) { + if (dma_has_cap(DMA_PRIVATE, device->cap_mask)) + continue; + list_for_each_entry(chan, &device->channels, device_node) + if (chan->client_count) + device->device_issue_pending(chan); + } + rcu_read_unlock(); +} +EXPORT_SYMBOL(dma_issue_pending_all); + +int dma_get_slave_caps(struct dma_chan *chan, struct dma_slave_caps *caps) +{ + struct dma_device *device; + + if (!chan || !caps) + return -EINVAL; + + device = chan->device; + + /* check if the channel supports slave transactions */ + if (!(test_bit(DMA_SLAVE, device->cap_mask.bits) || + test_bit(DMA_CYCLIC, device->cap_mask.bits))) + return -ENXIO; + + /* + * Check whether it reports it uses the generic slave + * capabilities, if not, that means it doesn't support any + * kind of slave capabilities reporting. + */ + if (!device->directions) + return -ENXIO; + + caps->src_addr_widths = device->src_addr_widths; + caps->dst_addr_widths = device->dst_addr_widths; + caps->directions = device->directions; + caps->min_burst = device->min_burst; + caps->max_burst = device->max_burst; + caps->max_sg_burst = device->max_sg_burst; + caps->residue_granularity = device->residue_granularity; + caps->descriptor_reuse = device->descriptor_reuse; + caps->cmd_pause = !!device->device_pause; + caps->cmd_resume = !!device->device_resume; + caps->cmd_terminate = !!device->device_terminate_all; + + /* + * DMA engine device might be configured with non-uniformly + * distributed slave capabilities per device channels. In this + * case the corresponding driver may provide the device_caps + * callback to override the generic capabilities with + * channel-specific ones. + */ + if (device->device_caps) + device->device_caps(chan, caps); + + return 0; +} +EXPORT_SYMBOL_GPL(dma_get_slave_caps); + +static struct dma_chan *private_candidate(const dma_cap_mask_t *mask, + struct dma_device *dev, + dma_filter_fn fn, void *fn_param) +{ + struct dma_chan *chan; + + if (mask && !dma_device_satisfies_mask(dev, mask)) { + dev_dbg(dev->dev, "%s: wrong capabilities\n", __func__); + return NULL; + } + /* devices with multiple channels need special handling as we need to + * ensure that all channels are either private or public. + */ + if (dev->chancnt > 1 && !dma_has_cap(DMA_PRIVATE, dev->cap_mask)) + list_for_each_entry(chan, &dev->channels, device_node) { + /* some channels are already publicly allocated */ + if (chan->client_count) + return NULL; + } + + list_for_each_entry(chan, &dev->channels, device_node) { + if (chan->client_count) { + dev_dbg(dev->dev, "%s: %s busy\n", + __func__, dma_chan_name(chan)); + continue; + } + if (fn && !fn(chan, fn_param)) { + dev_dbg(dev->dev, "%s: %s filter said false\n", + __func__, dma_chan_name(chan)); + continue; + } + return chan; + } + + return NULL; +} + +static struct dma_chan *find_candidate(struct dma_device *device, + const dma_cap_mask_t *mask, + dma_filter_fn fn, void *fn_param) +{ + struct dma_chan *chan = private_candidate(mask, device, fn, fn_param); + int err; + + if (chan) { + /* Found a suitable channel, try to grab, prep, and return it. + * We first set DMA_PRIVATE to disable balance_ref_count as this + * channel will not be published in the general-purpose + * allocator + */ + dma_cap_set(DMA_PRIVATE, device->cap_mask); + device->privatecnt++; + err = dma_chan_get(chan); + + if (err) { + if (err == -ENODEV) { + dev_dbg(device->dev, "%s: %s module removed\n", + __func__, dma_chan_name(chan)); + list_del_rcu(&device->global_node); + } else + dev_dbg(device->dev, + "%s: failed to get %s: (%d)\n", + __func__, dma_chan_name(chan), err); + + if (--device->privatecnt == 0) + dma_cap_clear(DMA_PRIVATE, device->cap_mask); + + chan = ERR_PTR(err); + } + } + + return chan ? chan : ERR_PTR(-EPROBE_DEFER); +} + +/** + * dma_get_slave_channel - try to get specific channel exclusively + * @chan: target channel + */ +struct dma_chan *dma_get_slave_channel(struct dma_chan *chan) +{ + /* lock against __dma_request_channel */ + mutex_lock(&dma_list_mutex); + + if (chan->client_count == 0) { + struct dma_device *device = chan->device; + int err; + + dma_cap_set(DMA_PRIVATE, device->cap_mask); + device->privatecnt++; + err = dma_chan_get(chan); + if (err) { + dev_dbg(chan->device->dev, + "%s: failed to get %s: (%d)\n", + __func__, dma_chan_name(chan), err); + chan = NULL; + if (--device->privatecnt == 0) + dma_cap_clear(DMA_PRIVATE, device->cap_mask); + } + } else + chan = NULL; + + mutex_unlock(&dma_list_mutex); + + + return chan; +} +EXPORT_SYMBOL_GPL(dma_get_slave_channel); + +struct dma_chan *dma_get_any_slave_channel(struct dma_device *device) +{ + dma_cap_mask_t mask; + struct dma_chan *chan; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + + /* lock against __dma_request_channel */ + mutex_lock(&dma_list_mutex); + + chan = find_candidate(device, &mask, NULL, NULL); + + mutex_unlock(&dma_list_mutex); + + return IS_ERR(chan) ? NULL : chan; +} +EXPORT_SYMBOL_GPL(dma_get_any_slave_channel); + +/** + * __dma_request_channel - try to allocate an exclusive channel + * @mask: capabilities that the channel must satisfy + * @fn: optional callback to disposition available channels + * @fn_param: opaque parameter to pass to dma_filter_fn() + * @np: device node to look for DMA channels + * + * Returns pointer to appropriate DMA channel on success or NULL. + */ +struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask, + dma_filter_fn fn, void *fn_param, + struct device_node *np) +{ + struct dma_device *device, *_d; + struct dma_chan *chan = NULL; + + /* Find a channel */ + mutex_lock(&dma_list_mutex); + list_for_each_entry_safe(device, _d, &dma_device_list, global_node) { + /* Finds a DMA controller with matching device node */ + if (np && device->dev->of_node && np != device->dev->of_node) + continue; + + chan = find_candidate(device, mask, fn, fn_param); + if (!IS_ERR(chan)) + break; + + chan = NULL; + } + mutex_unlock(&dma_list_mutex); + + pr_debug("%s: %s (%s)\n", + __func__, + chan ? "success" : "fail", + chan ? dma_chan_name(chan) : NULL); + + return chan; +} +EXPORT_SYMBOL_GPL(__dma_request_channel); + +static const struct dma_slave_map *dma_filter_match(struct dma_device *device, + const char *name, + struct device *dev) +{ + int i; + + if (!device->filter.mapcnt) + return NULL; + + for (i = 0; i < device->filter.mapcnt; i++) { + const struct dma_slave_map *map = &device->filter.map[i]; + + if (!strcmp(map->devname, dev_name(dev)) && + !strcmp(map->slave, name)) + return map; + } + + return NULL; +} + +/** + * dma_request_chan - try to allocate an exclusive slave channel + * @dev: pointer to client device structure + * @name: slave channel name + * + * Returns pointer to appropriate DMA channel on success or an error pointer. + */ +struct dma_chan *dma_request_chan(struct device *dev, const char *name) +{ + struct dma_device *d, *_d; + struct dma_chan *chan = NULL; + + /* If device-tree is present get slave info from here */ + if (dev->of_node) + chan = of_dma_request_slave_channel(dev->of_node, name); + + /* If device was enumerated by ACPI get slave info from here */ + if (has_acpi_companion(dev) && !chan) + chan = acpi_dma_request_slave_chan_by_name(dev, name); + + if (PTR_ERR(chan) == -EPROBE_DEFER) + return chan; + + if (!IS_ERR_OR_NULL(chan)) + goto found; + + /* Try to find the channel via the DMA filter map(s) */ + mutex_lock(&dma_list_mutex); + list_for_each_entry_safe(d, _d, &dma_device_list, global_node) { + dma_cap_mask_t mask; + const struct dma_slave_map *map = dma_filter_match(d, name, dev); + + if (!map) + continue; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + + chan = find_candidate(d, &mask, d->filter.fn, map->param); + if (!IS_ERR(chan)) + break; + } + mutex_unlock(&dma_list_mutex); + + if (IS_ERR(chan)) + return chan; + if (!chan) + return ERR_PTR(-EPROBE_DEFER); + +found: +#ifdef CONFIG_DEBUG_FS + chan->dbg_client_name = kasprintf(GFP_KERNEL, "%s:%s", dev_name(dev), + name); +#endif + + chan->name = kasprintf(GFP_KERNEL, "dma:%s", name); + if (!chan->name) + return chan; + chan->slave = dev; + + if (sysfs_create_link(&chan->dev->device.kobj, &dev->kobj, + DMA_SLAVE_NAME)) + dev_warn(dev, "Cannot create DMA %s symlink\n", DMA_SLAVE_NAME); + if (sysfs_create_link(&dev->kobj, &chan->dev->device.kobj, chan->name)) + dev_warn(dev, "Cannot create DMA %s symlink\n", chan->name); + + return chan; +} +EXPORT_SYMBOL_GPL(dma_request_chan); + +/** + * dma_request_chan_by_mask - allocate a channel satisfying certain capabilities + * @mask: capabilities that the channel must satisfy + * + * Returns pointer to appropriate DMA channel on success or an error pointer. + */ +struct dma_chan *dma_request_chan_by_mask(const dma_cap_mask_t *mask) +{ + struct dma_chan *chan; + + if (!mask) + return ERR_PTR(-ENODEV); + + chan = __dma_request_channel(mask, NULL, NULL, NULL); + if (!chan) { + mutex_lock(&dma_list_mutex); + if (list_empty(&dma_device_list)) + chan = ERR_PTR(-EPROBE_DEFER); + else + chan = ERR_PTR(-ENODEV); + mutex_unlock(&dma_list_mutex); + } + + return chan; +} +EXPORT_SYMBOL_GPL(dma_request_chan_by_mask); + +void dma_release_channel(struct dma_chan *chan) +{ + mutex_lock(&dma_list_mutex); + WARN_ONCE(chan->client_count != 1, + "chan reference count %d != 1\n", chan->client_count); + dma_chan_put(chan); + /* drop PRIVATE cap enabled by __dma_request_channel() */ + if (--chan->device->privatecnt == 0) + dma_cap_clear(DMA_PRIVATE, chan->device->cap_mask); + + if (chan->slave) { + sysfs_remove_link(&chan->dev->device.kobj, DMA_SLAVE_NAME); + sysfs_remove_link(&chan->slave->kobj, chan->name); + kfree(chan->name); + chan->name = NULL; + chan->slave = NULL; + } + +#ifdef CONFIG_DEBUG_FS + kfree(chan->dbg_client_name); + chan->dbg_client_name = NULL; +#endif + mutex_unlock(&dma_list_mutex); +} +EXPORT_SYMBOL_GPL(dma_release_channel); + +/** + * dmaengine_get - register interest in dma_channels + */ +void dmaengine_get(void) +{ + struct dma_device *device, *_d; + struct dma_chan *chan; + int err; + + mutex_lock(&dma_list_mutex); + dmaengine_ref_count++; + + /* try to grab channels */ + list_for_each_entry_safe(device, _d, &dma_device_list, global_node) { + if (dma_has_cap(DMA_PRIVATE, device->cap_mask)) + continue; + list_for_each_entry(chan, &device->channels, device_node) { + err = dma_chan_get(chan); + if (err == -ENODEV) { + /* module removed before we could use it */ + list_del_rcu(&device->global_node); + break; + } else if (err) + dev_dbg(chan->device->dev, + "%s: failed to get %s: (%d)\n", + __func__, dma_chan_name(chan), err); + } + } + + /* if this is the first reference and there were channels + * waiting we need to rebalance to get those channels + * incorporated into the channel table + */ + if (dmaengine_ref_count == 1) + dma_channel_rebalance(); + mutex_unlock(&dma_list_mutex); +} +EXPORT_SYMBOL(dmaengine_get); + +/** + * dmaengine_put - let DMA drivers be removed when ref_count == 0 + */ +void dmaengine_put(void) +{ + struct dma_device *device, *_d; + struct dma_chan *chan; + + mutex_lock(&dma_list_mutex); + dmaengine_ref_count--; + BUG_ON(dmaengine_ref_count < 0); + /* drop channel references */ + list_for_each_entry_safe(device, _d, &dma_device_list, global_node) { + if (dma_has_cap(DMA_PRIVATE, device->cap_mask)) + continue; + list_for_each_entry(chan, &device->channels, device_node) + dma_chan_put(chan); + } + mutex_unlock(&dma_list_mutex); +} +EXPORT_SYMBOL(dmaengine_put); + +static bool device_has_all_tx_types(struct dma_device *device) +{ + /* A device that satisfies this test has channels that will never cause + * an async_tx channel switch event as all possible operation types can + * be handled. + */ + #ifdef CONFIG_ASYNC_TX_DMA + if (!dma_has_cap(DMA_INTERRUPT, device->cap_mask)) + return false; + #endif + + #if IS_ENABLED(CONFIG_ASYNC_MEMCPY) + if (!dma_has_cap(DMA_MEMCPY, device->cap_mask)) + return false; + #endif + + #if IS_ENABLED(CONFIG_ASYNC_XOR) + if (!dma_has_cap(DMA_XOR, device->cap_mask)) + return false; + + #ifndef CONFIG_ASYNC_TX_DISABLE_XOR_VAL_DMA + if (!dma_has_cap(DMA_XOR_VAL, device->cap_mask)) + return false; + #endif + #endif + + #if IS_ENABLED(CONFIG_ASYNC_PQ) + if (!dma_has_cap(DMA_PQ, device->cap_mask)) + return false; + + #ifndef CONFIG_ASYNC_TX_DISABLE_PQ_VAL_DMA + if (!dma_has_cap(DMA_PQ_VAL, device->cap_mask)) + return false; + #endif + #endif + + return true; +} + +static int get_dma_id(struct dma_device *device) +{ + int rc = ida_alloc(&dma_ida, GFP_KERNEL); + + if (rc < 0) + return rc; + device->dev_id = rc; + return 0; +} + +static int __dma_async_device_channel_register(struct dma_device *device, + struct dma_chan *chan) +{ + int rc; + + chan->local = alloc_percpu(typeof(*chan->local)); + if (!chan->local) + return -ENOMEM; + chan->dev = kzalloc(sizeof(*chan->dev), GFP_KERNEL); + if (!chan->dev) { + rc = -ENOMEM; + goto err_free_local; + } + + /* + * When the chan_id is a negative value, we are dynamically adding + * the channel. Otherwise we are static enumerating. + */ + chan->chan_id = ida_alloc(&device->chan_ida, GFP_KERNEL); + if (chan->chan_id < 0) { + pr_err("%s: unable to alloc ida for chan: %d\n", + __func__, chan->chan_id); + rc = chan->chan_id; + goto err_free_dev; + } + + chan->dev->device.class = &dma_devclass; + chan->dev->device.parent = device->dev; + chan->dev->chan = chan; + chan->dev->dev_id = device->dev_id; + dev_set_name(&chan->dev->device, "dma%dchan%d", + device->dev_id, chan->chan_id); + rc = device_register(&chan->dev->device); + if (rc) + goto err_out_ida; + chan->client_count = 0; + device->chancnt++; + + return 0; + + err_out_ida: + ida_free(&device->chan_ida, chan->chan_id); + err_free_dev: + kfree(chan->dev); + err_free_local: + free_percpu(chan->local); + chan->local = NULL; + return rc; +} + +int dma_async_device_channel_register(struct dma_device *device, + struct dma_chan *chan) +{ + int rc; + + rc = __dma_async_device_channel_register(device, chan); + if (rc < 0) + return rc; + + dma_channel_rebalance(); + return 0; +} +EXPORT_SYMBOL_GPL(dma_async_device_channel_register); + +static void __dma_async_device_channel_unregister(struct dma_device *device, + struct dma_chan *chan) +{ + WARN_ONCE(!device->device_release && chan->client_count, + "%s called while %d clients hold a reference\n", + __func__, chan->client_count); + mutex_lock(&dma_list_mutex); + device->chancnt--; + chan->dev->chan = NULL; + mutex_unlock(&dma_list_mutex); + ida_free(&device->chan_ida, chan->chan_id); + device_unregister(&chan->dev->device); + free_percpu(chan->local); +} + +void dma_async_device_channel_unregister(struct dma_device *device, + struct dma_chan *chan) +{ + __dma_async_device_channel_unregister(device, chan); + dma_channel_rebalance(); +} +EXPORT_SYMBOL_GPL(dma_async_device_channel_unregister); + +/** + * dma_async_device_register - registers DMA devices found + * @device: pointer to &struct dma_device + * + * After calling this routine the structure should not be freed except in the + * device_release() callback which will be called after + * dma_async_device_unregister() is called and no further references are taken. + */ +int dma_async_device_register(struct dma_device *device) +{ + int rc; + struct dma_chan* chan; + + if (!device) + return -ENODEV; + + /* validate device routines */ + if (!device->dev) { + pr_err("DMAdevice must have dev\n"); + return -EIO; + } + + device->owner = device->dev->driver->owner; + + if (dma_has_cap(DMA_MEMCPY, device->cap_mask) && !device->device_prep_dma_memcpy) { + dev_err(device->dev, + "Device claims capability %s, but op is not defined\n", + "DMA_MEMCPY"); + return -EIO; + } + + if (dma_has_cap(DMA_XOR, device->cap_mask) && !device->device_prep_dma_xor) { + dev_err(device->dev, + "Device claims capability %s, but op is not defined\n", + "DMA_XOR"); + return -EIO; + } + + if (dma_has_cap(DMA_XOR_VAL, device->cap_mask) && !device->device_prep_dma_xor_val) { + dev_err(device->dev, + "Device claims capability %s, but op is not defined\n", + "DMA_XOR_VAL"); + return -EIO; + } + + if (dma_has_cap(DMA_PQ, device->cap_mask) && !device->device_prep_dma_pq) { + dev_err(device->dev, + "Device claims capability %s, but op is not defined\n", + "DMA_PQ"); + return -EIO; + } + + if (dma_has_cap(DMA_PQ_VAL, device->cap_mask) && !device->device_prep_dma_pq_val) { + dev_err(device->dev, + "Device claims capability %s, but op is not defined\n", + "DMA_PQ_VAL"); + return -EIO; + } + + if (dma_has_cap(DMA_MEMSET, device->cap_mask) && !device->device_prep_dma_memset) { + dev_err(device->dev, + "Device claims capability %s, but op is not defined\n", + "DMA_MEMSET"); + return -EIO; + } + + if (dma_has_cap(DMA_INTERRUPT, device->cap_mask) && !device->device_prep_dma_interrupt) { + dev_err(device->dev, + "Device claims capability %s, but op is not defined\n", + "DMA_INTERRUPT"); + return -EIO; + } + + if (dma_has_cap(DMA_CYCLIC, device->cap_mask) && !device->device_prep_dma_cyclic) { + dev_err(device->dev, + "Device claims capability %s, but op is not defined\n", + "DMA_CYCLIC"); + return -EIO; + } + + if (dma_has_cap(DMA_INTERLEAVE, device->cap_mask) && !device->device_prep_interleaved_dma) { + dev_err(device->dev, + "Device claims capability %s, but op is not defined\n", + "DMA_INTERLEAVE"); + return -EIO; + } + + + if (!device->device_tx_status) { + dev_err(device->dev, "Device tx_status is not defined\n"); + return -EIO; + } + + + if (!device->device_issue_pending) { + dev_err(device->dev, "Device issue_pending is not defined\n"); + return -EIO; + } + + if (!device->device_release) + dev_dbg(device->dev, + "WARN: Device release is not defined so it is not safe to unbind this driver while in use\n"); + + kref_init(&device->ref); + + /* note: this only matters in the + * CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH=n case + */ + if (device_has_all_tx_types(device)) + dma_cap_set(DMA_ASYNC_TX, device->cap_mask); + + rc = get_dma_id(device); + if (rc != 0) + return rc; + + ida_init(&device->chan_ida); + + /* represent channels in sysfs. Probably want devs too */ + list_for_each_entry(chan, &device->channels, device_node) { + rc = __dma_async_device_channel_register(device, chan); + if (rc < 0) + goto err_out; + } + + mutex_lock(&dma_list_mutex); + /* take references on public channels */ + if (dmaengine_ref_count && !dma_has_cap(DMA_PRIVATE, device->cap_mask)) + list_for_each_entry(chan, &device->channels, device_node) { + /* if clients are already waiting for channels we need + * to take references on their behalf + */ + if (dma_chan_get(chan) == -ENODEV) { + /* note we can only get here for the first + * channel as the remaining channels are + * guaranteed to get a reference + */ + rc = -ENODEV; + mutex_unlock(&dma_list_mutex); + goto err_out; + } + } + list_add_tail_rcu(&device->global_node, &dma_device_list); + if (dma_has_cap(DMA_PRIVATE, device->cap_mask)) + device->privatecnt++; /* Always private */ + dma_channel_rebalance(); + mutex_unlock(&dma_list_mutex); + + dmaengine_debug_register(device); + + return 0; + +err_out: + /* if we never registered a channel just release the idr */ + if (!device->chancnt) { + ida_free(&dma_ida, device->dev_id); + return rc; + } + + list_for_each_entry(chan, &device->channels, device_node) { + if (chan->local == NULL) + continue; + mutex_lock(&dma_list_mutex); + chan->dev->chan = NULL; + mutex_unlock(&dma_list_mutex); + device_unregister(&chan->dev->device); + free_percpu(chan->local); + } + return rc; +} +EXPORT_SYMBOL(dma_async_device_register); + +/** + * dma_async_device_unregister - unregister a DMA device + * @device: pointer to &struct dma_device + * + * This routine is called by dma driver exit routines, dmaengine holds module + * references to prevent it being called while channels are in use. + */ +void dma_async_device_unregister(struct dma_device *device) +{ + struct dma_chan *chan, *n; + + dmaengine_debug_unregister(device); + + list_for_each_entry_safe(chan, n, &device->channels, device_node) + __dma_async_device_channel_unregister(device, chan); + + mutex_lock(&dma_list_mutex); + /* + * setting DMA_PRIVATE ensures the device being torn down will not + * be used in the channel_table + */ + dma_cap_set(DMA_PRIVATE, device->cap_mask); + dma_channel_rebalance(); + ida_free(&dma_ida, device->dev_id); + dma_device_put(device); + mutex_unlock(&dma_list_mutex); +} +EXPORT_SYMBOL(dma_async_device_unregister); + +static void dmam_device_release(struct device *dev, void *res) +{ + struct dma_device *device; + + device = *(struct dma_device **)res; + dma_async_device_unregister(device); +} + +/** + * dmaenginem_async_device_register - registers DMA devices found + * @device: pointer to &struct dma_device + * + * The operation is managed and will be undone on driver detach. + */ +int dmaenginem_async_device_register(struct dma_device *device) +{ + void *p; + int ret; + + p = devres_alloc(dmam_device_release, sizeof(void *), GFP_KERNEL); + if (!p) + return -ENOMEM; + + ret = dma_async_device_register(device); + if (!ret) { + *(struct dma_device **)p = device; + devres_add(device->dev, p); + } else { + devres_free(p); + } + + return ret; +} +EXPORT_SYMBOL(dmaenginem_async_device_register); + +struct dmaengine_unmap_pool { + struct kmem_cache *cache; + const char *name; + mempool_t *pool; + size_t size; +}; + +#define __UNMAP_POOL(x) { .size = x, .name = "dmaengine-unmap-" __stringify(x) } +static struct dmaengine_unmap_pool unmap_pool[] = { + __UNMAP_POOL(2), + #if IS_ENABLED(CONFIG_DMA_ENGINE_RAID) + __UNMAP_POOL(16), + __UNMAP_POOL(128), + __UNMAP_POOL(256), + #endif +}; + +static struct dmaengine_unmap_pool *__get_unmap_pool(int nr) +{ + int order = get_count_order(nr); + + switch (order) { + case 0 ... 1: + return &unmap_pool[0]; +#if IS_ENABLED(CONFIG_DMA_ENGINE_RAID) + case 2 ... 4: + return &unmap_pool[1]; + case 5 ... 7: + return &unmap_pool[2]; + case 8: + return &unmap_pool[3]; +#endif + default: + BUG(); + return NULL; + } +} + +static void dmaengine_unmap(struct kref *kref) +{ + struct dmaengine_unmap_data *unmap = container_of(kref, typeof(*unmap), kref); + struct device *dev = unmap->dev; + int cnt, i; + + cnt = unmap->to_cnt; + for (i = 0; i < cnt; i++) + dma_unmap_page(dev, unmap->addr[i], unmap->len, + DMA_TO_DEVICE); + cnt += unmap->from_cnt; + for (; i < cnt; i++) + dma_unmap_page(dev, unmap->addr[i], unmap->len, + DMA_FROM_DEVICE); + cnt += unmap->bidi_cnt; + for (; i < cnt; i++) { + if (unmap->addr[i] == 0) + continue; + dma_unmap_page(dev, unmap->addr[i], unmap->len, + DMA_BIDIRECTIONAL); + } + cnt = unmap->map_cnt; + mempool_free(unmap, __get_unmap_pool(cnt)->pool); +} + +void dmaengine_unmap_put(struct dmaengine_unmap_data *unmap) +{ + if (unmap) + kref_put(&unmap->kref, dmaengine_unmap); +} +EXPORT_SYMBOL_GPL(dmaengine_unmap_put); + +static void dmaengine_destroy_unmap_pool(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(unmap_pool); i++) { + struct dmaengine_unmap_pool *p = &unmap_pool[i]; + + mempool_destroy(p->pool); + p->pool = NULL; + kmem_cache_destroy(p->cache); + p->cache = NULL; + } +} + +static int __init dmaengine_init_unmap_pool(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(unmap_pool); i++) { + struct dmaengine_unmap_pool *p = &unmap_pool[i]; + size_t size; + + size = sizeof(struct dmaengine_unmap_data) + + sizeof(dma_addr_t) * p->size; + + p->cache = kmem_cache_create(p->name, size, 0, + SLAB_HWCACHE_ALIGN, NULL); + if (!p->cache) + break; + p->pool = mempool_create_slab_pool(1, p->cache); + if (!p->pool) + break; + } + + if (i == ARRAY_SIZE(unmap_pool)) + return 0; + + dmaengine_destroy_unmap_pool(); + return -ENOMEM; +} + +struct dmaengine_unmap_data * +dmaengine_get_unmap_data(struct device *dev, int nr, gfp_t flags) +{ + struct dmaengine_unmap_data *unmap; + + unmap = mempool_alloc(__get_unmap_pool(nr)->pool, flags); + if (!unmap) + return NULL; + + memset(unmap, 0, sizeof(*unmap)); + kref_init(&unmap->kref); + unmap->dev = dev; + unmap->map_cnt = nr; + + return unmap; +} +EXPORT_SYMBOL(dmaengine_get_unmap_data); + +void dma_async_tx_descriptor_init(struct dma_async_tx_descriptor *tx, + struct dma_chan *chan) +{ + tx->chan = chan; + #ifdef CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH + spin_lock_init(&tx->lock); + #endif +} +EXPORT_SYMBOL(dma_async_tx_descriptor_init); + +static inline int desc_check_and_set_metadata_mode( + struct dma_async_tx_descriptor *desc, enum dma_desc_metadata_mode mode) +{ + /* Make sure that the metadata mode is not mixed */ + if (!desc->desc_metadata_mode) { + if (dmaengine_is_metadata_mode_supported(desc->chan, mode)) + desc->desc_metadata_mode = mode; + else + return -ENOTSUPP; + } else if (desc->desc_metadata_mode != mode) { + return -EINVAL; + } + + return 0; +} + +int dmaengine_desc_attach_metadata(struct dma_async_tx_descriptor *desc, + void *data, size_t len) +{ + int ret; + + if (!desc) + return -EINVAL; + + ret = desc_check_and_set_metadata_mode(desc, DESC_METADATA_CLIENT); + if (ret) + return ret; + + if (!desc->metadata_ops || !desc->metadata_ops->attach) + return -ENOTSUPP; + + return desc->metadata_ops->attach(desc, data, len); +} +EXPORT_SYMBOL_GPL(dmaengine_desc_attach_metadata); + +void *dmaengine_desc_get_metadata_ptr(struct dma_async_tx_descriptor *desc, + size_t *payload_len, size_t *max_len) +{ + int ret; + + if (!desc) + return ERR_PTR(-EINVAL); + + ret = desc_check_and_set_metadata_mode(desc, DESC_METADATA_ENGINE); + if (ret) + return ERR_PTR(ret); + + if (!desc->metadata_ops || !desc->metadata_ops->get_ptr) + return ERR_PTR(-ENOTSUPP); + + return desc->metadata_ops->get_ptr(desc, payload_len, max_len); +} +EXPORT_SYMBOL_GPL(dmaengine_desc_get_metadata_ptr); + +int dmaengine_desc_set_metadata_len(struct dma_async_tx_descriptor *desc, + size_t payload_len) +{ + int ret; + + if (!desc) + return -EINVAL; + + ret = desc_check_and_set_metadata_mode(desc, DESC_METADATA_ENGINE); + if (ret) + return ret; + + if (!desc->metadata_ops || !desc->metadata_ops->set_len) + return -ENOTSUPP; + + return desc->metadata_ops->set_len(desc, payload_len); +} +EXPORT_SYMBOL_GPL(dmaengine_desc_set_metadata_len); + +/** + * dma_wait_for_async_tx - spin wait for a transaction to complete + * @tx: in-flight transaction to wait on + */ +enum dma_status +dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx) +{ + unsigned long dma_sync_wait_timeout = jiffies + msecs_to_jiffies(5000); + + if (!tx) + return DMA_COMPLETE; + + while (tx->cookie == -EBUSY) { + if (time_after_eq(jiffies, dma_sync_wait_timeout)) { + dev_err(tx->chan->device->dev, + "%s timeout waiting for descriptor submission\n", + __func__); + return DMA_ERROR; + } + cpu_relax(); + } + return dma_sync_wait(tx->chan, tx->cookie); +} +EXPORT_SYMBOL_GPL(dma_wait_for_async_tx); + +/** + * dma_run_dependencies - process dependent operations on the target channel + * @tx: transaction with dependencies + * + * Helper routine for DMA drivers to process (start) dependent operations + * on their target channel. + */ +void dma_run_dependencies(struct dma_async_tx_descriptor *tx) +{ + struct dma_async_tx_descriptor *dep = txd_next(tx); + struct dma_async_tx_descriptor *dep_next; + struct dma_chan *chan; + + if (!dep) + return; + + /* we'll submit tx->next now, so clear the link */ + txd_clear_next(tx); + chan = dep->chan; + + /* keep submitting up until a channel switch is detected + * in that case we will be called again as a result of + * processing the interrupt from async_tx_channel_switch + */ + for (; dep; dep = dep_next) { + txd_lock(dep); + txd_clear_parent(dep); + dep_next = txd_next(dep); + if (dep_next && dep_next->chan == chan) + txd_clear_next(dep); /* ->next will be submitted */ + else + dep_next = NULL; /* submit current dep and terminate */ + txd_unlock(dep); + + dep->tx_submit(dep); + } + + chan->device->device_issue_pending(chan); +} +EXPORT_SYMBOL_GPL(dma_run_dependencies); + +static int __init dma_bus_init(void) +{ + int err = dmaengine_init_unmap_pool(); + + if (err) + return err; + + err = class_register(&dma_devclass); + if (!err) + dmaengine_debugfs_init(); + + return err; +} +arch_initcall(dma_bus_init); diff --git a/snd-alpx-dkms/snd-alpx/core/generic/6.2/dmaengine.h b/snd-alpx-dkms/snd-alpx/core/generic/6.2/dmaengine.h new file mode 100644 index 0000000..53f16d3 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/core/generic/6.2/dmaengine.h @@ -0,0 +1,201 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * The contents of this file are private to DMA engine drivers, and is not + * part of the API to be used by DMA engine users. + */ +#ifndef DMAENGINE_H +#define DMAENGINE_H + +#include <linux/bug.h> +#include <linux/dmaengine.h> + +/** + * dma_cookie_init - initialize the cookies for a DMA channel + * @chan: dma channel to initialize + */ +static inline void dma_cookie_init(struct dma_chan *chan) +{ + chan->cookie = DMA_MIN_COOKIE; + chan->completed_cookie = DMA_MIN_COOKIE; +} + +/** + * dma_cookie_assign - assign a DMA engine cookie to the descriptor + * @tx: descriptor needing cookie + * + * Assign a unique non-zero per-channel cookie to the descriptor. + * Note: caller is expected to hold a lock to prevent concurrency. + */ +static inline dma_cookie_t dma_cookie_assign(struct dma_async_tx_descriptor *tx) +{ + struct dma_chan *chan = tx->chan; + dma_cookie_t cookie; + + cookie = chan->cookie + 1; + if (cookie < DMA_MIN_COOKIE) + cookie = DMA_MIN_COOKIE; + tx->cookie = chan->cookie = cookie; + + return cookie; +} + +/** + * dma_cookie_complete - complete a descriptor + * @tx: descriptor to complete + * + * Mark this descriptor complete by updating the channels completed + * cookie marker. Zero the descriptors cookie to prevent accidental + * repeated completions. + * + * Note: caller is expected to hold a lock to prevent concurrency. + */ +static inline void dma_cookie_complete(struct dma_async_tx_descriptor *tx) +{ + BUG_ON(tx->cookie < DMA_MIN_COOKIE); + tx->chan->completed_cookie = tx->cookie; + tx->cookie = 0; +} + +/** + * dma_cookie_status - report cookie status + * @chan: dma channel + * @cookie: cookie we are interested in + * @state: dma_tx_state structure to return last/used cookies + * + * Report the status of the cookie, filling in the state structure if + * non-NULL. No locking is required. + */ +static inline enum dma_status dma_cookie_status(struct dma_chan *chan, + dma_cookie_t cookie, struct dma_tx_state *state) +{ + dma_cookie_t used, complete; + + used = chan->cookie; + complete = chan->completed_cookie; + barrier(); + if (state) { + state->last = complete; + state->used = used; + state->residue = 0; + state->in_flight_bytes = 0; + } + return dma_async_is_complete(cookie, complete, used); +} + +static inline void dma_set_residue(struct dma_tx_state *state, u32 residue) +{ + if (state) + state->residue = residue; +} + +static inline void dma_set_in_flight_bytes(struct dma_tx_state *state, + u32 in_flight_bytes) +{ + if (state) + state->in_flight_bytes = in_flight_bytes; +} + +struct dmaengine_desc_callback { + dma_async_tx_callback callback; + dma_async_tx_callback_result callback_result; + void *callback_param; +}; + +/** + * dmaengine_desc_get_callback - get the passed in callback function + * @tx: tx descriptor + * @cb: temp struct to hold the callback info + * + * Fill the passed in cb struct with what's available in the passed in + * tx descriptor struct + * No locking is required. + */ +static inline void +dmaengine_desc_get_callback(struct dma_async_tx_descriptor *tx, + struct dmaengine_desc_callback *cb) +{ + cb->callback = tx->callback; + cb->callback_result = tx->callback_result; + cb->callback_param = tx->callback_param; +} + +/** + * dmaengine_desc_callback_invoke - call the callback function in cb struct + * @cb: temp struct that is holding the callback info + * @result: transaction result + * + * Call the callback function provided in the cb struct with the parameter + * in the cb struct. + * Locking is dependent on the driver. + */ +static inline void +dmaengine_desc_callback_invoke(struct dmaengine_desc_callback *cb, + const struct dmaengine_result *result) +{ + struct dmaengine_result dummy_result = { + .result = DMA_TRANS_NOERROR, + .residue = 0 + }; + + if (cb->callback_result) { + if (!result) + result = &dummy_result; + cb->callback_result(cb->callback_param, result); + } else if (cb->callback) { + cb->callback(cb->callback_param); + } +} + +/** + * dmaengine_desc_get_callback_invoke - get the callback in tx descriptor and + * then immediately call the callback. + * @tx: dma async tx descriptor + * @result: transaction result + * + * Call dmaengine_desc_get_callback() and dmaengine_desc_callback_invoke() + * in a single function since no work is necessary in between for the driver. + * Locking is dependent on the driver. + */ +static inline void +dmaengine_desc_get_callback_invoke(struct dma_async_tx_descriptor *tx, + const struct dmaengine_result *result) +{ + struct dmaengine_desc_callback cb; + + dmaengine_desc_get_callback(tx, &cb); + dmaengine_desc_callback_invoke(&cb, result); +} + +/** + * dmaengine_desc_callback_valid - verify the callback is valid in cb + * @cb: callback info struct + * + * Return a bool that verifies whether callback in cb is valid or not. + * No locking is required. + */ +static inline bool +dmaengine_desc_callback_valid(struct dmaengine_desc_callback *cb) +{ + return cb->callback || cb->callback_result; +} + +struct dma_chan *dma_get_slave_channel(struct dma_chan *chan); +struct dma_chan *dma_get_any_slave_channel(struct dma_device *device); + +#ifdef CONFIG_DEBUG_FS +#include <linux/debugfs.h> + +static inline struct dentry * +dmaengine_get_debugfs_root(struct dma_device *dma_dev) { + return dma_dev->dbg_dev_root; +} +#else +struct dentry; +static inline struct dentry * +dmaengine_get_debugfs_root(struct dma_device *dma_dev) +{ + return NULL; +} +#endif /* CONFIG_DEBUG_FS */ + +#endif diff --git a/snd-alpx-dkms/snd-alpx/core/generic/6.2/virt-dma.c b/snd-alpx-dkms/snd-alpx/core/generic/6.2/virt-dma.c new file mode 100644 index 0000000..a6f4265 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/core/generic/6.2/virt-dma.c @@ -0,0 +1,142 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Virtual DMA channel support for DMAengine + * + * Copyright (C) 2012 Russell King + */ +#include <linux/device.h> +#include <linux/dmaengine.h> +#include <linux/module.h> +#include <linux/spinlock.h> + +#include "virt-dma.h" + +static struct virt_dma_desc *to_virt_desc(struct dma_async_tx_descriptor *tx) +{ + return container_of(tx, struct virt_dma_desc, tx); +} + +dma_cookie_t vchan_tx_submit(struct dma_async_tx_descriptor *tx) +{ + struct virt_dma_chan *vc = to_virt_chan(tx->chan); + struct virt_dma_desc *vd = to_virt_desc(tx); + unsigned long flags; + dma_cookie_t cookie; + + spin_lock_irqsave(&vc->lock, flags); + cookie = dma_cookie_assign(tx); + + list_move_tail(&vd->node, &vc->desc_submitted); + spin_unlock_irqrestore(&vc->lock, flags); + + dev_dbg(vc->chan.device->dev, "vchan %p: txd %p[%x]: submitted\n", + vc, vd, cookie); + + return cookie; +} +EXPORT_SYMBOL_GPL(vchan_tx_submit); + +/** + * vchan_tx_desc_free - free a reusable descriptor + * @tx: the transfer + * + * This function frees a previously allocated reusable descriptor. The only + * other way is to clear the DMA_CTRL_REUSE flag and submit one last time the + * transfer. + * + * Returns 0 upon success + */ +int vchan_tx_desc_free(struct dma_async_tx_descriptor *tx) +{ + struct virt_dma_chan *vc = to_virt_chan(tx->chan); + struct virt_dma_desc *vd = to_virt_desc(tx); + unsigned long flags; + + spin_lock_irqsave(&vc->lock, flags); + list_del(&vd->node); + spin_unlock_irqrestore(&vc->lock, flags); + + dev_dbg(vc->chan.device->dev, "vchan %p: txd %p[%x]: freeing\n", + vc, vd, vd->tx.cookie); + vc->desc_free(vd); + return 0; +} +EXPORT_SYMBOL_GPL(vchan_tx_desc_free); + +struct virt_dma_desc *vchan_find_desc(struct virt_dma_chan *vc, + dma_cookie_t cookie) +{ + struct virt_dma_desc *vd; + + list_for_each_entry(vd, &vc->desc_issued, node) + if (vd->tx.cookie == cookie) + return vd; + + return NULL; +} +EXPORT_SYMBOL_GPL(vchan_find_desc); + +/* + * This tasklet handles the completion of a DMA descriptor by + * calling its callback and freeing it. + */ +static void vchan_complete(struct tasklet_struct *t) +{ + struct virt_dma_chan *vc = from_tasklet(vc, t, task); + struct virt_dma_desc *vd, *_vd; + struct dmaengine_desc_callback cb; + LIST_HEAD(head); + + spin_lock_irq(&vc->lock); + list_splice_tail_init(&vc->desc_completed, &head); + vd = vc->cyclic; + if (vd) { + vc->cyclic = NULL; + dmaengine_desc_get_callback(&vd->tx, &cb); + } else { + memset(&cb, 0, sizeof(cb)); + } + spin_unlock_irq(&vc->lock); + + dmaengine_desc_callback_invoke(&cb, &vd->tx_result); + + list_for_each_entry_safe(vd, _vd, &head, node) { + dmaengine_desc_get_callback(&vd->tx, &cb); + + list_del(&vd->node); + dmaengine_desc_callback_invoke(&cb, &vd->tx_result); + vchan_vdesc_fini(vd); + } +} + +void vchan_dma_desc_free_list(struct virt_dma_chan *vc, struct list_head *head) +{ + struct virt_dma_desc *vd, *_vd; + + list_for_each_entry_safe(vd, _vd, head, node) { + list_del(&vd->node); + vchan_vdesc_fini(vd); + } +} +EXPORT_SYMBOL_GPL(vchan_dma_desc_free_list); + +void vchan_init(struct virt_dma_chan *vc, struct dma_device *dmadev) +{ + dma_cookie_init(&vc->chan); + + spin_lock_init(&vc->lock); + INIT_LIST_HEAD(&vc->desc_allocated); + INIT_LIST_HEAD(&vc->desc_submitted); + INIT_LIST_HEAD(&vc->desc_issued); + INIT_LIST_HEAD(&vc->desc_completed); + INIT_LIST_HEAD(&vc->desc_terminated); + + tasklet_setup(&vc->task, vchan_complete); + + vc->chan.device = dmadev; + list_add_tail(&vc->chan.device_node, &dmadev->channels); +} +EXPORT_SYMBOL_GPL(vchan_init); + +MODULE_AUTHOR("Russell King"); +MODULE_LICENSE("GPL"); diff --git a/snd-alpx-dkms/snd-alpx/core/generic/6.2/virt-dma.h b/snd-alpx-dkms/snd-alpx/core/generic/6.2/virt-dma.h new file mode 100644 index 0000000..e9f5250 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/core/generic/6.2/virt-dma.h @@ -0,0 +1,227 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Virtual DMA channel support for DMAengine + * + * Copyright (C) 2012 Russell King + */ +#ifndef VIRT_DMA_H +#define VIRT_DMA_H + +#include <linux/dmaengine.h> +#include <linux/interrupt.h> + +#include "dmaengine.h" + +struct virt_dma_desc { + struct dma_async_tx_descriptor tx; + struct dmaengine_result tx_result; + /* protected by vc.lock */ + struct list_head node; +}; + +struct virt_dma_chan { + struct dma_chan chan; + struct tasklet_struct task; + void (*desc_free)(struct virt_dma_desc *); + + spinlock_t lock; + + /* protected by vc.lock */ + struct list_head desc_allocated; + struct list_head desc_submitted; + struct list_head desc_issued; + struct list_head desc_completed; + struct list_head desc_terminated; + + struct virt_dma_desc *cyclic; +}; + +static inline struct virt_dma_chan *to_virt_chan(struct dma_chan *chan) +{ + return container_of(chan, struct virt_dma_chan, chan); +} + +void vchan_dma_desc_free_list(struct virt_dma_chan *vc, struct list_head *head); +void vchan_init(struct virt_dma_chan *vc, struct dma_device *dmadev); +struct virt_dma_desc *vchan_find_desc(struct virt_dma_chan *, dma_cookie_t); +extern dma_cookie_t vchan_tx_submit(struct dma_async_tx_descriptor *); +extern int vchan_tx_desc_free(struct dma_async_tx_descriptor *); + +/** + * vchan_tx_prep - prepare a descriptor + * @vc: virtual channel allocating this descriptor + * @vd: virtual descriptor to prepare + * @tx_flags: flags argument passed in to prepare function + */ +static inline struct dma_async_tx_descriptor *vchan_tx_prep(struct virt_dma_chan *vc, + struct virt_dma_desc *vd, unsigned long tx_flags) +{ + unsigned long flags; + + dma_async_tx_descriptor_init(&vd->tx, &vc->chan); + vd->tx.flags = tx_flags; + vd->tx.tx_submit = vchan_tx_submit; + vd->tx.desc_free = vchan_tx_desc_free; + + vd->tx_result.result = DMA_TRANS_NOERROR; + vd->tx_result.residue = 0; + + spin_lock_irqsave(&vc->lock, flags); + list_add_tail(&vd->node, &vc->desc_allocated); + spin_unlock_irqrestore(&vc->lock, flags); + + return &vd->tx; +} + +/** + * vchan_issue_pending - move submitted descriptors to issued list + * @vc: virtual channel to update + * + * vc.lock must be held by caller + */ +static inline bool vchan_issue_pending(struct virt_dma_chan *vc) +{ + list_splice_tail_init(&vc->desc_submitted, &vc->desc_issued); + return !list_empty(&vc->desc_issued); +} + +/** + * vchan_cookie_complete - report completion of a descriptor + * @vd: virtual descriptor to update + * + * vc.lock must be held by caller + */ +static inline void vchan_cookie_complete(struct virt_dma_desc *vd) +{ + struct virt_dma_chan *vc = to_virt_chan(vd->tx.chan); + dma_cookie_t cookie; + + cookie = vd->tx.cookie; + dma_cookie_complete(&vd->tx); + dev_vdbg(vc->chan.device->dev, "txd %p[%x]: marked complete\n", + vd, cookie); + list_add_tail(&vd->node, &vc->desc_completed); + + tasklet_schedule(&vc->task); +} + +/** + * vchan_vdesc_fini - Free or reuse a descriptor + * @vd: virtual descriptor to free/reuse + */ +static inline void vchan_vdesc_fini(struct virt_dma_desc *vd) +{ + struct virt_dma_chan *vc = to_virt_chan(vd->tx.chan); + + if (dmaengine_desc_test_reuse(&vd->tx)) { + unsigned long flags; + + spin_lock_irqsave(&vc->lock, flags); + list_add(&vd->node, &vc->desc_allocated); + spin_unlock_irqrestore(&vc->lock, flags); + } else { + vc->desc_free(vd); + } +} + +/** + * vchan_cyclic_callback - report the completion of a period + * @vd: virtual descriptor + */ +static inline void vchan_cyclic_callback(struct virt_dma_desc *vd) +{ + struct virt_dma_chan *vc = to_virt_chan(vd->tx.chan); + + vc->cyclic = vd; + tasklet_schedule(&vc->task); +} + +/** + * vchan_terminate_vdesc - Disable pending cyclic callback + * @vd: virtual descriptor to be terminated + * + * vc.lock must be held by caller + */ +static inline void vchan_terminate_vdesc(struct virt_dma_desc *vd) +{ + struct virt_dma_chan *vc = to_virt_chan(vd->tx.chan); + + list_add_tail(&vd->node, &vc->desc_terminated); + + if (vc->cyclic == vd) + vc->cyclic = NULL; +} + +/** + * vchan_next_desc - peek at the next descriptor to be processed + * @vc: virtual channel to obtain descriptor from + * + * vc.lock must be held by caller + */ +static inline struct virt_dma_desc *vchan_next_desc(struct virt_dma_chan *vc) +{ + return list_first_entry_or_null(&vc->desc_issued, + struct virt_dma_desc, node); +} + +/** + * vchan_get_all_descriptors - obtain all submitted and issued descriptors + * @vc: virtual channel to get descriptors from + * @head: list of descriptors found + * + * vc.lock must be held by caller + * + * Removes all submitted and issued descriptors from internal lists, and + * provides a list of all descriptors found + */ +static inline void vchan_get_all_descriptors(struct virt_dma_chan *vc, + struct list_head *head) +{ + list_splice_tail_init(&vc->desc_allocated, head); + list_splice_tail_init(&vc->desc_submitted, head); + list_splice_tail_init(&vc->desc_issued, head); + list_splice_tail_init(&vc->desc_completed, head); + list_splice_tail_init(&vc->desc_terminated, head); +} + +static inline void vchan_free_chan_resources(struct virt_dma_chan *vc) +{ + struct virt_dma_desc *vd; + unsigned long flags; + LIST_HEAD(head); + + spin_lock_irqsave(&vc->lock, flags); + vchan_get_all_descriptors(vc, &head); + list_for_each_entry(vd, &head, node) + dmaengine_desc_clear_reuse(&vd->tx); + spin_unlock_irqrestore(&vc->lock, flags); + + vchan_dma_desc_free_list(vc, &head); +} + +/** + * vchan_synchronize() - synchronize callback execution to the current context + * @vc: virtual channel to synchronize + * + * Makes sure that all scheduled or active callbacks have finished running. For + * proper operation the caller has to ensure that no new callbacks are scheduled + * after the invocation of this function started. + * Free up the terminated cyclic descriptor to prevent memory leakage. + */ +static inline void vchan_synchronize(struct virt_dma_chan *vc) +{ + LIST_HEAD(head); + unsigned long flags; + + tasklet_kill(&vc->task); + + spin_lock_irqsave(&vc->lock, flags); + + list_splice_tail_init(&vc->desc_terminated, &head); + + spin_unlock_irqrestore(&vc->lock, flags); + + vchan_dma_desc_free_list(vc, &head); +} + +#endif diff --git a/snd-alpx-dkms/snd-alpx/core/generic/6.2/xilinx/xdma-regs.h b/snd-alpx-dkms/snd-alpx/core/generic/6.2/xilinx/xdma-regs.h new file mode 100644 index 0000000..4ee96de --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/core/generic/6.2/xilinx/xdma-regs.h @@ -0,0 +1,169 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2017-2020 Xilinx, Inc. All rights reserved. + * Copyright (C) 2022, Advanced Micro Devices, Inc. + */ + +#ifndef __DMA_XDMA_REGS_H +#define __DMA_XDMA_REGS_H + +/* The length of register space exposed to host */ +#define XDMA_REG_SPACE_LEN 65536 + +/* + * maximum number of DMA channels for each direction: + * Host to Card (H2C) or Card to Host (C2H) + */ +#define XDMA_MAX_CHANNELS 4 + +/* + * macros to define the number of descriptor blocks can be used in one + * DMA transfer request. + * the DMA engine uses a linked list of descriptor blocks that specify the + * source, destination, and length of the DMA transfers. + */ +#define XDMA_DESC_BLOCK_NUM BIT(7) +#define XDMA_DESC_BLOCK_MASK (XDMA_DESC_BLOCK_NUM - 1) + +/* descriptor definitions */ +#define XDMA_DESC_ADJACENT 32 +#define XDMA_DESC_ADJACENT_MASK (XDMA_DESC_ADJACENT - 1) +#define XDMA_DESC_ADJACENT_BITS GENMASK(13, 8) +#define XDMA_DESC_MAGIC 0xad4bUL +#define XDMA_DESC_MAGIC_BITS GENMASK(31, 16) +#define XDMA_DESC_FLAGS_BITS GENMASK(7, 0) +#define XDMA_DESC_STOPPED BIT(0) +#define XDMA_DESC_COMPLETED BIT(1) +#define XDMA_DESC_BLEN_BITS 28 +#define XDMA_DESC_BLEN_MAX (BIT(XDMA_DESC_BLEN_BITS) - PAGE_SIZE) + +/* macros to construct the descriptor control word */ +#define XDMA_DESC_CONTROL(adjacent, flag) \ + (FIELD_PREP(XDMA_DESC_MAGIC_BITS, XDMA_DESC_MAGIC) | \ + FIELD_PREP(XDMA_DESC_ADJACENT_BITS, (adjacent) - 1) | \ + FIELD_PREP(XDMA_DESC_FLAGS_BITS, (flag))) +#define XDMA_DESC_CONTROL_LAST \ + XDMA_DESC_CONTROL(1, XDMA_DESC_STOPPED | XDMA_DESC_COMPLETED) +#define XDMA_DESC_CONTROL_CYCLIC \ + XDMA_DESC_CONTROL(1, XDMA_DESC_COMPLETED) + +/* + * Descriptor for a single contiguous memory block transfer. + * + * Multiple descriptors are linked by means of the next pointer. An additional + * extra adjacent number gives the amount of extra contiguous descriptors. + * + * The descriptors are in root complex memory, and the bytes in the 32-bit + * words must be in little-endian byte ordering. + */ +struct xdma_hw_desc { + __le32 control; + __le32 bytes; + __le64 src_addr; + __le64 dst_addr; + __le64 next_desc; +}; + +#define XDMA_DESC_SIZE sizeof(struct xdma_hw_desc) +#define XDMA_DESC_BLOCK_SIZE (XDMA_DESC_SIZE * XDMA_DESC_ADJACENT) +#define XDMA_DESC_BLOCK_ALIGN 32 +#define XDMA_DESC_BLOCK_BOUNDARY 4096 + +/* + * Channel registers + */ +#define XDMA_CHAN_IDENTIFIER 0x0 +#define XDMA_CHAN_CONTROL 0x4 +#define XDMA_CHAN_CONTROL_W1S 0x8 +#define XDMA_CHAN_CONTROL_W1C 0xc +#define XDMA_CHAN_STATUS 0x40 +#define XDMA_CHAN_STATUS_RC 0x44 +#define XDMA_CHAN_COMPLETED_DESC 0x48 +#define XDMA_CHAN_ALIGNMENTS 0x4c +#define XDMA_CHAN_INTR_ENABLE 0x90 +#define XDMA_CHAN_INTR_ENABLE_W1S 0x94 +#define XDMA_CHAN_INTR_ENABLE_W1C 0x9c + +#define XDMA_CHAN_STRIDE 0x100 +#define XDMA_CHAN_H2C_OFFSET 0x0 +#define XDMA_CHAN_C2H_OFFSET 0x1000 +#define XDMA_CHAN_H2C_TARGET 0x0 +#define XDMA_CHAN_C2H_TARGET 0x1 + +/* macro to check if channel is available */ +#define XDMA_CHAN_MAGIC 0x1fc0 +#define XDMA_CHAN_CHECK_TARGET(id, target) \ + (((u32)(id) >> 16) == XDMA_CHAN_MAGIC + (target)) + +/* bits of the channel control register */ +#define CHAN_CTRL_RUN_STOP BIT(0) +#define CHAN_CTRL_IE_DESC_STOPPED BIT(1) +#define CHAN_CTRL_IE_DESC_COMPLETED BIT(2) +#define CHAN_CTRL_IE_DESC_ALIGN_MISMATCH BIT(3) +#define CHAN_CTRL_IE_MAGIC_STOPPED BIT(4) +#define CHAN_CTRL_IE_IDLE_STOPPED BIT(6) +#define CHAN_CTRL_IE_READ_ERROR GENMASK(13, 9) +#define CHAN_CTRL_IE_WRITE_ERROR GENMASK(18, 14) +#define CHAN_CTRL_IE_DESC_ERROR GENMASK(23, 19) +#define CHAN_CTRL_NON_INCR_ADDR BIT(25) +#define CHAN_CTRL_POLL_MODE_WB BIT(26) +#define CHAN_CTRL_TRANSFER_INFO_WB BIT(27) + +#define CHAN_CTRL_START (CHAN_CTRL_RUN_STOP | \ + CHAN_CTRL_IE_DESC_STOPPED | \ + CHAN_CTRL_IE_DESC_COMPLETED | \ + CHAN_CTRL_IE_DESC_ALIGN_MISMATCH | \ + CHAN_CTRL_IE_MAGIC_STOPPED | \ + CHAN_CTRL_IE_READ_ERROR | \ + CHAN_CTRL_IE_WRITE_ERROR | \ + CHAN_CTRL_IE_DESC_ERROR) + +#define XDMA_CHAN_STATUS_MASK CHAN_CTRL_START + +#define XDMA_CHAN_ERROR_MASK (CHAN_CTRL_IE_DESC_ALIGN_MISMATCH | \ + CHAN_CTRL_IE_MAGIC_STOPPED | \ + CHAN_CTRL_IE_READ_ERROR | \ + CHAN_CTRL_IE_WRITE_ERROR | \ + CHAN_CTRL_IE_DESC_ERROR) + +/* bits of the channel interrupt enable mask */ +#define CHAN_IM_DESC_ERROR BIT(19) +#define CHAN_IM_READ_ERROR BIT(9) +#define CHAN_IM_IDLE_STOPPED BIT(6) +#define CHAN_IM_MAGIC_STOPPED BIT(4) +#define CHAN_IM_DESC_COMPLETED BIT(2) +#define CHAN_IM_DESC_STOPPED BIT(1) + +#define CHAN_IM_ALL (CHAN_IM_DESC_ERROR | CHAN_IM_READ_ERROR | \ + CHAN_IM_IDLE_STOPPED | CHAN_IM_MAGIC_STOPPED | \ + CHAN_IM_DESC_COMPLETED | CHAN_IM_DESC_STOPPED) + +/* + * Channel SGDMA registers + */ +#define XDMA_SGDMA_IDENTIFIER 0x4000 +#define XDMA_SGDMA_DESC_LO 0x4080 +#define XDMA_SGDMA_DESC_HI 0x4084 +#define XDMA_SGDMA_DESC_ADJ 0x4088 +#define XDMA_SGDMA_DESC_CREDIT 0x408c + +/* + * interrupt registers + */ +#define XDMA_IRQ_IDENTIFIER 0x2000 +#define XDMA_IRQ_USER_INT_EN 0x2004 +#define XDMA_IRQ_USER_INT_EN_W1S 0x2008 +#define XDMA_IRQ_USER_INT_EN_W1C 0x200c +#define XDMA_IRQ_CHAN_INT_EN 0x2010 +#define XDMA_IRQ_CHAN_INT_EN_W1S 0x2014 +#define XDMA_IRQ_CHAN_INT_EN_W1C 0x2018 +#define XDMA_IRQ_USER_INT_REQ 0x2040 +#define XDMA_IRQ_CHAN_INT_REQ 0x2044 +#define XDMA_IRQ_USER_INT_PEND 0x2048 +#define XDMA_IRQ_CHAN_INT_PEND 0x204c +#define XDMA_IRQ_USER_VEC_NUM 0x2080 +#define XDMA_IRQ_CHAN_VEC_NUM 0x20a0 + +#define XDMA_IRQ_VEC_SHIFT 8 + +#endif /* __DMA_XDMA_REGS_H */ diff --git a/snd-alpx-dkms/snd-alpx/core/generic/6.2/xilinx/xdma.c b/snd-alpx-dkms/snd-alpx/core/generic/6.2/xilinx/xdma.c new file mode 100644 index 0000000..6c89145 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/core/generic/6.2/xilinx/xdma.c @@ -0,0 +1,1437 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * DMA driver for Xilinx DMA/Bridge Subsystem + * + * Copyright (C) 2017-2020 Xilinx, Inc. All rights reserved. + * Copyright (C) 2022, Advanced Micro Devices, Inc. + */ + +/* + * The DMA/Bridge Subsystem for PCI Express allows for the movement of data + * between Host memory and the DMA subsystem. It does this by operating on + * 'descriptors' that contain information about the source, destination and + * amount of data to transfer. These direct memory transfers can be both in + * the Host to Card (H2C) and Card to Host (C2H) transfers. The DMA can be + * configured to have a single AXI4 Master interface shared by all channels + * or one AXI4-Stream interface for each channel enabled. Memory transfers are + * specified on a per-channel basis in descriptor linked lists, which the DMA + * fetches from host memory and processes. Events such as descriptor completion + * and errors are signaled using interrupts. The core also provides up to 16 + * user interrupt wires that generate interrupts to the host. + */ + +#include <linux/module.h> +#include <linux/mod_devicetable.h> +#include <linux/bitfield.h> +#include <linux/dmapool.h> + +#include <linux/regmap.h> + +#if defined (CONFIG_KERNEL_REDHAT) + #warning REDHAT Kernel + #if KERNEL_VERSION(5, 19, 0) <= LINUX_VERSION_CODE + /* Use Generic include */ + #include "../../../../include/5.6/virt-dma.h" + #elif KERNEL_VERSION(4, 18, 0) <= LINUX_VERSION_CODE + /* Use Generic include : files equal !! */ + #warning ReadHat 4.18 at least + #include "../../../../include/5.6/virt-dma.h" + #else + #error Redhat kernel NOT Supported + #endif + +#else + /* Generic Kernels */ + #warning "Generic Kernels" + #if KERNEL_VERSION(6, 3, 0) <= LINUX_VERSION_CODE + #include "../virt-dma.h" + #elif KERNEL_VERSION(5, 6, 0) <= LINUX_VERSION_CODE + #include "../../../../include/5.6/virt-dma.h" + #elif KERNEL_VERSION(5, 3, 0) <= LINUX_VERSION_CODE + #include "../../../../include/5.3/virt-dma.h" + #else + #include "../../../../include/4.16/virt-dma.h" + #endif + +#endif + + +#if KERNEL_VERSION(5, 6, 0) <= LINUX_VERSION_CODE +#include <linux/dmaengine.h> +#elif KERNEL_VERSION(5, 3, 0) <= LINUX_VERSION_CODE +#include "../../../../include/5.3/dmaengine.h" +#else +#include "../../../../include/4.16/dmaengine.h" +#endif + +#include "../../../../include/6.2/amd_xdma.h" +#include <linux/platform_device.h> +#include "../amd_xdma.h" +#include <linux/dma-mapping.h> +#include <linux/pci.h> + +#include "xdma-regs.h" + +/* mmio regmap config for all XDMA registers */ +static const struct regmap_config xdma_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = XDMA_REG_SPACE_LEN, +}; + +/** + * struct xdma_desc_block - Descriptor block + * @virt_addr: Virtual address of block start + * @dma_addr: DMA address of block start + */ +struct xdma_desc_block { + void *virt_addr; + dma_addr_t dma_addr; +}; + +/** + * struct xdma_c2h_write_back - Write back block , written by the XDMA. + * @magic_status_bit : magic (0x52B4) once written + * @length: effective transfer length (in bytes) + * @PADDING to be aligned on 32 bytes + * @associated dma address + */ +struct xdma_c2h_write_back { + __le32 magic_status_bit; + __le32 length; + u32 padding_1[6]; + dma_addr_t dma_addr; +}; + +/** + * struct xdma_chan - Driver specific DMA channel structure + * @vchan: Virtual channel + * @xdev_hdl: Pointer to DMA device structure + * @base: Offset of channel registers + * @desc_pool: Descriptor pool + * @busy: Busy flag of the channel + * @dir: Transferring direction of the channel + * @cfg: Transferring config of the channel + * @irq: IRQ assigned to the channel + * @write_back : C2H meta data write back + */ +struct xdma_chan { + struct virt_dma_chan vchan; + void *xdev_hdl; + u32 base; + struct dma_pool *desc_pool; + bool busy; + enum dma_transfer_direction dir; + struct dma_slave_config cfg; + u32 irq; + struct xdma_c2h_write_back* write_back; +}; + +/** + * struct xdma_desc - DMA desc structure + * @vdesc: Virtual DMA descriptor + * @chan: DMA channel pointer + * @dir: Transferring direction of the request + * @desc_blocks: Hardware descriptor blocks + * @dblk_num: Number of hardware descriptor blocks + * @desc_num: Number of hardware descriptors + * @completed_desc_num: Completed hardware descriptors + * @cyclic: Cyclic transfer vs. scatter-gather + * @interleaved_dma: Interleaved DMA transfer + * @periods: Number of periods in the cyclic transfer + * @period_size: Size of a period in bytes in cyclic transfers + * @frames_left: Number of frames left in interleaved DMA transfer + * @error: tx error flag + */ +struct xdma_desc { + struct virt_dma_desc vdesc; + struct xdma_chan *chan; + enum dma_transfer_direction dir; + struct xdma_desc_block *desc_blocks; + u32 dblk_num; + u32 desc_num; + u32 completed_desc_num; + bool cyclic; + bool interleaved_dma; + u32 periods; + u32 period_size; + u32 frames_left; + bool error; +}; + +#define XDMA_DEV_STATUS_REG_DMA BIT(0) +#define XDMA_DEV_STATUS_INIT_MSIX BIT(1) + +/** + * struct xdma_device - DMA device structure + * @pdev: Platform device pointer + * @dma_dev: DMA device structure + * @rmap: MMIO regmap for DMA registers + * @h2c_chans: Host to Card channels + * @c2h_chans: Card to Host channels + * @h2c_chan_num: Number of H2C channels + * @c2h_chan_num: Number of C2H channels + * @irq_start: Start IRQ assigned to device + * @irq_num: Number of IRQ assigned to device + * @status: Initialization status + */ +struct xdma_device { + struct platform_device *pdev; + struct dma_device dma_dev; + struct regmap *rmap; + struct xdma_chan *h2c_chans; + struct xdma_chan *c2h_chans; + u32 h2c_chan_num; + u32 c2h_chan_num; + u32 irq_start; + u32 irq_num; + u32 status; +}; + +#define xdma_err(xdev, fmt, args...) \ + dev_err(&(xdev)->pdev->dev, fmt, ##args) +#define XDMA_CHAN_NUM(_xd) ({ \ + typeof(_xd) (xd) = (_xd); \ + ((xd)->h2c_chan_num + (xd)->c2h_chan_num); }) + +/* Get the last desc in a desc block */ +static inline void *xdma_blk_last_desc(struct xdma_desc_block *block) +{ + return block->virt_addr + (XDMA_DESC_ADJACENT - 1) * XDMA_DESC_SIZE; +} + +/** + * xdma_link_sg_desc_blocks - Link SG descriptor blocks for DMA transfer + * @sw_desc: Tx descriptor pointer + */ +static void xdma_link_sg_desc_blocks(struct xdma_desc *sw_desc) +{ + struct xdma_desc_block *block; + u32 last_blk_desc, desc_control; + struct xdma_hw_desc *desc; + int i; + + desc_control = XDMA_DESC_CONTROL(XDMA_DESC_ADJACENT, 0); + for (i = 1; i < sw_desc->dblk_num; i++) { + block = &sw_desc->desc_blocks[i - 1]; + desc = xdma_blk_last_desc(block); + + if (!(i & XDMA_DESC_BLOCK_MASK)) { + desc->control = cpu_to_le32(XDMA_DESC_CONTROL_LAST); + continue; + } + desc->control = cpu_to_le32(desc_control); + desc->next_desc = cpu_to_le64(block[1].dma_addr); + } + + /* update the last block */ + last_blk_desc = (sw_desc->desc_num - 1) & XDMA_DESC_ADJACENT_MASK; + if (((sw_desc->dblk_num - 1) & XDMA_DESC_BLOCK_MASK) > 0) { + block = &sw_desc->desc_blocks[sw_desc->dblk_num - 2]; + desc = xdma_blk_last_desc(block); + desc_control = XDMA_DESC_CONTROL(last_blk_desc + 1, 0); + desc->control = cpu_to_le32(desc_control); + } + + block = &sw_desc->desc_blocks[sw_desc->dblk_num - 1]; + desc = block->virt_addr + last_blk_desc * XDMA_DESC_SIZE; + desc->control = cpu_to_le32(XDMA_DESC_CONTROL_LAST); +} + +/** + * xdma_link_cyclic_desc_blocks - Link cyclic descriptor blocks for DMA transfer + * @sw_desc: Tx descriptor pointer + */ +static void xdma_link_cyclic_desc_blocks(struct xdma_desc *sw_desc) +{ + struct xdma_desc_block *block; + struct xdma_hw_desc *desc; + int i; + + block = sw_desc->desc_blocks; + for (i = 0; i < sw_desc->desc_num - 1; i++) { + desc = block->virt_addr + i * XDMA_DESC_SIZE; + desc->next_desc = cpu_to_le64(block->dma_addr + ((i + 1) * XDMA_DESC_SIZE)); + } + desc = block->virt_addr + i * XDMA_DESC_SIZE; + desc->next_desc = cpu_to_le64(block->dma_addr); +} + +static inline struct xdma_chan *to_xdma_chan(struct dma_chan *chan) +{ + return container_of(chan, struct xdma_chan, vchan.chan); +} + +static inline struct xdma_desc *to_xdma_desc(struct virt_dma_desc *vdesc) +{ + return container_of(vdesc, struct xdma_desc, vdesc); +} + +/** + * xdma_channel_init - Initialize DMA channel registers + * @chan: DMA channel pointer + */ +static int xdma_channel_init(struct xdma_chan *chan) +{ + struct xdma_device *xdev = chan->xdev_hdl; + int ret; + unsigned int reg_ctrl = 0; + + regmap_read(xdev->rmap, chan->base + XDMA_CHAN_CONTROL, ®_ctrl); + dev_dbg(&xdev->pdev->dev, "CONTROL Init: 0x%08x\n", reg_ctrl); + + ret = regmap_write(xdev->rmap, chan->base + XDMA_CHAN_CONTROL_W1C, + CHAN_CTRL_NON_INCR_ADDR | CHAN_CTRL_TRANSFER_INFO_WB); + if (ret) + return ret; + + regmap_read(xdev->rmap, chan->base + XDMA_CHAN_CONTROL, ®_ctrl); + dev_dbg(&xdev->pdev->dev, "CONTROL Init: 0x%08x\n", reg_ctrl); + + ret = regmap_write(xdev->rmap, chan->base + XDMA_CHAN_INTR_ENABLE, + CHAN_IM_ALL); + if (ret) + return ret; + + return 0; +} + +/** + * xdma_free_desc - Free descriptor + * @vdesc: Virtual DMA descriptor + */ +static void xdma_free_desc(struct virt_dma_desc *vdesc) +{ + struct xdma_desc *sw_desc; + int i; + + sw_desc = to_xdma_desc(vdesc); + for (i = 0; i < sw_desc->dblk_num; i++) { + if (!sw_desc->desc_blocks[i].virt_addr) + break; + dma_pool_free(sw_desc->chan->desc_pool, + sw_desc->desc_blocks[i].virt_addr, + sw_desc->desc_blocks[i].dma_addr); + } + kfree(sw_desc->desc_blocks); + kfree(sw_desc); +} + +/** + * xdma_alloc_desc - Allocate descriptor + * @chan: DMA channel pointer + * @desc_num: Number of hardware descriptors + * @cyclic: Whether this is a cyclic transfer + */ +static struct xdma_desc * +xdma_alloc_desc(struct xdma_chan *chan, u32 desc_num, bool cyclic) +{ + struct xdma_desc *sw_desc; + struct xdma_hw_desc *desc; + dma_addr_t dma_addr; + u32 dblk_num; + u32 control; + void *addr; + int i, j; + + sw_desc = kzalloc(sizeof(*sw_desc), GFP_NOWAIT); + if (!sw_desc) + return NULL; + + sw_desc->chan = chan; + sw_desc->desc_num = desc_num; + sw_desc->cyclic = cyclic; + sw_desc->error = false; + dblk_num = DIV_ROUND_UP(desc_num, XDMA_DESC_ADJACENT); + sw_desc->desc_blocks = kcalloc(dblk_num, sizeof(*sw_desc->desc_blocks), + GFP_NOWAIT); + if (!sw_desc->desc_blocks) + goto failed; + + if (cyclic) + control = XDMA_DESC_CONTROL_CYCLIC; + else + control = XDMA_DESC_CONTROL(1, 0); + + sw_desc->dblk_num = dblk_num; + for (i = 0; i < sw_desc->dblk_num; i++) { + addr = dma_pool_alloc(chan->desc_pool, GFP_NOWAIT, &dma_addr); + if (!addr) + goto failed; + + sw_desc->desc_blocks[i].virt_addr = addr; + sw_desc->desc_blocks[i].dma_addr = dma_addr; + for (j = 0, desc = addr; j < XDMA_DESC_ADJACENT; j++) + desc[j].control = cpu_to_le32(control); + } + + if (cyclic) + xdma_link_cyclic_desc_blocks(sw_desc); + else + xdma_link_sg_desc_blocks(sw_desc); + + return sw_desc; + +failed: + xdma_free_desc(&sw_desc->vdesc); + return NULL; +} + +/** + * xdma_xfer_start - Start DMA transfer + * @xchan: DMA channel pointer + */ +static int xdma_xfer_start(struct xdma_chan *xchan) +{ + struct virt_dma_desc *vd = vchan_next_desc(&xchan->vchan); + struct xdma_device *xdev = xchan->xdev_hdl; + struct xdma_desc_block *block; + u32 val, completed_blocks; + struct xdma_desc *desc; + int ret; + + /* + * check if there is not any submitted descriptor or channel is busy. + * vchan lock should be held where this function is called. + */ + if (!vd || xchan->busy) + return -EINVAL; + + /* clear run stop bit to get ready for transfer */ + ret = regmap_write(xdev->rmap, xchan->base + XDMA_CHAN_CONTROL_W1C, + CHAN_CTRL_RUN_STOP); + if (ret) + return ret; + + desc = to_xdma_desc(vd); + if (desc->dir != xchan->dir) { + xdma_err(xdev, "incorrect request direction"); + return -EINVAL; + } + + /* set DMA engine to the first descriptor block */ + completed_blocks = desc->completed_desc_num / XDMA_DESC_ADJACENT; + block = &desc->desc_blocks[completed_blocks]; + val = lower_32_bits(block->dma_addr); + ret = regmap_write(xdev->rmap, xchan->base + XDMA_SGDMA_DESC_LO, val); + if (ret) + return ret; + + val = upper_32_bits(block->dma_addr); + ret = regmap_write(xdev->rmap, xchan->base + XDMA_SGDMA_DESC_HI, val); + if (ret) + return ret; + + if (completed_blocks + 1 == desc->dblk_num) + val = (desc->desc_num - 1) & XDMA_DESC_ADJACENT_MASK; + else + val = XDMA_DESC_ADJACENT - 1; + ret = regmap_write(xdev->rmap, xchan->base + XDMA_SGDMA_DESC_ADJ, val); + if (ret) + return ret; + + /* kick off DMA transfer, force 0=1 transition, USE Bit clear/set registers */ + + regmap_write(xdev->rmap, xchan->base + XDMA_CHAN_CONTROL_W1C, + CHAN_CTRL_START); + + ret = regmap_write(xdev->rmap, xchan->base + XDMA_CHAN_CONTROL_W1S, + CHAN_CTRL_START); + if (ret) + return ret; + + xchan->busy = true; + + return 0; +} + +/** + * xdma_xfer_stop - Stop DMA transfer + * @xchan: DMA channel pointer + */ +static int xdma_xfer_stop(struct xdma_chan *xchan) +{ + int ret; + u32 val; + struct xdma_device *xdev = xchan->xdev_hdl; + + /* clear run stop bit to prevent any further auto-triggering */ + ret = regmap_write(xdev->rmap, xchan->base + XDMA_CHAN_CONTROL_W1C, + CHAN_CTRL_RUN_STOP); + if (ret) + return ret; + + /* Clear the channel status register */ + ret = regmap_read(xdev->rmap, xchan->base + XDMA_CHAN_STATUS_RC, &val); + if (ret) + return ret; + + return 0; +} + +/** + * xdma_alloc_channels - Detect and allocate DMA channels + * @xdev: DMA device pointer + * @dir: Channel direction + */ +static int xdma_alloc_channels(struct xdma_device *xdev, + enum dma_transfer_direction dir) +{ + struct xdma_platdata *pdata = dev_get_platdata(&xdev->pdev->dev); + struct xdma_chan **chans, *xchan; + u32 base, identifier, target; + u32 *chan_num; + int i, j, ret; + + if (dir == DMA_MEM_TO_DEV) { + base = XDMA_CHAN_H2C_OFFSET; + target = XDMA_CHAN_H2C_TARGET; + chans = &xdev->h2c_chans; + chan_num = &xdev->h2c_chan_num; + } else if (dir == DMA_DEV_TO_MEM) { + base = XDMA_CHAN_C2H_OFFSET; + target = XDMA_CHAN_C2H_TARGET; + chans = &xdev->c2h_chans; + chan_num = &xdev->c2h_chan_num; + } else { + xdma_err(xdev, "invalid direction specified"); + return -EINVAL; + } + + /* detect number of available DMA channels */ + for (i = 0, *chan_num = 0; i < pdata->max_dma_channels; i++) { + ret = regmap_read(xdev->rmap, base + i * XDMA_CHAN_STRIDE, + &identifier); + if (ret) + return ret; + + /* check if it is available DMA channel */ + if (XDMA_CHAN_CHECK_TARGET(identifier, target)) + (*chan_num)++; + } + + if (!*chan_num) { + xdma_err(xdev, "does not probe any channel"); + return -EINVAL; + } + + *chans = devm_kcalloc(&xdev->pdev->dev, *chan_num, sizeof(**chans), + GFP_KERNEL); + if (!*chans) + return -ENOMEM; + + for (i = 0, j = 0; i < pdata->max_dma_channels; i++) { + ret = regmap_read(xdev->rmap, base + i * XDMA_CHAN_STRIDE, + &identifier); + if (ret) + return ret; + + if (!XDMA_CHAN_CHECK_TARGET(identifier, target)) + continue; + + if (j == *chan_num) { + xdma_err(xdev, "invalid channel number"); + return -EIO; + } + + /* init channel structure and hardware */ + xchan = &(*chans)[j]; + xchan->xdev_hdl = xdev; + xchan->base = base + i * XDMA_CHAN_STRIDE; + xchan->dir = dir; + + ret = xdma_channel_init(xchan); + if (ret) + return ret; + xchan->vchan.desc_free = xdma_free_desc; + vchan_init(&xchan->vchan, &xdev->dma_dev); + + j++; + } + + dev_info(&xdev->pdev->dev, "configured %d %s channels", j, + (dir == DMA_MEM_TO_DEV) ? "H2C" : "C2H"); + + return 0; +} + +/** + * xdma_issue_pending - Issue pending transactions + * @chan: DMA channel pointer + */ +static void xdma_issue_pending(struct dma_chan *chan) +{ + struct xdma_chan *xdma_chan = to_xdma_chan(chan); + unsigned long flags; + + spin_lock_irqsave(&xdma_chan->vchan.lock, flags); + if (vchan_issue_pending(&xdma_chan->vchan)) + xdma_xfer_start(xdma_chan); + spin_unlock_irqrestore(&xdma_chan->vchan.lock, flags); +} + +/** + * xdma_terminate_all - Terminate all transactions + * @chan: DMA channel pointer + */ +static int xdma_terminate_all(struct dma_chan *chan) +{ + struct xdma_chan *xdma_chan = to_xdma_chan(chan); + struct virt_dma_desc *vd; + unsigned long flags; + LIST_HEAD(head); + + xdma_xfer_stop(xdma_chan); + + spin_lock_irqsave(&xdma_chan->vchan.lock, flags); + + xdma_chan->busy = false; + vd = vchan_next_desc(&xdma_chan->vchan); + if (vd) { + list_del(&vd->node); + dma_cookie_complete(&vd->tx); + vchan_terminate_vdesc(vd); + } + vchan_get_all_descriptors(&xdma_chan->vchan, &head); + list_splice_tail(&head, &xdma_chan->vchan.desc_terminated); + + spin_unlock_irqrestore(&xdma_chan->vchan.lock, flags); + + return 0; +} + +/** + * xdma_synchronize - Synchronize terminated transactions + * @chan: DMA channel pointer + */ +static void xdma_synchronize(struct dma_chan *chan) +{ + struct xdma_chan *xdma_chan = to_xdma_chan(chan); + + vchan_synchronize(&xdma_chan->vchan); +} + +/** + * xdma_fill_descs - Fill hardware descriptors for one contiguous memory chunk. + * More than one descriptor will be used if the size is bigger + * than XDMA_DESC_BLEN_MAX. + * @sw_desc: Descriptor container + * @src_addr: First value for the ->src_addr field + * @dst_addr: First value for the ->dst_addr field + * @size: Size of the contiguous memory block + * @desc_start_num: Index of the first descriptor to take care of in @sw_desc + */ +static inline u32 xdma_fill_descs(struct xdma_desc *sw_desc, u64 src_addr, + u64 dst_addr, u32 size, u32 filled_descs_num) +{ + u32 left = size, len, desc_num = filled_descs_num; + struct xdma_desc_block *dblk; + struct xdma_hw_desc *desc; + + dblk = sw_desc->desc_blocks + (desc_num / XDMA_DESC_ADJACENT); + desc = dblk->virt_addr; + desc += desc_num & XDMA_DESC_ADJACENT_MASK; + do { + len = min_t(u32, left, XDMA_DESC_BLEN_MAX); + /* set hardware descriptor */ + desc->bytes = cpu_to_le32(len); + desc->src_addr = cpu_to_le64(src_addr); + desc->dst_addr = cpu_to_le64(dst_addr); + + dev_dbg(NULL, "desc[%u]:%p {src:0x%llx, dst: 0x%llx, length: %u}", + desc_num, + desc, + src_addr, + dst_addr, + len); + + if (!(++desc_num & XDMA_DESC_ADJACENT_MASK)) + desc = (++dblk)->virt_addr; + else + desc++; + + src_addr += len; + dst_addr += len; + left -= len; + } while (left); + + return desc_num - filled_descs_num; +} + +/** + * xdma_prep_device_sg - prepare a descriptor for a DMA transaction + * @chan: DMA channel pointer + * @sgl: Transfer scatter gather list + * @sg_len: Length of scatter gather list + * @dir: Transfer direction + * @flags: transfer ack flags + * @context: APP words of the descriptor + */ +static struct dma_async_tx_descriptor * +xdma_prep_device_sg(struct dma_chan *chan, struct scatterlist *sgl, + unsigned int sg_len, enum dma_transfer_direction dir, + unsigned long flags, void *context) +{ + struct xdma_chan *xdma_chan = to_xdma_chan(chan); + struct xdma_device *xdev = xdma_chan ->xdev_hdl; + + struct dma_async_tx_descriptor *tx_desc; + struct xdma_desc *sw_desc; + u32 desc_num = 0, i; + u64 addr, dev_addr, *src, *dst; + struct scatterlist *sg; + + for_each_sg(sgl, sg, sg_len, i) + desc_num += DIV_ROUND_UP(sg_dma_len(sg), XDMA_DESC_BLEN_MAX); + + sw_desc = xdma_alloc_desc(xdma_chan, desc_num, false); + if (!sw_desc) + return NULL; + sw_desc->dir = dir; + sw_desc->cyclic = false; + sw_desc->interleaved_dma = false; + + if (dir == DMA_MEM_TO_DEV) { + dev_addr = xdma_chan->cfg.dst_addr; + src = &addr; + dst = &dev_addr; + } else { + dev_addr = xdma_chan->cfg.src_addr ? xdma_chan->cfg.src_addr : xdma_chan->write_back->dma_addr; + src = &dev_addr; + dst = &addr; + } + + dev_dbg(&xdev->pdev->dev, "desc[%s]:%p {src: %p, dst: %p, length: %u}", + dir == DMA_MEM_TO_DEV ? "C2H" : "H2C", + sw_desc, + src, + dst, + sg_dma_len(sg)); + + + desc_num = 0; + for_each_sg(sgl, sg, sg_len, i) { + addr = sg_dma_address(sg); + desc_num += xdma_fill_descs(sw_desc, *src, *dst, sg_dma_len(sg), desc_num); + dev_addr += sg_dma_len(sg); + } + + tx_desc = vchan_tx_prep(&xdma_chan->vchan, &sw_desc->vdesc, flags); + if (!tx_desc) + goto failed; + + return tx_desc; + +failed: + xdma_free_desc(&sw_desc->vdesc); + + return NULL; +} + +/** + * xdma_prep_dma_cyclic - prepare for cyclic DMA transactions + * @chan: DMA channel pointer + * @address: Device DMA address to access + * @size: Total length to transfer + * @period_size: Period size to use for each transfer + * @dir: Transfer direction + * @flags: Transfer ack flags + */ +static struct dma_async_tx_descriptor * +xdma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t address, + size_t size, size_t period_size, + enum dma_transfer_direction dir, + unsigned long flags) +{ + struct xdma_chan *xdma_chan = to_xdma_chan(chan); + struct xdma_device *xdev = xdma_chan->xdev_hdl; + unsigned int periods = size / period_size; + struct dma_async_tx_descriptor *tx_desc; + struct xdma_desc *sw_desc; + u64 addr, dev_addr, *src, *dst; + u32 desc_num = 0; + unsigned int i; + + /* + * Simplify the whole logic by preventing an abnormally high number of + * periods and periods size. + */ + if (period_size > XDMA_DESC_BLEN_MAX) { + xdma_err(xdev, "period size limited to %lu bytes\n", XDMA_DESC_BLEN_MAX); + return NULL; + } + + if (periods > XDMA_DESC_ADJACENT) { + xdma_err(xdev, "number of periods limited to %u\n", XDMA_DESC_ADJACENT); + return NULL; + } + + sw_desc = xdma_alloc_desc(xdma_chan, periods, true); + if (!sw_desc) + return NULL; + + sw_desc->periods = periods; + sw_desc->period_size = period_size; + sw_desc->dir = dir; + sw_desc->interleaved_dma = false; + + addr = address; + if (dir == DMA_MEM_TO_DEV) { + dev_addr = xdma_chan->cfg.dst_addr; + src = &addr; + dst = &dev_addr; + } else { + dev_addr = xdma_chan->cfg.src_addr ? xdma_chan->cfg.src_addr : xdma_chan->write_back->dma_addr; + src = &dev_addr; + dst = &addr; + } + + dev_dbg(&xdev->pdev->dev, "desc[%s]:%p {src: %p, dst: %p, length: %lu}", + dir == DMA_MEM_TO_DEV ? "C2H" : "H2C", + sw_desc, + src, + dst, + period_size); + + for (i = 0; i < periods; i++) { + xdma_fill_descs(sw_desc, *src, *dst, period_size, desc_num++); + addr += period_size; + } + + tx_desc = vchan_tx_prep(&xdma_chan->vchan, &sw_desc->vdesc, flags); + if (!tx_desc) + goto failed; + + return tx_desc; + +failed: + xdma_free_desc(&sw_desc->vdesc); + + return NULL; +} + +/** + * xdma_prep_interleaved_dma - Prepare virtual descriptor for interleaved DMA transfers + * @chan: DMA channel + * @xt: DMA transfer template + * @flags: tx flags + */ +static struct dma_async_tx_descriptor * +xdma_prep_interleaved_dma(struct dma_chan *chan, + struct dma_interleaved_template *xt, + unsigned long flags) +{ + int i; + u32 desc_num = 0, period_size = 0; + struct dma_async_tx_descriptor *tx_desc; + struct xdma_chan *xchan = to_xdma_chan(chan); + struct xdma_desc *sw_desc; + u64 src_addr, dst_addr; + + for (i = 0; i < xt->frame_size; ++i) + desc_num += DIV_ROUND_UP(xt->sgl[i].size, XDMA_DESC_BLEN_MAX); + + sw_desc = xdma_alloc_desc(xchan, desc_num, false); + if (!sw_desc) + return NULL; + sw_desc->dir = xt->dir; + sw_desc->interleaved_dma = true; + sw_desc->cyclic = flags & DMA_PREP_REPEAT; + sw_desc->frames_left = xt->numf; + sw_desc->periods = xt->numf; + + desc_num = 0; + src_addr = xt->src_start; + dst_addr = xt->dst_start; + for (i = 0; i < xt->frame_size; ++i) { + desc_num += xdma_fill_descs(sw_desc, src_addr, dst_addr, xt->sgl[i].size, desc_num); + src_addr += dmaengine_get_src_icg(xt, &xt->sgl[i]) + (xt->src_inc ? + xt->sgl[i].size : 0); + dst_addr += dmaengine_get_dst_icg(xt, &xt->sgl[i]) + (xt->dst_inc ? + xt->sgl[i].size : 0); + period_size += xt->sgl[i].size; + } + sw_desc->period_size = period_size; + + tx_desc = vchan_tx_prep(&xchan->vchan, &sw_desc->vdesc, flags); + if (tx_desc) + return tx_desc; + + xdma_free_desc(&sw_desc->vdesc); + return NULL; +} + +/** + * xdma_device_config - Configure the DMA channel + * @chan: DMA channel + * @cfg: channel configuration + */ +static int xdma_device_config(struct dma_chan *chan, + struct dma_slave_config *cfg) +{ + struct xdma_chan *xdma_chan = to_xdma_chan(chan); + + memcpy(&xdma_chan->cfg, cfg, sizeof(*cfg)); + + return 0; +} + +/** + * xdma_free_chan_resources - Free channel resources + * @chan: DMA channel + */ +static void xdma_free_chan_resources(struct dma_chan *chan) +{ + struct xdma_chan *xdma_chan = to_xdma_chan(chan); + + vchan_free_chan_resources(&xdma_chan->vchan); + dma_pool_free(xdma_chan->desc_pool, + xdma_chan->write_back, + xdma_chan->write_back->dma_addr); + dma_pool_destroy(xdma_chan->desc_pool); + xdma_chan->desc_pool = NULL; +} + +/** + * xdma_alloc_chan_resources - Allocate channel resources + * @chan: DMA channel + */ +static int xdma_alloc_chan_resources(struct dma_chan *chan) +{ + struct xdma_chan *xdma_chan = to_xdma_chan(chan); + struct xdma_device *xdev = xdma_chan->xdev_hdl; + struct device *dev = xdev->dma_dev.dev; + dma_addr_t write_back_addr; + + while (dev && !dev_is_pci(dev)) + dev = dev->parent; + if (!dev) { + xdma_err(xdev, "unable to find pci device"); + return -EINVAL; + } + + //Allocate the pool WITH the H2C write back + xdma_chan->desc_pool = dma_pool_create(dma_chan_name(chan), dev, XDMA_DESC_BLOCK_SIZE + + sizeof(struct xdma_c2h_write_back), + XDMA_DESC_BLOCK_ALIGN, XDMA_DESC_BLOCK_BOUNDARY); + if (!xdma_chan->desc_pool) { + xdma_err(xdev, "unable to allocate descriptor pool"); + return -ENOMEM; + } + + /* Allocate the C2H write back out of the pool*/ + + xdma_chan->write_back = dma_pool_alloc(xdma_chan->desc_pool, GFP_NOWAIT, &write_back_addr); + + dev_dbg(dev, "C2H write_back : %p, dma_addr: %lld", xdma_chan->write_back, write_back_addr); + + if (!xdma_chan->write_back) { + xdma_err(xdev, "unable to allocate C2H write back block"); + return -ENOMEM; + } + xdma_chan->write_back->dma_addr = write_back_addr; + + + return 0; +} + +static enum dma_status xdma_tx_status(struct dma_chan *chan, dma_cookie_t cookie, + struct dma_tx_state *state) +{ + struct xdma_chan *xdma_chan = to_xdma_chan(chan); + struct xdma_desc *desc = NULL; + struct virt_dma_desc *vd; + enum dma_status ret; + unsigned long flags; + unsigned int period_idx; + u32 residue = 0; + + ret = dma_cookie_status(chan, cookie, state); + if (ret == DMA_COMPLETE) + return ret; + + spin_lock_irqsave(&xdma_chan->vchan.lock, flags); + + vd = vchan_find_desc(&xdma_chan->vchan, cookie); + if (!vd) + goto out; + + desc = to_xdma_desc(vd); + if (desc->error) { + ret = DMA_ERROR; + } else if (desc->cyclic) { + period_idx = desc->completed_desc_num % desc->periods; + residue = (desc->periods - period_idx) * desc->period_size; + dma_set_residue(state, residue); + } +out: + spin_unlock_irqrestore(&xdma_chan->vchan.lock, flags); + + return ret; +} + +/** + * xdma_channel_isr - XDMA channel interrupt handler + * @irq: IRQ number + * @dev_id: Pointer to the DMA channel structure + */ +static irqreturn_t xdma_channel_isr(int irq, void *dev_id) +{ + struct xdma_chan *xchan = dev_id; + u32 complete_desc_num = 0; + struct xdma_device *xdev = xchan->xdev_hdl; + struct virt_dma_desc *vd, *next_vd; + struct xdma_desc *desc; + int ret; + u32 st; + bool repeat_tx; + + spin_lock(&xchan->vchan.lock); + + /* get submitted request */ + vd = vchan_next_desc(&xchan->vchan); + if (!vd) + goto out; + + /* Clear-on-read the status register */ + ret = regmap_read(xdev->rmap, xchan->base + XDMA_CHAN_STATUS_RC, &st); + if (ret) + goto out; + + desc = to_xdma_desc(vd); + + st &= XDMA_CHAN_STATUS_MASK; + if ((st & XDMA_CHAN_ERROR_MASK) || + !(st & (CHAN_CTRL_IE_DESC_COMPLETED | CHAN_CTRL_IE_DESC_STOPPED))) { + desc->error = true; + xdma_err(xdev, "channel error, status register value: 0x%x", st); + goto out; + } + + ret = regmap_read(xdev->rmap, xchan->base + XDMA_CHAN_COMPLETED_DESC, + &complete_desc_num); + if (ret) + goto out; + + if (desc->interleaved_dma) { + xchan->busy = false; + desc->completed_desc_num += complete_desc_num; + if (complete_desc_num == XDMA_DESC_BLOCK_NUM * XDMA_DESC_ADJACENT) { + xdma_xfer_start(xchan); + goto out; + } + + /* last desc of any frame */ + desc->frames_left--; + if (desc->frames_left) + goto out; + + /* last desc of the last frame */ + repeat_tx = vd->tx.flags & DMA_PREP_REPEAT; + next_vd = list_first_entry_or_null(&vd->node, struct virt_dma_desc, node); + if (next_vd) + repeat_tx = repeat_tx && !(next_vd->tx.flags & DMA_PREP_LOAD_EOT); + if (repeat_tx) { + desc->frames_left = desc->periods; + desc->completed_desc_num = 0; + vchan_cyclic_callback(vd); + } else { + list_del(&vd->node); + vchan_cookie_complete(vd); + } + /* start (or continue) the tx of a first desc on the vc.desc_issued list, if any */ + xdma_xfer_start(xchan); + } else if (!desc->cyclic) { + xchan->busy = false; + desc->completed_desc_num += complete_desc_num; + + /* if all data blocks are transferred, remove and complete the request */ + if (desc->completed_desc_num == desc->desc_num) { + list_del(&vd->node); + vchan_cookie_complete(vd); + goto out; + } + + if (desc->completed_desc_num > desc->desc_num || + complete_desc_num != XDMA_DESC_BLOCK_NUM * XDMA_DESC_ADJACENT) + goto out; + + /* transfer the rest of data */ + xdma_xfer_start(xchan); + } else { + desc->completed_desc_num = complete_desc_num; + vchan_cyclic_callback(vd); + } + +out: + spin_unlock(&xchan->vchan.lock); + return IRQ_HANDLED; +} + +/** + * xdma_irq_fini - Uninitialize IRQ + * @xdev: DMA device pointer + */ +static void xdma_irq_fini(struct xdma_device *xdev) +{ + int i; + + /* disable interrupt */ + regmap_write(xdev->rmap, XDMA_IRQ_CHAN_INT_EN_W1C, ~0); + + /* free irq handler */ + for (i = 0; i < xdev->h2c_chan_num; i++) + free_irq(xdev->h2c_chans[i].irq, &xdev->h2c_chans[i]); + + for (i = 0; i < xdev->c2h_chan_num; i++) + free_irq(xdev->c2h_chans[i].irq, &xdev->c2h_chans[i]); +} + +/** + * xdma_set_vector_reg - configure hardware IRQ registers + * @xdev: DMA device pointer + * @vec_tbl_start: Start of IRQ registers + * @irq_start: Start of IRQ + * @irq_num: Number of IRQ + */ +static int xdma_set_vector_reg(struct xdma_device *xdev, u32 vec_tbl_start, + u32 irq_start, u32 irq_num) +{ + u32 shift, i, val = 0; + int ret; + + /* Each IRQ register is 32 bit and contains 4 IRQs */ + while (irq_num > 0) { + for (i = 0; i < 4; i++) { + shift = XDMA_IRQ_VEC_SHIFT * i; + val |= irq_start << shift; + irq_start++; + irq_num--; + if (!irq_num) + break; + } + + /* write IRQ register */ + ret = regmap_write(xdev->rmap, vec_tbl_start, val); + if (ret) + return ret; + vec_tbl_start += sizeof(u32); + val = 0; + } + + return 0; +} + +/** + * xdma_irq_init - initialize IRQs + * @xdev: DMA device pointer + */ +static int xdma_irq_init(struct xdma_device *xdev) +{ + u32 irq = xdev->irq_start; + u32 user_irq_start; + int i, j, ret; + + /* return failure if there are not enough IRQs */ + if (xdev->irq_num < XDMA_CHAN_NUM(xdev)) { + xdma_err(xdev, "not enough irq"); + return -EINVAL; + } + + /* setup H2C interrupt handler */ + for (i = 0; i < xdev->h2c_chan_num; i++) { + ret = request_irq(irq, xdma_channel_isr, 0, + "xdma-h2c-channel", &xdev->h2c_chans[i]); + if (ret) { + xdma_err(xdev, "H2C channel%d request irq%d failed: %d", + i, irq, ret); + goto failed_init_h2c; + } + xdev->h2c_chans[i].irq = irq; + irq++; + } + + /* setup C2H interrupt handler */ + for (j = 0; j < xdev->c2h_chan_num; j++) { + ret = request_irq(irq, xdma_channel_isr, 0, + "xdma-c2h-channel", &xdev->c2h_chans[j]); + if (ret) { + xdma_err(xdev, "C2H channel%d request irq%d failed: %d", + j, irq, ret); + goto failed_init_c2h; + } + xdev->c2h_chans[j].irq = irq; + irq++; + } + + /* config hardware IRQ registers */ + ret = xdma_set_vector_reg(xdev, XDMA_IRQ_CHAN_VEC_NUM, 0, + XDMA_CHAN_NUM(xdev)); + if (ret) { + xdma_err(xdev, "failed to set channel vectors: %d", ret); + goto failed_init_c2h; + } + + /* config user IRQ registers if needed */ + user_irq_start = XDMA_CHAN_NUM(xdev); + if (xdev->irq_num > user_irq_start) { + ret = xdma_set_vector_reg(xdev, XDMA_IRQ_USER_VEC_NUM, + user_irq_start, + xdev->irq_num - user_irq_start); + if (ret) { + xdma_err(xdev, "failed to set user vectors: %d", ret); + goto failed_init_c2h; + } + } + + /* enable interrupt */ + ret = regmap_write(xdev->rmap, XDMA_IRQ_CHAN_INT_EN_W1S, ~0); + if (ret) + goto failed_init_c2h; + + return 0; + +failed_init_c2h: + while (j--) + free_irq(xdev->c2h_chans[j].irq, &xdev->c2h_chans[j]); +failed_init_h2c: + while (i--) + free_irq(xdev->h2c_chans[i].irq, &xdev->h2c_chans[i]); + + return ret; +} + +static bool xdma_filter_fn(struct dma_chan *chan, void *param) +{ + struct xdma_chan *xdma_chan = to_xdma_chan(chan); + struct xdma_chan_info *chan_info = param; + + return chan_info->dir == xdma_chan->dir; +} + +/** + * xdma_disable_user_irq - Disable user interrupt + * @pdev: Pointer to the platform_device structure + * @irq_num: System IRQ number + */ +void xdma_disable_user_irq(struct platform_device *pdev, u32 irq_num) +{ + struct xdma_device *xdev = platform_get_drvdata(pdev); + u32 index; + + index = irq_num - xdev->irq_start; + if (index < XDMA_CHAN_NUM(xdev) || index >= xdev->irq_num) { + xdma_err(xdev, "invalid user irq number"); + return; + } + index -= XDMA_CHAN_NUM(xdev); + + regmap_write(xdev->rmap, XDMA_IRQ_USER_INT_EN_W1C, 1 << index); +} +EXPORT_SYMBOL(xdma_disable_user_irq); + +/** + * xdma_enable_user_irq - Enable user logic interrupt + * @pdev: Pointer to the platform_device structure + * @irq_num: System IRQ number + */ +int xdma_enable_user_irq(struct platform_device *pdev, u32 irq_num) +{ + struct xdma_device *xdev = platform_get_drvdata(pdev); + u32 index; + int ret; + + index = irq_num - xdev->irq_start; + if (index < XDMA_CHAN_NUM(xdev) || index >= xdev->irq_num) { + xdma_err(xdev, "invalid user irq number"); + return -EINVAL; + } + index -= XDMA_CHAN_NUM(xdev); + + ret = regmap_write(xdev->rmap, XDMA_IRQ_USER_INT_EN_W1S, 1 << index); + if (ret) + return ret; + + return 0; +} +EXPORT_SYMBOL(xdma_enable_user_irq); + +/** + * xdma_get_user_irq - Get system IRQ number + * @pdev: Pointer to the platform_device structure + * @user_irq_index: User logic IRQ wire index + * + * Return: The system IRQ number allocated for the given wire index. + */ +int xdma_get_user_irq(struct platform_device *pdev, u32 user_irq_index) +{ + struct xdma_device *xdev = platform_get_drvdata(pdev); + + if (XDMA_CHAN_NUM(xdev) + user_irq_index >= xdev->irq_num) { + xdma_err(xdev, "invalid user irq index"); + return -EINVAL; + } + + return xdev->irq_start + XDMA_CHAN_NUM(xdev) + user_irq_index; +} +EXPORT_SYMBOL(xdma_get_user_irq); + +/** + * xdma_remove - Driver remove function + * @pdev: Pointer to the platform_device structure + */ +static int xdma_remove(struct platform_device *pdev) +{ + struct xdma_device *xdev = platform_get_drvdata(pdev); + + if (xdev->status & XDMA_DEV_STATUS_INIT_MSIX) + xdma_irq_fini(xdev); + + if (xdev->status & XDMA_DEV_STATUS_REG_DMA) + dma_async_device_unregister(&xdev->dma_dev); + + return 0; +} + +/** + * xdma_probe - Driver probe function + * @pdev: Pointer to the platform_device structure + */ +static int xdma_probe(struct platform_device *pdev) +{ + struct xdma_platdata *pdata = dev_get_platdata(&pdev->dev); + struct xdma_device *xdev; + void __iomem *reg_base; + struct resource *res; + int ret = -ENODEV; + + if (pdata->max_dma_channels > XDMA_MAX_CHANNELS) { + dev_err(&pdev->dev, "invalid max dma channels %d", + pdata->max_dma_channels); + return -EINVAL; + } + + xdev = devm_kzalloc(&pdev->dev, sizeof(*xdev), GFP_KERNEL); + if (!xdev) + return -ENOMEM; + + platform_set_drvdata(pdev, xdev); + xdev->pdev = pdev; + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res) { + xdma_err(xdev, "failed to get irq resource"); + goto failed; + } + xdev->irq_start = res->start; + xdev->irq_num = resource_size(res); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + xdma_err(xdev, "failed to get io resource"); + goto failed; + } + + reg_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(reg_base)) { + xdma_err(xdev, "ioremap failed"); + goto failed; + } + + dev_dbg(&pdev->dev, " %s - config: %p (%lu bytes), reg_bits:%d, reg_stride:%d, pad_bits:%d, val_bits:%d, &val_bits:%p", + __func__, + &xdma_regmap_config, + sizeof(struct regmap_config), + xdma_regmap_config.reg_bits, + xdma_regmap_config.reg_stride, + xdma_regmap_config.pad_bits, + xdma_regmap_config.val_bits, + &xdma_regmap_config.val_bits); + + xdev->rmap = devm_regmap_init_mmio(&pdev->dev, reg_base, + &xdma_regmap_config); + if (IS_ERR(xdev->rmap)) { + ret = PTR_ERR(xdev->rmap); + xdma_err(xdev, "config regmap failed: %d", ret); + goto failed; + } + + INIT_LIST_HEAD(&xdev->dma_dev.channels); + + ret = xdma_alloc_channels(xdev, DMA_MEM_TO_DEV); + if (ret) { + xdma_err(xdev, "config H2C channels failed: %d", ret); + goto failed; + } + + ret = xdma_alloc_channels(xdev, DMA_DEV_TO_MEM); + if (ret) { + xdma_err(xdev, "config C2H channels failed: %d", ret); + goto failed; + } + + dma_cap_set(DMA_SLAVE, xdev->dma_dev.cap_mask); + dma_cap_set(DMA_PRIVATE, xdev->dma_dev.cap_mask); + dma_cap_set(DMA_CYCLIC, xdev->dma_dev.cap_mask); + dma_cap_set(DMA_INTERLEAVE, xdev->dma_dev.cap_mask); + dma_cap_set(DMA_REPEAT, xdev->dma_dev.cap_mask); + dma_cap_set(DMA_LOAD_EOT, xdev->dma_dev.cap_mask); + + xdev->dma_dev.dev = &pdev->dev; + xdev->dma_dev.residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT; + xdev->dma_dev.device_free_chan_resources = xdma_free_chan_resources; + xdev->dma_dev.device_alloc_chan_resources = xdma_alloc_chan_resources; + xdev->dma_dev.device_tx_status = xdma_tx_status; + xdev->dma_dev.device_prep_slave_sg = xdma_prep_device_sg; + xdev->dma_dev.device_config = xdma_device_config; + xdev->dma_dev.device_issue_pending = xdma_issue_pending; + xdev->dma_dev.device_terminate_all = xdma_terminate_all; + xdev->dma_dev.device_synchronize = xdma_synchronize; + xdev->dma_dev.filter.map = pdata->device_map; + xdev->dma_dev.filter.mapcnt = pdata->device_map_cnt; + xdev->dma_dev.filter.fn = xdma_filter_fn; + xdev->dma_dev.device_prep_dma_cyclic = xdma_prep_dma_cyclic; + xdev->dma_dev.device_prep_interleaved_dma = xdma_prep_interleaved_dma; + + ret = dma_async_device_register(&xdev->dma_dev); + if (ret) { + xdma_err(xdev, "failed to register Xilinx XDMA: %d", ret); + goto failed; + } + xdev->status |= XDMA_DEV_STATUS_REG_DMA; + + ret = xdma_irq_init(xdev); + if (ret) { + xdma_err(xdev, "failed to init msix: %d", ret); + goto failed; + } + xdev->status |= XDMA_DEV_STATUS_INIT_MSIX; + + return 0; + +failed: + xdma_remove(pdev); + + return ret; +} + +static const struct platform_device_id xdma_id_table[] = { + { "xdma", 0}, + { }, +}; + +static struct platform_driver xdma_driver = { + .driver = { + .name = "xdma", + }, + .id_table = xdma_id_table, + .probe = xdma_probe, + .remove = xdma_remove, +}; + +module_platform_driver(xdma_driver); + +MODULE_DESCRIPTION("AMD XDMA driver"); +MODULE_AUTHOR("XRT Team <runtimeca39d@amd.com>"); +MODULE_LICENSE("GPL"); diff --git a/snd-alpx-dkms/snd-alpx/core/generic/6.3/amd_xdma.h b/snd-alpx-dkms/snd-alpx/core/generic/6.3/amd_xdma.h new file mode 100644 index 0000000..b5e23e1 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/core/generic/6.3/amd_xdma.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2022, Advanced Micro Devices, Inc. + */ + +#ifndef _PLATDATA_AMD_XDMA_H +#define _PLATDATA_AMD_XDMA_H + +#include <linux/dmaengine.h> + +/** + * struct xdma_chan_info - DMA channel information + * This information is used to match channel when request dma channel + * @dir: Channel transfer direction + */ +struct xdma_chan_info { + enum dma_transfer_direction dir; +}; + +#define XDMA_FILTER_PARAM(chan_info) ((void *)(chan_info)) + +struct dma_slave_map; + +/** + * struct xdma_platdata - platform specific data for XDMA engine + * @max_dma_channels: Maximum dma channels in each direction + */ +struct xdma_platdata { + u32 max_dma_channels; + u32 device_map_cnt; + struct dma_slave_map *device_map; +}; + +#endif /* _PLATDATA_AMD_XDMA_H */ diff --git a/snd-alpx-dkms/snd-alpx/core/generic/6.3/dmaengine.h b/snd-alpx-dkms/snd-alpx/core/generic/6.3/dmaengine.h new file mode 100644 index 0000000..53f16d3 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/core/generic/6.3/dmaengine.h @@ -0,0 +1,201 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * The contents of this file are private to DMA engine drivers, and is not + * part of the API to be used by DMA engine users. + */ +#ifndef DMAENGINE_H +#define DMAENGINE_H + +#include <linux/bug.h> +#include <linux/dmaengine.h> + +/** + * dma_cookie_init - initialize the cookies for a DMA channel + * @chan: dma channel to initialize + */ +static inline void dma_cookie_init(struct dma_chan *chan) +{ + chan->cookie = DMA_MIN_COOKIE; + chan->completed_cookie = DMA_MIN_COOKIE; +} + +/** + * dma_cookie_assign - assign a DMA engine cookie to the descriptor + * @tx: descriptor needing cookie + * + * Assign a unique non-zero per-channel cookie to the descriptor. + * Note: caller is expected to hold a lock to prevent concurrency. + */ +static inline dma_cookie_t dma_cookie_assign(struct dma_async_tx_descriptor *tx) +{ + struct dma_chan *chan = tx->chan; + dma_cookie_t cookie; + + cookie = chan->cookie + 1; + if (cookie < DMA_MIN_COOKIE) + cookie = DMA_MIN_COOKIE; + tx->cookie = chan->cookie = cookie; + + return cookie; +} + +/** + * dma_cookie_complete - complete a descriptor + * @tx: descriptor to complete + * + * Mark this descriptor complete by updating the channels completed + * cookie marker. Zero the descriptors cookie to prevent accidental + * repeated completions. + * + * Note: caller is expected to hold a lock to prevent concurrency. + */ +static inline void dma_cookie_complete(struct dma_async_tx_descriptor *tx) +{ + BUG_ON(tx->cookie < DMA_MIN_COOKIE); + tx->chan->completed_cookie = tx->cookie; + tx->cookie = 0; +} + +/** + * dma_cookie_status - report cookie status + * @chan: dma channel + * @cookie: cookie we are interested in + * @state: dma_tx_state structure to return last/used cookies + * + * Report the status of the cookie, filling in the state structure if + * non-NULL. No locking is required. + */ +static inline enum dma_status dma_cookie_status(struct dma_chan *chan, + dma_cookie_t cookie, struct dma_tx_state *state) +{ + dma_cookie_t used, complete; + + used = chan->cookie; + complete = chan->completed_cookie; + barrier(); + if (state) { + state->last = complete; + state->used = used; + state->residue = 0; + state->in_flight_bytes = 0; + } + return dma_async_is_complete(cookie, complete, used); +} + +static inline void dma_set_residue(struct dma_tx_state *state, u32 residue) +{ + if (state) + state->residue = residue; +} + +static inline void dma_set_in_flight_bytes(struct dma_tx_state *state, + u32 in_flight_bytes) +{ + if (state) + state->in_flight_bytes = in_flight_bytes; +} + +struct dmaengine_desc_callback { + dma_async_tx_callback callback; + dma_async_tx_callback_result callback_result; + void *callback_param; +}; + +/** + * dmaengine_desc_get_callback - get the passed in callback function + * @tx: tx descriptor + * @cb: temp struct to hold the callback info + * + * Fill the passed in cb struct with what's available in the passed in + * tx descriptor struct + * No locking is required. + */ +static inline void +dmaengine_desc_get_callback(struct dma_async_tx_descriptor *tx, + struct dmaengine_desc_callback *cb) +{ + cb->callback = tx->callback; + cb->callback_result = tx->callback_result; + cb->callback_param = tx->callback_param; +} + +/** + * dmaengine_desc_callback_invoke - call the callback function in cb struct + * @cb: temp struct that is holding the callback info + * @result: transaction result + * + * Call the callback function provided in the cb struct with the parameter + * in the cb struct. + * Locking is dependent on the driver. + */ +static inline void +dmaengine_desc_callback_invoke(struct dmaengine_desc_callback *cb, + const struct dmaengine_result *result) +{ + struct dmaengine_result dummy_result = { + .result = DMA_TRANS_NOERROR, + .residue = 0 + }; + + if (cb->callback_result) { + if (!result) + result = &dummy_result; + cb->callback_result(cb->callback_param, result); + } else if (cb->callback) { + cb->callback(cb->callback_param); + } +} + +/** + * dmaengine_desc_get_callback_invoke - get the callback in tx descriptor and + * then immediately call the callback. + * @tx: dma async tx descriptor + * @result: transaction result + * + * Call dmaengine_desc_get_callback() and dmaengine_desc_callback_invoke() + * in a single function since no work is necessary in between for the driver. + * Locking is dependent on the driver. + */ +static inline void +dmaengine_desc_get_callback_invoke(struct dma_async_tx_descriptor *tx, + const struct dmaengine_result *result) +{ + struct dmaengine_desc_callback cb; + + dmaengine_desc_get_callback(tx, &cb); + dmaengine_desc_callback_invoke(&cb, result); +} + +/** + * dmaengine_desc_callback_valid - verify the callback is valid in cb + * @cb: callback info struct + * + * Return a bool that verifies whether callback in cb is valid or not. + * No locking is required. + */ +static inline bool +dmaengine_desc_callback_valid(struct dmaengine_desc_callback *cb) +{ + return cb->callback || cb->callback_result; +} + +struct dma_chan *dma_get_slave_channel(struct dma_chan *chan); +struct dma_chan *dma_get_any_slave_channel(struct dma_device *device); + +#ifdef CONFIG_DEBUG_FS +#include <linux/debugfs.h> + +static inline struct dentry * +dmaengine_get_debugfs_root(struct dma_device *dma_dev) { + return dma_dev->dbg_dev_root; +} +#else +struct dentry; +static inline struct dentry * +dmaengine_get_debugfs_root(struct dma_device *dma_dev) +{ + return NULL; +} +#endif /* CONFIG_DEBUG_FS */ + +#endif diff --git a/snd-alpx-dkms/snd-alpx/core/generic/6.3/virt-dma.c b/snd-alpx-dkms/snd-alpx/core/generic/6.3/virt-dma.c new file mode 100644 index 0000000..a6f4265 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/core/generic/6.3/virt-dma.c @@ -0,0 +1,142 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Virtual DMA channel support for DMAengine + * + * Copyright (C) 2012 Russell King + */ +#include <linux/device.h> +#include <linux/dmaengine.h> +#include <linux/module.h> +#include <linux/spinlock.h> + +#include "virt-dma.h" + +static struct virt_dma_desc *to_virt_desc(struct dma_async_tx_descriptor *tx) +{ + return container_of(tx, struct virt_dma_desc, tx); +} + +dma_cookie_t vchan_tx_submit(struct dma_async_tx_descriptor *tx) +{ + struct virt_dma_chan *vc = to_virt_chan(tx->chan); + struct virt_dma_desc *vd = to_virt_desc(tx); + unsigned long flags; + dma_cookie_t cookie; + + spin_lock_irqsave(&vc->lock, flags); + cookie = dma_cookie_assign(tx); + + list_move_tail(&vd->node, &vc->desc_submitted); + spin_unlock_irqrestore(&vc->lock, flags); + + dev_dbg(vc->chan.device->dev, "vchan %p: txd %p[%x]: submitted\n", + vc, vd, cookie); + + return cookie; +} +EXPORT_SYMBOL_GPL(vchan_tx_submit); + +/** + * vchan_tx_desc_free - free a reusable descriptor + * @tx: the transfer + * + * This function frees a previously allocated reusable descriptor. The only + * other way is to clear the DMA_CTRL_REUSE flag and submit one last time the + * transfer. + * + * Returns 0 upon success + */ +int vchan_tx_desc_free(struct dma_async_tx_descriptor *tx) +{ + struct virt_dma_chan *vc = to_virt_chan(tx->chan); + struct virt_dma_desc *vd = to_virt_desc(tx); + unsigned long flags; + + spin_lock_irqsave(&vc->lock, flags); + list_del(&vd->node); + spin_unlock_irqrestore(&vc->lock, flags); + + dev_dbg(vc->chan.device->dev, "vchan %p: txd %p[%x]: freeing\n", + vc, vd, vd->tx.cookie); + vc->desc_free(vd); + return 0; +} +EXPORT_SYMBOL_GPL(vchan_tx_desc_free); + +struct virt_dma_desc *vchan_find_desc(struct virt_dma_chan *vc, + dma_cookie_t cookie) +{ + struct virt_dma_desc *vd; + + list_for_each_entry(vd, &vc->desc_issued, node) + if (vd->tx.cookie == cookie) + return vd; + + return NULL; +} +EXPORT_SYMBOL_GPL(vchan_find_desc); + +/* + * This tasklet handles the completion of a DMA descriptor by + * calling its callback and freeing it. + */ +static void vchan_complete(struct tasklet_struct *t) +{ + struct virt_dma_chan *vc = from_tasklet(vc, t, task); + struct virt_dma_desc *vd, *_vd; + struct dmaengine_desc_callback cb; + LIST_HEAD(head); + + spin_lock_irq(&vc->lock); + list_splice_tail_init(&vc->desc_completed, &head); + vd = vc->cyclic; + if (vd) { + vc->cyclic = NULL; + dmaengine_desc_get_callback(&vd->tx, &cb); + } else { + memset(&cb, 0, sizeof(cb)); + } + spin_unlock_irq(&vc->lock); + + dmaengine_desc_callback_invoke(&cb, &vd->tx_result); + + list_for_each_entry_safe(vd, _vd, &head, node) { + dmaengine_desc_get_callback(&vd->tx, &cb); + + list_del(&vd->node); + dmaengine_desc_callback_invoke(&cb, &vd->tx_result); + vchan_vdesc_fini(vd); + } +} + +void vchan_dma_desc_free_list(struct virt_dma_chan *vc, struct list_head *head) +{ + struct virt_dma_desc *vd, *_vd; + + list_for_each_entry_safe(vd, _vd, head, node) { + list_del(&vd->node); + vchan_vdesc_fini(vd); + } +} +EXPORT_SYMBOL_GPL(vchan_dma_desc_free_list); + +void vchan_init(struct virt_dma_chan *vc, struct dma_device *dmadev) +{ + dma_cookie_init(&vc->chan); + + spin_lock_init(&vc->lock); + INIT_LIST_HEAD(&vc->desc_allocated); + INIT_LIST_HEAD(&vc->desc_submitted); + INIT_LIST_HEAD(&vc->desc_issued); + INIT_LIST_HEAD(&vc->desc_completed); + INIT_LIST_HEAD(&vc->desc_terminated); + + tasklet_setup(&vc->task, vchan_complete); + + vc->chan.device = dmadev; + list_add_tail(&vc->chan.device_node, &dmadev->channels); +} +EXPORT_SYMBOL_GPL(vchan_init); + +MODULE_AUTHOR("Russell King"); +MODULE_LICENSE("GPL"); diff --git a/snd-alpx-dkms/snd-alpx/core/generic/6.3/virt-dma.h b/snd-alpx-dkms/snd-alpx/core/generic/6.3/virt-dma.h new file mode 100644 index 0000000..e9f5250 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/core/generic/6.3/virt-dma.h @@ -0,0 +1,227 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Virtual DMA channel support for DMAengine + * + * Copyright (C) 2012 Russell King + */ +#ifndef VIRT_DMA_H +#define VIRT_DMA_H + +#include <linux/dmaengine.h> +#include <linux/interrupt.h> + +#include "dmaengine.h" + +struct virt_dma_desc { + struct dma_async_tx_descriptor tx; + struct dmaengine_result tx_result; + /* protected by vc.lock */ + struct list_head node; +}; + +struct virt_dma_chan { + struct dma_chan chan; + struct tasklet_struct task; + void (*desc_free)(struct virt_dma_desc *); + + spinlock_t lock; + + /* protected by vc.lock */ + struct list_head desc_allocated; + struct list_head desc_submitted; + struct list_head desc_issued; + struct list_head desc_completed; + struct list_head desc_terminated; + + struct virt_dma_desc *cyclic; +}; + +static inline struct virt_dma_chan *to_virt_chan(struct dma_chan *chan) +{ + return container_of(chan, struct virt_dma_chan, chan); +} + +void vchan_dma_desc_free_list(struct virt_dma_chan *vc, struct list_head *head); +void vchan_init(struct virt_dma_chan *vc, struct dma_device *dmadev); +struct virt_dma_desc *vchan_find_desc(struct virt_dma_chan *, dma_cookie_t); +extern dma_cookie_t vchan_tx_submit(struct dma_async_tx_descriptor *); +extern int vchan_tx_desc_free(struct dma_async_tx_descriptor *); + +/** + * vchan_tx_prep - prepare a descriptor + * @vc: virtual channel allocating this descriptor + * @vd: virtual descriptor to prepare + * @tx_flags: flags argument passed in to prepare function + */ +static inline struct dma_async_tx_descriptor *vchan_tx_prep(struct virt_dma_chan *vc, + struct virt_dma_desc *vd, unsigned long tx_flags) +{ + unsigned long flags; + + dma_async_tx_descriptor_init(&vd->tx, &vc->chan); + vd->tx.flags = tx_flags; + vd->tx.tx_submit = vchan_tx_submit; + vd->tx.desc_free = vchan_tx_desc_free; + + vd->tx_result.result = DMA_TRANS_NOERROR; + vd->tx_result.residue = 0; + + spin_lock_irqsave(&vc->lock, flags); + list_add_tail(&vd->node, &vc->desc_allocated); + spin_unlock_irqrestore(&vc->lock, flags); + + return &vd->tx; +} + +/** + * vchan_issue_pending - move submitted descriptors to issued list + * @vc: virtual channel to update + * + * vc.lock must be held by caller + */ +static inline bool vchan_issue_pending(struct virt_dma_chan *vc) +{ + list_splice_tail_init(&vc->desc_submitted, &vc->desc_issued); + return !list_empty(&vc->desc_issued); +} + +/** + * vchan_cookie_complete - report completion of a descriptor + * @vd: virtual descriptor to update + * + * vc.lock must be held by caller + */ +static inline void vchan_cookie_complete(struct virt_dma_desc *vd) +{ + struct virt_dma_chan *vc = to_virt_chan(vd->tx.chan); + dma_cookie_t cookie; + + cookie = vd->tx.cookie; + dma_cookie_complete(&vd->tx); + dev_vdbg(vc->chan.device->dev, "txd %p[%x]: marked complete\n", + vd, cookie); + list_add_tail(&vd->node, &vc->desc_completed); + + tasklet_schedule(&vc->task); +} + +/** + * vchan_vdesc_fini - Free or reuse a descriptor + * @vd: virtual descriptor to free/reuse + */ +static inline void vchan_vdesc_fini(struct virt_dma_desc *vd) +{ + struct virt_dma_chan *vc = to_virt_chan(vd->tx.chan); + + if (dmaengine_desc_test_reuse(&vd->tx)) { + unsigned long flags; + + spin_lock_irqsave(&vc->lock, flags); + list_add(&vd->node, &vc->desc_allocated); + spin_unlock_irqrestore(&vc->lock, flags); + } else { + vc->desc_free(vd); + } +} + +/** + * vchan_cyclic_callback - report the completion of a period + * @vd: virtual descriptor + */ +static inline void vchan_cyclic_callback(struct virt_dma_desc *vd) +{ + struct virt_dma_chan *vc = to_virt_chan(vd->tx.chan); + + vc->cyclic = vd; + tasklet_schedule(&vc->task); +} + +/** + * vchan_terminate_vdesc - Disable pending cyclic callback + * @vd: virtual descriptor to be terminated + * + * vc.lock must be held by caller + */ +static inline void vchan_terminate_vdesc(struct virt_dma_desc *vd) +{ + struct virt_dma_chan *vc = to_virt_chan(vd->tx.chan); + + list_add_tail(&vd->node, &vc->desc_terminated); + + if (vc->cyclic == vd) + vc->cyclic = NULL; +} + +/** + * vchan_next_desc - peek at the next descriptor to be processed + * @vc: virtual channel to obtain descriptor from + * + * vc.lock must be held by caller + */ +static inline struct virt_dma_desc *vchan_next_desc(struct virt_dma_chan *vc) +{ + return list_first_entry_or_null(&vc->desc_issued, + struct virt_dma_desc, node); +} + +/** + * vchan_get_all_descriptors - obtain all submitted and issued descriptors + * @vc: virtual channel to get descriptors from + * @head: list of descriptors found + * + * vc.lock must be held by caller + * + * Removes all submitted and issued descriptors from internal lists, and + * provides a list of all descriptors found + */ +static inline void vchan_get_all_descriptors(struct virt_dma_chan *vc, + struct list_head *head) +{ + list_splice_tail_init(&vc->desc_allocated, head); + list_splice_tail_init(&vc->desc_submitted, head); + list_splice_tail_init(&vc->desc_issued, head); + list_splice_tail_init(&vc->desc_completed, head); + list_splice_tail_init(&vc->desc_terminated, head); +} + +static inline void vchan_free_chan_resources(struct virt_dma_chan *vc) +{ + struct virt_dma_desc *vd; + unsigned long flags; + LIST_HEAD(head); + + spin_lock_irqsave(&vc->lock, flags); + vchan_get_all_descriptors(vc, &head); + list_for_each_entry(vd, &head, node) + dmaengine_desc_clear_reuse(&vd->tx); + spin_unlock_irqrestore(&vc->lock, flags); + + vchan_dma_desc_free_list(vc, &head); +} + +/** + * vchan_synchronize() - synchronize callback execution to the current context + * @vc: virtual channel to synchronize + * + * Makes sure that all scheduled or active callbacks have finished running. For + * proper operation the caller has to ensure that no new callbacks are scheduled + * after the invocation of this function started. + * Free up the terminated cyclic descriptor to prevent memory leakage. + */ +static inline void vchan_synchronize(struct virt_dma_chan *vc) +{ + LIST_HEAD(head); + unsigned long flags; + + tasklet_kill(&vc->task); + + spin_lock_irqsave(&vc->lock, flags); + + list_splice_tail_init(&vc->desc_terminated, &head); + + spin_unlock_irqrestore(&vc->lock, flags); + + vchan_dma_desc_free_list(vc, &head); +} + +#endif diff --git a/snd-alpx-dkms/snd-alpx/core/generic/6.3/xilinx/xdma-regs.h b/snd-alpx-dkms/snd-alpx/core/generic/6.3/xilinx/xdma-regs.h new file mode 100644 index 0000000..4ee96de --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/core/generic/6.3/xilinx/xdma-regs.h @@ -0,0 +1,169 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2017-2020 Xilinx, Inc. All rights reserved. + * Copyright (C) 2022, Advanced Micro Devices, Inc. + */ + +#ifndef __DMA_XDMA_REGS_H +#define __DMA_XDMA_REGS_H + +/* The length of register space exposed to host */ +#define XDMA_REG_SPACE_LEN 65536 + +/* + * maximum number of DMA channels for each direction: + * Host to Card (H2C) or Card to Host (C2H) + */ +#define XDMA_MAX_CHANNELS 4 + +/* + * macros to define the number of descriptor blocks can be used in one + * DMA transfer request. + * the DMA engine uses a linked list of descriptor blocks that specify the + * source, destination, and length of the DMA transfers. + */ +#define XDMA_DESC_BLOCK_NUM BIT(7) +#define XDMA_DESC_BLOCK_MASK (XDMA_DESC_BLOCK_NUM - 1) + +/* descriptor definitions */ +#define XDMA_DESC_ADJACENT 32 +#define XDMA_DESC_ADJACENT_MASK (XDMA_DESC_ADJACENT - 1) +#define XDMA_DESC_ADJACENT_BITS GENMASK(13, 8) +#define XDMA_DESC_MAGIC 0xad4bUL +#define XDMA_DESC_MAGIC_BITS GENMASK(31, 16) +#define XDMA_DESC_FLAGS_BITS GENMASK(7, 0) +#define XDMA_DESC_STOPPED BIT(0) +#define XDMA_DESC_COMPLETED BIT(1) +#define XDMA_DESC_BLEN_BITS 28 +#define XDMA_DESC_BLEN_MAX (BIT(XDMA_DESC_BLEN_BITS) - PAGE_SIZE) + +/* macros to construct the descriptor control word */ +#define XDMA_DESC_CONTROL(adjacent, flag) \ + (FIELD_PREP(XDMA_DESC_MAGIC_BITS, XDMA_DESC_MAGIC) | \ + FIELD_PREP(XDMA_DESC_ADJACENT_BITS, (adjacent) - 1) | \ + FIELD_PREP(XDMA_DESC_FLAGS_BITS, (flag))) +#define XDMA_DESC_CONTROL_LAST \ + XDMA_DESC_CONTROL(1, XDMA_DESC_STOPPED | XDMA_DESC_COMPLETED) +#define XDMA_DESC_CONTROL_CYCLIC \ + XDMA_DESC_CONTROL(1, XDMA_DESC_COMPLETED) + +/* + * Descriptor for a single contiguous memory block transfer. + * + * Multiple descriptors are linked by means of the next pointer. An additional + * extra adjacent number gives the amount of extra contiguous descriptors. + * + * The descriptors are in root complex memory, and the bytes in the 32-bit + * words must be in little-endian byte ordering. + */ +struct xdma_hw_desc { + __le32 control; + __le32 bytes; + __le64 src_addr; + __le64 dst_addr; + __le64 next_desc; +}; + +#define XDMA_DESC_SIZE sizeof(struct xdma_hw_desc) +#define XDMA_DESC_BLOCK_SIZE (XDMA_DESC_SIZE * XDMA_DESC_ADJACENT) +#define XDMA_DESC_BLOCK_ALIGN 32 +#define XDMA_DESC_BLOCK_BOUNDARY 4096 + +/* + * Channel registers + */ +#define XDMA_CHAN_IDENTIFIER 0x0 +#define XDMA_CHAN_CONTROL 0x4 +#define XDMA_CHAN_CONTROL_W1S 0x8 +#define XDMA_CHAN_CONTROL_W1C 0xc +#define XDMA_CHAN_STATUS 0x40 +#define XDMA_CHAN_STATUS_RC 0x44 +#define XDMA_CHAN_COMPLETED_DESC 0x48 +#define XDMA_CHAN_ALIGNMENTS 0x4c +#define XDMA_CHAN_INTR_ENABLE 0x90 +#define XDMA_CHAN_INTR_ENABLE_W1S 0x94 +#define XDMA_CHAN_INTR_ENABLE_W1C 0x9c + +#define XDMA_CHAN_STRIDE 0x100 +#define XDMA_CHAN_H2C_OFFSET 0x0 +#define XDMA_CHAN_C2H_OFFSET 0x1000 +#define XDMA_CHAN_H2C_TARGET 0x0 +#define XDMA_CHAN_C2H_TARGET 0x1 + +/* macro to check if channel is available */ +#define XDMA_CHAN_MAGIC 0x1fc0 +#define XDMA_CHAN_CHECK_TARGET(id, target) \ + (((u32)(id) >> 16) == XDMA_CHAN_MAGIC + (target)) + +/* bits of the channel control register */ +#define CHAN_CTRL_RUN_STOP BIT(0) +#define CHAN_CTRL_IE_DESC_STOPPED BIT(1) +#define CHAN_CTRL_IE_DESC_COMPLETED BIT(2) +#define CHAN_CTRL_IE_DESC_ALIGN_MISMATCH BIT(3) +#define CHAN_CTRL_IE_MAGIC_STOPPED BIT(4) +#define CHAN_CTRL_IE_IDLE_STOPPED BIT(6) +#define CHAN_CTRL_IE_READ_ERROR GENMASK(13, 9) +#define CHAN_CTRL_IE_WRITE_ERROR GENMASK(18, 14) +#define CHAN_CTRL_IE_DESC_ERROR GENMASK(23, 19) +#define CHAN_CTRL_NON_INCR_ADDR BIT(25) +#define CHAN_CTRL_POLL_MODE_WB BIT(26) +#define CHAN_CTRL_TRANSFER_INFO_WB BIT(27) + +#define CHAN_CTRL_START (CHAN_CTRL_RUN_STOP | \ + CHAN_CTRL_IE_DESC_STOPPED | \ + CHAN_CTRL_IE_DESC_COMPLETED | \ + CHAN_CTRL_IE_DESC_ALIGN_MISMATCH | \ + CHAN_CTRL_IE_MAGIC_STOPPED | \ + CHAN_CTRL_IE_READ_ERROR | \ + CHAN_CTRL_IE_WRITE_ERROR | \ + CHAN_CTRL_IE_DESC_ERROR) + +#define XDMA_CHAN_STATUS_MASK CHAN_CTRL_START + +#define XDMA_CHAN_ERROR_MASK (CHAN_CTRL_IE_DESC_ALIGN_MISMATCH | \ + CHAN_CTRL_IE_MAGIC_STOPPED | \ + CHAN_CTRL_IE_READ_ERROR | \ + CHAN_CTRL_IE_WRITE_ERROR | \ + CHAN_CTRL_IE_DESC_ERROR) + +/* bits of the channel interrupt enable mask */ +#define CHAN_IM_DESC_ERROR BIT(19) +#define CHAN_IM_READ_ERROR BIT(9) +#define CHAN_IM_IDLE_STOPPED BIT(6) +#define CHAN_IM_MAGIC_STOPPED BIT(4) +#define CHAN_IM_DESC_COMPLETED BIT(2) +#define CHAN_IM_DESC_STOPPED BIT(1) + +#define CHAN_IM_ALL (CHAN_IM_DESC_ERROR | CHAN_IM_READ_ERROR | \ + CHAN_IM_IDLE_STOPPED | CHAN_IM_MAGIC_STOPPED | \ + CHAN_IM_DESC_COMPLETED | CHAN_IM_DESC_STOPPED) + +/* + * Channel SGDMA registers + */ +#define XDMA_SGDMA_IDENTIFIER 0x4000 +#define XDMA_SGDMA_DESC_LO 0x4080 +#define XDMA_SGDMA_DESC_HI 0x4084 +#define XDMA_SGDMA_DESC_ADJ 0x4088 +#define XDMA_SGDMA_DESC_CREDIT 0x408c + +/* + * interrupt registers + */ +#define XDMA_IRQ_IDENTIFIER 0x2000 +#define XDMA_IRQ_USER_INT_EN 0x2004 +#define XDMA_IRQ_USER_INT_EN_W1S 0x2008 +#define XDMA_IRQ_USER_INT_EN_W1C 0x200c +#define XDMA_IRQ_CHAN_INT_EN 0x2010 +#define XDMA_IRQ_CHAN_INT_EN_W1S 0x2014 +#define XDMA_IRQ_CHAN_INT_EN_W1C 0x2018 +#define XDMA_IRQ_USER_INT_REQ 0x2040 +#define XDMA_IRQ_CHAN_INT_REQ 0x2044 +#define XDMA_IRQ_USER_INT_PEND 0x2048 +#define XDMA_IRQ_CHAN_INT_PEND 0x204c +#define XDMA_IRQ_USER_VEC_NUM 0x2080 +#define XDMA_IRQ_CHAN_VEC_NUM 0x20a0 + +#define XDMA_IRQ_VEC_SHIFT 8 + +#endif /* __DMA_XDMA_REGS_H */ diff --git a/snd-alpx-dkms/snd-alpx/core/generic/6.3/xilinx/xdma.c b/snd-alpx-dkms/snd-alpx/core/generic/6.3/xilinx/xdma.c new file mode 100644 index 0000000..ad42f05 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/core/generic/6.3/xilinx/xdma.c @@ -0,0 +1,1403 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * DMA driver for Xilinx DMA/Bridge Subsystem + * + * Copyright (C) 2017-2020 Xilinx, Inc. All rights reserved. + * Copyright (C) 2022, Advanced Micro Devices, Inc. + */ + +/* + * The DMA/Bridge Subsystem for PCI Express allows for the movement of data + * between Host memory and the DMA subsystem. It does this by operating on + * 'descriptors' that contain information about the source, destination and + * amount of data to transfer. These direct memory transfers can be both in + * the Host to Card (H2C) and Card to Host (C2H) transfers. The DMA can be + * configured to have a single AXI4 Master interface shared by all channels + * or one AXI4-Stream interface for each channel enabled. Memory transfers are + * specified on a per-channel basis in descriptor linked lists, which the DMA + * fetches from host memory and processes. Events such as descriptor completion + * and errors are signaled using interrupts. The core also provides up to 16 + * user interrupt wires that generate interrupts to the host. + */ + +#include <linux/module.h> +#include <linux/mod_devicetable.h> +#include <linux/bitfield.h> +#include <linux/dmapool.h> + +#include <linux/regmap.h> + +#if KERNEL_VERSION(5, 6, 0) <= LINUX_VERSION_CODE +#include <linux/dmaengine.h> +#elif KERNEL_VERSION(5, 3, 0) <= LINUX_VERSION_CODE +#include "../../../../include/5.3/dmaengine.h" +#else +#include "../../../../include/4.16/dmaengine.h" +#endif +#include "../../../../include/6.3/amd_xdma.h" +#include <linux/platform_device.h> +#include "../amd_xdma.h" +#include <linux/dma-mapping.h> +#include <linux/pci.h> +#if KERNEL_VERSION(6, 3, 0) <= LINUX_VERSION_CODE +#include "../virt-dma.h" +#elif KERNEL_VERSION(5, 6, 0) <= LINUX_VERSION_CODE +#include "../../../../include/5.6/virt-dma.h" +#elif KERNEL_VERSION(5, 3, 0) <= LINUX_VERSION_CODE +#include "../../../../include/5.3/virt-dma.h" +#else +#include "../../../../include/4.16/virt-dma.h" +#endif +#include "xdma-regs.h" + +/* mmio regmap config for all XDMA registers */ +static const struct regmap_config xdma_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = XDMA_REG_SPACE_LEN, +}; + +/** + * struct xdma_desc_block - Descriptor block + * @virt_addr: Virtual address of block start + * @dma_addr: DMA address of block start + */ +struct xdma_desc_block { + void *virt_addr; + dma_addr_t dma_addr; +}; + +/** + * struct xdma_c2h_write_back - Write back block , written by the XDMA. + * @magic_status_bit : magic (0x52B4) once written + * @length: effective transfer length (in bytes) + * @PADDING to be aligned on 32 bytes + * @associated dma address + */ +struct xdma_c2h_write_back { + __le32 magic_status_bit; + __le32 length; + u32 padding_1[6]; + dma_addr_t dma_addr; +}; + +/** + * struct xdma_chan - Driver specific DMA channel structure + * @vchan: Virtual channel + * @xdev_hdl: Pointer to DMA device structure + * @base: Offset of channel registers + * @desc_pool: Descriptor pool + * @busy: Busy flag of the channel + * @dir: Transferring direction of the channel + * @cfg: Transferring config of the channel + * @irq: IRQ assigned to the channel + * @write_back : C2H meta data write back + */ +struct xdma_chan { + struct virt_dma_chan vchan; + void *xdev_hdl; + u32 base; + struct dma_pool *desc_pool; + bool busy; + enum dma_transfer_direction dir; + struct dma_slave_config cfg; + u32 irq; + struct xdma_c2h_write_back* write_back; +}; + +/** + * struct xdma_desc - DMA desc structure + * @vdesc: Virtual DMA descriptor + * @chan: DMA channel pointer + * @dir: Transferring direction of the request + * @desc_blocks: Hardware descriptor blocks + * @dblk_num: Number of hardware descriptor blocks + * @desc_num: Number of hardware descriptors + * @completed_desc_num: Completed hardware descriptors + * @cyclic: Cyclic transfer vs. scatter-gather + * @interleaved_dma: Interleaved DMA transfer + * @periods: Number of periods in the cyclic transfer + * @period_size: Size of a period in bytes in cyclic transfers + * @frames_left: Number of frames left in interleaved DMA transfer + * @error: tx error flag + */ +struct xdma_desc { + struct virt_dma_desc vdesc; + struct xdma_chan *chan; + enum dma_transfer_direction dir; + struct xdma_desc_block *desc_blocks; + u32 dblk_num; + u32 desc_num; + u32 completed_desc_num; + bool cyclic; + bool interleaved_dma; + u32 periods; + u32 period_size; + u32 frames_left; + bool error; +}; + +#define XDMA_DEV_STATUS_REG_DMA BIT(0) +#define XDMA_DEV_STATUS_INIT_MSIX BIT(1) + +/** + * struct xdma_device - DMA device structure + * @pdev: Platform device pointer + * @dma_dev: DMA device structure + * @rmap: MMIO regmap for DMA registers + * @h2c_chans: Host to Card channels + * @c2h_chans: Card to Host channels + * @h2c_chan_num: Number of H2C channels + * @c2h_chan_num: Number of C2H channels + * @irq_start: Start IRQ assigned to device + * @irq_num: Number of IRQ assigned to device + * @status: Initialization status + */ +struct xdma_device { + struct platform_device *pdev; + struct dma_device dma_dev; + struct regmap *rmap; + struct xdma_chan *h2c_chans; + struct xdma_chan *c2h_chans; + u32 h2c_chan_num; + u32 c2h_chan_num; + u32 irq_start; + u32 irq_num; + u32 status; +}; + +#define xdma_err(xdev, fmt, args...) \ + dev_err(&(xdev)->pdev->dev, fmt, ##args) +#define XDMA_CHAN_NUM(_xd) ({ \ + typeof(_xd) (xd) = (_xd); \ + ((xd)->h2c_chan_num + (xd)->c2h_chan_num); }) + +/* Get the last desc in a desc block */ +static inline void *xdma_blk_last_desc(struct xdma_desc_block *block) +{ + return block->virt_addr + (XDMA_DESC_ADJACENT - 1) * XDMA_DESC_SIZE; +} + +/** + * xdma_link_sg_desc_blocks - Link SG descriptor blocks for DMA transfer + * @sw_desc: Tx descriptor pointer + */ +static void xdma_link_sg_desc_blocks(struct xdma_desc *sw_desc) +{ + struct xdma_desc_block *block; + u32 last_blk_desc, desc_control; + struct xdma_hw_desc *desc; + int i; + + desc_control = XDMA_DESC_CONTROL(XDMA_DESC_ADJACENT, 0); + for (i = 1; i < sw_desc->dblk_num; i++) { + block = &sw_desc->desc_blocks[i - 1]; + desc = xdma_blk_last_desc(block); + + if (!(i & XDMA_DESC_BLOCK_MASK)) { + desc->control = cpu_to_le32(XDMA_DESC_CONTROL_LAST); + continue; + } + desc->control = cpu_to_le32(desc_control); + desc->next_desc = cpu_to_le64(block[1].dma_addr); + } + + /* update the last block */ + last_blk_desc = (sw_desc->desc_num - 1) & XDMA_DESC_ADJACENT_MASK; + if (((sw_desc->dblk_num - 1) & XDMA_DESC_BLOCK_MASK) > 0) { + block = &sw_desc->desc_blocks[sw_desc->dblk_num - 2]; + desc = xdma_blk_last_desc(block); + desc_control = XDMA_DESC_CONTROL(last_blk_desc + 1, 0); + desc->control = cpu_to_le32(desc_control); + } + + block = &sw_desc->desc_blocks[sw_desc->dblk_num - 1]; + desc = block->virt_addr + last_blk_desc * XDMA_DESC_SIZE; + desc->control = cpu_to_le32(XDMA_DESC_CONTROL_LAST); +} + +/** + * xdma_link_cyclic_desc_blocks - Link cyclic descriptor blocks for DMA transfer + * @sw_desc: Tx descriptor pointer + */ +static void xdma_link_cyclic_desc_blocks(struct xdma_desc *sw_desc) +{ + struct xdma_desc_block *block; + struct xdma_hw_desc *desc; + int i; + + block = sw_desc->desc_blocks; + for (i = 0; i < sw_desc->desc_num - 1; i++) { + desc = block->virt_addr + i * XDMA_DESC_SIZE; + desc->next_desc = cpu_to_le64(block->dma_addr + ((i + 1) * XDMA_DESC_SIZE)); + } + desc = block->virt_addr + i * XDMA_DESC_SIZE; + desc->next_desc = cpu_to_le64(block->dma_addr); +} + +static inline struct xdma_chan *to_xdma_chan(struct dma_chan *chan) +{ + return container_of(chan, struct xdma_chan, vchan.chan); +} + +static inline struct xdma_desc *to_xdma_desc(struct virt_dma_desc *vdesc) +{ + return container_of(vdesc, struct xdma_desc, vdesc); +} + +/** + * xdma_channel_init - Initialize DMA channel registers + * @chan: DMA channel pointer + */ +static int xdma_channel_init(struct xdma_chan *chan) +{ + struct xdma_device *xdev = chan->xdev_hdl; + int ret; + unsigned int reg_ctrl = 0; + + regmap_read(xdev->rmap, chan->base + XDMA_CHAN_CONTROL, ®_ctrl); + dev_dbg(&xdev->pdev->dev, "CONTROL Init: 0x%08x\n", reg_ctrl); + + ret = regmap_write(xdev->rmap, chan->base + XDMA_CHAN_CONTROL_W1C, + CHAN_CTRL_NON_INCR_ADDR | CHAN_CTRL_TRANSFER_INFO_WB); + if (ret) + return ret; + + regmap_read(xdev->rmap, chan->base + XDMA_CHAN_CONTROL, ®_ctrl); + dev_dbg(&xdev->pdev->dev, "CONTROL Init: 0x%08x\n", reg_ctrl); + + ret = regmap_write(xdev->rmap, chan->base + XDMA_CHAN_INTR_ENABLE, + CHAN_IM_ALL); + if (ret) + return ret; + + return 0; +} + +/** + * xdma_free_desc - Free descriptor + * @vdesc: Virtual DMA descriptor + */ +static void xdma_free_desc(struct virt_dma_desc *vdesc) +{ + struct xdma_desc *sw_desc; + int i; + + sw_desc = to_xdma_desc(vdesc); + for (i = 0; i < sw_desc->dblk_num; i++) { + if (!sw_desc->desc_blocks[i].virt_addr) + break; + dma_pool_free(sw_desc->chan->desc_pool, + sw_desc->desc_blocks[i].virt_addr, + sw_desc->desc_blocks[i].dma_addr); + } + kfree(sw_desc->desc_blocks); + kfree(sw_desc); +} + +/** + * xdma_alloc_desc - Allocate descriptor + * @chan: DMA channel pointer + * @desc_num: Number of hardware descriptors + * @cyclic: Whether this is a cyclic transfer + */ +static struct xdma_desc * +xdma_alloc_desc(struct xdma_chan *chan, u32 desc_num, bool cyclic) +{ + struct xdma_desc *sw_desc; + struct xdma_hw_desc *desc; + dma_addr_t dma_addr; + u32 dblk_num; + u32 control; + void *addr; + int i, j; + + sw_desc = kzalloc(sizeof(*sw_desc), GFP_NOWAIT); + if (!sw_desc) + return NULL; + + sw_desc->chan = chan; + sw_desc->desc_num = desc_num; + sw_desc->cyclic = cyclic; + sw_desc->error = false; + dblk_num = DIV_ROUND_UP(desc_num, XDMA_DESC_ADJACENT); + sw_desc->desc_blocks = kcalloc(dblk_num, sizeof(*sw_desc->desc_blocks), + GFP_NOWAIT); + if (!sw_desc->desc_blocks) + goto failed; + + if (cyclic) + control = XDMA_DESC_CONTROL_CYCLIC; + else + control = XDMA_DESC_CONTROL(1, 0); + + sw_desc->dblk_num = dblk_num; + for (i = 0; i < sw_desc->dblk_num; i++) { + addr = dma_pool_alloc(chan->desc_pool, GFP_NOWAIT, &dma_addr); + if (!addr) + goto failed; + + sw_desc->desc_blocks[i].virt_addr = addr; + sw_desc->desc_blocks[i].dma_addr = dma_addr; + for (j = 0, desc = addr; j < XDMA_DESC_ADJACENT; j++) + desc[j].control = cpu_to_le32(control); + } + + if (cyclic) + xdma_link_cyclic_desc_blocks(sw_desc); + else + xdma_link_sg_desc_blocks(sw_desc); + + return sw_desc; + +failed: + xdma_free_desc(&sw_desc->vdesc); + return NULL; +} + +/** + * xdma_xfer_start - Start DMA transfer + * @xchan: DMA channel pointer + */ +static int xdma_xfer_start(struct xdma_chan *xchan) +{ + struct virt_dma_desc *vd = vchan_next_desc(&xchan->vchan); + struct xdma_device *xdev = xchan->xdev_hdl; + struct xdma_desc_block *block; + u32 val, completed_blocks; + struct xdma_desc *desc; + int ret; + + /* + * check if there is not any submitted descriptor or channel is busy. + * vchan lock should be held where this function is called. + */ + if (!vd || xchan->busy) + return -EINVAL; + + /* clear run stop bit to get ready for transfer */ + ret = regmap_write(xdev->rmap, xchan->base + XDMA_CHAN_CONTROL_W1C, + CHAN_CTRL_RUN_STOP); + if (ret) + return ret; + + desc = to_xdma_desc(vd); + if (desc->dir != xchan->dir) { + xdma_err(xdev, "incorrect request direction"); + return -EINVAL; + } + + /* set DMA engine to the first descriptor block */ + completed_blocks = desc->completed_desc_num / XDMA_DESC_ADJACENT; + block = &desc->desc_blocks[completed_blocks]; + val = lower_32_bits(block->dma_addr); + ret = regmap_write(xdev->rmap, xchan->base + XDMA_SGDMA_DESC_LO, val); + if (ret) + return ret; + + val = upper_32_bits(block->dma_addr); + ret = regmap_write(xdev->rmap, xchan->base + XDMA_SGDMA_DESC_HI, val); + if (ret) + return ret; + + if (completed_blocks + 1 == desc->dblk_num) + val = (desc->desc_num - 1) & XDMA_DESC_ADJACENT_MASK; + else + val = XDMA_DESC_ADJACENT - 1; + ret = regmap_write(xdev->rmap, xchan->base + XDMA_SGDMA_DESC_ADJ, val); + if (ret) + return ret; + + /* kick off DMA transfer, force 0=1 transition, USE Bit clear/set registers */ + + regmap_write(xdev->rmap, xchan->base + XDMA_CHAN_CONTROL_W1C, + CHAN_CTRL_START); + + ret = regmap_write(xdev->rmap, xchan->base + XDMA_CHAN_CONTROL_W1S, + CHAN_CTRL_START); + if (ret) + return ret; + + xchan->busy = true; + + return 0; +} + +/** + * xdma_xfer_stop - Stop DMA transfer + * @xchan: DMA channel pointer + */ +static int xdma_xfer_stop(struct xdma_chan *xchan) +{ + int ret; + u32 val; + struct xdma_device *xdev = xchan->xdev_hdl; + + /* clear run stop bit to prevent any further auto-triggering */ + ret = regmap_write(xdev->rmap, xchan->base + XDMA_CHAN_CONTROL_W1C, + CHAN_CTRL_RUN_STOP); + if (ret) + return ret; + + /* Clear the channel status register */ + ret = regmap_read(xdev->rmap, xchan->base + XDMA_CHAN_STATUS_RC, &val); + if (ret) + return ret; + + return 0; +} + +/** + * xdma_alloc_channels - Detect and allocate DMA channels + * @xdev: DMA device pointer + * @dir: Channel direction + */ +static int xdma_alloc_channels(struct xdma_device *xdev, + enum dma_transfer_direction dir) +{ + struct xdma_platdata *pdata = dev_get_platdata(&xdev->pdev->dev); + struct xdma_chan **chans, *xchan; + u32 base, identifier, target; + u32 *chan_num; + int i, j, ret; + + if (dir == DMA_MEM_TO_DEV) { + base = XDMA_CHAN_H2C_OFFSET; + target = XDMA_CHAN_H2C_TARGET; + chans = &xdev->h2c_chans; + chan_num = &xdev->h2c_chan_num; + } else if (dir == DMA_DEV_TO_MEM) { + base = XDMA_CHAN_C2H_OFFSET; + target = XDMA_CHAN_C2H_TARGET; + chans = &xdev->c2h_chans; + chan_num = &xdev->c2h_chan_num; + } else { + xdma_err(xdev, "invalid direction specified"); + return -EINVAL; + } + + /* detect number of available DMA channels */ + for (i = 0, *chan_num = 0; i < pdata->max_dma_channels; i++) { + ret = regmap_read(xdev->rmap, base + i * XDMA_CHAN_STRIDE, + &identifier); + if (ret) + return ret; + + /* check if it is available DMA channel */ + if (XDMA_CHAN_CHECK_TARGET(identifier, target)) + (*chan_num)++; + } + + if (!*chan_num) { + xdma_err(xdev, "does not probe any channel"); + return -EINVAL; + } + + *chans = devm_kcalloc(&xdev->pdev->dev, *chan_num, sizeof(**chans), + GFP_KERNEL); + if (!*chans) + return -ENOMEM; + + for (i = 0, j = 0; i < pdata->max_dma_channels; i++) { + ret = regmap_read(xdev->rmap, base + i * XDMA_CHAN_STRIDE, + &identifier); + if (ret) + return ret; + + if (!XDMA_CHAN_CHECK_TARGET(identifier, target)) + continue; + + if (j == *chan_num) { + xdma_err(xdev, "invalid channel number"); + return -EIO; + } + + /* init channel structure and hardware */ + xchan = &(*chans)[j]; + xchan->xdev_hdl = xdev; + xchan->base = base + i * XDMA_CHAN_STRIDE; + xchan->dir = dir; + + ret = xdma_channel_init(xchan); + if (ret) + return ret; + xchan->vchan.desc_free = xdma_free_desc; + vchan_init(&xchan->vchan, &xdev->dma_dev); + + j++; + } + + dev_info(&xdev->pdev->dev, "configured %d %s channels", j, + (dir == DMA_MEM_TO_DEV) ? "H2C" : "C2H"); + + return 0; +} + +/** + * xdma_issue_pending - Issue pending transactions + * @chan: DMA channel pointer + */ +static void xdma_issue_pending(struct dma_chan *chan) +{ + struct xdma_chan *xdma_chan = to_xdma_chan(chan); + unsigned long flags; + + spin_lock_irqsave(&xdma_chan->vchan.lock, flags); + if (vchan_issue_pending(&xdma_chan->vchan)) + xdma_xfer_start(xdma_chan); + spin_unlock_irqrestore(&xdma_chan->vchan.lock, flags); +} + +/** + * xdma_terminate_all - Terminate all transactions + * @chan: DMA channel pointer + */ +static int xdma_terminate_all(struct dma_chan *chan) +{ + struct xdma_chan *xdma_chan = to_xdma_chan(chan); + struct virt_dma_desc *vd; + unsigned long flags; + LIST_HEAD(head); + + xdma_xfer_stop(xdma_chan); + + spin_lock_irqsave(&xdma_chan->vchan.lock, flags); + + xdma_chan->busy = false; + vd = vchan_next_desc(&xdma_chan->vchan); + if (vd) { + list_del(&vd->node); + dma_cookie_complete(&vd->tx); + vchan_terminate_vdesc(vd); + } + vchan_get_all_descriptors(&xdma_chan->vchan, &head); + list_splice_tail(&head, &xdma_chan->vchan.desc_terminated); + + spin_unlock_irqrestore(&xdma_chan->vchan.lock, flags); + + return 0; +} + +/** + * xdma_synchronize - Synchronize terminated transactions + * @chan: DMA channel pointer + */ +static void xdma_synchronize(struct dma_chan *chan) +{ + struct xdma_chan *xdma_chan = to_xdma_chan(chan); + + vchan_synchronize(&xdma_chan->vchan); +} + +/** + * xdma_fill_descs - Fill hardware descriptors for one contiguous memory chunk. + * More than one descriptor will be used if the size is bigger + * than XDMA_DESC_BLEN_MAX. + * @sw_desc: Descriptor container + * @src_addr: First value for the ->src_addr field + * @dst_addr: First value for the ->dst_addr field + * @size: Size of the contiguous memory block + * @desc_start_num: Index of the first descriptor to take care of in @sw_desc + */ +static inline u32 xdma_fill_descs(struct xdma_desc *sw_desc, u64 src_addr, + u64 dst_addr, u32 size, u32 filled_descs_num) +{ + u32 left = size, len, desc_num = filled_descs_num; + struct xdma_desc_block *dblk; + struct xdma_hw_desc *desc; + + dblk = sw_desc->desc_blocks + (desc_num / XDMA_DESC_ADJACENT); + desc = dblk->virt_addr; + desc += desc_num & XDMA_DESC_ADJACENT_MASK; + do { + len = min_t(u32, left, XDMA_DESC_BLEN_MAX); + /* set hardware descriptor */ + desc->bytes = cpu_to_le32(len); + desc->src_addr = cpu_to_le64(src_addr); + desc->dst_addr = cpu_to_le64(dst_addr); + + dev_dbg(NULL, "desc[%u]:%p {src:0x%llx, dst: 0x%llx, length: %u}", + desc_num, + desc, + src_addr, + dst_addr, + len); + + if (!(++desc_num & XDMA_DESC_ADJACENT_MASK)) + desc = (++dblk)->virt_addr; + else + desc++; + + src_addr += len; + dst_addr += len; + left -= len; + } while (left); + + return desc_num - filled_descs_num; +} + +/** + * xdma_prep_device_sg - prepare a descriptor for a DMA transaction + * @chan: DMA channel pointer + * @sgl: Transfer scatter gather list + * @sg_len: Length of scatter gather list + * @dir: Transfer direction + * @flags: transfer ack flags + * @context: APP words of the descriptor + */ +static struct dma_async_tx_descriptor * +xdma_prep_device_sg(struct dma_chan *chan, struct scatterlist *sgl, + unsigned int sg_len, enum dma_transfer_direction dir, + unsigned long flags, void *context) +{ + struct xdma_chan *xdma_chan = to_xdma_chan(chan); + struct xdma_device *xdev = xdma_chan ->xdev_hdl; + + struct dma_async_tx_descriptor *tx_desc; + struct xdma_desc *sw_desc; + u32 desc_num = 0, i; + u64 addr, dev_addr, *src, *dst; + struct scatterlist *sg; + + for_each_sg(sgl, sg, sg_len, i) + desc_num += DIV_ROUND_UP(sg_dma_len(sg), XDMA_DESC_BLEN_MAX); + + sw_desc = xdma_alloc_desc(xdma_chan, desc_num, false); + if (!sw_desc) + return NULL; + sw_desc->dir = dir; + sw_desc->cyclic = false; + sw_desc->interleaved_dma = false; + + if (dir == DMA_MEM_TO_DEV) { + dev_addr = xdma_chan->cfg.dst_addr; + src = &addr; + dst = &dev_addr; + } else { + dev_addr = xdma_chan->cfg.src_addr ? xdma_chan->cfg.src_addr : xdma_chan->write_back->dma_addr; + src = &dev_addr; + dst = &addr; + } + + dev_dbg(&xdev->pdev->dev, "desc[%s]:%p {src: %p, dst: %p, length: %u}", + dir == DMA_MEM_TO_DEV ? "C2H" : "H2C", + sw_desc, + src, + dst, + sg_dma_len(sg)); + + + desc_num = 0; + for_each_sg(sgl, sg, sg_len, i) { + addr = sg_dma_address(sg); + desc_num += xdma_fill_descs(sw_desc, *src, *dst, sg_dma_len(sg), desc_num); + dev_addr += sg_dma_len(sg); + } + + tx_desc = vchan_tx_prep(&xdma_chan->vchan, &sw_desc->vdesc, flags); + if (!tx_desc) + goto failed; + + return tx_desc; + +failed: + xdma_free_desc(&sw_desc->vdesc); + + return NULL; +} + +/** + * xdma_prep_dma_cyclic - prepare for cyclic DMA transactions + * @chan: DMA channel pointer + * @address: Device DMA address to access + * @size: Total length to transfer + * @period_size: Period size to use for each transfer + * @dir: Transfer direction + * @flags: Transfer ack flags + */ +static struct dma_async_tx_descriptor * +xdma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t address, + size_t size, size_t period_size, + enum dma_transfer_direction dir, + unsigned long flags) +{ + struct xdma_chan *xdma_chan = to_xdma_chan(chan); + struct xdma_device *xdev = xdma_chan->xdev_hdl; + unsigned int periods = size / period_size; + struct dma_async_tx_descriptor *tx_desc; + struct xdma_desc *sw_desc; + u64 addr, dev_addr, *src, *dst; + u32 desc_num = 0; + unsigned int i; + + /* + * Simplify the whole logic by preventing an abnormally high number of + * periods and periods size. + */ + if (period_size > XDMA_DESC_BLEN_MAX) { + xdma_err(xdev, "period size limited to %lu bytes\n", XDMA_DESC_BLEN_MAX); + return NULL; + } + + if (periods > XDMA_DESC_ADJACENT) { + xdma_err(xdev, "number of periods limited to %u\n", XDMA_DESC_ADJACENT); + return NULL; + } + + sw_desc = xdma_alloc_desc(xdma_chan, periods, true); + if (!sw_desc) + return NULL; + + sw_desc->periods = periods; + sw_desc->period_size = period_size; + sw_desc->dir = dir; + sw_desc->interleaved_dma = false; + + addr = address; + if (dir == DMA_MEM_TO_DEV) { + dev_addr = xdma_chan->cfg.dst_addr; + src = &addr; + dst = &dev_addr; + } else { + dev_addr = xdma_chan->cfg.src_addr ? xdma_chan->cfg.src_addr : xdma_chan->write_back->dma_addr; + src = &dev_addr; + dst = &addr; + } + + dev_dbg(&xdev->pdev->dev, "desc[%s]:%p {src: %p, dst: %p, length: %lu}", + dir == DMA_MEM_TO_DEV ? "C2H" : "H2C", + sw_desc, + src, + dst, + period_size); + + for (i = 0; i < periods; i++) { + xdma_fill_descs(sw_desc, *src, *dst, period_size, desc_num++); + addr += period_size; + } + + tx_desc = vchan_tx_prep(&xdma_chan->vchan, &sw_desc->vdesc, flags); + if (!tx_desc) + goto failed; + + return tx_desc; + +failed: + xdma_free_desc(&sw_desc->vdesc); + + return NULL; +} + +/** + * xdma_prep_interleaved_dma - Prepare virtual descriptor for interleaved DMA transfers + * @chan: DMA channel + * @xt: DMA transfer template + * @flags: tx flags + */ +static struct dma_async_tx_descriptor * +xdma_prep_interleaved_dma(struct dma_chan *chan, + struct dma_interleaved_template *xt, + unsigned long flags) +{ + int i; + u32 desc_num = 0, period_size = 0; + struct dma_async_tx_descriptor *tx_desc; + struct xdma_chan *xchan = to_xdma_chan(chan); + struct xdma_desc *sw_desc; + u64 src_addr, dst_addr; + + for (i = 0; i < xt->frame_size; ++i) + desc_num += DIV_ROUND_UP(xt->sgl[i].size, XDMA_DESC_BLEN_MAX); + + sw_desc = xdma_alloc_desc(xchan, desc_num, false); + if (!sw_desc) + return NULL; + sw_desc->dir = xt->dir; + sw_desc->interleaved_dma = true; + sw_desc->cyclic = flags & DMA_PREP_REPEAT; + sw_desc->frames_left = xt->numf; + sw_desc->periods = xt->numf; + + desc_num = 0; + src_addr = xt->src_start; + dst_addr = xt->dst_start; + for (i = 0; i < xt->frame_size; ++i) { + desc_num += xdma_fill_descs(sw_desc, src_addr, dst_addr, xt->sgl[i].size, desc_num); + src_addr += dmaengine_get_src_icg(xt, &xt->sgl[i]) + (xt->src_inc ? + xt->sgl[i].size : 0); + dst_addr += dmaengine_get_dst_icg(xt, &xt->sgl[i]) + (xt->dst_inc ? + xt->sgl[i].size : 0); + period_size += xt->sgl[i].size; + } + sw_desc->period_size = period_size; + + tx_desc = vchan_tx_prep(&xchan->vchan, &sw_desc->vdesc, flags); + if (tx_desc) + return tx_desc; + + xdma_free_desc(&sw_desc->vdesc); + return NULL; +} + +/** + * xdma_device_config - Configure the DMA channel + * @chan: DMA channel + * @cfg: channel configuration + */ +static int xdma_device_config(struct dma_chan *chan, + struct dma_slave_config *cfg) +{ + struct xdma_chan *xdma_chan = to_xdma_chan(chan); + + memcpy(&xdma_chan->cfg, cfg, sizeof(*cfg)); + + return 0; +} + +/** + * xdma_free_chan_resources - Free channel resources + * @chan: DMA channel + */ +static void xdma_free_chan_resources(struct dma_chan *chan) +{ + struct xdma_chan *xdma_chan = to_xdma_chan(chan); + + vchan_free_chan_resources(&xdma_chan->vchan); + dma_pool_free(xdma_chan->desc_pool, + xdma_chan->write_back, + xdma_chan->write_back->dma_addr); + dma_pool_destroy(xdma_chan->desc_pool); + xdma_chan->desc_pool = NULL; +} + +/** + * xdma_alloc_chan_resources - Allocate channel resources + * @chan: DMA channel + */ +static int xdma_alloc_chan_resources(struct dma_chan *chan) +{ + struct xdma_chan *xdma_chan = to_xdma_chan(chan); + struct xdma_device *xdev = xdma_chan->xdev_hdl; + struct device *dev = xdev->dma_dev.dev; + dma_addr_t write_back_addr; + + while (dev && !dev_is_pci(dev)) + dev = dev->parent; + if (!dev) { + xdma_err(xdev, "unable to find pci device"); + return -EINVAL; + } + + //Allocate the pool WITH the H2C write back + xdma_chan->desc_pool = dma_pool_create(dma_chan_name(chan), dev, XDMA_DESC_BLOCK_SIZE + + sizeof(struct xdma_c2h_write_back), + XDMA_DESC_BLOCK_ALIGN, XDMA_DESC_BLOCK_BOUNDARY); + if (!xdma_chan->desc_pool) { + xdma_err(xdev, "unable to allocate descriptor pool"); + return -ENOMEM; + } + + /* Allocate the C2H write back out of the pool*/ + + xdma_chan->write_back = dma_pool_alloc(xdma_chan->desc_pool, GFP_NOWAIT, &write_back_addr); + + dev_dbg(dev, "C2H write_back : %p, dma_addr: %lld", xdma_chan->write_back, write_back_addr); + + if (!xdma_chan->write_back) { + xdma_err(xdev, "unable to allocate C2H write back block"); + return -ENOMEM; + } + xdma_chan->write_back->dma_addr = write_back_addr; + + + return 0; +} + +static enum dma_status xdma_tx_status(struct dma_chan *chan, dma_cookie_t cookie, + struct dma_tx_state *state) +{ + struct xdma_chan *xdma_chan = to_xdma_chan(chan); + struct xdma_desc *desc = NULL; + struct virt_dma_desc *vd; + enum dma_status ret; + unsigned long flags; + unsigned int period_idx; + u32 residue = 0; + + ret = dma_cookie_status(chan, cookie, state); + if (ret == DMA_COMPLETE) + return ret; + + spin_lock_irqsave(&xdma_chan->vchan.lock, flags); + + vd = vchan_find_desc(&xdma_chan->vchan, cookie); + if (!vd) + goto out; + + desc = to_xdma_desc(vd); + if (desc->error) { + ret = DMA_ERROR; + } else if (desc->cyclic) { + period_idx = desc->completed_desc_num % desc->periods; + residue = (desc->periods - period_idx) * desc->period_size; + dma_set_residue(state, residue); + } +out: + spin_unlock_irqrestore(&xdma_chan->vchan.lock, flags); + + return ret; +} + +/** + * xdma_channel_isr - XDMA channel interrupt handler + * @irq: IRQ number + * @dev_id: Pointer to the DMA channel structure + */ +static irqreturn_t xdma_channel_isr(int irq, void *dev_id) +{ + struct xdma_chan *xchan = dev_id; + u32 complete_desc_num = 0; + struct xdma_device *xdev = xchan->xdev_hdl; + struct virt_dma_desc *vd, *next_vd; + struct xdma_desc *desc; + int ret; + u32 st; + bool repeat_tx; + + spin_lock(&xchan->vchan.lock); + + /* get submitted request */ + vd = vchan_next_desc(&xchan->vchan); + if (!vd) + goto out; + + /* Clear-on-read the status register */ + ret = regmap_read(xdev->rmap, xchan->base + XDMA_CHAN_STATUS_RC, &st); + if (ret) + goto out; + + desc = to_xdma_desc(vd); + + st &= XDMA_CHAN_STATUS_MASK; + if ((st & XDMA_CHAN_ERROR_MASK) || + !(st & (CHAN_CTRL_IE_DESC_COMPLETED | CHAN_CTRL_IE_DESC_STOPPED))) { + desc->error = true; + xdma_err(xdev, "channel error, status register value: 0x%x", st); + goto out; + } + + ret = regmap_read(xdev->rmap, xchan->base + XDMA_CHAN_COMPLETED_DESC, + &complete_desc_num); + if (ret) + goto out; + + if (desc->interleaved_dma) { + xchan->busy = false; + desc->completed_desc_num += complete_desc_num; + if (complete_desc_num == XDMA_DESC_BLOCK_NUM * XDMA_DESC_ADJACENT) { + xdma_xfer_start(xchan); + goto out; + } + + /* last desc of any frame */ + desc->frames_left--; + if (desc->frames_left) + goto out; + + /* last desc of the last frame */ + repeat_tx = vd->tx.flags & DMA_PREP_REPEAT; + next_vd = list_first_entry_or_null(&vd->node, struct virt_dma_desc, node); + if (next_vd) + repeat_tx = repeat_tx && !(next_vd->tx.flags & DMA_PREP_LOAD_EOT); + if (repeat_tx) { + desc->frames_left = desc->periods; + desc->completed_desc_num = 0; + vchan_cyclic_callback(vd); + } else { + list_del(&vd->node); + vchan_cookie_complete(vd); + } + /* start (or continue) the tx of a first desc on the vc.desc_issued list, if any */ + xdma_xfer_start(xchan); + } else if (!desc->cyclic) { + xchan->busy = false; + desc->completed_desc_num += complete_desc_num; + + /* if all data blocks are transferred, remove and complete the request */ + if (desc->completed_desc_num == desc->desc_num) { + list_del(&vd->node); + vchan_cookie_complete(vd); + goto out; + } + + if (desc->completed_desc_num > desc->desc_num || + complete_desc_num != XDMA_DESC_BLOCK_NUM * XDMA_DESC_ADJACENT) + goto out; + + /* transfer the rest of data */ + xdma_xfer_start(xchan); + } else { + desc->completed_desc_num = complete_desc_num; + vchan_cyclic_callback(vd); + } + +out: + spin_unlock(&xchan->vchan.lock); + return IRQ_HANDLED; +} + +/** + * xdma_irq_fini - Uninitialize IRQ + * @xdev: DMA device pointer + */ +static void xdma_irq_fini(struct xdma_device *xdev) +{ + int i; + + /* disable interrupt */ + regmap_write(xdev->rmap, XDMA_IRQ_CHAN_INT_EN_W1C, ~0); + + /* free irq handler */ + for (i = 0; i < xdev->h2c_chan_num; i++) + free_irq(xdev->h2c_chans[i].irq, &xdev->h2c_chans[i]); + + for (i = 0; i < xdev->c2h_chan_num; i++) + free_irq(xdev->c2h_chans[i].irq, &xdev->c2h_chans[i]); +} + +/** + * xdma_set_vector_reg - configure hardware IRQ registers + * @xdev: DMA device pointer + * @vec_tbl_start: Start of IRQ registers + * @irq_start: Start of IRQ + * @irq_num: Number of IRQ + */ +static int xdma_set_vector_reg(struct xdma_device *xdev, u32 vec_tbl_start, + u32 irq_start, u32 irq_num) +{ + u32 shift, i, val = 0; + int ret; + + /* Each IRQ register is 32 bit and contains 4 IRQs */ + while (irq_num > 0) { + for (i = 0; i < 4; i++) { + shift = XDMA_IRQ_VEC_SHIFT * i; + val |= irq_start << shift; + irq_start++; + irq_num--; + if (!irq_num) + break; + } + + /* write IRQ register */ + ret = regmap_write(xdev->rmap, vec_tbl_start, val); + if (ret) + return ret; + vec_tbl_start += sizeof(u32); + val = 0; + } + + return 0; +} + +/** + * xdma_irq_init - initialize IRQs + * @xdev: DMA device pointer + */ +static int xdma_irq_init(struct xdma_device *xdev) +{ + u32 irq = xdev->irq_start; + u32 user_irq_start; + int i, j, ret; + + /* return failure if there are not enough IRQs */ + if (xdev->irq_num < XDMA_CHAN_NUM(xdev)) { + xdma_err(xdev, "not enough irq"); + return -EINVAL; + } + + /* setup H2C interrupt handler */ + for (i = 0; i < xdev->h2c_chan_num; i++) { + ret = request_irq(irq, xdma_channel_isr, 0, + "xdma-h2c-channel", &xdev->h2c_chans[i]); + if (ret) { + xdma_err(xdev, "H2C channel%d request irq%d failed: %d", + i, irq, ret); + goto failed_init_h2c; + } + xdev->h2c_chans[i].irq = irq; + irq++; + } + + /* setup C2H interrupt handler */ + for (j = 0; j < xdev->c2h_chan_num; j++) { + ret = request_irq(irq, xdma_channel_isr, 0, + "xdma-c2h-channel", &xdev->c2h_chans[j]); + if (ret) { + xdma_err(xdev, "C2H channel%d request irq%d failed: %d", + j, irq, ret); + goto failed_init_c2h; + } + xdev->c2h_chans[j].irq = irq; + irq++; + } + + /* config hardware IRQ registers */ + ret = xdma_set_vector_reg(xdev, XDMA_IRQ_CHAN_VEC_NUM, 0, + XDMA_CHAN_NUM(xdev)); + if (ret) { + xdma_err(xdev, "failed to set channel vectors: %d", ret); + goto failed_init_c2h; + } + + /* config user IRQ registers if needed */ + user_irq_start = XDMA_CHAN_NUM(xdev); + if (xdev->irq_num > user_irq_start) { + ret = xdma_set_vector_reg(xdev, XDMA_IRQ_USER_VEC_NUM, + user_irq_start, + xdev->irq_num - user_irq_start); + if (ret) { + xdma_err(xdev, "failed to set user vectors: %d", ret); + goto failed_init_c2h; + } + } + + /* enable interrupt */ + ret = regmap_write(xdev->rmap, XDMA_IRQ_CHAN_INT_EN_W1S, ~0); + if (ret) + goto failed_init_c2h; + + return 0; + +failed_init_c2h: + while (j--) + free_irq(xdev->c2h_chans[j].irq, &xdev->c2h_chans[j]); +failed_init_h2c: + while (i--) + free_irq(xdev->h2c_chans[i].irq, &xdev->h2c_chans[i]); + + return ret; +} + +static bool xdma_filter_fn(struct dma_chan *chan, void *param) +{ + struct xdma_chan *xdma_chan = to_xdma_chan(chan); + struct xdma_chan_info *chan_info = param; + + return chan_info->dir == xdma_chan->dir; +} + +/** + * xdma_disable_user_irq - Disable user interrupt + * @pdev: Pointer to the platform_device structure + * @irq_num: System IRQ number + */ +void xdma_disable_user_irq(struct platform_device *pdev, u32 irq_num) +{ + struct xdma_device *xdev = platform_get_drvdata(pdev); + u32 index; + + index = irq_num - xdev->irq_start; + if (index < XDMA_CHAN_NUM(xdev) || index >= xdev->irq_num) { + xdma_err(xdev, "invalid user irq number"); + return; + } + index -= XDMA_CHAN_NUM(xdev); + + regmap_write(xdev->rmap, XDMA_IRQ_USER_INT_EN_W1C, 1 << index); +} +EXPORT_SYMBOL(xdma_disable_user_irq); + +/** + * xdma_enable_user_irq - Enable user logic interrupt + * @pdev: Pointer to the platform_device structure + * @irq_num: System IRQ number + */ +int xdma_enable_user_irq(struct platform_device *pdev, u32 irq_num) +{ + struct xdma_device *xdev = platform_get_drvdata(pdev); + u32 index; + int ret; + + index = irq_num - xdev->irq_start; + if (index < XDMA_CHAN_NUM(xdev) || index >= xdev->irq_num) { + xdma_err(xdev, "invalid user irq number"); + return -EINVAL; + } + index -= XDMA_CHAN_NUM(xdev); + + ret = regmap_write(xdev->rmap, XDMA_IRQ_USER_INT_EN_W1S, 1 << index); + if (ret) + return ret; + + return 0; +} +EXPORT_SYMBOL(xdma_enable_user_irq); + +/** + * xdma_get_user_irq - Get system IRQ number + * @pdev: Pointer to the platform_device structure + * @user_irq_index: User logic IRQ wire index + * + * Return: The system IRQ number allocated for the given wire index. + */ +int xdma_get_user_irq(struct platform_device *pdev, u32 user_irq_index) +{ + struct xdma_device *xdev = platform_get_drvdata(pdev); + + if (XDMA_CHAN_NUM(xdev) + user_irq_index >= xdev->irq_num) { + xdma_err(xdev, "invalid user irq index"); + return -EINVAL; + } + + return xdev->irq_start + XDMA_CHAN_NUM(xdev) + user_irq_index; +} +EXPORT_SYMBOL(xdma_get_user_irq); + +/** + * xdma_remove - Driver remove function + * @pdev: Pointer to the platform_device structure + */ +static void xdma_remove(struct platform_device *pdev) +{ + struct xdma_device *xdev = platform_get_drvdata(pdev); + + if (xdev->status & XDMA_DEV_STATUS_INIT_MSIX) + xdma_irq_fini(xdev); + + if (xdev->status & XDMA_DEV_STATUS_REG_DMA) + dma_async_device_unregister(&xdev->dma_dev); +} + +/** + * xdma_probe - Driver probe function + * @pdev: Pointer to the platform_device structure + */ +static int xdma_probe(struct platform_device *pdev) +{ + struct xdma_platdata *pdata = dev_get_platdata(&pdev->dev); + struct xdma_device *xdev; + void __iomem *reg_base; + struct resource *res; + int ret = -ENODEV; + + if (pdata->max_dma_channels > XDMA_MAX_CHANNELS) { + dev_err(&pdev->dev, "invalid max dma channels %d", + pdata->max_dma_channels); + return -EINVAL; + } + + xdev = devm_kzalloc(&pdev->dev, sizeof(*xdev), GFP_KERNEL); + if (!xdev) + return -ENOMEM; + + platform_set_drvdata(pdev, xdev); + xdev->pdev = pdev; + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res) { + xdma_err(xdev, "failed to get irq resource"); + goto failed; + } + xdev->irq_start = res->start; + xdev->irq_num = resource_size(res); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + xdma_err(xdev, "failed to get io resource"); + goto failed; + } + + reg_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(reg_base)) { + xdma_err(xdev, "ioremap failed"); + goto failed; + } + + xdev->rmap = devm_regmap_init_mmio(&pdev->dev, reg_base, + &xdma_regmap_config); + if (IS_ERR(xdev->rmap)) { + ret = PTR_ERR(xdev->rmap); + xdma_err(xdev, "config regmap failed: %d", ret); + goto failed; + } + + INIT_LIST_HEAD(&xdev->dma_dev.channels); + + ret = xdma_alloc_channels(xdev, DMA_MEM_TO_DEV); + if (ret) { + xdma_err(xdev, "config H2C channels failed: %d", ret); + goto failed; + } + + ret = xdma_alloc_channels(xdev, DMA_DEV_TO_MEM); + if (ret) { + xdma_err(xdev, "config C2H channels failed: %d", ret); + goto failed; + } + + dma_cap_set(DMA_SLAVE, xdev->dma_dev.cap_mask); + dma_cap_set(DMA_PRIVATE, xdev->dma_dev.cap_mask); + dma_cap_set(DMA_CYCLIC, xdev->dma_dev.cap_mask); + dma_cap_set(DMA_INTERLEAVE, xdev->dma_dev.cap_mask); + dma_cap_set(DMA_REPEAT, xdev->dma_dev.cap_mask); + dma_cap_set(DMA_LOAD_EOT, xdev->dma_dev.cap_mask); + + xdev->dma_dev.dev = &pdev->dev; + xdev->dma_dev.residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT; + xdev->dma_dev.device_free_chan_resources = xdma_free_chan_resources; + xdev->dma_dev.device_alloc_chan_resources = xdma_alloc_chan_resources; + xdev->dma_dev.device_tx_status = xdma_tx_status; + xdev->dma_dev.device_prep_slave_sg = xdma_prep_device_sg; + xdev->dma_dev.device_config = xdma_device_config; + xdev->dma_dev.device_issue_pending = xdma_issue_pending; + xdev->dma_dev.device_terminate_all = xdma_terminate_all; + xdev->dma_dev.device_synchronize = xdma_synchronize; + xdev->dma_dev.filter.map = pdata->device_map; + xdev->dma_dev.filter.mapcnt = pdata->device_map_cnt; + xdev->dma_dev.filter.fn = xdma_filter_fn; + xdev->dma_dev.device_prep_dma_cyclic = xdma_prep_dma_cyclic; + xdev->dma_dev.device_prep_interleaved_dma = xdma_prep_interleaved_dma; + + ret = dma_async_device_register(&xdev->dma_dev); + if (ret) { + xdma_err(xdev, "failed to register Xilinx XDMA: %d", ret); + goto failed; + } + xdev->status |= XDMA_DEV_STATUS_REG_DMA; + + ret = xdma_irq_init(xdev); + if (ret) { + xdma_err(xdev, "failed to init msix: %d", ret); + goto failed; + } + xdev->status |= XDMA_DEV_STATUS_INIT_MSIX; + + return 0; + +failed: + xdma_remove(pdev); + + return ret; +} + +static const struct platform_device_id xdma_id_table[] = { + { "xdma", 0}, + { }, +}; + +static struct platform_driver xdma_driver = { + .driver = { + .name = "xdma", + }, + .id_table = xdma_id_table, + .probe = xdma_probe, + .remove_new = xdma_remove, +}; + +module_platform_driver(xdma_driver); + +MODULE_DESCRIPTION("AMD XDMA driver"); +MODULE_AUTHOR("XRT Team <runtimeca39d@amd.com>"); +MODULE_LICENSE("GPL"); diff --git a/snd-alpx-dkms/snd-alpx/dkms.conf b/snd-alpx-dkms/snd-alpx/dkms.conf new file mode 100644 index 0000000..4af6f73 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/dkms.conf @@ -0,0 +1,10 @@ +PACKAGE_VERSION="3.4.3" +PACKAGE_NAME="snd-alpx" +CLEAN="make clean" +MAKE[0]="make -Bj KERNEL_VERSION=${kernelver} all" +BUILT_MODULE_NAME[0]="snd-alpx" +BUILT_MODULE_NAME[1]="snd-alpx-xdma" +DEST_MODULE_LOCATION[0]="/extra/digigram" +DEST_MODULE_LOCATION[1]="/extra/digigram" +AUTOINSTALL="yes" +BUILD_EXCLUSIVE_ARCH="x86_64" diff --git a/snd-alpx-dkms/snd-alpx/include/4.16/dmaengine.h b/snd-alpx-dkms/snd-alpx/include/4.16/dmaengine.h new file mode 100644 index 0000000..501c0b0 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/include/4.16/dmaengine.h @@ -0,0 +1,174 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * The contents of this file are private to DMA engine drivers, and is not + * part of the API to be used by DMA engine users. + */ +#ifndef DMAENGINE_H +#define DMAENGINE_H + +#include <linux/bug.h> +#include <linux/dmaengine.h> + +/** + * dma_cookie_init - initialize the cookies for a DMA channel + * @chan: dma channel to initialize + */ +static inline void dma_cookie_init(struct dma_chan *chan) +{ + chan->cookie = DMA_MIN_COOKIE; + chan->completed_cookie = DMA_MIN_COOKIE; +} + +/** + * dma_cookie_assign - assign a DMA engine cookie to the descriptor + * @tx: descriptor needing cookie + * + * Assign a unique non-zero per-channel cookie to the descriptor. + * Note: caller is expected to hold a lock to prevent concurrency. + */ +static inline dma_cookie_t dma_cookie_assign(struct dma_async_tx_descriptor *tx) +{ + struct dma_chan *chan = tx->chan; + dma_cookie_t cookie; + + cookie = chan->cookie + 1; + if (cookie < DMA_MIN_COOKIE) + cookie = DMA_MIN_COOKIE; + tx->cookie = chan->cookie = cookie; + + return cookie; +} + +/** + * dma_cookie_complete - complete a descriptor + * @tx: descriptor to complete + * + * Mark this descriptor complete by updating the channels completed + * cookie marker. Zero the descriptors cookie to prevent accidental + * repeated completions. + * + * Note: caller is expected to hold a lock to prevent concurrency. + */ +static inline void dma_cookie_complete(struct dma_async_tx_descriptor *tx) +{ + BUG_ON(tx->cookie < DMA_MIN_COOKIE); + tx->chan->completed_cookie = tx->cookie; + tx->cookie = 0; +} + +/** + * dma_cookie_status - report cookie status + * @chan: dma channel + * @cookie: cookie we are interested in + * @state: dma_tx_state structure to return last/used cookies + * + * Report the status of the cookie, filling in the state structure if + * non-NULL. No locking is required. + */ +static inline enum dma_status dma_cookie_status(struct dma_chan *chan, + dma_cookie_t cookie, struct dma_tx_state *state) +{ + dma_cookie_t used, complete; + + used = chan->cookie; + complete = chan->completed_cookie; + barrier(); + if (state) { + state->last = complete; + state->used = used; + state->residue = 0; + } + return dma_async_is_complete(cookie, complete, used); +} + +static inline void dma_set_residue(struct dma_tx_state *state, u32 residue) +{ + if (state) + state->residue = residue; +} + +struct dmaengine_desc_callback { + dma_async_tx_callback callback; + dma_async_tx_callback_result callback_result; + void *callback_param; +}; + +/** + * dmaengine_desc_get_callback - get the passed in callback function + * @tx: tx descriptor + * @cb: temp struct to hold the callback info + * + * Fill the passed in cb struct with what's available in the passed in + * tx descriptor struct + * No locking is required. + */ +static inline void +dmaengine_desc_get_callback(struct dma_async_tx_descriptor *tx, + struct dmaengine_desc_callback *cb) +{ + cb->callback = tx->callback; + cb->callback_result = tx->callback_result; + cb->callback_param = tx->callback_param; +} + +/** + * dmaengine_desc_callback_invoke - call the callback function in cb struct + * @cb: temp struct that is holding the callback info + * @result: transaction result + * + * Call the callback function provided in the cb struct with the parameter + * in the cb struct. + * Locking is dependent on the driver. + */ +static inline void +dmaengine_desc_callback_invoke(struct dmaengine_desc_callback *cb, + const struct dmaengine_result *result) +{ + struct dmaengine_result dummy_result = { + .result = DMA_TRANS_NOERROR, + .residue = 0 + }; + + if (cb->callback_result) { + if (!result) + result = &dummy_result; + cb->callback_result(cb->callback_param, result); + } else if (cb->callback) { + cb->callback(cb->callback_param); + } +} + +/** + * dmaengine_desc_get_callback_invoke - get the callback in tx descriptor and + * then immediately call the callback. + * @tx: dma async tx descriptor + * @result: transaction result + * + * Call dmaengine_desc_get_callback() and dmaengine_desc_callback_invoke() + * in a single function since no work is necessary in between for the driver. + * Locking is dependent on the driver. + */ +static inline void +dmaengine_desc_get_callback_invoke(struct dma_async_tx_descriptor *tx, + const struct dmaengine_result *result) +{ + struct dmaengine_desc_callback cb; + + dmaengine_desc_get_callback(tx, &cb); + dmaengine_desc_callback_invoke(&cb, result); +} + +/** + * dmaengine_desc_callback_valid - verify the callback is valid in cb + * @cb: callback info struct + * + * Return a bool that verifies whether callback in cb is valid or not. + * No locking is required. + */ +static inline bool +dmaengine_desc_callback_valid(struct dmaengine_desc_callback *cb) +{ + return (cb->callback) ? true : false; +} + +#endif diff --git a/snd-alpx-dkms/snd-alpx/include/4.16/virt-dma.h b/snd-alpx-dkms/snd-alpx/include/4.16/virt-dma.h new file mode 100644 index 0000000..b09b75a --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/include/4.16/virt-dma.h @@ -0,0 +1,221 @@ +/* + * Virtual DMA channel support for DMAengine + * + * Copyright (C) 2012 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef VIRT_DMA_H +#define VIRT_DMA_H + +#include <linux/dmaengine.h> +#include <linux/interrupt.h> + +#include "dmaengine.h" + +struct virt_dma_desc { + struct dma_async_tx_descriptor tx; + /* protected by vc.lock */ + struct list_head node; +}; + +struct virt_dma_chan { + struct dma_chan chan; + struct tasklet_struct task; + void (*desc_free)(struct virt_dma_desc *); + + spinlock_t lock; + + /* protected by vc.lock */ + struct list_head desc_allocated; + struct list_head desc_submitted; + struct list_head desc_issued; + struct list_head desc_completed; + + struct virt_dma_desc *cyclic; + struct virt_dma_desc *vd_terminated; +}; + +static inline struct virt_dma_chan *to_virt_chan(struct dma_chan *chan) +{ + return container_of(chan, struct virt_dma_chan, chan); +} + +void vchan_dma_desc_free_list(struct virt_dma_chan *vc, struct list_head *head); +void vchan_init(struct virt_dma_chan *vc, struct dma_device *dmadev); +struct virt_dma_desc *vchan_find_desc(struct virt_dma_chan *, dma_cookie_t); +extern dma_cookie_t vchan_tx_submit(struct dma_async_tx_descriptor *); +extern int vchan_tx_desc_free(struct dma_async_tx_descriptor *); + +/** + * vchan_tx_prep - prepare a descriptor + * @vc: virtual channel allocating this descriptor + * @vd: virtual descriptor to prepare + * @tx_flags: flags argument passed in to prepare function + */ +static inline struct dma_async_tx_descriptor *vchan_tx_prep(struct virt_dma_chan *vc, + struct virt_dma_desc *vd, unsigned long tx_flags) +{ + unsigned long flags; + + dma_async_tx_descriptor_init(&vd->tx, &vc->chan); + vd->tx.flags = tx_flags; + vd->tx.tx_submit = vchan_tx_submit; + vd->tx.desc_free = vchan_tx_desc_free; + + spin_lock_irqsave(&vc->lock, flags); + list_add_tail(&vd->node, &vc->desc_allocated); + spin_unlock_irqrestore(&vc->lock, flags); + + return &vd->tx; +} + +/** + * vchan_issue_pending - move submitted descriptors to issued list + * @vc: virtual channel to update + * + * vc.lock must be held by caller + */ +static inline bool vchan_issue_pending(struct virt_dma_chan *vc) +{ + list_splice_tail_init(&vc->desc_submitted, &vc->desc_issued); + return !list_empty(&vc->desc_issued); +} + +/** + * vchan_cookie_complete - report completion of a descriptor + * @vd: virtual descriptor to update + * + * vc.lock must be held by caller + */ +static inline void vchan_cookie_complete(struct virt_dma_desc *vd) +{ + struct virt_dma_chan *vc = to_virt_chan(vd->tx.chan); + dma_cookie_t cookie; + + cookie = vd->tx.cookie; + dma_cookie_complete(&vd->tx); + dev_vdbg(vc->chan.device->dev, "txd %p[%x]: marked complete\n", + vd, cookie); + list_add_tail(&vd->node, &vc->desc_completed); + + tasklet_schedule(&vc->task); +} + +/** + * vchan_vdesc_fini - Free or reuse a descriptor + * @vd: virtual descriptor to free/reuse + */ +static inline void vchan_vdesc_fini(struct virt_dma_desc *vd) +{ + struct virt_dma_chan *vc = to_virt_chan(vd->tx.chan); + + if (dmaengine_desc_test_reuse(&vd->tx)) + list_add(&vd->node, &vc->desc_allocated); + else + vc->desc_free(vd); +} + +/** + * vchan_cyclic_callback - report the completion of a period + * @vd: virtual descriptor + */ +static inline void vchan_cyclic_callback(struct virt_dma_desc *vd) +{ + struct virt_dma_chan *vc = to_virt_chan(vd->tx.chan); + + vc->cyclic = vd; + tasklet_schedule(&vc->task); +} + +/** + * vchan_terminate_vdesc - Disable pending cyclic callback + * @vd: virtual descriptor to be terminated + * + * vc.lock must be held by caller + */ +static inline void vchan_terminate_vdesc(struct virt_dma_desc *vd) +{ + struct virt_dma_chan *vc = to_virt_chan(vd->tx.chan); + + /* free up stuck descriptor */ + if (vc->vd_terminated) + vchan_vdesc_fini(vc->vd_terminated); + + vc->vd_terminated = vd; + if (vc->cyclic == vd) + vc->cyclic = NULL; +} + +/** + * vchan_next_desc - peek at the next descriptor to be processed + * @vc: virtual channel to obtain descriptor from + * + * vc.lock must be held by caller + */ +static inline struct virt_dma_desc *vchan_next_desc(struct virt_dma_chan *vc) +{ + return list_first_entry_or_null(&vc->desc_issued, + struct virt_dma_desc, node); +} + +/** + * vchan_get_all_descriptors - obtain all submitted and issued descriptors + * @vc: virtual channel to get descriptors from + * @head: list of descriptors found + * + * vc.lock must be held by caller + * + * Removes all submitted and issued descriptors from internal lists, and + * provides a list of all descriptors found + */ +static inline void vchan_get_all_descriptors(struct virt_dma_chan *vc, + struct list_head *head) +{ + list_splice_tail_init(&vc->desc_allocated, head); + list_splice_tail_init(&vc->desc_submitted, head); + list_splice_tail_init(&vc->desc_issued, head); + list_splice_tail_init(&vc->desc_completed, head); +} + +static inline void vchan_free_chan_resources(struct virt_dma_chan *vc) +{ + struct virt_dma_desc *vd; + unsigned long flags; + LIST_HEAD(head); + + spin_lock_irqsave(&vc->lock, flags); + vchan_get_all_descriptors(vc, &head); + list_for_each_entry(vd, &head, node) + dmaengine_desc_clear_reuse(&vd->tx); + spin_unlock_irqrestore(&vc->lock, flags); + + vchan_dma_desc_free_list(vc, &head); +} + +/** + * vchan_synchronize() - synchronize callback execution to the current context + * @vc: virtual channel to synchronize + * + * Makes sure that all scheduled or active callbacks have finished running. For + * proper operation the caller has to ensure that no new callbacks are scheduled + * after the invocation of this function started. + * Free up the terminated cyclic descriptor to prevent memory leakage. + */ +static inline void vchan_synchronize(struct virt_dma_chan *vc) +{ + unsigned long flags; + + tasklet_kill(&vc->task); + + spin_lock_irqsave(&vc->lock, flags); + if (vc->vd_terminated) { + vchan_vdesc_fini(vc->vd_terminated); + vc->vd_terminated = NULL; + } + spin_unlock_irqrestore(&vc->lock, flags); +} + +#endif diff --git a/snd-alpx-dkms/snd-alpx/include/5.10/regmap.h b/snd-alpx-dkms/snd-alpx/include/5.10/regmap.h new file mode 100644 index 0000000..e7834d9 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/include/5.10/regmap.h @@ -0,0 +1,1765 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef __LINUX_REGMAP_H +#define __LINUX_REGMAP_H + +/* + * Register map access API + * + * Copyright 2011 Wolfson Microelectronics plc + * + * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> + */ + +#include <linux/list.h> +#include <linux/rbtree.h> +#include <linux/ktime.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/bug.h> +#include <linux/lockdep.h> +#include <linux/iopoll.h> +#include <linux/fwnode.h> + +struct module; +struct clk; +struct device; +struct device_node; +struct i2c_client; +struct i3c_device; +struct irq_domain; +struct slim_device; +struct spi_device; +struct spmi_device; +struct regmap; +struct regmap_range_cfg; +struct regmap_field; +struct snd_ac97; +struct sdw_slave; + +/* An enum of all the supported cache types */ +enum regcache_type { + REGCACHE_NONE, + REGCACHE_RBTREE, + REGCACHE_COMPRESSED, + REGCACHE_FLAT, +}; + +/** + * struct reg_default - Default value for a register. + * + * @reg: Register address. + * @def: Register default value. + * + * We use an array of structs rather than a simple array as many modern devices + * have very sparse register maps. + */ +struct reg_default { + unsigned int reg; + unsigned int def; +}; + +/** + * struct reg_sequence - An individual write from a sequence of writes. + * + * @reg: Register address. + * @def: Register value. + * @delay_us: Delay to be applied after the register write in microseconds + * + * Register/value pairs for sequences of writes with an optional delay in + * microseconds to be applied after each write. + */ +struct reg_sequence { + unsigned int reg; + unsigned int def; + unsigned int delay_us; +}; + +#define REG_SEQ(_reg, _def, _delay_us) { \ + .reg = _reg, \ + .def = _def, \ + .delay_us = _delay_us, \ + } +#define REG_SEQ0(_reg, _def) REG_SEQ(_reg, _def, 0) + +/** + * regmap_read_poll_timeout - Poll until a condition is met or a timeout occurs + * + * @map: Regmap to read from + * @addr: Address to poll + * @val: Unsigned integer variable to read the value into + * @cond: Break condition (usually involving @val) + * @sleep_us: Maximum time to sleep between reads in us (0 + * tight-loops). Should be less than ~20ms since usleep_range + * is used (see Documentation/timers/timers-howto.rst). + * @timeout_us: Timeout in us, 0 means never timeout + * + * Returns 0 on success and -ETIMEDOUT upon a timeout or the regmap_read + * error return value in case of a error read. In the two former cases, + * the last read value at @addr is stored in @val. Must not be called + * from atomic context if sleep_us or timeout_us are used. + * + * This is modelled after the readx_poll_timeout macros in linux/iopoll.h. + */ +#define regmap_read_poll_timeout(map, addr, val, cond, sleep_us, timeout_us) \ +({ \ + int __ret, __tmp; \ + __tmp = read_poll_timeout(regmap_read, __ret, __ret || (cond), \ + sleep_us, timeout_us, false, (map), (addr), &(val)); \ + __ret ?: __tmp; \ +}) + +/** + * regmap_read_poll_timeout_atomic - Poll until a condition is met or a timeout occurs + * + * @map: Regmap to read from + * @addr: Address to poll + * @val: Unsigned integer variable to read the value into + * @cond: Break condition (usually involving @val) + * @delay_us: Time to udelay between reads in us (0 tight-loops). + * Should be less than ~10us since udelay is used + * (see Documentation/timers/timers-howto.rst). + * @timeout_us: Timeout in us, 0 means never timeout + * + * Returns 0 on success and -ETIMEDOUT upon a timeout or the regmap_read + * error return value in case of a error read. In the two former cases, + * the last read value at @addr is stored in @val. + * + * This is modelled after the readx_poll_timeout_atomic macros in linux/iopoll.h. + * + * Note: In general regmap cannot be used in atomic context. If you want to use + * this macro then first setup your regmap for atomic use (flat or no cache + * and MMIO regmap). + */ +#define regmap_read_poll_timeout_atomic(map, addr, val, cond, delay_us, timeout_us) \ +({ \ + u64 __timeout_us = (timeout_us); \ + unsigned long __delay_us = (delay_us); \ + ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); \ + int __ret; \ + for (;;) { \ + __ret = regmap_read((map), (addr), &(val)); \ + if (__ret) \ + break; \ + if (cond) \ + break; \ + if ((__timeout_us) && \ + ktime_compare(ktime_get(), __timeout) > 0) { \ + __ret = regmap_read((map), (addr), &(val)); \ + break; \ + } \ + if (__delay_us) \ + udelay(__delay_us); \ + } \ + __ret ?: ((cond) ? 0 : -ETIMEDOUT); \ +}) + +/** + * regmap_field_read_poll_timeout - Poll until a condition is met or timeout + * + * @field: Regmap field to read from + * @val: Unsigned integer variable to read the value into + * @cond: Break condition (usually involving @val) + * @sleep_us: Maximum time to sleep between reads in us (0 + * tight-loops). Should be less than ~20ms since usleep_range + * is used (see Documentation/timers/timers-howto.rst). + * @timeout_us: Timeout in us, 0 means never timeout + * + * Returns 0 on success and -ETIMEDOUT upon a timeout or the regmap_field_read + * error return value in case of a error read. In the two former cases, + * the last read value at @addr is stored in @val. Must not be called + * from atomic context if sleep_us or timeout_us are used. + * + * This is modelled after the readx_poll_timeout macros in linux/iopoll.h. + */ +#define regmap_field_read_poll_timeout(field, val, cond, sleep_us, timeout_us) \ +({ \ + int __ret, __tmp; \ + __tmp = read_poll_timeout(regmap_field_read, __ret, __ret || (cond), \ + sleep_us, timeout_us, false, (field), &(val)); \ + __ret ?: __tmp; \ +}) + +#ifdef CONFIG_REGMAP + +enum regmap_endian { + /* Unspecified -> 0 -> Backwards compatible default */ + REGMAP_ENDIAN_DEFAULT = 0, + REGMAP_ENDIAN_BIG, + REGMAP_ENDIAN_LITTLE, + REGMAP_ENDIAN_NATIVE, +}; + +/** + * struct regmap_range - A register range, used for access related checks + * (readable/writeable/volatile/precious checks) + * + * @range_min: address of first register + * @range_max: address of last register + */ +struct regmap_range { + unsigned int range_min; + unsigned int range_max; +}; + +#define regmap_reg_range(low, high) { .range_min = low, .range_max = high, } + +/** + * struct regmap_access_table - A table of register ranges for access checks + * + * @yes_ranges : pointer to an array of regmap ranges used as "yes ranges" + * @n_yes_ranges: size of the above array + * @no_ranges: pointer to an array of regmap ranges used as "no ranges" + * @n_no_ranges: size of the above array + * + * A table of ranges including some yes ranges and some no ranges. + * If a register belongs to a no_range, the corresponding check function + * will return false. If a register belongs to a yes range, the corresponding + * check function will return true. "no_ranges" are searched first. + */ +struct regmap_access_table { + const struct regmap_range *yes_ranges; + unsigned int n_yes_ranges; + const struct regmap_range *no_ranges; + unsigned int n_no_ranges; +}; + +typedef void (*regmap_lock)(void *); +typedef void (*regmap_unlock)(void *); + +/** + * struct regmap_config - Configuration for the register map of a device. + * + * @name: Optional name of the regmap. Useful when a device has multiple + * register regions. + * + * @reg_bits: Number of bits in a register address, mandatory. + * @reg_stride: The register address stride. Valid register addresses are a + * multiple of this value. If set to 0, a value of 1 will be + * used. + * @pad_bits: Number of bits of padding between register and value. + * @val_bits: Number of bits in a register value, mandatory. + * + * @writeable_reg: Optional callback returning true if the register + * can be written to. If this field is NULL but wr_table + * (see below) is not, the check is performed on such table + * (a register is writeable if it belongs to one of the ranges + * specified by wr_table). + * @readable_reg: Optional callback returning true if the register + * can be read from. If this field is NULL but rd_table + * (see below) is not, the check is performed on such table + * (a register is readable if it belongs to one of the ranges + * specified by rd_table). + * @volatile_reg: Optional callback returning true if the register + * value can't be cached. If this field is NULL but + * volatile_table (see below) is not, the check is performed on + * such table (a register is volatile if it belongs to one of + * the ranges specified by volatile_table). + * @precious_reg: Optional callback returning true if the register + * should not be read outside of a call from the driver + * (e.g., a clear on read interrupt status register). If this + * field is NULL but precious_table (see below) is not, the + * check is performed on such table (a register is precious if + * it belongs to one of the ranges specified by precious_table). + * @writeable_noinc_reg: Optional callback returning true if the register + * supports multiple write operations without incrementing + * the register number. If this field is NULL but + * wr_noinc_table (see below) is not, the check is + * performed on such table (a register is no increment + * writeable if it belongs to one of the ranges specified + * by wr_noinc_table). + * @readable_noinc_reg: Optional callback returning true if the register + * supports multiple read operations without incrementing + * the register number. If this field is NULL but + * rd_noinc_table (see below) is not, the check is + * performed on such table (a register is no increment + * readable if it belongs to one of the ranges specified + * by rd_noinc_table). + * @disable_locking: This regmap is either protected by external means or + * is guaranteed not to be accessed from multiple threads. + * Don't use any locking mechanisms. + * @lock: Optional lock callback (overrides regmap's default lock + * function, based on spinlock or mutex). + * @unlock: As above for unlocking. + * @lock_arg: this field is passed as the only argument of lock/unlock + * functions (ignored in case regular lock/unlock functions + * are not overridden). + * @reg_read: Optional callback that if filled will be used to perform + * all the reads from the registers. Should only be provided for + * devices whose read operation cannot be represented as a simple + * read operation on a bus such as SPI, I2C, etc. Most of the + * devices do not need this. + * @reg_write: Same as above for writing. + * @fast_io: Register IO is fast. Use a spinlock instead of a mutex + * to perform locking. This field is ignored if custom lock/unlock + * functions are used (see fields lock/unlock of struct regmap_config). + * This field is a duplicate of a similar file in + * 'struct regmap_bus' and serves exact same purpose. + * Use it only for "no-bus" cases. + * @max_register: Optional, specifies the maximum valid register address. + * @wr_table: Optional, points to a struct regmap_access_table specifying + * valid ranges for write access. + * @rd_table: As above, for read access. + * @volatile_table: As above, for volatile registers. + * @precious_table: As above, for precious registers. + * @wr_noinc_table: As above, for no increment writeable registers. + * @rd_noinc_table: As above, for no increment readable registers. + * @reg_defaults: Power on reset values for registers (for use with + * register cache support). + * @num_reg_defaults: Number of elements in reg_defaults. + * + * @read_flag_mask: Mask to be set in the top bytes of the register when doing + * a read. + * @write_flag_mask: Mask to be set in the top bytes of the register when doing + * a write. If both read_flag_mask and write_flag_mask are + * empty and zero_flag_mask is not set the regmap_bus default + * masks are used. + * @zero_flag_mask: If set, read_flag_mask and write_flag_mask are used even + * if they are both empty. + * @use_single_read: If set, converts the bulk read operation into a series of + * single read operations. This is useful for a device that + * does not support bulk read. + * @use_single_write: If set, converts the bulk write operation into a series of + * single write operations. This is useful for a device that + * does not support bulk write. + * @can_multi_write: If set, the device supports the multi write mode of bulk + * write operations, if clear multi write requests will be + * split into individual write operations + * + * @cache_type: The actual cache type. + * @reg_defaults_raw: Power on reset values for registers (for use with + * register cache support). + * @num_reg_defaults_raw: Number of elements in reg_defaults_raw. + * @reg_format_endian: Endianness for formatted register addresses. If this is + * DEFAULT, the @reg_format_endian_default value from the + * regmap bus is used. + * @val_format_endian: Endianness for formatted register values. If this is + * DEFAULT, the @reg_format_endian_default value from the + * regmap bus is used. + * + * @ranges: Array of configuration entries for virtual address ranges. + * @num_ranges: Number of range configuration entries. + * @use_hwlock: Indicate if a hardware spinlock should be used. + * @hwlock_id: Specify the hardware spinlock id. + * @hwlock_mode: The hardware spinlock mode, should be HWLOCK_IRQSTATE, + * HWLOCK_IRQ or 0. + * @can_sleep: Optional, specifies whether regmap operations can sleep. + */ +struct regmap_config { + const char *name; + + int reg_bits; + int reg_stride; + int pad_bits; + int val_bits; + + bool (*writeable_reg)(struct device *dev, unsigned int reg); + bool (*readable_reg)(struct device *dev, unsigned int reg); + bool (*volatile_reg)(struct device *dev, unsigned int reg); + bool (*precious_reg)(struct device *dev, unsigned int reg); + bool (*writeable_noinc_reg)(struct device *dev, unsigned int reg); + bool (*readable_noinc_reg)(struct device *dev, unsigned int reg); + + bool disable_locking; + regmap_lock lock; + regmap_unlock unlock; + void *lock_arg; + + int (*reg_read)(void *context, unsigned int reg, unsigned int *val); + int (*reg_write)(void *context, unsigned int reg, unsigned int val); + + bool fast_io; + + unsigned int max_register; + const struct regmap_access_table *wr_table; + const struct regmap_access_table *rd_table; + const struct regmap_access_table *volatile_table; + const struct regmap_access_table *precious_table; + const struct regmap_access_table *wr_noinc_table; + const struct regmap_access_table *rd_noinc_table; + const struct reg_default *reg_defaults; + unsigned int num_reg_defaults; + enum regcache_type cache_type; + const void *reg_defaults_raw; + unsigned int num_reg_defaults_raw; + + unsigned long read_flag_mask; + unsigned long write_flag_mask; + bool zero_flag_mask; + + bool use_single_read; + bool use_single_write; + bool can_multi_write; + + enum regmap_endian reg_format_endian; + enum regmap_endian val_format_endian; + + const struct regmap_range_cfg *ranges; + unsigned int num_ranges; + + bool use_hwlock; + unsigned int hwlock_id; + unsigned int hwlock_mode; + + bool can_sleep; +}; + +/** + * struct regmap_range_cfg - Configuration for indirectly accessed or paged + * registers. + * + * @name: Descriptive name for diagnostics + * + * @range_min: Address of the lowest register address in virtual range. + * @range_max: Address of the highest register in virtual range. + * + * @selector_reg: Register with selector field. + * @selector_mask: Bit mask for selector value. + * @selector_shift: Bit shift for selector value. + * + * @window_start: Address of first (lowest) register in data window. + * @window_len: Number of registers in data window. + * + * Registers, mapped to this virtual range, are accessed in two steps: + * 1. page selector register update; + * 2. access through data window registers. + */ +struct regmap_range_cfg { + const char *name; + + /* Registers of virtual address range */ + unsigned int range_min; + unsigned int range_max; + + /* Page selector for indirect addressing */ + unsigned int selector_reg; + unsigned int selector_mask; + int selector_shift; + + /* Data window (per each page) */ + unsigned int window_start; + unsigned int window_len; +}; + +struct regmap_async; + +typedef int (*regmap_hw_write)(void *context, const void *data, + size_t count); +typedef int (*regmap_hw_gather_write)(void *context, + const void *reg, size_t reg_len, + const void *val, size_t val_len); +typedef int (*regmap_hw_async_write)(void *context, + const void *reg, size_t reg_len, + const void *val, size_t val_len, + struct regmap_async *async); +typedef int (*regmap_hw_read)(void *context, + const void *reg_buf, size_t reg_size, + void *val_buf, size_t val_size); +typedef int (*regmap_hw_reg_read)(void *context, unsigned int reg, + unsigned int *val); +typedef int (*regmap_hw_reg_write)(void *context, unsigned int reg, + unsigned int val); +typedef int (*regmap_hw_reg_update_bits)(void *context, unsigned int reg, + unsigned int mask, unsigned int val); +typedef struct regmap_async *(*regmap_hw_async_alloc)(void); +typedef void (*regmap_hw_free_context)(void *context); + +/** + * struct regmap_bus - Description of a hardware bus for the register map + * infrastructure. + * + * @fast_io: Register IO is fast. Use a spinlock instead of a mutex + * to perform locking. This field is ignored if custom lock/unlock + * functions are used (see fields lock/unlock of + * struct regmap_config). + * @write: Write operation. + * @gather_write: Write operation with split register/value, return -ENOTSUPP + * if not implemented on a given device. + * @async_write: Write operation which completes asynchronously, optional and + * must serialise with respect to non-async I/O. + * @reg_write: Write a single register value to the given register address. This + * write operation has to complete when returning from the function. + * @reg_update_bits: Update bits operation to be used against volatile + * registers, intended for devices supporting some mechanism + * for setting clearing bits without having to + * read/modify/write. + * @read: Read operation. Data is returned in the buffer used to transmit + * data. + * @reg_read: Read a single register value from a given register address. + * @free_context: Free context. + * @async_alloc: Allocate a regmap_async() structure. + * @read_flag_mask: Mask to be set in the top byte of the register when doing + * a read. + * @reg_format_endian_default: Default endianness for formatted register + * addresses. Used when the regmap_config specifies DEFAULT. If this is + * DEFAULT, BIG is assumed. + * @val_format_endian_default: Default endianness for formatted register + * values. Used when the regmap_config specifies DEFAULT. If this is + * DEFAULT, BIG is assumed. + * @max_raw_read: Max raw read size that can be used on the bus. + * @max_raw_write: Max raw write size that can be used on the bus. + */ +struct regmap_bus { + bool fast_io; + regmap_hw_write write; + regmap_hw_gather_write gather_write; + regmap_hw_async_write async_write; + regmap_hw_reg_write reg_write; + regmap_hw_reg_update_bits reg_update_bits; + regmap_hw_read read; + regmap_hw_reg_read reg_read; + regmap_hw_free_context free_context; + regmap_hw_async_alloc async_alloc; + u8 read_flag_mask; + enum regmap_endian reg_format_endian_default; + enum regmap_endian val_format_endian_default; + size_t max_raw_read; + size_t max_raw_write; +}; + +/* + * __regmap_init functions. + * + * These functions take a lock key and name parameter, and should not be called + * directly. Instead, use the regmap_init macros that generate a key and name + * for each call. + */ +struct regmap *__regmap_init(struct device *dev, + const struct regmap_bus *bus, + void *bus_context, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__regmap_init_i2c(struct i2c_client *i2c, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__regmap_init_sccb(struct i2c_client *i2c, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__regmap_init_slimbus(struct slim_device *slimbus, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__regmap_init_spi(struct spi_device *dev, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__regmap_init_spmi_base(struct spmi_device *dev, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__regmap_init_spmi_ext(struct spmi_device *dev, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__regmap_init_w1(struct device *w1_dev, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__regmap_init_mmio_clk(struct device *dev, const char *clk_id, + void __iomem *regs, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__regmap_init_ac97(struct snd_ac97 *ac97, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__regmap_init_sdw(struct sdw_slave *sdw, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__regmap_init_spi_avmm(struct spi_device *spi, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); + +struct regmap *__devm_regmap_init(struct device *dev, + const struct regmap_bus *bus, + void *bus_context, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__devm_regmap_init_i2c(struct i2c_client *i2c, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__devm_regmap_init_sccb(struct i2c_client *i2c, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__devm_regmap_init_spi(struct spi_device *dev, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__devm_regmap_init_spmi_base(struct spmi_device *dev, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__devm_regmap_init_spmi_ext(struct spmi_device *dev, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__devm_regmap_init_w1(struct device *w1_dev, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__devm_regmap_init_mmio_clk(struct device *dev, + const char *clk_id, + void __iomem *regs, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__devm_regmap_init_ac97(struct snd_ac97 *ac97, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__devm_regmap_init_sdw(struct sdw_slave *sdw, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__devm_regmap_init_slimbus(struct slim_device *slimbus, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__devm_regmap_init_i3c(struct i3c_device *i3c, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__devm_regmap_init_spi_avmm(struct spi_device *spi, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +/* + * Wrapper for regmap_init macros to include a unique lockdep key and name + * for each call. No-op if CONFIG_LOCKDEP is not set. + * + * @fn: Real function to call (in the form __[*_]regmap_init[_*]) + * @name: Config variable name (#config in the calling macro) + **/ +#ifdef CONFIG_LOCKDEP +#define __regmap_lockdep_wrapper(fn, name, ...) \ +( \ + ({ \ + static struct lock_class_key _key; \ + fn(__VA_ARGS__, &_key, \ + KBUILD_BASENAME ":" \ + __stringify(__LINE__) ":" \ + "(" name ")->lock"); \ + }) \ +) +#else +#define __regmap_lockdep_wrapper(fn, name, ...) fn(__VA_ARGS__, NULL, NULL) +#endif + +/** + * regmap_init() - Initialise register map + * + * @dev: Device that will be interacted with + * @bus: Bus-specific callbacks to use with device + * @bus_context: Data passed to bus-specific callbacks + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer to + * a struct regmap. This function should generally not be called + * directly, it should be called by bus-specific init functions. + */ +#define regmap_init(dev, bus, bus_context, config) \ + __regmap_lockdep_wrapper(__regmap_init, #config, \ + dev, bus, bus_context, config) +int regmap_attach_dev(struct device *dev, struct regmap *map, + const struct regmap_config *config); + +/** + * regmap_init_i2c() - Initialise register map + * + * @i2c: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer to + * a struct regmap. + */ +#define regmap_init_i2c(i2c, config) \ + __regmap_lockdep_wrapper(__regmap_init_i2c, #config, \ + i2c, config) + +/** + * regmap_init_sccb() - Initialise register map + * + * @i2c: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer to + * a struct regmap. + */ +#define regmap_init_sccb(i2c, config) \ + __regmap_lockdep_wrapper(__regmap_init_sccb, #config, \ + i2c, config) + +/** + * regmap_init_slimbus() - Initialise register map + * + * @slimbus: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer to + * a struct regmap. + */ +#define regmap_init_slimbus(slimbus, config) \ + __regmap_lockdep_wrapper(__regmap_init_slimbus, #config, \ + slimbus, config) + +/** + * regmap_init_spi() - Initialise register map + * + * @dev: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer to + * a struct regmap. + */ +#define regmap_init_spi(dev, config) \ + __regmap_lockdep_wrapper(__regmap_init_spi, #config, \ + dev, config) + +/** + * regmap_init_spmi_base() - Create regmap for the Base register space + * + * @dev: SPMI device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer to + * a struct regmap. + */ +#define regmap_init_spmi_base(dev, config) \ + __regmap_lockdep_wrapper(__regmap_init_spmi_base, #config, \ + dev, config) + +/** + * regmap_init_spmi_ext() - Create regmap for Ext register space + * + * @dev: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer to + * a struct regmap. + */ +#define regmap_init_spmi_ext(dev, config) \ + __regmap_lockdep_wrapper(__regmap_init_spmi_ext, #config, \ + dev, config) + +/** + * regmap_init_w1() - Initialise register map + * + * @w1_dev: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer to + * a struct regmap. + */ +#define regmap_init_w1(w1_dev, config) \ + __regmap_lockdep_wrapper(__regmap_init_w1, #config, \ + w1_dev, config) + +/** + * regmap_init_mmio_clk() - Initialise register map with register clock + * + * @dev: Device that will be interacted with + * @clk_id: register clock consumer ID + * @regs: Pointer to memory-mapped IO region + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer to + * a struct regmap. + */ +#define regmap_init_mmio_clk(dev, clk_id, regs, config) \ + __regmap_lockdep_wrapper(__regmap_init_mmio_clk, #config, \ + dev, clk_id, regs, config) + +/** + * regmap_init_mmio() - Initialise register map + * + * @dev: Device that will be interacted with + * @regs: Pointer to memory-mapped IO region + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer to + * a struct regmap. + */ +#define regmap_init_mmio(dev, regs, config) \ + regmap_init_mmio_clk(dev, NULL, regs, config) + +/** + * regmap_init_ac97() - Initialise AC'97 register map + * + * @ac97: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer to + * a struct regmap. + */ +#define regmap_init_ac97(ac97, config) \ + __regmap_lockdep_wrapper(__regmap_init_ac97, #config, \ + ac97, config) +bool regmap_ac97_default_volatile(struct device *dev, unsigned int reg); + +/** + * regmap_init_sdw() - Initialise register map + * + * @sdw: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer to + * a struct regmap. + */ +#define regmap_init_sdw(sdw, config) \ + __regmap_lockdep_wrapper(__regmap_init_sdw, #config, \ + sdw, config) + +/** + * regmap_init_spi_avmm() - Initialize register map for Intel SPI Slave + * to AVMM Bus Bridge + * + * @spi: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. + */ +#define regmap_init_spi_avmm(spi, config) \ + __regmap_lockdep_wrapper(__regmap_init_spi_avmm, #config, \ + spi, config) + +/** + * devm_regmap_init() - Initialise managed register map + * + * @dev: Device that will be interacted with + * @bus: Bus-specific callbacks to use with device + * @bus_context: Data passed to bus-specific callbacks + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. This function should generally not be called + * directly, it should be called by bus-specific init functions. The + * map will be automatically freed by the device management code. + */ +#define devm_regmap_init(dev, bus, bus_context, config) \ + __regmap_lockdep_wrapper(__devm_regmap_init, #config, \ + dev, bus, bus_context, config) + +/** + * devm_regmap_init_i2c() - Initialise managed register map + * + * @i2c: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. The regmap will be automatically freed by the + * device management code. + */ +#define devm_regmap_init_i2c(i2c, config) \ + __regmap_lockdep_wrapper(__devm_regmap_init_i2c, #config, \ + i2c, config) + +/** + * devm_regmap_init_sccb() - Initialise managed register map + * + * @i2c: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. The regmap will be automatically freed by the + * device management code. + */ +#define devm_regmap_init_sccb(i2c, config) \ + __regmap_lockdep_wrapper(__devm_regmap_init_sccb, #config, \ + i2c, config) + +/** + * devm_regmap_init_spi() - Initialise register map + * + * @dev: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. The map will be automatically freed by the + * device management code. + */ +#define devm_regmap_init_spi(dev, config) \ + __regmap_lockdep_wrapper(__devm_regmap_init_spi, #config, \ + dev, config) + +/** + * devm_regmap_init_spmi_base() - Create managed regmap for Base register space + * + * @dev: SPMI device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. The regmap will be automatically freed by the + * device management code. + */ +#define devm_regmap_init_spmi_base(dev, config) \ + __regmap_lockdep_wrapper(__devm_regmap_init_spmi_base, #config, \ + dev, config) + +/** + * devm_regmap_init_spmi_ext() - Create managed regmap for Ext register space + * + * @dev: SPMI device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. The regmap will be automatically freed by the + * device management code. + */ +#define devm_regmap_init_spmi_ext(dev, config) \ + __regmap_lockdep_wrapper(__devm_regmap_init_spmi_ext, #config, \ + dev, config) + +/** + * devm_regmap_init_w1() - Initialise managed register map + * + * @w1_dev: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. The regmap will be automatically freed by the + * device management code. + */ +#define devm_regmap_init_w1(w1_dev, config) \ + __regmap_lockdep_wrapper(__devm_regmap_init_w1, #config, \ + w1_dev, config) +/** + * devm_regmap_init_mmio_clk() - Initialise managed register map with clock + * + * @dev: Device that will be interacted with + * @clk_id: register clock consumer ID + * @regs: Pointer to memory-mapped IO region + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. The regmap will be automatically freed by the + * device management code. + */ +#define devm_regmap_init_mmio_clk(dev, clk_id, regs, config) \ + __regmap_lockdep_wrapper(__devm_regmap_init_mmio_clk, #config, \ + dev, clk_id, regs, config) + +/** + * devm_regmap_init_mmio() - Initialise managed register map + * + * @dev: Device that will be interacted with + * @regs: Pointer to memory-mapped IO region + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. The regmap will be automatically freed by the + * device management code. + */ +#define devm_regmap_init_mmio(dev, regs, config) \ + devm_regmap_init_mmio_clk(dev, NULL, regs, config) + +/** + * devm_regmap_init_ac97() - Initialise AC'97 register map + * + * @ac97: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. The regmap will be automatically freed by the + * device management code. + */ +#define devm_regmap_init_ac97(ac97, config) \ + __regmap_lockdep_wrapper(__devm_regmap_init_ac97, #config, \ + ac97, config) + +/** + * devm_regmap_init_sdw() - Initialise managed register map + * + * @sdw: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. The regmap will be automatically freed by the + * device management code. + */ +#define devm_regmap_init_sdw(sdw, config) \ + __regmap_lockdep_wrapper(__devm_regmap_init_sdw, #config, \ + sdw, config) + +/** + * devm_regmap_init_slimbus() - Initialise managed register map + * + * @slimbus: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. The regmap will be automatically freed by the + * device management code. + */ +#define devm_regmap_init_slimbus(slimbus, config) \ + __regmap_lockdep_wrapper(__devm_regmap_init_slimbus, #config, \ + slimbus, config) + +/** + * devm_regmap_init_i3c() - Initialise managed register map + * + * @i3c: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. The regmap will be automatically freed by the + * device management code. + */ +#define devm_regmap_init_i3c(i3c, config) \ + __regmap_lockdep_wrapper(__devm_regmap_init_i3c, #config, \ + i3c, config) + +/** + * devm_regmap_init_spi_avmm() - Initialize register map for Intel SPI Slave + * to AVMM Bus Bridge + * + * @spi: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. The map will be automatically freed by the + * device management code. + */ +#define devm_regmap_init_spi_avmm(spi, config) \ + __regmap_lockdep_wrapper(__devm_regmap_init_spi_avmm, #config, \ + spi, config) + +int regmap_mmio_attach_clk(struct regmap *map, struct clk *clk); +void regmap_mmio_detach_clk(struct regmap *map); +void regmap_exit(struct regmap *map); +int regmap_reinit_cache(struct regmap *map, + const struct regmap_config *config); +struct regmap *dev_get_regmap(struct device *dev, const char *name); +struct device *regmap_get_device(struct regmap *map); +int regmap_write(struct regmap *map, unsigned int reg, unsigned int val); +int regmap_write_async(struct regmap *map, unsigned int reg, unsigned int val); +int regmap_raw_write(struct regmap *map, unsigned int reg, + const void *val, size_t val_len); +int regmap_noinc_write(struct regmap *map, unsigned int reg, + const void *val, size_t val_len); +int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, + size_t val_count); +int regmap_multi_reg_write(struct regmap *map, const struct reg_sequence *regs, + int num_regs); +int regmap_multi_reg_write_bypassed(struct regmap *map, + const struct reg_sequence *regs, + int num_regs); +int regmap_raw_write_async(struct regmap *map, unsigned int reg, + const void *val, size_t val_len); +int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val); +int regmap_raw_read(struct regmap *map, unsigned int reg, + void *val, size_t val_len); +int regmap_noinc_read(struct regmap *map, unsigned int reg, + void *val, size_t val_len); +int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val, + size_t val_count); +int regmap_update_bits_base(struct regmap *map, unsigned int reg, + unsigned int mask, unsigned int val, + bool *change, bool async, bool force); + +static inline int regmap_update_bits(struct regmap *map, unsigned int reg, + unsigned int mask, unsigned int val) +{ + return regmap_update_bits_base(map, reg, mask, val, NULL, false, false); +} + +static inline int regmap_update_bits_async(struct regmap *map, unsigned int reg, + unsigned int mask, unsigned int val) +{ + return regmap_update_bits_base(map, reg, mask, val, NULL, true, false); +} + +static inline int regmap_update_bits_check(struct regmap *map, unsigned int reg, + unsigned int mask, unsigned int val, + bool *change) +{ + return regmap_update_bits_base(map, reg, mask, val, + change, false, false); +} + +static inline int +regmap_update_bits_check_async(struct regmap *map, unsigned int reg, + unsigned int mask, unsigned int val, + bool *change) +{ + return regmap_update_bits_base(map, reg, mask, val, + change, true, false); +} + +static inline int regmap_write_bits(struct regmap *map, unsigned int reg, + unsigned int mask, unsigned int val) +{ + return regmap_update_bits_base(map, reg, mask, val, NULL, false, true); +} + +int regmap_get_val_bytes(struct regmap *map); +int regmap_get_max_register(struct regmap *map); +int regmap_get_reg_stride(struct regmap *map); +int regmap_async_complete(struct regmap *map); +bool regmap_can_raw_write(struct regmap *map); +size_t regmap_get_raw_read_max(struct regmap *map); +size_t regmap_get_raw_write_max(struct regmap *map); + +int regcache_sync(struct regmap *map); +int regcache_sync_region(struct regmap *map, unsigned int min, + unsigned int max); +int regcache_drop_region(struct regmap *map, unsigned int min, + unsigned int max); +void regcache_cache_only(struct regmap *map, bool enable); +void regcache_cache_bypass(struct regmap *map, bool enable); +void regcache_mark_dirty(struct regmap *map); + +bool regmap_check_range_table(struct regmap *map, unsigned int reg, + const struct regmap_access_table *table); + +int regmap_register_patch(struct regmap *map, const struct reg_sequence *regs, + int num_regs); +int regmap_parse_val(struct regmap *map, const void *buf, + unsigned int *val); + +static inline bool regmap_reg_in_range(unsigned int reg, + const struct regmap_range *range) +{ + return reg >= range->range_min && reg <= range->range_max; +} + +bool regmap_reg_in_ranges(unsigned int reg, + const struct regmap_range *ranges, + unsigned int nranges); + +static inline int regmap_set_bits(struct regmap *map, + unsigned int reg, unsigned int bits) +{ + return regmap_update_bits_base(map, reg, bits, bits, + NULL, false, false); +} + +static inline int regmap_clear_bits(struct regmap *map, + unsigned int reg, unsigned int bits) +{ + return regmap_update_bits_base(map, reg, bits, 0, NULL, false, false); +} + +int regmap_test_bits(struct regmap *map, unsigned int reg, unsigned int bits); + +/** + * struct reg_field - Description of an register field + * + * @reg: Offset of the register within the regmap bank + * @lsb: lsb of the register field. + * @msb: msb of the register field. + * @id_size: port size if it has some ports + * @id_offset: address offset for each ports + */ +struct reg_field { + unsigned int reg; + unsigned int lsb; + unsigned int msb; + unsigned int id_size; + unsigned int id_offset; +}; + +#define REG_FIELD(_reg, _lsb, _msb) { \ + .reg = _reg, \ + .lsb = _lsb, \ + .msb = _msb, \ + } + +#define REG_FIELD_ID(_reg, _lsb, _msb, _size, _offset) { \ + .reg = _reg, \ + .lsb = _lsb, \ + .msb = _msb, \ + .id_size = _size, \ + .id_offset = _offset, \ + } + +struct regmap_field *regmap_field_alloc(struct regmap *regmap, + struct reg_field reg_field); +void regmap_field_free(struct regmap_field *field); + +struct regmap_field *devm_regmap_field_alloc(struct device *dev, + struct regmap *regmap, struct reg_field reg_field); +void devm_regmap_field_free(struct device *dev, struct regmap_field *field); + +int regmap_field_bulk_alloc(struct regmap *regmap, + struct regmap_field **rm_field, + struct reg_field *reg_field, + int num_fields); +void regmap_field_bulk_free(struct regmap_field *field); +int devm_regmap_field_bulk_alloc(struct device *dev, struct regmap *regmap, + struct regmap_field **field, + struct reg_field *reg_field, int num_fields); +void devm_regmap_field_bulk_free(struct device *dev, + struct regmap_field *field); + +int regmap_field_read(struct regmap_field *field, unsigned int *val); +int regmap_field_update_bits_base(struct regmap_field *field, + unsigned int mask, unsigned int val, + bool *change, bool async, bool force); +int regmap_fields_read(struct regmap_field *field, unsigned int id, + unsigned int *val); +int regmap_fields_update_bits_base(struct regmap_field *field, unsigned int id, + unsigned int mask, unsigned int val, + bool *change, bool async, bool force); + +static inline int regmap_field_write(struct regmap_field *field, + unsigned int val) +{ + return regmap_field_update_bits_base(field, ~0, val, + NULL, false, false); +} + +static inline int regmap_field_force_write(struct regmap_field *field, + unsigned int val) +{ + return regmap_field_update_bits_base(field, ~0, val, NULL, false, true); +} + +static inline int regmap_field_update_bits(struct regmap_field *field, + unsigned int mask, unsigned int val) +{ + return regmap_field_update_bits_base(field, mask, val, + NULL, false, false); +} + +static inline int +regmap_field_force_update_bits(struct regmap_field *field, + unsigned int mask, unsigned int val) +{ + return regmap_field_update_bits_base(field, mask, val, + NULL, false, true); +} + +static inline int regmap_fields_write(struct regmap_field *field, + unsigned int id, unsigned int val) +{ + return regmap_fields_update_bits_base(field, id, ~0, val, + NULL, false, false); +} + +static inline int regmap_fields_force_write(struct regmap_field *field, + unsigned int id, unsigned int val) +{ + return regmap_fields_update_bits_base(field, id, ~0, val, + NULL, false, true); +} + +static inline int +regmap_fields_update_bits(struct regmap_field *field, unsigned int id, + unsigned int mask, unsigned int val) +{ + return regmap_fields_update_bits_base(field, id, mask, val, + NULL, false, false); +} + +static inline int +regmap_fields_force_update_bits(struct regmap_field *field, unsigned int id, + unsigned int mask, unsigned int val) +{ + return regmap_fields_update_bits_base(field, id, mask, val, + NULL, false, true); +} + +/** + * struct regmap_irq_type - IRQ type definitions. + * + * @type_reg_offset: Offset register for the irq type setting. + * @type_rising_val: Register value to configure RISING type irq. + * @type_falling_val: Register value to configure FALLING type irq. + * @type_level_low_val: Register value to configure LEVEL_LOW type irq. + * @type_level_high_val: Register value to configure LEVEL_HIGH type irq. + * @types_supported: logical OR of IRQ_TYPE_* flags indicating supported types. + */ +struct regmap_irq_type { + unsigned int type_reg_offset; + unsigned int type_reg_mask; + unsigned int type_rising_val; + unsigned int type_falling_val; + unsigned int type_level_low_val; + unsigned int type_level_high_val; + unsigned int types_supported; +}; + +/** + * struct regmap_irq - Description of an IRQ for the generic regmap irq_chip. + * + * @reg_offset: Offset of the status/mask register within the bank + * @mask: Mask used to flag/control the register. + * @type: IRQ trigger type setting details if supported. + */ +struct regmap_irq { + unsigned int reg_offset; + unsigned int mask; + struct regmap_irq_type type; +}; + +#define REGMAP_IRQ_REG(_irq, _off, _mask) \ + [_irq] = { .reg_offset = (_off), .mask = (_mask) } + +#define REGMAP_IRQ_REG_LINE(_id, _reg_bits) \ + [_id] = { \ + .mask = BIT((_id) % (_reg_bits)), \ + .reg_offset = (_id) / (_reg_bits), \ + } + +#define REGMAP_IRQ_MAIN_REG_OFFSET(arr) \ + { .num_regs = ARRAY_SIZE((arr)), .offset = &(arr)[0] } + +struct regmap_irq_sub_irq_map { + unsigned int num_regs; + unsigned int *offset; +}; + +/** + * struct regmap_irq_chip - Description of a generic regmap irq_chip. + * + * @name: Descriptive name for IRQ controller. + * + * @main_status: Base main status register address. For chips which have + * interrupts arranged in separate sub-irq blocks with own IRQ + * registers and which have a main IRQ registers indicating + * sub-irq blocks with unhandled interrupts. For such chips fill + * sub-irq register information in status_base, mask_base and + * ack_base. + * @num_main_status_bits: Should be given to chips where number of meaningfull + * main status bits differs from num_regs. + * @sub_reg_offsets: arrays of mappings from main register bits to sub irq + * registers. First item in array describes the registers + * for first main status bit. Second array for second bit etc. + * Offset is given as sub register status offset to + * status_base. Should contain num_regs arrays. + * Can be provided for chips with more complex mapping than + * 1.st bit to 1.st sub-reg, 2.nd bit to 2.nd sub-reg, ... + * @num_main_regs: Number of 'main status' irq registers for chips which have + * main_status set. + * + * @status_base: Base status register address. + * @mask_base: Base mask register address. + * @mask_writeonly: Base mask register is write only. + * @unmask_base: Base unmask register address. for chips who have + * separate mask and unmask registers + * @ack_base: Base ack address. If zero then the chip is clear on read. + * Using zero value is possible with @use_ack bit. + * @wake_base: Base address for wake enables. If zero unsupported. + * @type_base: Base address for irq type. If zero unsupported. + * @irq_reg_stride: Stride to use for chips where registers are not contiguous. + * @init_ack_masked: Ack all masked interrupts once during initalization. + * @mask_invert: Inverted mask register: cleared bits are masked out. + * @use_ack: Use @ack register even if it is zero. + * @ack_invert: Inverted ack register: cleared bits for ack. + * @clear_ack: Use this to set 1 and 0 or vice-versa to clear interrupts. + * @wake_invert: Inverted wake register: cleared bits are wake enabled. + * @type_invert: Invert the type flags. + * @type_in_mask: Use the mask registers for controlling irq type. For + * interrupts defining type_rising/falling_mask use mask_base + * for edge configuration and never update bits in type_base. + * @clear_on_unmask: For chips with interrupts cleared on read: read the status + * registers before unmasking interrupts to clear any bits + * set when they were masked. + * @runtime_pm: Hold a runtime PM lock on the device when accessing it. + * + * @num_regs: Number of registers in each control bank. + * @irqs: Descriptors for individual IRQs. Interrupt numbers are + * assigned based on the index in the array of the interrupt. + * @num_irqs: Number of descriptors. + * @num_type_reg: Number of type registers. + * @type_reg_stride: Stride to use for chips where type registers are not + * contiguous. + * @handle_pre_irq: Driver specific callback to handle interrupt from device + * before regmap_irq_handler process the interrupts. + * @handle_post_irq: Driver specific callback to handle interrupt from device + * after handling the interrupts in regmap_irq_handler(). + * @irq_drv_data: Driver specific IRQ data which is passed as parameter when + * driver specific pre/post interrupt handler is called. + * + * This is not intended to handle every possible interrupt controller, but + * it should handle a substantial proportion of those that are found in the + * wild. + */ +struct regmap_irq_chip { + const char *name; + + unsigned int main_status; + unsigned int num_main_status_bits; + struct regmap_irq_sub_irq_map *sub_reg_offsets; + int num_main_regs; + + unsigned int status_base; + unsigned int mask_base; + unsigned int unmask_base; + unsigned int ack_base; + unsigned int wake_base; + unsigned int type_base; + unsigned int irq_reg_stride; + bool mask_writeonly:1; + bool init_ack_masked:1; + bool mask_invert:1; + bool use_ack:1; + bool ack_invert:1; + bool clear_ack:1; + bool wake_invert:1; + bool runtime_pm:1; + bool type_invert:1; + bool type_in_mask:1; + bool clear_on_unmask:1; + + int num_regs; + + const struct regmap_irq *irqs; + int num_irqs; + + int num_type_reg; + unsigned int type_reg_stride; + + int (*handle_pre_irq)(void *irq_drv_data); + int (*handle_post_irq)(void *irq_drv_data); + void *irq_drv_data; +}; + +struct regmap_irq_chip_data; + +int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, + int irq_base, const struct regmap_irq_chip *chip, + struct regmap_irq_chip_data **data); +int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode, + struct regmap *map, int irq, + int irq_flags, int irq_base, + const struct regmap_irq_chip *chip, + struct regmap_irq_chip_data **data); +void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *data); + +int devm_regmap_add_irq_chip(struct device *dev, struct regmap *map, int irq, + int irq_flags, int irq_base, + const struct regmap_irq_chip *chip, + struct regmap_irq_chip_data **data); +int devm_regmap_add_irq_chip_fwnode(struct device *dev, + struct fwnode_handle *fwnode, + struct regmap *map, int irq, + int irq_flags, int irq_base, + const struct regmap_irq_chip *chip, + struct regmap_irq_chip_data **data); +void devm_regmap_del_irq_chip(struct device *dev, int irq, + struct regmap_irq_chip_data *data); + +int regmap_irq_chip_get_base(struct regmap_irq_chip_data *data); +int regmap_irq_get_virq(struct regmap_irq_chip_data *data, int irq); +struct irq_domain *regmap_irq_get_domain(struct regmap_irq_chip_data *data); + +#else + +/* + * These stubs should only ever be called by generic code which has + * regmap based facilities, if they ever get called at runtime + * something is going wrong and something probably needs to select + * REGMAP. + */ + +static inline int regmap_write(struct regmap *map, unsigned int reg, + unsigned int val) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_write_async(struct regmap *map, unsigned int reg, + unsigned int val) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_raw_write(struct regmap *map, unsigned int reg, + const void *val, size_t val_len) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_raw_write_async(struct regmap *map, unsigned int reg, + const void *val, size_t val_len) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_noinc_write(struct regmap *map, unsigned int reg, + const void *val, size_t val_len) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_bulk_write(struct regmap *map, unsigned int reg, + const void *val, size_t val_count) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_read(struct regmap *map, unsigned int reg, + unsigned int *val) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_raw_read(struct regmap *map, unsigned int reg, + void *val, size_t val_len) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_noinc_read(struct regmap *map, unsigned int reg, + void *val, size_t val_len) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_bulk_read(struct regmap *map, unsigned int reg, + void *val, size_t val_count) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_update_bits_base(struct regmap *map, unsigned int reg, + unsigned int mask, unsigned int val, + bool *change, bool async, bool force) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_set_bits(struct regmap *map, + unsigned int reg, unsigned int bits) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_clear_bits(struct regmap *map, + unsigned int reg, unsigned int bits) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_test_bits(struct regmap *map, + unsigned int reg, unsigned int bits) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_field_update_bits_base(struct regmap_field *field, + unsigned int mask, unsigned int val, + bool *change, bool async, bool force) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_fields_update_bits_base(struct regmap_field *field, + unsigned int id, + unsigned int mask, unsigned int val, + bool *change, bool async, bool force) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_update_bits(struct regmap *map, unsigned int reg, + unsigned int mask, unsigned int val) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_update_bits_async(struct regmap *map, unsigned int reg, + unsigned int mask, unsigned int val) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_update_bits_check(struct regmap *map, unsigned int reg, + unsigned int mask, unsigned int val, + bool *change) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int +regmap_update_bits_check_async(struct regmap *map, unsigned int reg, + unsigned int mask, unsigned int val, + bool *change) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_write_bits(struct regmap *map, unsigned int reg, + unsigned int mask, unsigned int val) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_field_write(struct regmap_field *field, + unsigned int val) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_field_force_write(struct regmap_field *field, + unsigned int val) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_field_update_bits(struct regmap_field *field, + unsigned int mask, unsigned int val) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int +regmap_field_force_update_bits(struct regmap_field *field, + unsigned int mask, unsigned int val) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_fields_write(struct regmap_field *field, + unsigned int id, unsigned int val) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_fields_force_write(struct regmap_field *field, + unsigned int id, unsigned int val) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int +regmap_fields_update_bits(struct regmap_field *field, unsigned int id, + unsigned int mask, unsigned int val) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int +regmap_fields_force_update_bits(struct regmap_field *field, unsigned int id, + unsigned int mask, unsigned int val) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_get_val_bytes(struct regmap *map) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_get_max_register(struct regmap *map) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_get_reg_stride(struct regmap *map) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regcache_sync(struct regmap *map) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regcache_sync_region(struct regmap *map, unsigned int min, + unsigned int max) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regcache_drop_region(struct regmap *map, unsigned int min, + unsigned int max) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline void regcache_cache_only(struct regmap *map, bool enable) +{ + WARN_ONCE(1, "regmap API is disabled"); +} + +static inline void regcache_cache_bypass(struct regmap *map, bool enable) +{ + WARN_ONCE(1, "regmap API is disabled"); +} + +static inline void regcache_mark_dirty(struct regmap *map) +{ + WARN_ONCE(1, "regmap API is disabled"); +} + +static inline void regmap_async_complete(struct regmap *map) +{ + WARN_ONCE(1, "regmap API is disabled"); +} + +static inline int regmap_register_patch(struct regmap *map, + const struct reg_sequence *regs, + int num_regs) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_parse_val(struct regmap *map, const void *buf, + unsigned int *val) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline struct regmap *dev_get_regmap(struct device *dev, + const char *name) +{ + return NULL; +} + +static inline struct device *regmap_get_device(struct regmap *map) +{ + WARN_ONCE(1, "regmap API is disabled"); + return NULL; +} + +#endif + +#endif diff --git a/snd-alpx-dkms/snd-alpx/include/5.14/regmap.h b/snd-alpx-dkms/snd-alpx/include/5.14/regmap.h new file mode 100644 index 0000000..8eb7922 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/include/5.14/regmap.h @@ -0,0 +1,2041 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef __LINUX_REGMAP_H +#define __LINUX_REGMAP_H + +/* + * Register map access API + * + * Copyright 2011 Wolfson Microelectronics plc + * + * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> + */ + +#include <linux/list.h> +#include <linux/rbtree.h> +#include <linux/ktime.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/bug.h> +#include <linux/lockdep.h> +#include <linux/iopoll.h> +#include <linux/fwnode.h> + +struct module; +struct clk; +struct device; +struct device_node; +struct fsi_device; +struct i2c_client; +struct i3c_device; +struct irq_domain; +struct mdio_device; +struct slim_device; +struct spi_device; +struct spmi_device; +struct regmap; +struct regmap_range_cfg; +struct regmap_field; +struct snd_ac97; +struct sdw_slave; + +/* + * regmap_mdio address encoding. IEEE 802.3ae clause 45 addresses consist of a + * device address and a register address. + */ +#define REGMAP_MDIO_C45_DEVAD_SHIFT 16 +#define REGMAP_MDIO_C45_DEVAD_MASK GENMASK(20, 16) +#define REGMAP_MDIO_C45_REGNUM_MASK GENMASK(15, 0) + +/* + * regmap.reg_shift indicates by how much we must shift registers prior to + * performing any operation. It's a signed value, positive numbers means + * downshifting the register's address, while negative numbers means upshifting. + */ +#define REGMAP_UPSHIFT(s) (-(s)) +#define REGMAP_DOWNSHIFT(s) (s) + +/* An enum of all the supported cache types */ +enum regcache_type { + REGCACHE_NONE, + REGCACHE_RBTREE, + REGCACHE_FLAT, + REGCACHE_MAPLE, +}; + +/** + * struct reg_default - Default value for a register. + * + * @reg: Register address. + * @def: Register default value. + * + * We use an array of structs rather than a simple array as many modern devices + * have very sparse register maps. + */ +struct reg_default { + unsigned int reg; + unsigned int def; +}; + +/** + * struct reg_sequence - An individual write from a sequence of writes. + * + * @reg: Register address. + * @def: Register value. + * @delay_us: Delay to be applied after the register write in microseconds + * + * Register/value pairs for sequences of writes with an optional delay in + * microseconds to be applied after each write. + */ +struct reg_sequence { + unsigned int reg; + unsigned int def; + unsigned int delay_us; +}; + +#define REG_SEQ(_reg, _def, _delay_us) { \ + .reg = _reg, \ + .def = _def, \ + .delay_us = _delay_us, \ + } +#define REG_SEQ0(_reg, _def) REG_SEQ(_reg, _def, 0) + +/** + * regmap_read_poll_timeout - Poll until a condition is met or a timeout occurs + * + * @map: Regmap to read from + * @addr: Address to poll + * @val: Unsigned integer variable to read the value into + * @cond: Break condition (usually involving @val) + * @sleep_us: Maximum time to sleep between reads in us (0 + * tight-loops). Should be less than ~20ms since usleep_range + * is used (see Documentation/timers/timers-howto.rst). + * @timeout_us: Timeout in us, 0 means never timeout + * + * Returns 0 on success and -ETIMEDOUT upon a timeout or the regmap_read + * error return value in case of a error read. In the two former cases, + * the last read value at @addr is stored in @val. Must not be called + * from atomic context if sleep_us or timeout_us are used. + * + * This is modelled after the readx_poll_timeout macros in linux/iopoll.h. + */ +#define regmap_read_poll_timeout(map, addr, val, cond, sleep_us, timeout_us) \ +({ \ + int __ret, __tmp; \ + __tmp = read_poll_timeout(regmap_read, __ret, __ret || (cond), \ + sleep_us, timeout_us, false, (map), (addr), &(val)); \ + __ret ?: __tmp; \ +}) + +/** + * regmap_read_poll_timeout_atomic - Poll until a condition is met or a timeout occurs + * + * @map: Regmap to read from + * @addr: Address to poll + * @val: Unsigned integer variable to read the value into + * @cond: Break condition (usually involving @val) + * @delay_us: Time to udelay between reads in us (0 tight-loops). + * Should be less than ~10us since udelay is used + * (see Documentation/timers/timers-howto.rst). + * @timeout_us: Timeout in us, 0 means never timeout + * + * Returns 0 on success and -ETIMEDOUT upon a timeout or the regmap_read + * error return value in case of a error read. In the two former cases, + * the last read value at @addr is stored in @val. + * + * This is modelled after the readx_poll_timeout_atomic macros in linux/iopoll.h. + * + * Note: In general regmap cannot be used in atomic context. If you want to use + * this macro then first setup your regmap for atomic use (flat or no cache + * and MMIO regmap). + */ +#define regmap_read_poll_timeout_atomic(map, addr, val, cond, delay_us, timeout_us) \ +({ \ + u64 __timeout_us = (timeout_us); \ + unsigned long __delay_us = (delay_us); \ + ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); \ + int __ret; \ + for (;;) { \ + __ret = regmap_read((map), (addr), &(val)); \ + if (__ret) \ + break; \ + if (cond) \ + break; \ + if ((__timeout_us) && \ + ktime_compare(ktime_get(), __timeout) > 0) { \ + __ret = regmap_read((map), (addr), &(val)); \ + break; \ + } \ + if (__delay_us) \ + udelay(__delay_us); \ + } \ + __ret ?: ((cond) ? 0 : -ETIMEDOUT); \ +}) + +/** + * regmap_field_read_poll_timeout - Poll until a condition is met or timeout + * + * @field: Regmap field to read from + * @val: Unsigned integer variable to read the value into + * @cond: Break condition (usually involving @val) + * @sleep_us: Maximum time to sleep between reads in us (0 + * tight-loops). Should be less than ~20ms since usleep_range + * is used (see Documentation/timers/timers-howto.rst). + * @timeout_us: Timeout in us, 0 means never timeout + * + * Returns 0 on success and -ETIMEDOUT upon a timeout or the regmap_field_read + * error return value in case of a error read. In the two former cases, + * the last read value at @addr is stored in @val. Must not be called + * from atomic context if sleep_us or timeout_us are used. + * + * This is modelled after the readx_poll_timeout macros in linux/iopoll.h. + */ +#define regmap_field_read_poll_timeout(field, val, cond, sleep_us, timeout_us) \ +({ \ + int __ret, __tmp; \ + __tmp = read_poll_timeout(regmap_field_read, __ret, __ret || (cond), \ + sleep_us, timeout_us, false, (field), &(val)); \ + __ret ?: __tmp; \ +}) + +#ifdef CONFIG_REGMAP + +enum regmap_endian { + /* Unspecified -> 0 -> Backwards compatible default */ + REGMAP_ENDIAN_DEFAULT = 0, + REGMAP_ENDIAN_BIG, + REGMAP_ENDIAN_LITTLE, + REGMAP_ENDIAN_NATIVE, +}; + +/** + * struct regmap_range - A register range, used for access related checks + * (readable/writeable/volatile/precious checks) + * + * @range_min: address of first register + * @range_max: address of last register + */ +struct regmap_range { + unsigned int range_min; + unsigned int range_max; +}; + +#define regmap_reg_range(low, high) { .range_min = low, .range_max = high, } + +/** + * struct regmap_access_table - A table of register ranges for access checks + * + * @yes_ranges : pointer to an array of regmap ranges used as "yes ranges" + * @n_yes_ranges: size of the above array + * @no_ranges: pointer to an array of regmap ranges used as "no ranges" + * @n_no_ranges: size of the above array + * + * A table of ranges including some yes ranges and some no ranges. + * If a register belongs to a no_range, the corresponding check function + * will return false. If a register belongs to a yes range, the corresponding + * check function will return true. "no_ranges" are searched first. + */ +struct regmap_access_table { + const struct regmap_range *yes_ranges; + unsigned int n_yes_ranges; + const struct regmap_range *no_ranges; + unsigned int n_no_ranges; +}; + +typedef void (*regmap_lock)(void *); +typedef void (*regmap_unlock)(void *); + +/** + * struct regmap_config - Configuration for the register map of a device. + * + * @name: Optional name of the regmap. Useful when a device has multiple + * register regions. + * + * @reg_bits: Number of bits in a register address, mandatory. + * @reg_stride: The register address stride. Valid register addresses are a + * multiple of this value. If set to 0, a value of 1 will be + * used. + * @reg_shift: The number of bits to shift the register before performing any + * operations. Any positive number will be downshifted, and negative + * values will be upshifted + * @reg_base: Value to be added to every register address before performing any + * operation. + * @pad_bits: Number of bits of padding between register and value. + * @val_bits: Number of bits in a register value, mandatory. + * + * @writeable_reg: Optional callback returning true if the register + * can be written to. If this field is NULL but wr_table + * (see below) is not, the check is performed on such table + * (a register is writeable if it belongs to one of the ranges + * specified by wr_table). + * @readable_reg: Optional callback returning true if the register + * can be read from. If this field is NULL but rd_table + * (see below) is not, the check is performed on such table + * (a register is readable if it belongs to one of the ranges + * specified by rd_table). + * @volatile_reg: Optional callback returning true if the register + * value can't be cached. If this field is NULL but + * volatile_table (see below) is not, the check is performed on + * such table (a register is volatile if it belongs to one of + * the ranges specified by volatile_table). + * @precious_reg: Optional callback returning true if the register + * should not be read outside of a call from the driver + * (e.g., a clear on read interrupt status register). If this + * field is NULL but precious_table (see below) is not, the + * check is performed on such table (a register is precious if + * it belongs to one of the ranges specified by precious_table). + * @writeable_noinc_reg: Optional callback returning true if the register + * supports multiple write operations without incrementing + * the register number. If this field is NULL but + * wr_noinc_table (see below) is not, the check is + * performed on such table (a register is no increment + * writeable if it belongs to one of the ranges specified + * by wr_noinc_table). + * @readable_noinc_reg: Optional callback returning true if the register + * supports multiple read operations without incrementing + * the register number. If this field is NULL but + * rd_noinc_table (see below) is not, the check is + * performed on such table (a register is no increment + * readable if it belongs to one of the ranges specified + * by rd_noinc_table). + * @disable_locking: This regmap is either protected by external means or + * is guaranteed not to be accessed from multiple threads. + * Don't use any locking mechanisms. + * @lock: Optional lock callback (overrides regmap's default lock + * function, based on spinlock or mutex). + * @unlock: As above for unlocking. + * @lock_arg: this field is passed as the only argument of lock/unlock + * functions (ignored in case regular lock/unlock functions + * are not overridden). + * @reg_read: Optional callback that if filled will be used to perform + * all the reads from the registers. Should only be provided for + * devices whose read operation cannot be represented as a simple + * read operation on a bus such as SPI, I2C, etc. Most of the + * devices do not need this. + * @reg_write: Same as above for writing. + * @reg_update_bits: Optional callback that if filled will be used to perform + * all the update_bits(rmw) operation. Should only be provided + * if the function require special handling with lock and reg + * handling and the operation cannot be represented as a simple + * update_bits operation on a bus such as SPI, I2C, etc. + * @read: Optional callback that if filled will be used to perform all the + * bulk reads from the registers. Data is returned in the buffer used + * to transmit data. + * @write: Same as above for writing. + * @max_raw_read: Max raw read size that can be used on the device. + * @max_raw_write: Max raw write size that can be used on the device. + * @fast_io: Register IO is fast. Use a spinlock instead of a mutex + * to perform locking. This field is ignored if custom lock/unlock + * functions are used (see fields lock/unlock of struct regmap_config). + * This field is a duplicate of a similar file in + * 'struct regmap_bus' and serves exact same purpose. + * Use it only for "no-bus" cases. + * @io_port: Support IO port accessors. Makes sense only when MMIO vs. IO port + * access can be distinguished. + * @max_register: Optional, specifies the maximum valid register address. + * @wr_table: Optional, points to a struct regmap_access_table specifying + * valid ranges for write access. + * @rd_table: As above, for read access. + * @volatile_table: As above, for volatile registers. + * @precious_table: As above, for precious registers. + * @wr_noinc_table: As above, for no increment writeable registers. + * @rd_noinc_table: As above, for no increment readable registers. + * @reg_defaults: Power on reset values for registers (for use with + * register cache support). + * @num_reg_defaults: Number of elements in reg_defaults. + * + * @read_flag_mask: Mask to be set in the top bytes of the register when doing + * a read. + * @write_flag_mask: Mask to be set in the top bytes of the register when doing + * a write. If both read_flag_mask and write_flag_mask are + * empty and zero_flag_mask is not set the regmap_bus default + * masks are used. + * @zero_flag_mask: If set, read_flag_mask and write_flag_mask are used even + * if they are both empty. + * @use_relaxed_mmio: If set, MMIO R/W operations will not use memory barriers. + * This can avoid load on devices which don't require strict + * orderings, but drivers should carefully add any explicit + * memory barriers when they may require them. + * @use_single_read: If set, converts the bulk read operation into a series of + * single read operations. This is useful for a device that + * does not support bulk read. + * @use_single_write: If set, converts the bulk write operation into a series of + * single write operations. This is useful for a device that + * does not support bulk write. + * @can_multi_write: If set, the device supports the multi write mode of bulk + * write operations, if clear multi write requests will be + * split into individual write operations + * + * @cache_type: The actual cache type. + * @reg_defaults_raw: Power on reset values for registers (for use with + * register cache support). + * @num_reg_defaults_raw: Number of elements in reg_defaults_raw. + * @reg_format_endian: Endianness for formatted register addresses. If this is + * DEFAULT, the @reg_format_endian_default value from the + * regmap bus is used. + * @val_format_endian: Endianness for formatted register values. If this is + * DEFAULT, the @reg_format_endian_default value from the + * regmap bus is used. + * + * @ranges: Array of configuration entries for virtual address ranges. + * @num_ranges: Number of range configuration entries. + * @use_hwlock: Indicate if a hardware spinlock should be used. + * @use_raw_spinlock: Indicate if a raw spinlock should be used. + * @hwlock_id: Specify the hardware spinlock id. + * @hwlock_mode: The hardware spinlock mode, should be HWLOCK_IRQSTATE, + * HWLOCK_IRQ or 0. + * @can_sleep: Optional, specifies whether regmap operations can sleep. + */ +struct regmap_config { + const char *name; + + int reg_bits; + int reg_stride; + int reg_shift; + unsigned int reg_base; + int pad_bits; + int val_bits; + + bool (*writeable_reg)(struct device *dev, unsigned int reg); + bool (*readable_reg)(struct device *dev, unsigned int reg); + bool (*volatile_reg)(struct device *dev, unsigned int reg); + bool (*precious_reg)(struct device *dev, unsigned int reg); + bool (*writeable_noinc_reg)(struct device *dev, unsigned int reg); + bool (*readable_noinc_reg)(struct device *dev, unsigned int reg); + + bool disable_locking; + regmap_lock lock; + regmap_unlock unlock; + void *lock_arg; + + int (*reg_read)(void *context, unsigned int reg, unsigned int *val); + int (*reg_write)(void *context, unsigned int reg, unsigned int val); + int (*reg_update_bits)(void *context, unsigned int reg, + unsigned int mask, unsigned int val); + /* Bulk read/write */ + int (*read)(void *context, const void *reg_buf, size_t reg_size, + void *val_buf, size_t val_size); + int (*write)(void *context, const void *data, size_t count); + size_t max_raw_read; + size_t max_raw_write; + + bool fast_io; + bool io_port; + + unsigned int max_register; + const struct regmap_access_table *wr_table; + const struct regmap_access_table *rd_table; + const struct regmap_access_table *volatile_table; + const struct regmap_access_table *precious_table; + const struct regmap_access_table *wr_noinc_table; + const struct regmap_access_table *rd_noinc_table; + const struct reg_default *reg_defaults; + unsigned int num_reg_defaults; + enum regcache_type cache_type; + const void *reg_defaults_raw; + unsigned int num_reg_defaults_raw; + + unsigned long read_flag_mask; + unsigned long write_flag_mask; + bool zero_flag_mask; + + bool use_single_read; + bool use_single_write; + bool use_relaxed_mmio; + bool can_multi_write; + + enum regmap_endian reg_format_endian; + enum regmap_endian val_format_endian; + + const struct regmap_range_cfg *ranges; + unsigned int num_ranges; + + bool use_hwlock; + bool use_raw_spinlock; + unsigned int hwlock_id; + unsigned int hwlock_mode; + + bool can_sleep; +}; + +/** + * struct regmap_range_cfg - Configuration for indirectly accessed or paged + * registers. + * + * @name: Descriptive name for diagnostics + * + * @range_min: Address of the lowest register address in virtual range. + * @range_max: Address of the highest register in virtual range. + * + * @selector_reg: Register with selector field. + * @selector_mask: Bit mask for selector value. + * @selector_shift: Bit shift for selector value. + * + * @window_start: Address of first (lowest) register in data window. + * @window_len: Number of registers in data window. + * + * Registers, mapped to this virtual range, are accessed in two steps: + * 1. page selector register update; + * 2. access through data window registers. + */ +struct regmap_range_cfg { + const char *name; + + /* Registers of virtual address range */ + unsigned int range_min; + unsigned int range_max; + + /* Page selector for indirect addressing */ + unsigned int selector_reg; + unsigned int selector_mask; + int selector_shift; + + /* Data window (per each page) */ + unsigned int window_start; + unsigned int window_len; +}; + +struct regmap_async; + +typedef int (*regmap_hw_write)(void *context, const void *data, + size_t count); +typedef int (*regmap_hw_gather_write)(void *context, + const void *reg, size_t reg_len, + const void *val, size_t val_len); +typedef int (*regmap_hw_async_write)(void *context, + const void *reg, size_t reg_len, + const void *val, size_t val_len, + struct regmap_async *async); +typedef int (*regmap_hw_read)(void *context, + const void *reg_buf, size_t reg_size, + void *val_buf, size_t val_size); +typedef int (*regmap_hw_reg_read)(void *context, unsigned int reg, + unsigned int *val); +typedef int (*regmap_hw_reg_noinc_read)(void *context, unsigned int reg, + void *val, size_t val_count); +typedef int (*regmap_hw_reg_write)(void *context, unsigned int reg, + unsigned int val); +typedef int (*regmap_hw_reg_noinc_write)(void *context, unsigned int reg, + const void *val, size_t val_count); +typedef int (*regmap_hw_reg_update_bits)(void *context, unsigned int reg, + unsigned int mask, unsigned int val); +typedef struct regmap_async *(*regmap_hw_async_alloc)(void); +typedef void (*regmap_hw_free_context)(void *context); + +/** + * struct regmap_bus - Description of a hardware bus for the register map + * infrastructure. + * + * @fast_io: Register IO is fast. Use a spinlock instead of a mutex + * to perform locking. This field is ignored if custom lock/unlock + * functions are used (see fields lock/unlock of + * struct regmap_config). + * @free_on_exit: kfree this on exit of regmap + * @write: Write operation. + * @gather_write: Write operation with split register/value, return -ENOTSUPP + * if not implemented on a given device. + * @async_write: Write operation which completes asynchronously, optional and + * must serialise with respect to non-async I/O. + * @reg_write: Write a single register value to the given register address. This + * write operation has to complete when returning from the function. + * @reg_write_noinc: Write multiple register value to the same register. This + * write operation has to complete when returning from the function. + * @reg_update_bits: Update bits operation to be used against volatile + * registers, intended for devices supporting some mechanism + * for setting clearing bits without having to + * read/modify/write. + * @read: Read operation. Data is returned in the buffer used to transmit + * data. + * @reg_read: Read a single register value from a given register address. + * @free_context: Free context. + * @async_alloc: Allocate a regmap_async() structure. + * @read_flag_mask: Mask to be set in the top byte of the register when doing + * a read. + * @reg_format_endian_default: Default endianness for formatted register + * addresses. Used when the regmap_config specifies DEFAULT. If this is + * DEFAULT, BIG is assumed. + * @val_format_endian_default: Default endianness for formatted register + * values. Used when the regmap_config specifies DEFAULT. If this is + * DEFAULT, BIG is assumed. + * @max_raw_read: Max raw read size that can be used on the bus. + * @max_raw_write: Max raw write size that can be used on the bus. + */ +struct regmap_bus { + bool fast_io; + bool free_on_exit; + regmap_hw_write write; + regmap_hw_gather_write gather_write; + regmap_hw_async_write async_write; + regmap_hw_reg_write reg_write; + regmap_hw_reg_noinc_write reg_noinc_write; + regmap_hw_reg_update_bits reg_update_bits; + regmap_hw_read read; + regmap_hw_reg_read reg_read; + regmap_hw_reg_noinc_read reg_noinc_read; + regmap_hw_free_context free_context; + regmap_hw_async_alloc async_alloc; + u8 read_flag_mask; + enum regmap_endian reg_format_endian_default; + enum regmap_endian val_format_endian_default; + size_t max_raw_read; + size_t max_raw_write; +}; + +/* + * __regmap_init functions. + * + * These functions take a lock key and name parameter, and should not be called + * directly. Instead, use the regmap_init macros that generate a key and name + * for each call. + */ +struct regmap *__regmap_init(struct device *dev, + const struct regmap_bus *bus, + void *bus_context, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__regmap_init_i2c(struct i2c_client *i2c, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__regmap_init_mdio(struct mdio_device *mdio_dev, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__regmap_init_sccb(struct i2c_client *i2c, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__regmap_init_slimbus(struct slim_device *slimbus, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__regmap_init_spi(struct spi_device *dev, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__regmap_init_spmi_base(struct spmi_device *dev, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__regmap_init_spmi_ext(struct spmi_device *dev, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__regmap_init_w1(struct device *w1_dev, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__regmap_init_mmio_clk(struct device *dev, const char *clk_id, + void __iomem *regs, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__regmap_init_ac97(struct snd_ac97 *ac97, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__regmap_init_sdw(struct sdw_slave *sdw, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__regmap_init_sdw_mbq(struct sdw_slave *sdw, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__regmap_init_spi_avmm(struct spi_device *spi, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__regmap_init_fsi(struct fsi_device *fsi_dev, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); + +struct regmap *__devm_regmap_init(struct device *dev, + const struct regmap_bus *bus, + void *bus_context, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__devm_regmap_init_i2c(struct i2c_client *i2c, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__devm_regmap_init_mdio(struct mdio_device *mdio_dev, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__devm_regmap_init_sccb(struct i2c_client *i2c, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__devm_regmap_init_spi(struct spi_device *dev, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__devm_regmap_init_spmi_base(struct spmi_device *dev, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__devm_regmap_init_spmi_ext(struct spmi_device *dev, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__devm_regmap_init_w1(struct device *w1_dev, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__devm_regmap_init_mmio_clk(struct device *dev, + const char *clk_id, + void __iomem *regs, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__devm_regmap_init_ac97(struct snd_ac97 *ac97, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__devm_regmap_init_sdw(struct sdw_slave *sdw, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__devm_regmap_init_sdw_mbq(struct sdw_slave *sdw, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__devm_regmap_init_slimbus(struct slim_device *slimbus, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__devm_regmap_init_i3c(struct i3c_device *i3c, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__devm_regmap_init_spi_avmm(struct spi_device *spi, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); +struct regmap *__devm_regmap_init_fsi(struct fsi_device *fsi_dev, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); + +/* + * Wrapper for regmap_init macros to include a unique lockdep key and name + * for each call. No-op if CONFIG_LOCKDEP is not set. + * + * @fn: Real function to call (in the form __[*_]regmap_init[_*]) + * @name: Config variable name (#config in the calling macro) + **/ +#ifdef CONFIG_LOCKDEP +#define __regmap_lockdep_wrapper(fn, name, ...) \ +( \ + ({ \ + static struct lock_class_key _key; \ + fn(__VA_ARGS__, &_key, \ + KBUILD_BASENAME ":" \ + __stringify(__LINE__) ":" \ + "(" name ")->lock"); \ + }) \ +) +#else +#define __regmap_lockdep_wrapper(fn, name, ...) fn(__VA_ARGS__, NULL, NULL) +#endif + +/** + * regmap_init() - Initialise register map + * + * @dev: Device that will be interacted with + * @bus: Bus-specific callbacks to use with device + * @bus_context: Data passed to bus-specific callbacks + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer to + * a struct regmap. This function should generally not be called + * directly, it should be called by bus-specific init functions. + */ +#define regmap_init(dev, bus, bus_context, config) \ + __regmap_lockdep_wrapper(__regmap_init, #config, \ + dev, bus, bus_context, config) +int regmap_attach_dev(struct device *dev, struct regmap *map, + const struct regmap_config *config); + +/** + * regmap_init_i2c() - Initialise register map + * + * @i2c: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer to + * a struct regmap. + */ +#define regmap_init_i2c(i2c, config) \ + __regmap_lockdep_wrapper(__regmap_init_i2c, #config, \ + i2c, config) + +/** + * regmap_init_mdio() - Initialise register map + * + * @mdio_dev: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer to + * a struct regmap. + */ +#define regmap_init_mdio(mdio_dev, config) \ + __regmap_lockdep_wrapper(__regmap_init_mdio, #config, \ + mdio_dev, config) + +/** + * regmap_init_sccb() - Initialise register map + * + * @i2c: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer to + * a struct regmap. + */ +#define regmap_init_sccb(i2c, config) \ + __regmap_lockdep_wrapper(__regmap_init_sccb, #config, \ + i2c, config) + +/** + * regmap_init_slimbus() - Initialise register map + * + * @slimbus: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer to + * a struct regmap. + */ +#define regmap_init_slimbus(slimbus, config) \ + __regmap_lockdep_wrapper(__regmap_init_slimbus, #config, \ + slimbus, config) + +/** + * regmap_init_spi() - Initialise register map + * + * @dev: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer to + * a struct regmap. + */ +#define regmap_init_spi(dev, config) \ + __regmap_lockdep_wrapper(__regmap_init_spi, #config, \ + dev, config) + +/** + * regmap_init_spmi_base() - Create regmap for the Base register space + * + * @dev: SPMI device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer to + * a struct regmap. + */ +#define regmap_init_spmi_base(dev, config) \ + __regmap_lockdep_wrapper(__regmap_init_spmi_base, #config, \ + dev, config) + +/** + * regmap_init_spmi_ext() - Create regmap for Ext register space + * + * @dev: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer to + * a struct regmap. + */ +#define regmap_init_spmi_ext(dev, config) \ + __regmap_lockdep_wrapper(__regmap_init_spmi_ext, #config, \ + dev, config) + +/** + * regmap_init_w1() - Initialise register map + * + * @w1_dev: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer to + * a struct regmap. + */ +#define regmap_init_w1(w1_dev, config) \ + __regmap_lockdep_wrapper(__regmap_init_w1, #config, \ + w1_dev, config) + +/** + * regmap_init_mmio_clk() - Initialise register map with register clock + * + * @dev: Device that will be interacted with + * @clk_id: register clock consumer ID + * @regs: Pointer to memory-mapped IO region + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer to + * a struct regmap. + */ +#define regmap_init_mmio_clk(dev, clk_id, regs, config) \ + __regmap_lockdep_wrapper(__regmap_init_mmio_clk, #config, \ + dev, clk_id, regs, config) + +/** + * regmap_init_mmio() - Initialise register map + * + * @dev: Device that will be interacted with + * @regs: Pointer to memory-mapped IO region + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer to + * a struct regmap. + */ +#define regmap_init_mmio(dev, regs, config) \ + regmap_init_mmio_clk(dev, NULL, regs, config) + +/** + * regmap_init_ac97() - Initialise AC'97 register map + * + * @ac97: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer to + * a struct regmap. + */ +#define regmap_init_ac97(ac97, config) \ + __regmap_lockdep_wrapper(__regmap_init_ac97, #config, \ + ac97, config) +bool regmap_ac97_default_volatile(struct device *dev, unsigned int reg); + +/** + * regmap_init_sdw() - Initialise register map + * + * @sdw: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer to + * a struct regmap. + */ +#define regmap_init_sdw(sdw, config) \ + __regmap_lockdep_wrapper(__regmap_init_sdw, #config, \ + sdw, config) + +/** + * regmap_init_sdw_mbq() - Initialise register map + * + * @sdw: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer to + * a struct regmap. + */ +#define regmap_init_sdw_mbq(sdw, config) \ + __regmap_lockdep_wrapper(__regmap_init_sdw_mbq, #config, \ + sdw, config) + +/** + * regmap_init_spi_avmm() - Initialize register map for Intel SPI Slave + * to AVMM Bus Bridge + * + * @spi: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. + */ +#define regmap_init_spi_avmm(spi, config) \ + __regmap_lockdep_wrapper(__regmap_init_spi_avmm, #config, \ + spi, config) + +/** + * regmap_init_fsi() - Initialise register map + * + * @fsi_dev: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer to + * a struct regmap. + */ +#define regmap_init_fsi(fsi_dev, config) \ + __regmap_lockdep_wrapper(__regmap_init_fsi, #config, fsi_dev, \ + config) + +/** + * devm_regmap_init() - Initialise managed register map + * + * @dev: Device that will be interacted with + * @bus: Bus-specific callbacks to use with device + * @bus_context: Data passed to bus-specific callbacks + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. This function should generally not be called + * directly, it should be called by bus-specific init functions. The + * map will be automatically freed by the device management code. + */ +#define devm_regmap_init(dev, bus, bus_context, config) \ + __regmap_lockdep_wrapper(__devm_regmap_init, #config, \ + dev, bus, bus_context, config) + +/** + * devm_regmap_init_i2c() - Initialise managed register map + * + * @i2c: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. The regmap will be automatically freed by the + * device management code. + */ +#define devm_regmap_init_i2c(i2c, config) \ + __regmap_lockdep_wrapper(__devm_regmap_init_i2c, #config, \ + i2c, config) + +/** + * devm_regmap_init_mdio() - Initialise managed register map + * + * @mdio_dev: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. The regmap will be automatically freed by the + * device management code. + */ +#define devm_regmap_init_mdio(mdio_dev, config) \ + __regmap_lockdep_wrapper(__devm_regmap_init_mdio, #config, \ + mdio_dev, config) + +/** + * devm_regmap_init_sccb() - Initialise managed register map + * + * @i2c: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. The regmap will be automatically freed by the + * device management code. + */ +#define devm_regmap_init_sccb(i2c, config) \ + __regmap_lockdep_wrapper(__devm_regmap_init_sccb, #config, \ + i2c, config) + +/** + * devm_regmap_init_spi() - Initialise register map + * + * @dev: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. The map will be automatically freed by the + * device management code. + */ +#define devm_regmap_init_spi(dev, config) \ + __regmap_lockdep_wrapper(__devm_regmap_init_spi, #config, \ + dev, config) + +/** + * devm_regmap_init_spmi_base() - Create managed regmap for Base register space + * + * @dev: SPMI device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. The regmap will be automatically freed by the + * device management code. + */ +#define devm_regmap_init_spmi_base(dev, config) \ + __regmap_lockdep_wrapper(__devm_regmap_init_spmi_base, #config, \ + dev, config) + +/** + * devm_regmap_init_spmi_ext() - Create managed regmap for Ext register space + * + * @dev: SPMI device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. The regmap will be automatically freed by the + * device management code. + */ +#define devm_regmap_init_spmi_ext(dev, config) \ + __regmap_lockdep_wrapper(__devm_regmap_init_spmi_ext, #config, \ + dev, config) + +/** + * devm_regmap_init_w1() - Initialise managed register map + * + * @w1_dev: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. The regmap will be automatically freed by the + * device management code. + */ +#define devm_regmap_init_w1(w1_dev, config) \ + __regmap_lockdep_wrapper(__devm_regmap_init_w1, #config, \ + w1_dev, config) +/** + * devm_regmap_init_mmio_clk() - Initialise managed register map with clock + * + * @dev: Device that will be interacted with + * @clk_id: register clock consumer ID + * @regs: Pointer to memory-mapped IO region + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. The regmap will be automatically freed by the + * device management code. + */ +#define devm_regmap_init_mmio_clk(dev, clk_id, regs, config) \ + __regmap_lockdep_wrapper(__devm_regmap_init_mmio_clk, #config, \ + dev, clk_id, regs, config) + +/** + * devm_regmap_init_mmio() - Initialise managed register map + * + * @dev: Device that will be interacted with + * @regs: Pointer to memory-mapped IO region + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. The regmap will be automatically freed by the + * device management code. + */ +#define devm_regmap_init_mmio(dev, regs, config) \ + devm_regmap_init_mmio_clk(dev, NULL, regs, config) + +/** + * devm_regmap_init_ac97() - Initialise AC'97 register map + * + * @ac97: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. The regmap will be automatically freed by the + * device management code. + */ +#define devm_regmap_init_ac97(ac97, config) \ + __regmap_lockdep_wrapper(__devm_regmap_init_ac97, #config, \ + ac97, config) + +/** + * devm_regmap_init_sdw() - Initialise managed register map + * + * @sdw: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. The regmap will be automatically freed by the + * device management code. + */ +#define devm_regmap_init_sdw(sdw, config) \ + __regmap_lockdep_wrapper(__devm_regmap_init_sdw, #config, \ + sdw, config) + +/** + * devm_regmap_init_sdw_mbq() - Initialise managed register map + * + * @sdw: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. The regmap will be automatically freed by the + * device management code. + */ +#define devm_regmap_init_sdw_mbq(sdw, config) \ + __regmap_lockdep_wrapper(__devm_regmap_init_sdw_mbq, #config, \ + sdw, config) + +/** + * devm_regmap_init_slimbus() - Initialise managed register map + * + * @slimbus: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. The regmap will be automatically freed by the + * device management code. + */ +#define devm_regmap_init_slimbus(slimbus, config) \ + __regmap_lockdep_wrapper(__devm_regmap_init_slimbus, #config, \ + slimbus, config) + +/** + * devm_regmap_init_i3c() - Initialise managed register map + * + * @i3c: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. The regmap will be automatically freed by the + * device management code. + */ +#define devm_regmap_init_i3c(i3c, config) \ + __regmap_lockdep_wrapper(__devm_regmap_init_i3c, #config, \ + i3c, config) + +/** + * devm_regmap_init_spi_avmm() - Initialize register map for Intel SPI Slave + * to AVMM Bus Bridge + * + * @spi: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. The map will be automatically freed by the + * device management code. + */ +#define devm_regmap_init_spi_avmm(spi, config) \ + __regmap_lockdep_wrapper(__devm_regmap_init_spi_avmm, #config, \ + spi, config) + +/** + * devm_regmap_init_fsi() - Initialise managed register map + * + * @fsi_dev: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. The regmap will be automatically freed by the + * device management code. + */ +#define devm_regmap_init_fsi(fsi_dev, config) \ + __regmap_lockdep_wrapper(__devm_regmap_init_fsi, #config, \ + fsi_dev, config) + +int regmap_mmio_attach_clk(struct regmap *map, struct clk *clk); +void regmap_mmio_detach_clk(struct regmap *map); +void regmap_exit(struct regmap *map); +int regmap_reinit_cache(struct regmap *map, + const struct regmap_config *config); +struct regmap *dev_get_regmap(struct device *dev, const char *name); +struct device *regmap_get_device(struct regmap *map); +int regmap_write(struct regmap *map, unsigned int reg, unsigned int val); +int regmap_write_async(struct regmap *map, unsigned int reg, unsigned int val); +int regmap_raw_write(struct regmap *map, unsigned int reg, + const void *val, size_t val_len); +int regmap_noinc_write(struct regmap *map, unsigned int reg, + const void *val, size_t val_len); +int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, + size_t val_count); +int regmap_multi_reg_write(struct regmap *map, const struct reg_sequence *regs, + int num_regs); +int regmap_multi_reg_write_bypassed(struct regmap *map, + const struct reg_sequence *regs, + int num_regs); +int regmap_raw_write_async(struct regmap *map, unsigned int reg, + const void *val, size_t val_len); +int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val); +int regmap_raw_read(struct regmap *map, unsigned int reg, + void *val, size_t val_len); +int regmap_noinc_read(struct regmap *map, unsigned int reg, + void *val, size_t val_len); +int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val, + size_t val_count); +int regmap_update_bits_base(struct regmap *map, unsigned int reg, + unsigned int mask, unsigned int val, + bool *change, bool async, bool force); + +static inline int regmap_update_bits(struct regmap *map, unsigned int reg, + unsigned int mask, unsigned int val) +{ + return regmap_update_bits_base(map, reg, mask, val, NULL, false, false); +} + +static inline int regmap_update_bits_async(struct regmap *map, unsigned int reg, + unsigned int mask, unsigned int val) +{ + return regmap_update_bits_base(map, reg, mask, val, NULL, true, false); +} + +static inline int regmap_update_bits_check(struct regmap *map, unsigned int reg, + unsigned int mask, unsigned int val, + bool *change) +{ + return regmap_update_bits_base(map, reg, mask, val, + change, false, false); +} + +static inline int +regmap_update_bits_check_async(struct regmap *map, unsigned int reg, + unsigned int mask, unsigned int val, + bool *change) +{ + return regmap_update_bits_base(map, reg, mask, val, + change, true, false); +} + +static inline int regmap_write_bits(struct regmap *map, unsigned int reg, + unsigned int mask, unsigned int val) +{ + return regmap_update_bits_base(map, reg, mask, val, NULL, false, true); +} + +int regmap_get_val_bytes(struct regmap *map); +int regmap_get_max_register(struct regmap *map); +int regmap_get_reg_stride(struct regmap *map); +bool regmap_might_sleep(struct regmap *map); +int regmap_async_complete(struct regmap *map); +bool regmap_can_raw_write(struct regmap *map); +size_t regmap_get_raw_read_max(struct regmap *map); +size_t regmap_get_raw_write_max(struct regmap *map); + +int regcache_sync(struct regmap *map); +int regcache_sync_region(struct regmap *map, unsigned int min, + unsigned int max); +int regcache_drop_region(struct regmap *map, unsigned int min, + unsigned int max); +void regcache_cache_only(struct regmap *map, bool enable); +void regcache_cache_bypass(struct regmap *map, bool enable); +void regcache_mark_dirty(struct regmap *map); +bool regcache_reg_cached(struct regmap *map, unsigned int reg); + +bool regmap_check_range_table(struct regmap *map, unsigned int reg, + const struct regmap_access_table *table); + +int regmap_register_patch(struct regmap *map, const struct reg_sequence *regs, + int num_regs); +int regmap_parse_val(struct regmap *map, const void *buf, + unsigned int *val); + +static inline bool regmap_reg_in_range(unsigned int reg, + const struct regmap_range *range) +{ + return reg >= range->range_min && reg <= range->range_max; +} + +bool regmap_reg_in_ranges(unsigned int reg, + const struct regmap_range *ranges, + unsigned int nranges); + +static inline int regmap_set_bits(struct regmap *map, + unsigned int reg, unsigned int bits) +{ + return regmap_update_bits_base(map, reg, bits, bits, + NULL, false, false); +} + +static inline int regmap_clear_bits(struct regmap *map, + unsigned int reg, unsigned int bits) +{ + return regmap_update_bits_base(map, reg, bits, 0, NULL, false, false); +} + +int regmap_test_bits(struct regmap *map, unsigned int reg, unsigned int bits); + +/** + * struct reg_field - Description of an register field + * + * @reg: Offset of the register within the regmap bank + * @lsb: lsb of the register field. + * @msb: msb of the register field. + * @id_size: port size if it has some ports + * @id_offset: address offset for each ports + */ +struct reg_field { + unsigned int reg; + unsigned int lsb; + unsigned int msb; + unsigned int id_size; + unsigned int id_offset; +}; + +#define REG_FIELD(_reg, _lsb, _msb) { \ + .reg = _reg, \ + .lsb = _lsb, \ + .msb = _msb, \ + } + +#define REG_FIELD_ID(_reg, _lsb, _msb, _size, _offset) { \ + .reg = _reg, \ + .lsb = _lsb, \ + .msb = _msb, \ + .id_size = _size, \ + .id_offset = _offset, \ + } + +struct regmap_field *regmap_field_alloc(struct regmap *regmap, + struct reg_field reg_field); +void regmap_field_free(struct regmap_field *field); + +struct regmap_field *devm_regmap_field_alloc(struct device *dev, + struct regmap *regmap, struct reg_field reg_field); +void devm_regmap_field_free(struct device *dev, struct regmap_field *field); + +int regmap_field_bulk_alloc(struct regmap *regmap, + struct regmap_field **rm_field, + const struct reg_field *reg_field, + int num_fields); +void regmap_field_bulk_free(struct regmap_field *field); +int devm_regmap_field_bulk_alloc(struct device *dev, struct regmap *regmap, + struct regmap_field **field, + const struct reg_field *reg_field, + int num_fields); +void devm_regmap_field_bulk_free(struct device *dev, + struct regmap_field *field); + +int regmap_field_read(struct regmap_field *field, unsigned int *val); +int regmap_field_update_bits_base(struct regmap_field *field, + unsigned int mask, unsigned int val, + bool *change, bool async, bool force); +int regmap_fields_read(struct regmap_field *field, unsigned int id, + unsigned int *val); +int regmap_fields_update_bits_base(struct regmap_field *field, unsigned int id, + unsigned int mask, unsigned int val, + bool *change, bool async, bool force); + +static inline int regmap_field_write(struct regmap_field *field, + unsigned int val) +{ + return regmap_field_update_bits_base(field, ~0, val, + NULL, false, false); +} + +static inline int regmap_field_force_write(struct regmap_field *field, + unsigned int val) +{ + return regmap_field_update_bits_base(field, ~0, val, NULL, false, true); +} + +static inline int regmap_field_update_bits(struct regmap_field *field, + unsigned int mask, unsigned int val) +{ + return regmap_field_update_bits_base(field, mask, val, + NULL, false, false); +} + +static inline int regmap_field_set_bits(struct regmap_field *field, + unsigned int bits) +{ + return regmap_field_update_bits_base(field, bits, bits, NULL, false, + false); +} + +static inline int regmap_field_clear_bits(struct regmap_field *field, + unsigned int bits) +{ + return regmap_field_update_bits_base(field, bits, 0, NULL, false, + false); +} + +int regmap_field_test_bits(struct regmap_field *field, unsigned int bits); + +static inline int +regmap_field_force_update_bits(struct regmap_field *field, + unsigned int mask, unsigned int val) +{ + return regmap_field_update_bits_base(field, mask, val, + NULL, false, true); +} + +static inline int regmap_fields_write(struct regmap_field *field, + unsigned int id, unsigned int val) +{ + return regmap_fields_update_bits_base(field, id, ~0, val, + NULL, false, false); +} + +static inline int regmap_fields_force_write(struct regmap_field *field, + unsigned int id, unsigned int val) +{ + return regmap_fields_update_bits_base(field, id, ~0, val, + NULL, false, true); +} + +static inline int +regmap_fields_update_bits(struct regmap_field *field, unsigned int id, + unsigned int mask, unsigned int val) +{ + return regmap_fields_update_bits_base(field, id, mask, val, + NULL, false, false); +} + +static inline int +regmap_fields_force_update_bits(struct regmap_field *field, unsigned int id, + unsigned int mask, unsigned int val) +{ + return regmap_fields_update_bits_base(field, id, mask, val, + NULL, false, true); +} + +/** + * struct regmap_irq_type - IRQ type definitions. + * + * @type_reg_offset: Offset register for the irq type setting. + * @type_rising_val: Register value to configure RISING type irq. + * @type_falling_val: Register value to configure FALLING type irq. + * @type_level_low_val: Register value to configure LEVEL_LOW type irq. + * @type_level_high_val: Register value to configure LEVEL_HIGH type irq. + * @types_supported: logical OR of IRQ_TYPE_* flags indicating supported types. + */ +struct regmap_irq_type { + unsigned int type_reg_offset; + unsigned int type_reg_mask; + unsigned int type_rising_val; + unsigned int type_falling_val; + unsigned int type_level_low_val; + unsigned int type_level_high_val; + unsigned int types_supported; +}; + +/** + * struct regmap_irq - Description of an IRQ for the generic regmap irq_chip. + * + * @reg_offset: Offset of the status/mask register within the bank + * @mask: Mask used to flag/control the register. + * @type: IRQ trigger type setting details if supported. + */ +struct regmap_irq { + unsigned int reg_offset; + unsigned int mask; + struct regmap_irq_type type; +}; + +#define REGMAP_IRQ_REG(_irq, _off, _mask) \ + [_irq] = { .reg_offset = (_off), .mask = (_mask) } + +#define REGMAP_IRQ_REG_LINE(_id, _reg_bits) \ + [_id] = { \ + .mask = BIT((_id) % (_reg_bits)), \ + .reg_offset = (_id) / (_reg_bits), \ + } + +#define REGMAP_IRQ_MAIN_REG_OFFSET(arr) \ + { .num_regs = ARRAY_SIZE((arr)), .offset = &(arr)[0] } + +struct regmap_irq_sub_irq_map { + unsigned int num_regs; + unsigned int *offset; +}; + +struct regmap_irq_chip_data; + +/** + * struct regmap_irq_chip - Description of a generic regmap irq_chip. + * + * @name: Descriptive name for IRQ controller. + * + * @main_status: Base main status register address. For chips which have + * interrupts arranged in separate sub-irq blocks with own IRQ + * registers and which have a main IRQ registers indicating + * sub-irq blocks with unhandled interrupts. For such chips fill + * sub-irq register information in status_base, mask_base and + * ack_base. + * @num_main_status_bits: Should be given to chips where number of meaningfull + * main status bits differs from num_regs. + * @sub_reg_offsets: arrays of mappings from main register bits to sub irq + * registers. First item in array describes the registers + * for first main status bit. Second array for second bit etc. + * Offset is given as sub register status offset to + * status_base. Should contain num_regs arrays. + * Can be provided for chips with more complex mapping than + * 1.st bit to 1.st sub-reg, 2.nd bit to 2.nd sub-reg, ... + * When used with not_fixed_stride, each one-element array + * member contains offset calculated as address from each + * peripheral to first peripheral. + * @num_main_regs: Number of 'main status' irq registers for chips which have + * main_status set. + * + * @status_base: Base status register address. + * @mask_base: Base mask register address. Mask bits are set to 1 when an + * interrupt is masked, 0 when unmasked. + * @unmask_base: Base unmask register address. Unmask bits are set to 1 when + * an interrupt is unmasked and 0 when masked. + * @ack_base: Base ack address. If zero then the chip is clear on read. + * Using zero value is possible with @use_ack bit. + * @wake_base: Base address for wake enables. If zero unsupported. + * @type_base: Base address for irq type. If zero unsupported. Deprecated, + * use @config_base instead. + * @virt_reg_base: Base addresses for extra config regs. Deprecated, use + * @config_base instead. + * @config_base: Base address for IRQ type config regs. If null unsupported. + * @irq_reg_stride: Stride to use for chips where registers are not contiguous. + * @init_ack_masked: Ack all masked interrupts once during initalization. + * @mask_unmask_non_inverted: Controls mask bit inversion for chips that set + * both @mask_base and @unmask_base. If false, mask and unmask bits are + * inverted (which is deprecated behavior); if true, bits will not be + * inverted and the registers keep their normal behavior. Note that if + * you use only one of @mask_base or @unmask_base, this flag has no + * effect and is unnecessary. Any new drivers that set both @mask_base + * and @unmask_base should set this to true to avoid relying on the + * deprecated behavior. + * @use_ack: Use @ack register even if it is zero. + * @ack_invert: Inverted ack register: cleared bits for ack. + * @clear_ack: Use this to set 1 and 0 or vice-versa to clear interrupts. + * @wake_invert: Inverted wake register: cleared bits are wake enabled. + * @type_in_mask: Use the mask registers for controlling irq type. Use this if + * the hardware provides separate bits for rising/falling edge + * or low/high level interrupts and they should be combined into + * a single logical interrupt. Use &struct regmap_irq_type data + * to define the mask bit for each irq type. + * @clear_on_unmask: For chips with interrupts cleared on read: read the status + * registers before unmasking interrupts to clear any bits + * set when they were masked. + * @not_fixed_stride: Used when chip peripherals are not laid out with fixed + * stride. Must be used with sub_reg_offsets containing the + * offsets to each peripheral. Deprecated; the same thing + * can be accomplished with a @get_irq_reg callback, without + * the need for a @sub_reg_offsets table. + * @status_invert: Inverted status register: cleared bits are active interrupts. + * @runtime_pm: Hold a runtime PM lock on the device when accessing it. + * @no_status: No status register: all interrupts assumed generated by device. + * + * @num_regs: Number of registers in each control bank. + * @irqs: Descriptors for individual IRQs. Interrupt numbers are + * assigned based on the index in the array of the interrupt. + * @num_irqs: Number of descriptors. + * @num_type_reg: Number of type registers. Deprecated, use config registers + * instead. + * @num_virt_regs: Number of non-standard irq configuration registers. + * If zero unsupported. Deprecated, use config registers + * instead. + * @num_config_bases: Number of config base registers. + * @num_config_regs: Number of config registers for each config base register. + * @handle_pre_irq: Driver specific callback to handle interrupt from device + * before regmap_irq_handler process the interrupts. + * @handle_post_irq: Driver specific callback to handle interrupt from device + * after handling the interrupts in regmap_irq_handler(). + * @handle_mask_sync: Callback used to handle IRQ mask syncs. The index will be + * in the range [0, num_regs) + * @set_type_virt: Driver specific callback to extend regmap_irq_set_type() + * and configure virt regs. Deprecated, use @set_type_config + * callback and config registers instead. + * @set_type_config: Callback used for configuring irq types. + * @get_irq_reg: Callback for mapping (base register, index) pairs to register + * addresses. The base register will be one of @status_base, + * @mask_base, etc., @main_status, or any of @config_base. + * The index will be in the range [0, num_main_regs[ for the + * main status base, [0, num_type_settings[ for any config + * register base, and [0, num_regs[ for any other base. + * If unspecified then regmap_irq_get_irq_reg_linear() is used. + * @irq_drv_data: Driver specific IRQ data which is passed as parameter when + * driver specific pre/post interrupt handler is called. + * + * This is not intended to handle every possible interrupt controller, but + * it should handle a substantial proportion of those that are found in the + * wild. + */ +struct regmap_irq_chip { + const char *name; + + unsigned int main_status; + unsigned int num_main_status_bits; + struct regmap_irq_sub_irq_map *sub_reg_offsets; + int num_main_regs; + + unsigned int status_base; + unsigned int mask_base; + unsigned int unmask_base; + unsigned int ack_base; + unsigned int wake_base; + unsigned int type_base; + unsigned int *virt_reg_base; + const unsigned int *config_base; + unsigned int irq_reg_stride; + unsigned int init_ack_masked:1; + unsigned int mask_unmask_non_inverted:1; + unsigned int use_ack:1; + unsigned int ack_invert:1; + unsigned int clear_ack:1; + unsigned int wake_invert:1; + unsigned int runtime_pm:1; + unsigned int type_in_mask:1; + unsigned int clear_on_unmask:1; + unsigned int not_fixed_stride:1; + unsigned int status_invert:1; + unsigned int no_status:1; + + int num_regs; + + const struct regmap_irq *irqs; + int num_irqs; + + int num_type_reg; + int num_virt_regs; + int num_config_bases; + int num_config_regs; + + int (*handle_pre_irq)(void *irq_drv_data); + int (*handle_post_irq)(void *irq_drv_data); + int (*handle_mask_sync)(struct regmap *map, int index, + unsigned int mask_buf_def, + unsigned int mask_buf, void *irq_drv_data); + int (*set_type_virt)(unsigned int **buf, unsigned int type, + unsigned long hwirq, int reg); + int (*set_type_config)(unsigned int **buf, unsigned int type, + const struct regmap_irq *irq_data, int idx, + void *irq_drv_data); + unsigned int (*get_irq_reg)(struct regmap_irq_chip_data *data, + unsigned int base, int index); + void *irq_drv_data; +}; + +unsigned int regmap_irq_get_irq_reg_linear(struct regmap_irq_chip_data *data, + unsigned int base, int index); +int regmap_irq_set_type_config_simple(unsigned int **buf, unsigned int type, + const struct regmap_irq *irq_data, + int idx, void *irq_drv_data); + +int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, + int irq_base, const struct regmap_irq_chip *chip, + struct regmap_irq_chip_data **data); +int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode, + struct regmap *map, int irq, + int irq_flags, int irq_base, + const struct regmap_irq_chip *chip, + struct regmap_irq_chip_data **data); +void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *data); + +int devm_regmap_add_irq_chip(struct device *dev, struct regmap *map, int irq, + int irq_flags, int irq_base, + const struct regmap_irq_chip *chip, + struct regmap_irq_chip_data **data); +int devm_regmap_add_irq_chip_fwnode(struct device *dev, + struct fwnode_handle *fwnode, + struct regmap *map, int irq, + int irq_flags, int irq_base, + const struct regmap_irq_chip *chip, + struct regmap_irq_chip_data **data); +void devm_regmap_del_irq_chip(struct device *dev, int irq, + struct regmap_irq_chip_data *data); + +int regmap_irq_chip_get_base(struct regmap_irq_chip_data *data); +int regmap_irq_get_virq(struct regmap_irq_chip_data *data, int irq); +struct irq_domain *regmap_irq_get_domain(struct regmap_irq_chip_data *data); + +#else + +/* + * These stubs should only ever be called by generic code which has + * regmap based facilities, if they ever get called at runtime + * something is going wrong and something probably needs to select + * REGMAP. + */ + +static inline int regmap_write(struct regmap *map, unsigned int reg, + unsigned int val) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_write_async(struct regmap *map, unsigned int reg, + unsigned int val) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_raw_write(struct regmap *map, unsigned int reg, + const void *val, size_t val_len) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_raw_write_async(struct regmap *map, unsigned int reg, + const void *val, size_t val_len) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_noinc_write(struct regmap *map, unsigned int reg, + const void *val, size_t val_len) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_bulk_write(struct regmap *map, unsigned int reg, + const void *val, size_t val_count) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_read(struct regmap *map, unsigned int reg, + unsigned int *val) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_raw_read(struct regmap *map, unsigned int reg, + void *val, size_t val_len) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_noinc_read(struct regmap *map, unsigned int reg, + void *val, size_t val_len) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_bulk_read(struct regmap *map, unsigned int reg, + void *val, size_t val_count) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_update_bits_base(struct regmap *map, unsigned int reg, + unsigned int mask, unsigned int val, + bool *change, bool async, bool force) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_set_bits(struct regmap *map, + unsigned int reg, unsigned int bits) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_clear_bits(struct regmap *map, + unsigned int reg, unsigned int bits) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_test_bits(struct regmap *map, + unsigned int reg, unsigned int bits) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_field_update_bits_base(struct regmap_field *field, + unsigned int mask, unsigned int val, + bool *change, bool async, bool force) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_fields_update_bits_base(struct regmap_field *field, + unsigned int id, + unsigned int mask, unsigned int val, + bool *change, bool async, bool force) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_update_bits(struct regmap *map, unsigned int reg, + unsigned int mask, unsigned int val) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_update_bits_async(struct regmap *map, unsigned int reg, + unsigned int mask, unsigned int val) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_update_bits_check(struct regmap *map, unsigned int reg, + unsigned int mask, unsigned int val, + bool *change) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int +regmap_update_bits_check_async(struct regmap *map, unsigned int reg, + unsigned int mask, unsigned int val, + bool *change) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_write_bits(struct regmap *map, unsigned int reg, + unsigned int mask, unsigned int val) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_field_write(struct regmap_field *field, + unsigned int val) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_field_force_write(struct regmap_field *field, + unsigned int val) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_field_update_bits(struct regmap_field *field, + unsigned int mask, unsigned int val) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int +regmap_field_force_update_bits(struct regmap_field *field, + unsigned int mask, unsigned int val) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_field_set_bits(struct regmap_field *field, + unsigned int bits) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_field_clear_bits(struct regmap_field *field, + unsigned int bits) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_field_test_bits(struct regmap_field *field, + unsigned int bits) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_fields_write(struct regmap_field *field, + unsigned int id, unsigned int val) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_fields_force_write(struct regmap_field *field, + unsigned int id, unsigned int val) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int +regmap_fields_update_bits(struct regmap_field *field, unsigned int id, + unsigned int mask, unsigned int val) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int +regmap_fields_force_update_bits(struct regmap_field *field, unsigned int id, + unsigned int mask, unsigned int val) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_get_val_bytes(struct regmap *map) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_get_max_register(struct regmap *map) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_get_reg_stride(struct regmap *map) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline bool regmap_might_sleep(struct regmap *map) +{ + WARN_ONCE(1, "regmap API is disabled"); + return true; +} + +static inline int regcache_sync(struct regmap *map) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regcache_sync_region(struct regmap *map, unsigned int min, + unsigned int max) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regcache_drop_region(struct regmap *map, unsigned int min, + unsigned int max) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline void regcache_cache_only(struct regmap *map, bool enable) +{ + WARN_ONCE(1, "regmap API is disabled"); +} + +static inline void regcache_cache_bypass(struct regmap *map, bool enable) +{ + WARN_ONCE(1, "regmap API is disabled"); +} + +static inline void regcache_mark_dirty(struct regmap *map) +{ + WARN_ONCE(1, "regmap API is disabled"); +} + +static inline void regmap_async_complete(struct regmap *map) +{ + WARN_ONCE(1, "regmap API is disabled"); +} + +static inline int regmap_register_patch(struct regmap *map, + const struct reg_sequence *regs, + int num_regs) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline int regmap_parse_val(struct regmap *map, const void *buf, + unsigned int *val) +{ + WARN_ONCE(1, "regmap API is disabled"); + return -EINVAL; +} + +static inline struct regmap *dev_get_regmap(struct device *dev, + const char *name) +{ + return NULL; +} + +static inline struct device *regmap_get_device(struct regmap *map) +{ + WARN_ONCE(1, "regmap API is disabled"); + return NULL; +} + +#endif + +#endif diff --git a/snd-alpx-dkms/snd-alpx/include/5.3/dmaengine.h b/snd-alpx-dkms/snd-alpx/include/5.3/dmaengine.h new file mode 100644 index 0000000..501c0b0 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/include/5.3/dmaengine.h @@ -0,0 +1,174 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * The contents of this file are private to DMA engine drivers, and is not + * part of the API to be used by DMA engine users. + */ +#ifndef DMAENGINE_H +#define DMAENGINE_H + +#include <linux/bug.h> +#include <linux/dmaengine.h> + +/** + * dma_cookie_init - initialize the cookies for a DMA channel + * @chan: dma channel to initialize + */ +static inline void dma_cookie_init(struct dma_chan *chan) +{ + chan->cookie = DMA_MIN_COOKIE; + chan->completed_cookie = DMA_MIN_COOKIE; +} + +/** + * dma_cookie_assign - assign a DMA engine cookie to the descriptor + * @tx: descriptor needing cookie + * + * Assign a unique non-zero per-channel cookie to the descriptor. + * Note: caller is expected to hold a lock to prevent concurrency. + */ +static inline dma_cookie_t dma_cookie_assign(struct dma_async_tx_descriptor *tx) +{ + struct dma_chan *chan = tx->chan; + dma_cookie_t cookie; + + cookie = chan->cookie + 1; + if (cookie < DMA_MIN_COOKIE) + cookie = DMA_MIN_COOKIE; + tx->cookie = chan->cookie = cookie; + + return cookie; +} + +/** + * dma_cookie_complete - complete a descriptor + * @tx: descriptor to complete + * + * Mark this descriptor complete by updating the channels completed + * cookie marker. Zero the descriptors cookie to prevent accidental + * repeated completions. + * + * Note: caller is expected to hold a lock to prevent concurrency. + */ +static inline void dma_cookie_complete(struct dma_async_tx_descriptor *tx) +{ + BUG_ON(tx->cookie < DMA_MIN_COOKIE); + tx->chan->completed_cookie = tx->cookie; + tx->cookie = 0; +} + +/** + * dma_cookie_status - report cookie status + * @chan: dma channel + * @cookie: cookie we are interested in + * @state: dma_tx_state structure to return last/used cookies + * + * Report the status of the cookie, filling in the state structure if + * non-NULL. No locking is required. + */ +static inline enum dma_status dma_cookie_status(struct dma_chan *chan, + dma_cookie_t cookie, struct dma_tx_state *state) +{ + dma_cookie_t used, complete; + + used = chan->cookie; + complete = chan->completed_cookie; + barrier(); + if (state) { + state->last = complete; + state->used = used; + state->residue = 0; + } + return dma_async_is_complete(cookie, complete, used); +} + +static inline void dma_set_residue(struct dma_tx_state *state, u32 residue) +{ + if (state) + state->residue = residue; +} + +struct dmaengine_desc_callback { + dma_async_tx_callback callback; + dma_async_tx_callback_result callback_result; + void *callback_param; +}; + +/** + * dmaengine_desc_get_callback - get the passed in callback function + * @tx: tx descriptor + * @cb: temp struct to hold the callback info + * + * Fill the passed in cb struct with what's available in the passed in + * tx descriptor struct + * No locking is required. + */ +static inline void +dmaengine_desc_get_callback(struct dma_async_tx_descriptor *tx, + struct dmaengine_desc_callback *cb) +{ + cb->callback = tx->callback; + cb->callback_result = tx->callback_result; + cb->callback_param = tx->callback_param; +} + +/** + * dmaengine_desc_callback_invoke - call the callback function in cb struct + * @cb: temp struct that is holding the callback info + * @result: transaction result + * + * Call the callback function provided in the cb struct with the parameter + * in the cb struct. + * Locking is dependent on the driver. + */ +static inline void +dmaengine_desc_callback_invoke(struct dmaengine_desc_callback *cb, + const struct dmaengine_result *result) +{ + struct dmaengine_result dummy_result = { + .result = DMA_TRANS_NOERROR, + .residue = 0 + }; + + if (cb->callback_result) { + if (!result) + result = &dummy_result; + cb->callback_result(cb->callback_param, result); + } else if (cb->callback) { + cb->callback(cb->callback_param); + } +} + +/** + * dmaengine_desc_get_callback_invoke - get the callback in tx descriptor and + * then immediately call the callback. + * @tx: dma async tx descriptor + * @result: transaction result + * + * Call dmaengine_desc_get_callback() and dmaengine_desc_callback_invoke() + * in a single function since no work is necessary in between for the driver. + * Locking is dependent on the driver. + */ +static inline void +dmaengine_desc_get_callback_invoke(struct dma_async_tx_descriptor *tx, + const struct dmaengine_result *result) +{ + struct dmaengine_desc_callback cb; + + dmaengine_desc_get_callback(tx, &cb); + dmaengine_desc_callback_invoke(&cb, result); +} + +/** + * dmaengine_desc_callback_valid - verify the callback is valid in cb + * @cb: callback info struct + * + * Return a bool that verifies whether callback in cb is valid or not. + * No locking is required. + */ +static inline bool +dmaengine_desc_callback_valid(struct dmaengine_desc_callback *cb) +{ + return (cb->callback) ? true : false; +} + +#endif diff --git a/snd-alpx-dkms/snd-alpx/include/5.3/virt-dma.h b/snd-alpx-dkms/snd-alpx/include/5.3/virt-dma.h new file mode 100644 index 0000000..ab158ba --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/include/5.3/virt-dma.h @@ -0,0 +1,222 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Virtual DMA channel support for DMAengine + * + * Copyright (C) 2012 Russell King + */ +#ifndef VIRT_DMA_H +#define VIRT_DMA_H + +#include <linux/dmaengine.h> +#include <linux/interrupt.h> + +#include "dmaengine.h" + +struct virt_dma_desc { + struct dma_async_tx_descriptor tx; + struct dmaengine_result tx_result; + /* protected by vc.lock */ + struct list_head node; +}; + +struct virt_dma_chan { + struct dma_chan chan; + struct tasklet_struct task; + void (*desc_free)(struct virt_dma_desc *); + + spinlock_t lock; + + /* protected by vc.lock */ + struct list_head desc_allocated; + struct list_head desc_submitted; + struct list_head desc_issued; + struct list_head desc_completed; + + struct virt_dma_desc *cyclic; + struct virt_dma_desc *vd_terminated; +}; + +static inline struct virt_dma_chan *to_virt_chan(struct dma_chan *chan) +{ + return container_of(chan, struct virt_dma_chan, chan); +} + +void vchan_dma_desc_free_list(struct virt_dma_chan *vc, struct list_head *head); +void vchan_init(struct virt_dma_chan *vc, struct dma_device *dmadev); +struct virt_dma_desc *vchan_find_desc(struct virt_dma_chan *, dma_cookie_t); +extern dma_cookie_t vchan_tx_submit(struct dma_async_tx_descriptor *); +extern int vchan_tx_desc_free(struct dma_async_tx_descriptor *); + +/** + * vchan_tx_prep - prepare a descriptor + * @vc: virtual channel allocating this descriptor + * @vd: virtual descriptor to prepare + * @tx_flags: flags argument passed in to prepare function + */ +static inline struct dma_async_tx_descriptor *vchan_tx_prep(struct virt_dma_chan *vc, + struct virt_dma_desc *vd, unsigned long tx_flags) +{ + unsigned long flags; + + dma_async_tx_descriptor_init(&vd->tx, &vc->chan); + vd->tx.flags = tx_flags; + vd->tx.tx_submit = vchan_tx_submit; + vd->tx.desc_free = vchan_tx_desc_free; + + vd->tx_result.result = DMA_TRANS_NOERROR; + vd->tx_result.residue = 0; + + spin_lock_irqsave(&vc->lock, flags); + list_add_tail(&vd->node, &vc->desc_allocated); + spin_unlock_irqrestore(&vc->lock, flags); + + return &vd->tx; +} + +/** + * vchan_issue_pending - move submitted descriptors to issued list + * @vc: virtual channel to update + * + * vc.lock must be held by caller + */ +static inline bool vchan_issue_pending(struct virt_dma_chan *vc) +{ + list_splice_tail_init(&vc->desc_submitted, &vc->desc_issued); + return !list_empty(&vc->desc_issued); +} + +/** + * vchan_cookie_complete - report completion of a descriptor + * @vd: virtual descriptor to update + * + * vc.lock must be held by caller + */ +static inline void vchan_cookie_complete(struct virt_dma_desc *vd) +{ + struct virt_dma_chan *vc = to_virt_chan(vd->tx.chan); + dma_cookie_t cookie; + + cookie = vd->tx.cookie; + dma_cookie_complete(&vd->tx); + dev_vdbg(vc->chan.device->dev, "txd %p[%x]: marked complete\n", + vd, cookie); + list_add_tail(&vd->node, &vc->desc_completed); + + tasklet_schedule(&vc->task); +} + +/** + * vchan_vdesc_fini - Free or reuse a descriptor + * @vd: virtual descriptor to free/reuse + */ +static inline void vchan_vdesc_fini(struct virt_dma_desc *vd) +{ + struct virt_dma_chan *vc = to_virt_chan(vd->tx.chan); + + if (dmaengine_desc_test_reuse(&vd->tx)) + list_add(&vd->node, &vc->desc_allocated); + else + vc->desc_free(vd); +} + +/** + * vchan_cyclic_callback - report the completion of a period + * @vd: virtual descriptor + */ +static inline void vchan_cyclic_callback(struct virt_dma_desc *vd) +{ + struct virt_dma_chan *vc = to_virt_chan(vd->tx.chan); + + vc->cyclic = vd; + tasklet_schedule(&vc->task); +} + +/** + * vchan_terminate_vdesc - Disable pending cyclic callback + * @vd: virtual descriptor to be terminated + * + * vc.lock must be held by caller + */ +static inline void vchan_terminate_vdesc(struct virt_dma_desc *vd) +{ + struct virt_dma_chan *vc = to_virt_chan(vd->tx.chan); + + /* free up stuck descriptor */ + if (vc->vd_terminated) + vchan_vdesc_fini(vc->vd_terminated); + + vc->vd_terminated = vd; + if (vc->cyclic == vd) + vc->cyclic = NULL; +} + +/** + * vchan_next_desc - peek at the next descriptor to be processed + * @vc: virtual channel to obtain descriptor from + * + * vc.lock must be held by caller + */ +static inline struct virt_dma_desc *vchan_next_desc(struct virt_dma_chan *vc) +{ + return list_first_entry_or_null(&vc->desc_issued, + struct virt_dma_desc, node); +} + +/** + * vchan_get_all_descriptors - obtain all submitted and issued descriptors + * @vc: virtual channel to get descriptors from + * @head: list of descriptors found + * + * vc.lock must be held by caller + * + * Removes all submitted and issued descriptors from internal lists, and + * provides a list of all descriptors found + */ +static inline void vchan_get_all_descriptors(struct virt_dma_chan *vc, + struct list_head *head) +{ + list_splice_tail_init(&vc->desc_allocated, head); + list_splice_tail_init(&vc->desc_submitted, head); + list_splice_tail_init(&vc->desc_issued, head); + list_splice_tail_init(&vc->desc_completed, head); +} + +static inline void vchan_free_chan_resources(struct virt_dma_chan *vc) +{ + struct virt_dma_desc *vd; + unsigned long flags; + LIST_HEAD(head); + + spin_lock_irqsave(&vc->lock, flags); + vchan_get_all_descriptors(vc, &head); + list_for_each_entry(vd, &head, node) + dmaengine_desc_clear_reuse(&vd->tx); + spin_unlock_irqrestore(&vc->lock, flags); + + vchan_dma_desc_free_list(vc, &head); +} + +/** + * vchan_synchronize() - synchronize callback execution to the current context + * @vc: virtual channel to synchronize + * + * Makes sure that all scheduled or active callbacks have finished running. For + * proper operation the caller has to ensure that no new callbacks are scheduled + * after the invocation of this function started. + * Free up the terminated cyclic descriptor to prevent memory leakage. + */ +static inline void vchan_synchronize(struct virt_dma_chan *vc) +{ + unsigned long flags; + + tasklet_kill(&vc->task); + + spin_lock_irqsave(&vc->lock, flags); + if (vc->vd_terminated) { + vchan_vdesc_fini(vc->vd_terminated); + vc->vd_terminated = NULL; + } + spin_unlock_irqrestore(&vc->lock, flags); +} + +#endif diff --git a/snd-alpx-dkms/snd-alpx/include/5.6/dmaengine.h b/snd-alpx-dkms/snd-alpx/include/5.6/dmaengine.h new file mode 100644 index 0000000..e8a320c --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/include/5.6/dmaengine.h @@ -0,0 +1,185 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * The contents of this file are private to DMA engine drivers, and is not + * part of the API to be used by DMA engine users. + */ +#ifndef DMAENGINE_H +#define DMAENGINE_H + +#include <linux/bug.h> +#include <linux/dmaengine.h> + +/** + * dma_cookie_init - initialize the cookies for a DMA channel + * @chan: dma channel to initialize + */ +static inline void dma_cookie_init(struct dma_chan *chan) +{ + chan->cookie = DMA_MIN_COOKIE; + chan->completed_cookie = DMA_MIN_COOKIE; +} + +/** + * dma_cookie_assign - assign a DMA engine cookie to the descriptor + * @tx: descriptor needing cookie + * + * Assign a unique non-zero per-channel cookie to the descriptor. + * Note: caller is expected to hold a lock to prevent concurrency. + */ +static inline dma_cookie_t dma_cookie_assign(struct dma_async_tx_descriptor *tx) +{ + struct dma_chan *chan = tx->chan; + dma_cookie_t cookie; + + cookie = chan->cookie + 1; + if (cookie < DMA_MIN_COOKIE) + cookie = DMA_MIN_COOKIE; + tx->cookie = chan->cookie = cookie; + + return cookie; +} + +/** + * dma_cookie_complete - complete a descriptor + * @tx: descriptor to complete + * + * Mark this descriptor complete by updating the channels completed + * cookie marker. Zero the descriptors cookie to prevent accidental + * repeated completions. + * + * Note: caller is expected to hold a lock to prevent concurrency. + */ +static inline void dma_cookie_complete(struct dma_async_tx_descriptor *tx) +{ + BUG_ON(tx->cookie < DMA_MIN_COOKIE); + tx->chan->completed_cookie = tx->cookie; + tx->cookie = 0; +} + +/** + * dma_cookie_status - report cookie status + * @chan: dma channel + * @cookie: cookie we are interested in + * @state: dma_tx_state structure to return last/used cookies + * + * Report the status of the cookie, filling in the state structure if + * non-NULL. No locking is required. + */ +static inline enum dma_status dma_cookie_status(struct dma_chan *chan, + dma_cookie_t cookie, struct dma_tx_state *state) +{ + dma_cookie_t used, complete; + + used = chan->cookie; + complete = chan->completed_cookie; + barrier(); + if (state) { + state->last = complete; + state->used = used; + state->residue = 0; + state->in_flight_bytes = 0; + } + return dma_async_is_complete(cookie, complete, used); +} + +static inline void dma_set_residue(struct dma_tx_state *state, u32 residue) +{ + if (state) + state->residue = residue; +} + +static inline void dma_set_in_flight_bytes(struct dma_tx_state *state, + u32 in_flight_bytes) +{ + if (state) + state->in_flight_bytes = in_flight_bytes; +} + +struct dmaengine_desc_callback { + dma_async_tx_callback callback; + dma_async_tx_callback_result callback_result; + void *callback_param; +}; + +/** + * dmaengine_desc_get_callback - get the passed in callback function + * @tx: tx descriptor + * @cb: temp struct to hold the callback info + * + * Fill the passed in cb struct with what's available in the passed in + * tx descriptor struct + * No locking is required. + */ +static inline void +dmaengine_desc_get_callback(struct dma_async_tx_descriptor *tx, + struct dmaengine_desc_callback *cb) +{ + cb->callback = tx->callback; + cb->callback_result = tx->callback_result; + cb->callback_param = tx->callback_param; +} + +/** + * dmaengine_desc_callback_invoke - call the callback function in cb struct + * @cb: temp struct that is holding the callback info + * @result: transaction result + * + * Call the callback function provided in the cb struct with the parameter + * in the cb struct. + * Locking is dependent on the driver. + */ +static inline void +dmaengine_desc_callback_invoke(struct dmaengine_desc_callback *cb, + const struct dmaengine_result *result) +{ + struct dmaengine_result dummy_result = { + .result = DMA_TRANS_NOERROR, + .residue = 0 + }; + + if (cb->callback_result) { + if (!result) + result = &dummy_result; + cb->callback_result(cb->callback_param, result); + } else if (cb->callback) { + cb->callback(cb->callback_param); + } +} + +/** + * dmaengine_desc_get_callback_invoke - get the callback in tx descriptor and + * then immediately call the callback. + * @tx: dma async tx descriptor + * @result: transaction result + * + * Call dmaengine_desc_get_callback() and dmaengine_desc_callback_invoke() + * in a single function since no work is necessary in between for the driver. + * Locking is dependent on the driver. + */ +static inline void +dmaengine_desc_get_callback_invoke(struct dma_async_tx_descriptor *tx, + const struct dmaengine_result *result) +{ + struct dmaengine_desc_callback cb; + + dmaengine_desc_get_callback(tx, &cb); + dmaengine_desc_callback_invoke(&cb, result); +} + +/** + * dmaengine_desc_callback_valid - verify the callback is valid in cb + * @cb: callback info struct + * + * Return a bool that verifies whether callback in cb is valid or not. + * No locking is required. + */ +static inline bool +dmaengine_desc_callback_valid(struct dmaengine_desc_callback *cb) +{ + return (cb->callback) ? true : false; +} + +struct dma_chan *dma_get_slave_channel(struct dma_chan *chan); +struct dma_chan *dma_get_any_slave_channel(struct dma_device *device); + +#endif diff --git a/snd-alpx-dkms/snd-alpx/include/5.6/virt-dma.h b/snd-alpx-dkms/snd-alpx/include/5.6/virt-dma.h new file mode 100644 index 0000000..e9f5250 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/include/5.6/virt-dma.h @@ -0,0 +1,227 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Virtual DMA channel support for DMAengine + * + * Copyright (C) 2012 Russell King + */ +#ifndef VIRT_DMA_H +#define VIRT_DMA_H + +#include <linux/dmaengine.h> +#include <linux/interrupt.h> + +#include "dmaengine.h" + +struct virt_dma_desc { + struct dma_async_tx_descriptor tx; + struct dmaengine_result tx_result; + /* protected by vc.lock */ + struct list_head node; +}; + +struct virt_dma_chan { + struct dma_chan chan; + struct tasklet_struct task; + void (*desc_free)(struct virt_dma_desc *); + + spinlock_t lock; + + /* protected by vc.lock */ + struct list_head desc_allocated; + struct list_head desc_submitted; + struct list_head desc_issued; + struct list_head desc_completed; + struct list_head desc_terminated; + + struct virt_dma_desc *cyclic; +}; + +static inline struct virt_dma_chan *to_virt_chan(struct dma_chan *chan) +{ + return container_of(chan, struct virt_dma_chan, chan); +} + +void vchan_dma_desc_free_list(struct virt_dma_chan *vc, struct list_head *head); +void vchan_init(struct virt_dma_chan *vc, struct dma_device *dmadev); +struct virt_dma_desc *vchan_find_desc(struct virt_dma_chan *, dma_cookie_t); +extern dma_cookie_t vchan_tx_submit(struct dma_async_tx_descriptor *); +extern int vchan_tx_desc_free(struct dma_async_tx_descriptor *); + +/** + * vchan_tx_prep - prepare a descriptor + * @vc: virtual channel allocating this descriptor + * @vd: virtual descriptor to prepare + * @tx_flags: flags argument passed in to prepare function + */ +static inline struct dma_async_tx_descriptor *vchan_tx_prep(struct virt_dma_chan *vc, + struct virt_dma_desc *vd, unsigned long tx_flags) +{ + unsigned long flags; + + dma_async_tx_descriptor_init(&vd->tx, &vc->chan); + vd->tx.flags = tx_flags; + vd->tx.tx_submit = vchan_tx_submit; + vd->tx.desc_free = vchan_tx_desc_free; + + vd->tx_result.result = DMA_TRANS_NOERROR; + vd->tx_result.residue = 0; + + spin_lock_irqsave(&vc->lock, flags); + list_add_tail(&vd->node, &vc->desc_allocated); + spin_unlock_irqrestore(&vc->lock, flags); + + return &vd->tx; +} + +/** + * vchan_issue_pending - move submitted descriptors to issued list + * @vc: virtual channel to update + * + * vc.lock must be held by caller + */ +static inline bool vchan_issue_pending(struct virt_dma_chan *vc) +{ + list_splice_tail_init(&vc->desc_submitted, &vc->desc_issued); + return !list_empty(&vc->desc_issued); +} + +/** + * vchan_cookie_complete - report completion of a descriptor + * @vd: virtual descriptor to update + * + * vc.lock must be held by caller + */ +static inline void vchan_cookie_complete(struct virt_dma_desc *vd) +{ + struct virt_dma_chan *vc = to_virt_chan(vd->tx.chan); + dma_cookie_t cookie; + + cookie = vd->tx.cookie; + dma_cookie_complete(&vd->tx); + dev_vdbg(vc->chan.device->dev, "txd %p[%x]: marked complete\n", + vd, cookie); + list_add_tail(&vd->node, &vc->desc_completed); + + tasklet_schedule(&vc->task); +} + +/** + * vchan_vdesc_fini - Free or reuse a descriptor + * @vd: virtual descriptor to free/reuse + */ +static inline void vchan_vdesc_fini(struct virt_dma_desc *vd) +{ + struct virt_dma_chan *vc = to_virt_chan(vd->tx.chan); + + if (dmaengine_desc_test_reuse(&vd->tx)) { + unsigned long flags; + + spin_lock_irqsave(&vc->lock, flags); + list_add(&vd->node, &vc->desc_allocated); + spin_unlock_irqrestore(&vc->lock, flags); + } else { + vc->desc_free(vd); + } +} + +/** + * vchan_cyclic_callback - report the completion of a period + * @vd: virtual descriptor + */ +static inline void vchan_cyclic_callback(struct virt_dma_desc *vd) +{ + struct virt_dma_chan *vc = to_virt_chan(vd->tx.chan); + + vc->cyclic = vd; + tasklet_schedule(&vc->task); +} + +/** + * vchan_terminate_vdesc - Disable pending cyclic callback + * @vd: virtual descriptor to be terminated + * + * vc.lock must be held by caller + */ +static inline void vchan_terminate_vdesc(struct virt_dma_desc *vd) +{ + struct virt_dma_chan *vc = to_virt_chan(vd->tx.chan); + + list_add_tail(&vd->node, &vc->desc_terminated); + + if (vc->cyclic == vd) + vc->cyclic = NULL; +} + +/** + * vchan_next_desc - peek at the next descriptor to be processed + * @vc: virtual channel to obtain descriptor from + * + * vc.lock must be held by caller + */ +static inline struct virt_dma_desc *vchan_next_desc(struct virt_dma_chan *vc) +{ + return list_first_entry_or_null(&vc->desc_issued, + struct virt_dma_desc, node); +} + +/** + * vchan_get_all_descriptors - obtain all submitted and issued descriptors + * @vc: virtual channel to get descriptors from + * @head: list of descriptors found + * + * vc.lock must be held by caller + * + * Removes all submitted and issued descriptors from internal lists, and + * provides a list of all descriptors found + */ +static inline void vchan_get_all_descriptors(struct virt_dma_chan *vc, + struct list_head *head) +{ + list_splice_tail_init(&vc->desc_allocated, head); + list_splice_tail_init(&vc->desc_submitted, head); + list_splice_tail_init(&vc->desc_issued, head); + list_splice_tail_init(&vc->desc_completed, head); + list_splice_tail_init(&vc->desc_terminated, head); +} + +static inline void vchan_free_chan_resources(struct virt_dma_chan *vc) +{ + struct virt_dma_desc *vd; + unsigned long flags; + LIST_HEAD(head); + + spin_lock_irqsave(&vc->lock, flags); + vchan_get_all_descriptors(vc, &head); + list_for_each_entry(vd, &head, node) + dmaengine_desc_clear_reuse(&vd->tx); + spin_unlock_irqrestore(&vc->lock, flags); + + vchan_dma_desc_free_list(vc, &head); +} + +/** + * vchan_synchronize() - synchronize callback execution to the current context + * @vc: virtual channel to synchronize + * + * Makes sure that all scheduled or active callbacks have finished running. For + * proper operation the caller has to ensure that no new callbacks are scheduled + * after the invocation of this function started. + * Free up the terminated cyclic descriptor to prevent memory leakage. + */ +static inline void vchan_synchronize(struct virt_dma_chan *vc) +{ + LIST_HEAD(head); + unsigned long flags; + + tasklet_kill(&vc->task); + + spin_lock_irqsave(&vc->lock, flags); + + list_splice_tail_init(&vc->desc_terminated, &head); + + spin_unlock_irqrestore(&vc->lock, flags); + + vchan_dma_desc_free_list(vc, &head); +} + +#endif diff --git a/snd-alpx-dkms/snd-alpx/include/6.2/amd_xdma.h b/snd-alpx-dkms/snd-alpx/include/6.2/amd_xdma.h new file mode 100644 index 0000000..ceba69e --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/include/6.2/amd_xdma.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2022, Advanced Micro Devices, Inc. + */ + +#ifndef _DMAENGINE_AMD_XDMA_H +#define _DMAENGINE_AMD_XDMA_H + +#include <linux/interrupt.h> +#include <linux/platform_device.h> + +int xdma_enable_user_irq(struct platform_device *pdev, u32 irq_num); +void xdma_disable_user_irq(struct platform_device *pdev, u32 irq_num); +int xdma_get_user_irq(struct platform_device *pdev, u32 user_irq_index); + +#endif /* _DMAENGINE_AMD_XDMA_H */ diff --git a/snd-alpx-dkms/snd-alpx/include/6.2/dmaengine.h b/snd-alpx-dkms/snd-alpx/include/6.2/dmaengine.h new file mode 100644 index 0000000..c3656e5 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/include/6.2/dmaengine.h @@ -0,0 +1,1637 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved. + */ +#ifndef LINUX_DMAENGINE_H +#define LINUX_DMAENGINE_H + +#include <linux/device.h> +#include <linux/err.h> +#include <linux/uio.h> +#include <linux/bug.h> +#include <linux/scatterlist.h> +#include <linux/bitmap.h> +#include <linux/types.h> +#include <asm/page.h> + +/** + * typedef dma_cookie_t - an opaque DMA cookie + * + * if dma_cookie_t is >0 it's a DMA request cookie, <0 it's an error code + */ +typedef s32 dma_cookie_t; +#define DMA_MIN_COOKIE 1 + +static inline int dma_submit_error(dma_cookie_t cookie) +{ + return cookie < 0 ? cookie : 0; +} + +/** + * enum dma_status - DMA transaction status + * @DMA_COMPLETE: transaction completed + * @DMA_IN_PROGRESS: transaction not yet processed + * @DMA_PAUSED: transaction is paused + * @DMA_ERROR: transaction failed + */ +enum dma_status { + DMA_COMPLETE, + DMA_IN_PROGRESS, + DMA_PAUSED, + DMA_ERROR, + DMA_OUT_OF_ORDER, +}; + +/** + * enum dma_transaction_type - DMA transaction types/indexes + * + * Note: The DMA_ASYNC_TX capability is not to be set by drivers. It is + * automatically set as dma devices are registered. + */ +enum dma_transaction_type { + DMA_MEMCPY, + DMA_XOR, + DMA_PQ, + DMA_XOR_VAL, + DMA_PQ_VAL, + DMA_MEMSET, + DMA_MEMSET_SG, + DMA_INTERRUPT, + DMA_PRIVATE, + DMA_ASYNC_TX, + DMA_SLAVE, + DMA_CYCLIC, + DMA_INTERLEAVE, + DMA_COMPLETION_NO_ORDER, + DMA_REPEAT, + DMA_LOAD_EOT, +/* last transaction type for creation of the capabilities mask */ + DMA_TX_TYPE_END, +}; + +/** + * enum dma_transfer_direction - dma transfer mode and direction indicator + * @DMA_MEM_TO_MEM: Async/Memcpy mode + * @DMA_MEM_TO_DEV: Slave mode & From Memory to Device + * @DMA_DEV_TO_MEM: Slave mode & From Device to Memory + * @DMA_DEV_TO_DEV: Slave mode & From Device to Device + */ +enum dma_transfer_direction { + DMA_MEM_TO_MEM, + DMA_MEM_TO_DEV, + DMA_DEV_TO_MEM, + DMA_DEV_TO_DEV, + DMA_TRANS_NONE, +}; + +/** + * Interleaved Transfer Request + * ---------------------------- + * A chunk is collection of contiguous bytes to be transferred. + * The gap(in bytes) between two chunks is called inter-chunk-gap(ICG). + * ICGs may or may not change between chunks. + * A FRAME is the smallest series of contiguous {chunk,icg} pairs, + * that when repeated an integral number of times, specifies the transfer. + * A transfer template is specification of a Frame, the number of times + * it is to be repeated and other per-transfer attributes. + * + * Practically, a client driver would have ready a template for each + * type of transfer it is going to need during its lifetime and + * set only 'src_start' and 'dst_start' before submitting the requests. + * + * + * | Frame-1 | Frame-2 | ~ | Frame-'numf' | + * |====....==.===...=...|====....==.===...=...| ~ |====....==.===...=...| + * + * == Chunk size + * ... ICG + */ + +/** + * struct data_chunk - Element of scatter-gather list that makes a frame. + * @size: Number of bytes to read from source. + * size_dst := fn(op, size_src), so doesn't mean much for destination. + * @icg: Number of bytes to jump after last src/dst address of this + * chunk and before first src/dst address for next chunk. + * Ignored for dst(assumed 0), if dst_inc is true and dst_sgl is false. + * Ignored for src(assumed 0), if src_inc is true and src_sgl is false. + * @dst_icg: Number of bytes to jump after last dst address of this + * chunk and before the first dst address for next chunk. + * Ignored if dst_inc is true and dst_sgl is false. + * @src_icg: Number of bytes to jump after last src address of this + * chunk and before the first src address for next chunk. + * Ignored if src_inc is true and src_sgl is false. + */ +struct data_chunk { + size_t size; + size_t icg; + size_t dst_icg; + size_t src_icg; +}; + +/** + * struct dma_interleaved_template - Template to convey DMAC the transfer pattern + * and attributes. + * @src_start: Bus address of source for the first chunk. + * @dst_start: Bus address of destination for the first chunk. + * @dir: Specifies the type of Source and Destination. + * @src_inc: If the source address increments after reading from it. + * @dst_inc: If the destination address increments after writing to it. + * @src_sgl: If the 'icg' of sgl[] applies to Source (scattered read). + * Otherwise, source is read contiguously (icg ignored). + * Ignored if src_inc is false. + * @dst_sgl: If the 'icg' of sgl[] applies to Destination (scattered write). + * Otherwise, destination is filled contiguously (icg ignored). + * Ignored if dst_inc is false. + * @numf: Number of frames in this template. + * @frame_size: Number of chunks in a frame i.e, size of sgl[]. + * @sgl: Array of {chunk,icg} pairs that make up a frame. + */ +struct dma_interleaved_template { + dma_addr_t src_start; + dma_addr_t dst_start; + enum dma_transfer_direction dir; + bool src_inc; + bool dst_inc; + bool src_sgl; + bool dst_sgl; + size_t numf; + size_t frame_size; + struct data_chunk sgl[]; +}; + +/** + * enum dma_ctrl_flags - DMA flags to augment operation preparation, + * control completion, and communicate status. + * @DMA_PREP_INTERRUPT - trigger an interrupt (callback) upon completion of + * this transaction + * @DMA_CTRL_ACK - if clear, the descriptor cannot be reused until the client + * acknowledges receipt, i.e. has a chance to establish any dependency + * chains + * @DMA_PREP_PQ_DISABLE_P - prevent generation of P while generating Q + * @DMA_PREP_PQ_DISABLE_Q - prevent generation of Q while generating P + * @DMA_PREP_CONTINUE - indicate to a driver that it is reusing buffers as + * sources that were the result of a previous operation, in the case of a PQ + * operation it continues the calculation with new sources + * @DMA_PREP_FENCE - tell the driver that subsequent operations depend + * on the result of this operation + * @DMA_CTRL_REUSE: client can reuse the descriptor and submit again till + * cleared or freed + * @DMA_PREP_CMD: tell the driver that the data passed to DMA API is command + * data and the descriptor should be in different format from normal + * data descriptors. + * @DMA_PREP_REPEAT: tell the driver that the transaction shall be automatically + * repeated when it ends until a transaction is issued on the same channel + * with the DMA_PREP_LOAD_EOT flag set. This flag is only applicable to + * interleaved transactions and is ignored for all other transaction types. + * @DMA_PREP_LOAD_EOT: tell the driver that the transaction shall replace any + * active repeated (as indicated by DMA_PREP_REPEAT) transaction when the + * repeated transaction ends. Not setting this flag when the previously queued + * transaction is marked with DMA_PREP_REPEAT will cause the new transaction + * to never be processed and stay in the issued queue forever. The flag is + * ignored if the previous transaction is not a repeated transaction. + */ +enum dma_ctrl_flags { + DMA_PREP_INTERRUPT = (1 << 0), + DMA_CTRL_ACK = (1 << 1), + DMA_PREP_PQ_DISABLE_P = (1 << 2), + DMA_PREP_PQ_DISABLE_Q = (1 << 3), + DMA_PREP_CONTINUE = (1 << 4), + DMA_PREP_FENCE = (1 << 5), + DMA_CTRL_REUSE = (1 << 6), + DMA_PREP_CMD = (1 << 7), + DMA_PREP_REPEAT = (1 << 8), + DMA_PREP_LOAD_EOT = (1 << 9), +}; + +/** + * enum sum_check_bits - bit position of pq_check_flags + */ +enum sum_check_bits { + SUM_CHECK_P = 0, + SUM_CHECK_Q = 1, +}; + +/** + * enum pq_check_flags - result of async_{xor,pq}_zero_sum operations + * @SUM_CHECK_P_RESULT - 1 if xor zero sum error, 0 otherwise + * @SUM_CHECK_Q_RESULT - 1 if reed-solomon zero sum error, 0 otherwise + */ +enum sum_check_flags { + SUM_CHECK_P_RESULT = (1 << SUM_CHECK_P), + SUM_CHECK_Q_RESULT = (1 << SUM_CHECK_Q), +}; + + +/** + * dma_cap_mask_t - capabilities bitmap modeled after cpumask_t. + * See linux/cpumask.h + */ +typedef struct { DECLARE_BITMAP(bits, DMA_TX_TYPE_END); } dma_cap_mask_t; + +/** + * enum dma_desc_metadata_mode - per descriptor metadata mode types supported + * @DESC_METADATA_CLIENT - the metadata buffer is allocated/provided by the + * client driver and it is attached (via the dmaengine_desc_attach_metadata() + * helper) to the descriptor. + * + * Client drivers interested to use this mode can follow: + * - DMA_MEM_TO_DEV / DEV_MEM_TO_MEM: + * 1. prepare the descriptor (dmaengine_prep_*) + * construct the metadata in the client's buffer + * 2. use dmaengine_desc_attach_metadata() to attach the buffer to the + * descriptor + * 3. submit the transfer + * - DMA_DEV_TO_MEM: + * 1. prepare the descriptor (dmaengine_prep_*) + * 2. use dmaengine_desc_attach_metadata() to attach the buffer to the + * descriptor + * 3. submit the transfer + * 4. when the transfer is completed, the metadata should be available in the + * attached buffer + * + * @DESC_METADATA_ENGINE - the metadata buffer is allocated/managed by the DMA + * driver. The client driver can ask for the pointer, maximum size and the + * currently used size of the metadata and can directly update or read it. + * dmaengine_desc_get_metadata_ptr() and dmaengine_desc_set_metadata_len() is + * provided as helper functions. + * + * Note: the metadata area for the descriptor is no longer valid after the + * transfer has been completed (valid up to the point when the completion + * callback returns if used). + * + * Client drivers interested to use this mode can follow: + * - DMA_MEM_TO_DEV / DEV_MEM_TO_MEM: + * 1. prepare the descriptor (dmaengine_prep_*) + * 2. use dmaengine_desc_get_metadata_ptr() to get the pointer to the engine's + * metadata area + * 3. update the metadata at the pointer + * 4. use dmaengine_desc_set_metadata_len() to tell the DMA engine the amount + * of data the client has placed into the metadata buffer + * 5. submit the transfer + * - DMA_DEV_TO_MEM: + * 1. prepare the descriptor (dmaengine_prep_*) + * 2. submit the transfer + * 3. on transfer completion, use dmaengine_desc_get_metadata_ptr() to get the + * pointer to the engine's metadata area + * 4. Read out the metadata from the pointer + * + * Note: the two mode is not compatible and clients must use one mode for a + * descriptor. + */ +enum dma_desc_metadata_mode { + DESC_METADATA_NONE = 0, + DESC_METADATA_CLIENT = BIT(0), + DESC_METADATA_ENGINE = BIT(1), +}; + +/** + * struct dma_chan_percpu - the per-CPU part of struct dma_chan + * @memcpy_count: transaction counter + * @bytes_transferred: byte counter + */ +struct dma_chan_percpu { + /* stats */ + unsigned long memcpy_count; + unsigned long bytes_transferred; +}; + +/** + * struct dma_router - DMA router structure + * @dev: pointer to the DMA router device + * @route_free: function to be called when the route can be disconnected + */ +struct dma_router { + struct device *dev; + void (*route_free)(struct device *dev, void *route_data); +}; + +/** + * struct dma_chan - devices supply DMA channels, clients use them + * @device: ptr to the dma device who supplies this channel, always !%NULL + * @slave: ptr to the device using this channel + * @cookie: last cookie value returned to client + * @completed_cookie: last completed cookie for this channel + * @chan_id: channel ID for sysfs + * @dev: class device for sysfs + * @name: backlink name for sysfs + * @dbg_client_name: slave name for debugfs in format: + * dev_name(requester's dev):channel name, for example: "2b00000.mcasp:tx" + * @device_node: used to add this to the device chan list + * @local: per-cpu pointer to a struct dma_chan_percpu + * @client_count: how many clients are using this channel + * @table_count: number of appearances in the mem-to-mem allocation table + * @router: pointer to the DMA router structure + * @route_data: channel specific data for the router + * @private: private data for certain client-channel associations + */ +struct dma_chan { + struct dma_device *device; + struct device *slave; + dma_cookie_t cookie; + dma_cookie_t completed_cookie; + + /* sysfs */ + int chan_id; + struct dma_chan_dev *dev; + const char *name; +#ifdef CONFIG_DEBUG_FS + char *dbg_client_name; +#endif + + struct list_head device_node; + struct dma_chan_percpu __percpu *local; + int client_count; + int table_count; + + /* DMA router */ + struct dma_router *router; + void *route_data; + + void *private; +}; + +/** + * struct dma_chan_dev - relate sysfs device node to backing channel device + * @chan: driver channel device + * @device: sysfs device + * @dev_id: parent dma_device dev_id + * @chan_dma_dev: The channel is using custom/different dma-mapping + * compared to the parent dma_device + */ +struct dma_chan_dev { + struct dma_chan *chan; + struct device device; + int dev_id; + bool chan_dma_dev; +}; + +/** + * enum dma_slave_buswidth - defines bus width of the DMA slave + * device, source or target buses + */ +enum dma_slave_buswidth { + DMA_SLAVE_BUSWIDTH_UNDEFINED = 0, + DMA_SLAVE_BUSWIDTH_1_BYTE = 1, + DMA_SLAVE_BUSWIDTH_2_BYTES = 2, + DMA_SLAVE_BUSWIDTH_3_BYTES = 3, + DMA_SLAVE_BUSWIDTH_4_BYTES = 4, + DMA_SLAVE_BUSWIDTH_8_BYTES = 8, + DMA_SLAVE_BUSWIDTH_16_BYTES = 16, + DMA_SLAVE_BUSWIDTH_32_BYTES = 32, + DMA_SLAVE_BUSWIDTH_64_BYTES = 64, + DMA_SLAVE_BUSWIDTH_128_BYTES = 128, +}; + +/** + * struct dma_slave_config - dma slave channel runtime config + * @direction: whether the data shall go in or out on this slave + * channel, right now. DMA_MEM_TO_DEV and DMA_DEV_TO_MEM are + * legal values. DEPRECATED, drivers should use the direction argument + * to the device_prep_slave_sg and device_prep_dma_cyclic functions or + * the dir field in the dma_interleaved_template structure. + * @src_addr: this is the physical address where DMA slave data + * should be read (RX), if the source is memory this argument is + * ignored. + * @dst_addr: this is the physical address where DMA slave data + * should be written (TX), if the destination is memory this argument + * is ignored. + * @src_addr_width: this is the width in bytes of the source (RX) + * register where DMA data shall be read. If the source + * is memory this may be ignored depending on architecture. + * Legal values: 1, 2, 3, 4, 8, 16, 32, 64, 128. + * @dst_addr_width: same as src_addr_width but for destination + * target (TX) mutatis mutandis. + * @src_maxburst: the maximum number of words (note: words, as in + * units of the src_addr_width member, not bytes) that can be sent + * in one burst to the device. Typically something like half the + * FIFO depth on I/O peripherals so you don't overflow it. This + * may or may not be applicable on memory sources. + * @dst_maxburst: same as src_maxburst but for destination target + * mutatis mutandis. + * @src_port_window_size: The length of the register area in words the data need + * to be accessed on the device side. It is only used for devices which is using + * an area instead of a single register to receive the data. Typically the DMA + * loops in this area in order to transfer the data. + * @dst_port_window_size: same as src_port_window_size but for the destination + * port. + * @device_fc: Flow Controller Settings. Only valid for slave channels. Fill + * with 'true' if peripheral should be flow controller. Direction will be + * selected at Runtime. + * @peripheral_config: peripheral configuration for programming peripheral + * for dmaengine transfer + * @peripheral_size: peripheral configuration buffer size + * + * This struct is passed in as configuration data to a DMA engine + * in order to set up a certain channel for DMA transport at runtime. + * The DMA device/engine has to provide support for an additional + * callback in the dma_device structure, device_config and this struct + * will then be passed in as an argument to the function. + * + * The rationale for adding configuration information to this struct is as + * follows: if it is likely that more than one DMA slave controllers in + * the world will support the configuration option, then make it generic. + * If not: if it is fixed so that it be sent in static from the platform + * data, then prefer to do that. + */ +struct dma_slave_config { + enum dma_transfer_direction direction; + phys_addr_t src_addr; + phys_addr_t dst_addr; + enum dma_slave_buswidth src_addr_width; + enum dma_slave_buswidth dst_addr_width; + u32 src_maxburst; + u32 dst_maxburst; + u32 src_port_window_size; + u32 dst_port_window_size; + bool device_fc; + void *peripheral_config; + size_t peripheral_size; +}; + +/** + * enum dma_residue_granularity - Granularity of the reported transfer residue + * @DMA_RESIDUE_GRANULARITY_DESCRIPTOR: Residue reporting is not support. The + * DMA channel is only able to tell whether a descriptor has been completed or + * not, which means residue reporting is not supported by this channel. The + * residue field of the dma_tx_state field will always be 0. + * @DMA_RESIDUE_GRANULARITY_SEGMENT: Residue is updated after each successfully + * completed segment of the transfer (For cyclic transfers this is after each + * period). This is typically implemented by having the hardware generate an + * interrupt after each transferred segment and then the drivers updates the + * outstanding residue by the size of the segment. Another possibility is if + * the hardware supports scatter-gather and the segment descriptor has a field + * which gets set after the segment has been completed. The driver then counts + * the number of segments without the flag set to compute the residue. + * @DMA_RESIDUE_GRANULARITY_BURST: Residue is updated after each transferred + * burst. This is typically only supported if the hardware has a progress + * register of some sort (E.g. a register with the current read/write address + * or a register with the amount of bursts/beats/bytes that have been + * transferred or still need to be transferred). + */ +enum dma_residue_granularity { + DMA_RESIDUE_GRANULARITY_DESCRIPTOR = 0, + DMA_RESIDUE_GRANULARITY_SEGMENT = 1, + DMA_RESIDUE_GRANULARITY_BURST = 2, +}; + +/** + * struct dma_slave_caps - expose capabilities of a slave channel only + * @src_addr_widths: bit mask of src addr widths the channel supports. + * Width is specified in bytes, e.g. for a channel supporting + * a width of 4 the mask should have BIT(4) set. + * @dst_addr_widths: bit mask of dst addr widths the channel supports + * @directions: bit mask of slave directions the channel supports. + * Since the enum dma_transfer_direction is not defined as bit flag for + * each type, the dma controller should set BIT(<TYPE>) and same + * should be checked by controller as well + * @min_burst: min burst capability per-transfer + * @max_burst: max burst capability per-transfer + * @max_sg_burst: max number of SG list entries executed in a single burst + * DMA tansaction with no software intervention for reinitialization. + * Zero value means unlimited number of entries. + * @cmd_pause: true, if pause is supported (i.e. for reading residue or + * for resume later) + * @cmd_resume: true, if resume is supported + * @cmd_terminate: true, if terminate cmd is supported + * @residue_granularity: granularity of the reported transfer residue + * @descriptor_reuse: if a descriptor can be reused by client and + * resubmitted multiple times + */ +struct dma_slave_caps { + u32 src_addr_widths; + u32 dst_addr_widths; + u32 directions; + u32 min_burst; + u32 max_burst; + u32 max_sg_burst; + bool cmd_pause; + bool cmd_resume; + bool cmd_terminate; + enum dma_residue_granularity residue_granularity; + bool descriptor_reuse; +}; + +static inline const char *dma_chan_name(struct dma_chan *chan) +{ + return dev_name(&chan->dev->device); +} + +void dma_chan_cleanup(struct kref *kref); + +/** + * typedef dma_filter_fn - callback filter for dma_request_channel + * @chan: channel to be reviewed + * @filter_param: opaque parameter passed through dma_request_channel + * + * When this optional parameter is specified in a call to dma_request_channel a + * suitable channel is passed to this routine for further dispositioning before + * being returned. Where 'suitable' indicates a non-busy channel that + * satisfies the given capability mask. It returns 'true' to indicate that the + * channel is suitable. + */ +typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param); + +typedef void (*dma_async_tx_callback)(void *dma_async_param); + +enum dmaengine_tx_result { + DMA_TRANS_NOERROR = 0, /* SUCCESS */ + DMA_TRANS_READ_FAILED, /* Source DMA read failed */ + DMA_TRANS_WRITE_FAILED, /* Destination DMA write failed */ + DMA_TRANS_ABORTED, /* Op never submitted / aborted */ +}; + +struct dmaengine_result { + enum dmaengine_tx_result result; + u32 residue; +}; + +typedef void (*dma_async_tx_callback_result)(void *dma_async_param, + const struct dmaengine_result *result); + +struct dmaengine_unmap_data { +#if IS_ENABLED(CONFIG_DMA_ENGINE_RAID) + u16 map_cnt; +#else + u8 map_cnt; +#endif + u8 to_cnt; + u8 from_cnt; + u8 bidi_cnt; + struct device *dev; + struct kref kref; + size_t len; + dma_addr_t addr[]; +}; + +struct dma_async_tx_descriptor; + +struct dma_descriptor_metadata_ops { + int (*attach)(struct dma_async_tx_descriptor *desc, void *data, + size_t len); + + void *(*get_ptr)(struct dma_async_tx_descriptor *desc, + size_t *payload_len, size_t *max_len); + int (*set_len)(struct dma_async_tx_descriptor *desc, + size_t payload_len); +}; + +/** + * struct dma_async_tx_descriptor - async transaction descriptor + * ---dma generic offload fields--- + * @cookie: tracking cookie for this transaction, set to -EBUSY if + * this tx is sitting on a dependency list + * @flags: flags to augment operation preparation, control completion, and + * communicate status + * @phys: physical address of the descriptor + * @chan: target channel for this operation + * @tx_submit: accept the descriptor, assign ordered cookie and mark the + * descriptor pending. To be pushed on .issue_pending() call + * @callback: routine to call after this operation is complete + * @callback_param: general parameter to pass to the callback routine + * @desc_metadata_mode: core managed metadata mode to protect mixed use of + * DESC_METADATA_CLIENT or DESC_METADATA_ENGINE. Otherwise + * DESC_METADATA_NONE + * @metadata_ops: DMA driver provided metadata mode ops, need to be set by the + * DMA driver if metadata mode is supported with the descriptor + * ---async_tx api specific fields--- + * @next: at completion submit this descriptor + * @parent: pointer to the next level up in the dependency chain + * @lock: protect the parent and next pointers + */ +struct dma_async_tx_descriptor { + dma_cookie_t cookie; + enum dma_ctrl_flags flags; /* not a 'long' to pack with cookie */ + dma_addr_t phys; + struct dma_chan *chan; + dma_cookie_t (*tx_submit)(struct dma_async_tx_descriptor *tx); + int (*desc_free)(struct dma_async_tx_descriptor *tx); + dma_async_tx_callback callback; + dma_async_tx_callback_result callback_result; + void *callback_param; + struct dmaengine_unmap_data *unmap; + enum dma_desc_metadata_mode desc_metadata_mode; + struct dma_descriptor_metadata_ops *metadata_ops; +#ifdef CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH + struct dma_async_tx_descriptor *next; + struct dma_async_tx_descriptor *parent; + spinlock_t lock; +#endif +}; + +#ifdef CONFIG_DMA_ENGINE +static inline void dma_set_unmap(struct dma_async_tx_descriptor *tx, + struct dmaengine_unmap_data *unmap) +{ + kref_get(&unmap->kref); + tx->unmap = unmap; +} + +struct dmaengine_unmap_data * +dmaengine_get_unmap_data(struct device *dev, int nr, gfp_t flags); +void dmaengine_unmap_put(struct dmaengine_unmap_data *unmap); +#else +static inline void dma_set_unmap(struct dma_async_tx_descriptor *tx, + struct dmaengine_unmap_data *unmap) +{ +} +static inline struct dmaengine_unmap_data * +dmaengine_get_unmap_data(struct device *dev, int nr, gfp_t flags) +{ + return NULL; +} +static inline void dmaengine_unmap_put(struct dmaengine_unmap_data *unmap) +{ +} +#endif + +static inline void dma_descriptor_unmap(struct dma_async_tx_descriptor *tx) +{ + if (!tx->unmap) + return; + + dmaengine_unmap_put(tx->unmap); + tx->unmap = NULL; +} + +#ifndef CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH +static inline void txd_lock(struct dma_async_tx_descriptor *txd) +{ +} +static inline void txd_unlock(struct dma_async_tx_descriptor *txd) +{ +} +static inline void txd_chain(struct dma_async_tx_descriptor *txd, struct dma_async_tx_descriptor *next) +{ + BUG(); +} +static inline void txd_clear_parent(struct dma_async_tx_descriptor *txd) +{ +} +static inline void txd_clear_next(struct dma_async_tx_descriptor *txd) +{ +} +static inline struct dma_async_tx_descriptor *txd_next(struct dma_async_tx_descriptor *txd) +{ + return NULL; +} +static inline struct dma_async_tx_descriptor *txd_parent(struct dma_async_tx_descriptor *txd) +{ + return NULL; +} + +#else +static inline void txd_lock(struct dma_async_tx_descriptor *txd) +{ + spin_lock_bh(&txd->lock); +} +static inline void txd_unlock(struct dma_async_tx_descriptor *txd) +{ + spin_unlock_bh(&txd->lock); +} +static inline void txd_chain(struct dma_async_tx_descriptor *txd, struct dma_async_tx_descriptor *next) +{ + txd->next = next; + next->parent = txd; +} +static inline void txd_clear_parent(struct dma_async_tx_descriptor *txd) +{ + txd->parent = NULL; +} +static inline void txd_clear_next(struct dma_async_tx_descriptor *txd) +{ + txd->next = NULL; +} +static inline struct dma_async_tx_descriptor *txd_parent(struct dma_async_tx_descriptor *txd) +{ + return txd->parent; +} +static inline struct dma_async_tx_descriptor *txd_next(struct dma_async_tx_descriptor *txd) +{ + return txd->next; +} +#endif + +/** + * struct dma_tx_state - filled in to report the status of + * a transfer. + * @last: last completed DMA cookie + * @used: last issued DMA cookie (i.e. the one in progress) + * @residue: the remaining number of bytes left to transmit + * on the selected transfer for states DMA_IN_PROGRESS and + * DMA_PAUSED if this is implemented in the driver, else 0 + * @in_flight_bytes: amount of data in bytes cached by the DMA. + */ +struct dma_tx_state { + dma_cookie_t last; + dma_cookie_t used; + u32 residue; + u32 in_flight_bytes; +}; + +/** + * enum dmaengine_alignment - defines alignment of the DMA async tx + * buffers + */ +enum dmaengine_alignment { + DMAENGINE_ALIGN_1_BYTE = 0, + DMAENGINE_ALIGN_2_BYTES = 1, + DMAENGINE_ALIGN_4_BYTES = 2, + DMAENGINE_ALIGN_8_BYTES = 3, + DMAENGINE_ALIGN_16_BYTES = 4, + DMAENGINE_ALIGN_32_BYTES = 5, + DMAENGINE_ALIGN_64_BYTES = 6, + DMAENGINE_ALIGN_128_BYTES = 7, + DMAENGINE_ALIGN_256_BYTES = 8, +}; + +/** + * struct dma_slave_map - associates slave device and it's slave channel with + * parameter to be used by a filter function + * @devname: name of the device + * @slave: slave channel name + * @param: opaque parameter to pass to struct dma_filter.fn + */ +struct dma_slave_map { + const char *devname; + const char *slave; + void *param; +}; + +/** + * struct dma_filter - information for slave device/channel to filter_fn/param + * mapping + * @fn: filter function callback + * @mapcnt: number of slave device/channel in the map + * @map: array of channel to filter mapping data + */ +struct dma_filter { + dma_filter_fn fn; + int mapcnt; + const struct dma_slave_map *map; +}; + +/** + * struct dma_device - info on the entity supplying DMA services + * @ref: reference is taken and put every time a channel is allocated or freed + * @chancnt: how many DMA channels are supported + * @privatecnt: how many DMA channels are requested by dma_request_channel + * @channels: the list of struct dma_chan + * @global_node: list_head for global dma_device_list + * @filter: information for device/slave to filter function/param mapping + * @cap_mask: one or more dma_capability flags + * @desc_metadata_modes: supported metadata modes by the DMA device + * @max_xor: maximum number of xor sources, 0 if no capability + * @max_pq: maximum number of PQ sources and PQ-continue capability + * @copy_align: alignment shift for memcpy operations + * @xor_align: alignment shift for xor operations + * @pq_align: alignment shift for pq operations + * @fill_align: alignment shift for memset operations + * @dev_id: unique device ID + * @dev: struct device reference for dma mapping api + * @owner: owner module (automatically set based on the provided dev) + * @chan_ida: unique channel ID + * @src_addr_widths: bit mask of src addr widths the device supports + * Width is specified in bytes, e.g. for a device supporting + * a width of 4 the mask should have BIT(4) set. + * @dst_addr_widths: bit mask of dst addr widths the device supports + * @directions: bit mask of slave directions the device supports. + * Since the enum dma_transfer_direction is not defined as bit flag for + * each type, the dma controller should set BIT(<TYPE>) and same + * should be checked by controller as well + * @min_burst: min burst capability per-transfer + * @max_burst: max burst capability per-transfer + * @max_sg_burst: max number of SG list entries executed in a single burst + * DMA tansaction with no software intervention for reinitialization. + * Zero value means unlimited number of entries. + * @descriptor_reuse: a submitted transfer can be resubmitted after completion + * @residue_granularity: granularity of the transfer residue reported + * by tx_status + * @device_alloc_chan_resources: allocate resources and return the + * number of allocated descriptors + * @device_router_config: optional callback for DMA router configuration + * @device_free_chan_resources: release DMA channel's resources + * @device_prep_dma_memcpy: prepares a memcpy operation + * @device_prep_dma_xor: prepares a xor operation + * @device_prep_dma_xor_val: prepares a xor validation operation + * @device_prep_dma_pq: prepares a pq operation + * @device_prep_dma_pq_val: prepares a pqzero_sum operation + * @device_prep_dma_memset: prepares a memset operation + * @device_prep_dma_memset_sg: prepares a memset operation over a scatter list + * @device_prep_dma_interrupt: prepares an end of chain interrupt operation + * @device_prep_slave_sg: prepares a slave dma operation + * @device_prep_dma_cyclic: prepare a cyclic dma operation suitable for audio. + * The function takes a buffer of size buf_len. The callback function will + * be called after period_len bytes have been transferred. + * @device_prep_interleaved_dma: Transfer expression in a generic way. + * @device_prep_dma_imm_data: DMA's 8 byte immediate data to the dst address + * @device_caps: May be used to override the generic DMA slave capabilities + * with per-channel specific ones + * @device_config: Pushes a new configuration to a channel, return 0 or an error + * code + * @device_pause: Pauses any transfer happening on a channel. Returns + * 0 or an error code + * @device_resume: Resumes any transfer on a channel previously + * paused. Returns 0 or an error code + * @device_terminate_all: Aborts all transfers on a channel. Returns 0 + * or an error code + * @device_synchronize: Synchronizes the termination of a transfers to the + * current context. + * @device_tx_status: poll for transaction completion, the optional + * txstate parameter can be supplied with a pointer to get a + * struct with auxiliary transfer status information, otherwise the call + * will just return a simple status code + * @device_issue_pending: push pending transactions to hardware + * @device_release: called sometime atfer dma_async_device_unregister() is + * called and there are no further references to this structure. This + * must be implemented to free resources however many existing drivers + * do not and are therefore not safe to unbind while in use. + * @dbg_summary_show: optional routine to show contents in debugfs; default code + * will be used when this is omitted, but custom code can show extra, + * controller specific information. + * @dbg_dev_root: the root folder in debugfs for this device + */ +struct dma_device { + struct kref ref; + unsigned int chancnt; + unsigned int privatecnt; + struct list_head channels; + struct list_head global_node; + struct dma_filter filter; + dma_cap_mask_t cap_mask; + enum dma_desc_metadata_mode desc_metadata_modes; + unsigned short max_xor; + unsigned short max_pq; + enum dmaengine_alignment copy_align; + enum dmaengine_alignment xor_align; + enum dmaengine_alignment pq_align; + enum dmaengine_alignment fill_align; + #define DMA_HAS_PQ_CONTINUE (1 << 15) + + int dev_id; + struct device *dev; + struct module *owner; + struct ida chan_ida; + + u32 src_addr_widths; + u32 dst_addr_widths; + u32 directions; + u32 min_burst; + u32 max_burst; + u32 max_sg_burst; + bool descriptor_reuse; + enum dma_residue_granularity residue_granularity; + + int (*device_alloc_chan_resources)(struct dma_chan *chan); + int (*device_router_config)(struct dma_chan *chan); + void (*device_free_chan_resources)(struct dma_chan *chan); + + struct dma_async_tx_descriptor *(*device_prep_dma_memcpy)( + struct dma_chan *chan, dma_addr_t dst, dma_addr_t src, + size_t len, unsigned long flags); + struct dma_async_tx_descriptor *(*device_prep_dma_xor)( + struct dma_chan *chan, dma_addr_t dst, dma_addr_t *src, + unsigned int src_cnt, size_t len, unsigned long flags); + struct dma_async_tx_descriptor *(*device_prep_dma_xor_val)( + struct dma_chan *chan, dma_addr_t *src, unsigned int src_cnt, + size_t len, enum sum_check_flags *result, unsigned long flags); + struct dma_async_tx_descriptor *(*device_prep_dma_pq)( + struct dma_chan *chan, dma_addr_t *dst, dma_addr_t *src, + unsigned int src_cnt, const unsigned char *scf, + size_t len, unsigned long flags); + struct dma_async_tx_descriptor *(*device_prep_dma_pq_val)( + struct dma_chan *chan, dma_addr_t *pq, dma_addr_t *src, + unsigned int src_cnt, const unsigned char *scf, size_t len, + enum sum_check_flags *pqres, unsigned long flags); + struct dma_async_tx_descriptor *(*device_prep_dma_memset)( + struct dma_chan *chan, dma_addr_t dest, int value, size_t len, + unsigned long flags); + struct dma_async_tx_descriptor *(*device_prep_dma_memset_sg)( + struct dma_chan *chan, struct scatterlist *sg, + unsigned int nents, int value, unsigned long flags); + struct dma_async_tx_descriptor *(*device_prep_dma_interrupt)( + struct dma_chan *chan, unsigned long flags); + + struct dma_async_tx_descriptor *(*device_prep_slave_sg)( + struct dma_chan *chan, struct scatterlist *sgl, + unsigned int sg_len, enum dma_transfer_direction direction, + unsigned long flags, void *context); + struct dma_async_tx_descriptor *(*device_prep_dma_cyclic)( + struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, + size_t period_len, enum dma_transfer_direction direction, + unsigned long flags); + struct dma_async_tx_descriptor *(*device_prep_interleaved_dma)( + struct dma_chan *chan, struct dma_interleaved_template *xt, + unsigned long flags); + struct dma_async_tx_descriptor *(*device_prep_dma_imm_data)( + struct dma_chan *chan, dma_addr_t dst, u64 data, + unsigned long flags); + + void (*device_caps)(struct dma_chan *chan, struct dma_slave_caps *caps); + int (*device_config)(struct dma_chan *chan, struct dma_slave_config *config); + int (*device_pause)(struct dma_chan *chan); + int (*device_resume)(struct dma_chan *chan); + int (*device_terminate_all)(struct dma_chan *chan); + void (*device_synchronize)(struct dma_chan *chan); + + enum dma_status (*device_tx_status)(struct dma_chan *chan, + dma_cookie_t cookie, + struct dma_tx_state *txstate); + void (*device_issue_pending)(struct dma_chan *chan); + void (*device_release)(struct dma_device *dev); + /* debugfs support */ + void (*dbg_summary_show)(struct seq_file *s, struct dma_device *dev); + struct dentry *dbg_dev_root; +}; + +static inline int dmaengine_slave_config(struct dma_chan *chan, + struct dma_slave_config *config) +{ + if (chan->device->device_config) + return chan->device->device_config(chan, config); + + return -ENOSYS; +} + +static inline bool is_slave_direction(enum dma_transfer_direction direction) +{ + return (direction == DMA_MEM_TO_DEV) || (direction == DMA_DEV_TO_MEM); +} + +static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_single( + struct dma_chan *chan, dma_addr_t buf, size_t len, + enum dma_transfer_direction dir, unsigned long flags) +{ + struct scatterlist sg; + sg_init_table(&sg, 1); + sg_dma_address(&sg) = buf; + sg_dma_len(&sg) = len; + + if (!chan || !chan->device || !chan->device->device_prep_slave_sg) + return NULL; + + return chan->device->device_prep_slave_sg(chan, &sg, 1, + dir, flags, NULL); +} + +static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_sg( + struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, + enum dma_transfer_direction dir, unsigned long flags) +{ + if (!chan || !chan->device || !chan->device->device_prep_slave_sg) + return NULL; + + return chan->device->device_prep_slave_sg(chan, sgl, sg_len, + dir, flags, NULL); +} + +#ifdef CONFIG_RAPIDIO_DMA_ENGINE +struct rio_dma_ext; +static inline struct dma_async_tx_descriptor *dmaengine_prep_rio_sg( + struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, + enum dma_transfer_direction dir, unsigned long flags, + struct rio_dma_ext *rio_ext) +{ + if (!chan || !chan->device || !chan->device->device_prep_slave_sg) + return NULL; + + return chan->device->device_prep_slave_sg(chan, sgl, sg_len, + dir, flags, rio_ext); +} +#endif + +static inline struct dma_async_tx_descriptor *dmaengine_prep_dma_cyclic( + struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, + size_t period_len, enum dma_transfer_direction dir, + unsigned long flags) +{ + if (!chan || !chan->device || !chan->device->device_prep_dma_cyclic) + return NULL; + + return chan->device->device_prep_dma_cyclic(chan, buf_addr, buf_len, + period_len, dir, flags); +} + +static inline struct dma_async_tx_descriptor *dmaengine_prep_interleaved_dma( + struct dma_chan *chan, struct dma_interleaved_template *xt, + unsigned long flags) +{ + if (!chan || !chan->device || !chan->device->device_prep_interleaved_dma) + return NULL; + if (flags & DMA_PREP_REPEAT && + !test_bit(DMA_REPEAT, chan->device->cap_mask.bits)) + return NULL; + + return chan->device->device_prep_interleaved_dma(chan, xt, flags); +} + +/** + * dmaengine_prep_dma_memset() - Prepare a DMA memset descriptor. + * @chan: The channel to be used for this descriptor + * @dest: Address of buffer to be set + * @value: Treated as a single byte value that fills the destination buffer + * @len: The total size of dest + * @flags: DMA engine flags + */ +static inline struct dma_async_tx_descriptor *dmaengine_prep_dma_memset( + struct dma_chan *chan, dma_addr_t dest, int value, size_t len, + unsigned long flags) +{ + if (!chan || !chan->device || !chan->device->device_prep_dma_memset) + return NULL; + + return chan->device->device_prep_dma_memset(chan, dest, value, + len, flags); +} + +static inline struct dma_async_tx_descriptor *dmaengine_prep_dma_memcpy( + struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, + size_t len, unsigned long flags) +{ + if (!chan || !chan->device || !chan->device->device_prep_dma_memcpy) + return NULL; + + return chan->device->device_prep_dma_memcpy(chan, dest, src, + len, flags); +} + +static inline bool dmaengine_is_metadata_mode_supported(struct dma_chan *chan, + enum dma_desc_metadata_mode mode) +{ + if (!chan) + return false; + + return !!(chan->device->desc_metadata_modes & mode); +} + +#ifdef CONFIG_DMA_ENGINE +int dmaengine_desc_attach_metadata(struct dma_async_tx_descriptor *desc, + void *data, size_t len); +void *dmaengine_desc_get_metadata_ptr(struct dma_async_tx_descriptor *desc, + size_t *payload_len, size_t *max_len); +int dmaengine_desc_set_metadata_len(struct dma_async_tx_descriptor *desc, + size_t payload_len); +#else /* CONFIG_DMA_ENGINE */ +static inline int dmaengine_desc_attach_metadata( + struct dma_async_tx_descriptor *desc, void *data, size_t len) +{ + return -EINVAL; +} +static inline void *dmaengine_desc_get_metadata_ptr( + struct dma_async_tx_descriptor *desc, size_t *payload_len, + size_t *max_len) +{ + return NULL; +} +static inline int dmaengine_desc_set_metadata_len( + struct dma_async_tx_descriptor *desc, size_t payload_len) +{ + return -EINVAL; +} +#endif /* CONFIG_DMA_ENGINE */ + +/** + * dmaengine_terminate_all() - Terminate all active DMA transfers + * @chan: The channel for which to terminate the transfers + * + * This function is DEPRECATED use either dmaengine_terminate_sync() or + * dmaengine_terminate_async() instead. + */ +static inline int dmaengine_terminate_all(struct dma_chan *chan) +{ + if (chan->device->device_terminate_all) + return chan->device->device_terminate_all(chan); + + return -ENOSYS; +} + +/** + * dmaengine_terminate_async() - Terminate all active DMA transfers + * @chan: The channel for which to terminate the transfers + * + * Calling this function will terminate all active and pending descriptors + * that have previously been submitted to the channel. It is not guaranteed + * though that the transfer for the active descriptor has stopped when the + * function returns. Furthermore it is possible the complete callback of a + * submitted transfer is still running when this function returns. + * + * dmaengine_synchronize() needs to be called before it is safe to free + * any memory that is accessed by previously submitted descriptors or before + * freeing any resources accessed from within the completion callback of any + * previously submitted descriptors. + * + * This function can be called from atomic context as well as from within a + * complete callback of a descriptor submitted on the same channel. + * + * If none of the two conditions above apply consider using + * dmaengine_terminate_sync() instead. + */ +static inline int dmaengine_terminate_async(struct dma_chan *chan) +{ + if (chan->device->device_terminate_all) + return chan->device->device_terminate_all(chan); + + return -EINVAL; +} + +/** + * dmaengine_synchronize() - Synchronize DMA channel termination + * @chan: The channel to synchronize + * + * Synchronizes to the DMA channel termination to the current context. When this + * function returns it is guaranteed that all transfers for previously issued + * descriptors have stopped and it is safe to free the memory associated + * with them. Furthermore it is guaranteed that all complete callback functions + * for a previously submitted descriptor have finished running and it is safe to + * free resources accessed from within the complete callbacks. + * + * The behavior of this function is undefined if dma_async_issue_pending() has + * been called between dmaengine_terminate_async() and this function. + * + * This function must only be called from non-atomic context and must not be + * called from within a complete callback of a descriptor submitted on the same + * channel. + */ +static inline void dmaengine_synchronize(struct dma_chan *chan) +{ + might_sleep(); + + if (chan->device->device_synchronize) + chan->device->device_synchronize(chan); +} + +/** + * dmaengine_terminate_sync() - Terminate all active DMA transfers + * @chan: The channel for which to terminate the transfers + * + * Calling this function will terminate all active and pending transfers + * that have previously been submitted to the channel. It is similar to + * dmaengine_terminate_async() but guarantees that the DMA transfer has actually + * stopped and that all complete callbacks have finished running when the + * function returns. + * + * This function must only be called from non-atomic context and must not be + * called from within a complete callback of a descriptor submitted on the same + * channel. + */ +static inline int dmaengine_terminate_sync(struct dma_chan *chan) +{ + int ret; + + ret = dmaengine_terminate_async(chan); + if (ret) + return ret; + + dmaengine_synchronize(chan); + + return 0; +} + +static inline int dmaengine_pause(struct dma_chan *chan) +{ + if (chan->device->device_pause) + return chan->device->device_pause(chan); + + return -ENOSYS; +} + +static inline int dmaengine_resume(struct dma_chan *chan) +{ + if (chan->device->device_resume) + return chan->device->device_resume(chan); + + return -ENOSYS; +} + +static inline enum dma_status dmaengine_tx_status(struct dma_chan *chan, + dma_cookie_t cookie, struct dma_tx_state *state) +{ + return chan->device->device_tx_status(chan, cookie, state); +} + +static inline dma_cookie_t dmaengine_submit(struct dma_async_tx_descriptor *desc) +{ + return desc->tx_submit(desc); +} + +static inline bool dmaengine_check_align(enum dmaengine_alignment align, + size_t off1, size_t off2, size_t len) +{ + return !(((1 << align) - 1) & (off1 | off2 | len)); +} + +static inline bool is_dma_copy_aligned(struct dma_device *dev, size_t off1, + size_t off2, size_t len) +{ + return dmaengine_check_align(dev->copy_align, off1, off2, len); +} + +static inline bool is_dma_xor_aligned(struct dma_device *dev, size_t off1, + size_t off2, size_t len) +{ + return dmaengine_check_align(dev->xor_align, off1, off2, len); +} + +static inline bool is_dma_pq_aligned(struct dma_device *dev, size_t off1, + size_t off2, size_t len) +{ + return dmaengine_check_align(dev->pq_align, off1, off2, len); +} + +static inline bool is_dma_fill_aligned(struct dma_device *dev, size_t off1, + size_t off2, size_t len) +{ + return dmaengine_check_align(dev->fill_align, off1, off2, len); +} + +static inline void +dma_set_maxpq(struct dma_device *dma, int maxpq, int has_pq_continue) +{ + dma->max_pq = maxpq; + if (has_pq_continue) + dma->max_pq |= DMA_HAS_PQ_CONTINUE; +} + +static inline bool dmaf_continue(enum dma_ctrl_flags flags) +{ + return (flags & DMA_PREP_CONTINUE) == DMA_PREP_CONTINUE; +} + +static inline bool dmaf_p_disabled_continue(enum dma_ctrl_flags flags) +{ + enum dma_ctrl_flags mask = DMA_PREP_CONTINUE | DMA_PREP_PQ_DISABLE_P; + + return (flags & mask) == mask; +} + +static inline bool dma_dev_has_pq_continue(struct dma_device *dma) +{ + return (dma->max_pq & DMA_HAS_PQ_CONTINUE) == DMA_HAS_PQ_CONTINUE; +} + +static inline unsigned short dma_dev_to_maxpq(struct dma_device *dma) +{ + return dma->max_pq & ~DMA_HAS_PQ_CONTINUE; +} + +/* dma_maxpq - reduce maxpq in the face of continued operations + * @dma - dma device with PQ capability + * @flags - to check if DMA_PREP_CONTINUE and DMA_PREP_PQ_DISABLE_P are set + * + * When an engine does not support native continuation we need 3 extra + * source slots to reuse P and Q with the following coefficients: + * 1/ {00} * P : remove P from Q', but use it as a source for P' + * 2/ {01} * Q : use Q to continue Q' calculation + * 3/ {00} * Q : subtract Q from P' to cancel (2) + * + * In the case where P is disabled we only need 1 extra source: + * 1/ {01} * Q : use Q to continue Q' calculation + */ +static inline int dma_maxpq(struct dma_device *dma, enum dma_ctrl_flags flags) +{ + if (dma_dev_has_pq_continue(dma) || !dmaf_continue(flags)) + return dma_dev_to_maxpq(dma); + if (dmaf_p_disabled_continue(flags)) + return dma_dev_to_maxpq(dma) - 1; + if (dmaf_continue(flags)) + return dma_dev_to_maxpq(dma) - 3; + BUG(); +} + +static inline size_t dmaengine_get_icg(bool inc, bool sgl, size_t icg, + size_t dir_icg) +{ + if (inc) { + if (dir_icg) + return dir_icg; + if (sgl) + return icg; + } + + return 0; +} + +static inline size_t dmaengine_get_dst_icg(struct dma_interleaved_template *xt, + struct data_chunk *chunk) +{ + return dmaengine_get_icg(xt->dst_inc, xt->dst_sgl, + chunk->icg, chunk->dst_icg); +} + +static inline size_t dmaengine_get_src_icg(struct dma_interleaved_template *xt, + struct data_chunk *chunk) +{ + return dmaengine_get_icg(xt->src_inc, xt->src_sgl, + chunk->icg, chunk->src_icg); +} + +/* --- public DMA engine API --- */ + +#ifdef CONFIG_DMA_ENGINE +void dmaengine_get(void); +void dmaengine_put(void); +#else +static inline void dmaengine_get(void) +{ +} +static inline void dmaengine_put(void) +{ +} +#endif + +#ifdef CONFIG_ASYNC_TX_DMA +#define async_dmaengine_get() dmaengine_get() +#define async_dmaengine_put() dmaengine_put() +#ifndef CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH +#define async_dma_find_channel(type) dma_find_channel(DMA_ASYNC_TX) +#else +#define async_dma_find_channel(type) dma_find_channel(type) +#endif /* CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH */ +#else +static inline void async_dmaengine_get(void) +{ +} +static inline void async_dmaengine_put(void) +{ +} +static inline struct dma_chan * +async_dma_find_channel(enum dma_transaction_type type) +{ + return NULL; +} +#endif /* CONFIG_ASYNC_TX_DMA */ +void dma_async_tx_descriptor_init(struct dma_async_tx_descriptor *tx, + struct dma_chan *chan); + +static inline void async_tx_ack(struct dma_async_tx_descriptor *tx) +{ + tx->flags |= DMA_CTRL_ACK; +} + +static inline void async_tx_clear_ack(struct dma_async_tx_descriptor *tx) +{ + tx->flags &= ~DMA_CTRL_ACK; +} + +static inline bool async_tx_test_ack(struct dma_async_tx_descriptor *tx) +{ + return (tx->flags & DMA_CTRL_ACK) == DMA_CTRL_ACK; +} + +#define dma_cap_set(tx, mask) __dma_cap_set((tx), &(mask)) +static inline void +__dma_cap_set(enum dma_transaction_type tx_type, dma_cap_mask_t *dstp) +{ + set_bit(tx_type, dstp->bits); +} + +#define dma_cap_clear(tx, mask) __dma_cap_clear((tx), &(mask)) +static inline void +__dma_cap_clear(enum dma_transaction_type tx_type, dma_cap_mask_t *dstp) +{ + clear_bit(tx_type, dstp->bits); +} + +#define dma_cap_zero(mask) __dma_cap_zero(&(mask)) +static inline void __dma_cap_zero(dma_cap_mask_t *dstp) +{ + bitmap_zero(dstp->bits, DMA_TX_TYPE_END); +} + +#define dma_has_cap(tx, mask) __dma_has_cap((tx), &(mask)) +static inline int +__dma_has_cap(enum dma_transaction_type tx_type, dma_cap_mask_t *srcp) +{ + return test_bit(tx_type, srcp->bits); +} + +#define for_each_dma_cap_mask(cap, mask) \ + for_each_set_bit(cap, mask.bits, DMA_TX_TYPE_END) + +/** + * dma_async_issue_pending - flush pending transactions to HW + * @chan: target DMA channel + * + * This allows drivers to push copies to HW in batches, + * reducing MMIO writes where possible. + */ +static inline void dma_async_issue_pending(struct dma_chan *chan) +{ + chan->device->device_issue_pending(chan); +} + +/** + * dma_async_is_tx_complete - poll for transaction completion + * @chan: DMA channel + * @cookie: transaction identifier to check status of + * @last: returns last completed cookie, can be NULL + * @used: returns last issued cookie, can be NULL + * + * If @last and @used are passed in, upon return they reflect the driver + * internal state and can be used with dma_async_is_complete() to check + * the status of multiple cookies without re-checking hardware state. + */ +static inline enum dma_status dma_async_is_tx_complete(struct dma_chan *chan, + dma_cookie_t cookie, dma_cookie_t *last, dma_cookie_t *used) +{ + struct dma_tx_state state; + enum dma_status status; + + status = chan->device->device_tx_status(chan, cookie, &state); + if (last) + *last = state.last; + if (used) + *used = state.used; + return status; +} + +/** + * dma_async_is_complete - test a cookie against chan state + * @cookie: transaction identifier to test status of + * @last_complete: last know completed transaction + * @last_used: last cookie value handed out + * + * dma_async_is_complete() is used in dma_async_is_tx_complete() + * the test logic is separated for lightweight testing of multiple cookies + */ +static inline enum dma_status dma_async_is_complete(dma_cookie_t cookie, + dma_cookie_t last_complete, dma_cookie_t last_used) +{ + if (last_complete <= last_used) { + if ((cookie <= last_complete) || (cookie > last_used)) + return DMA_COMPLETE; + } else { + if ((cookie <= last_complete) && (cookie > last_used)) + return DMA_COMPLETE; + } + return DMA_IN_PROGRESS; +} + +static inline void +dma_set_tx_state(struct dma_tx_state *st, dma_cookie_t last, dma_cookie_t used, u32 residue) +{ + if (!st) + return; + + st->last = last; + st->used = used; + st->residue = residue; +} + +#ifdef CONFIG_DMA_ENGINE +struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type); +enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie); +enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx); +void dma_issue_pending_all(void); +struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask, + dma_filter_fn fn, void *fn_param, + struct device_node *np); + +struct dma_chan *dma_request_chan(struct device *dev, const char *name); +struct dma_chan *dma_request_chan_by_mask(const dma_cap_mask_t *mask); + +void dma_release_channel(struct dma_chan *chan); +int dma_get_slave_caps(struct dma_chan *chan, struct dma_slave_caps *caps); +#else +static inline struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type) +{ + return NULL; +} +static inline enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie) +{ + return DMA_COMPLETE; +} +static inline enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx) +{ + return DMA_COMPLETE; +} +static inline void dma_issue_pending_all(void) +{ +} +static inline struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask, + dma_filter_fn fn, + void *fn_param, + struct device_node *np) +{ + return NULL; +} +static inline struct dma_chan *dma_request_chan(struct device *dev, + const char *name) +{ + return ERR_PTR(-ENODEV); +} +static inline struct dma_chan *dma_request_chan_by_mask( + const dma_cap_mask_t *mask) +{ + return ERR_PTR(-ENODEV); +} +static inline void dma_release_channel(struct dma_chan *chan) +{ +} +static inline int dma_get_slave_caps(struct dma_chan *chan, + struct dma_slave_caps *caps) +{ + return -ENXIO; +} +#endif + +static inline int dmaengine_desc_set_reuse(struct dma_async_tx_descriptor *tx) +{ + struct dma_slave_caps caps; + int ret; + + ret = dma_get_slave_caps(tx->chan, &caps); + if (ret) + return ret; + + if (!caps.descriptor_reuse) + return -EPERM; + + tx->flags |= DMA_CTRL_REUSE; + return 0; +} + +static inline void dmaengine_desc_clear_reuse(struct dma_async_tx_descriptor *tx) +{ + tx->flags &= ~DMA_CTRL_REUSE; +} + +static inline bool dmaengine_desc_test_reuse(struct dma_async_tx_descriptor *tx) +{ + return (tx->flags & DMA_CTRL_REUSE) == DMA_CTRL_REUSE; +} + +static inline int dmaengine_desc_free(struct dma_async_tx_descriptor *desc) +{ + /* this is supported for reusable desc, so check that */ + if (!dmaengine_desc_test_reuse(desc)) + return -EPERM; + + return desc->desc_free(desc); +} + +/* --- DMA device --- */ + +int dma_async_device_register(struct dma_device *device); +int dmaenginem_async_device_register(struct dma_device *device); +void dma_async_device_unregister(struct dma_device *device); +int dma_async_device_channel_register(struct dma_device *device, + struct dma_chan *chan); +void dma_async_device_channel_unregister(struct dma_device *device, + struct dma_chan *chan); +void dma_run_dependencies(struct dma_async_tx_descriptor *tx); +#define dma_request_channel(mask, x, y) \ + __dma_request_channel(&(mask), x, y, NULL) + +/* Deprecated, please use dma_request_chan() directly */ +static inline struct dma_chan * __deprecated +dma_request_slave_channel(struct device *dev, const char *name) +{ + struct dma_chan *ch = dma_request_chan(dev, name); + + return IS_ERR(ch) ? NULL : ch; +} + +static inline struct dma_chan +*dma_request_slave_channel_compat(const dma_cap_mask_t mask, + dma_filter_fn fn, void *fn_param, + struct device *dev, const char *name) +{ + struct dma_chan *chan; + + chan = dma_request_slave_channel(dev, name); + if (chan) + return chan; + + if (!fn || !fn_param) + return NULL; + + return __dma_request_channel(&mask, fn, fn_param, NULL); +} + +static inline char * +dmaengine_get_direction_text(enum dma_transfer_direction dir) +{ + switch (dir) { + case DMA_DEV_TO_MEM: + return "DEV_TO_MEM"; + case DMA_MEM_TO_DEV: + return "MEM_TO_DEV"; + case DMA_MEM_TO_MEM: + return "MEM_TO_MEM"; + case DMA_DEV_TO_DEV: + return "DEV_TO_DEV"; + default: + return "invalid"; + } +} + +static inline struct device *dmaengine_get_dma_device(struct dma_chan *chan) +{ + if (chan->dev->chan_dma_dev) + return &chan->dev->device; + + return chan->device->dev; +} + +#endif /* DMAENGINE_H */ diff --git a/snd-alpx-dkms/snd-alpx/include/6.3/amd_xdma.h b/snd-alpx-dkms/snd-alpx/include/6.3/amd_xdma.h new file mode 100644 index 0000000..ceba69e --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/include/6.3/amd_xdma.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2022, Advanced Micro Devices, Inc. + */ + +#ifndef _DMAENGINE_AMD_XDMA_H +#define _DMAENGINE_AMD_XDMA_H + +#include <linux/interrupt.h> +#include <linux/platform_device.h> + +int xdma_enable_user_irq(struct platform_device *pdev, u32 irq_num); +void xdma_disable_user_irq(struct platform_device *pdev, u32 irq_num); +int xdma_get_user_irq(struct platform_device *pdev, u32 user_irq_index); + +#endif /* _DMAENGINE_AMD_XDMA_H */ diff --git a/snd-alpx-dkms/snd-alpx/include/6.3/dmaengine.h b/snd-alpx-dkms/snd-alpx/include/6.3/dmaengine.h new file mode 100644 index 0000000..c3656e5 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/include/6.3/dmaengine.h @@ -0,0 +1,1637 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved. + */ +#ifndef LINUX_DMAENGINE_H +#define LINUX_DMAENGINE_H + +#include <linux/device.h> +#include <linux/err.h> +#include <linux/uio.h> +#include <linux/bug.h> +#include <linux/scatterlist.h> +#include <linux/bitmap.h> +#include <linux/types.h> +#include <asm/page.h> + +/** + * typedef dma_cookie_t - an opaque DMA cookie + * + * if dma_cookie_t is >0 it's a DMA request cookie, <0 it's an error code + */ +typedef s32 dma_cookie_t; +#define DMA_MIN_COOKIE 1 + +static inline int dma_submit_error(dma_cookie_t cookie) +{ + return cookie < 0 ? cookie : 0; +} + +/** + * enum dma_status - DMA transaction status + * @DMA_COMPLETE: transaction completed + * @DMA_IN_PROGRESS: transaction not yet processed + * @DMA_PAUSED: transaction is paused + * @DMA_ERROR: transaction failed + */ +enum dma_status { + DMA_COMPLETE, + DMA_IN_PROGRESS, + DMA_PAUSED, + DMA_ERROR, + DMA_OUT_OF_ORDER, +}; + +/** + * enum dma_transaction_type - DMA transaction types/indexes + * + * Note: The DMA_ASYNC_TX capability is not to be set by drivers. It is + * automatically set as dma devices are registered. + */ +enum dma_transaction_type { + DMA_MEMCPY, + DMA_XOR, + DMA_PQ, + DMA_XOR_VAL, + DMA_PQ_VAL, + DMA_MEMSET, + DMA_MEMSET_SG, + DMA_INTERRUPT, + DMA_PRIVATE, + DMA_ASYNC_TX, + DMA_SLAVE, + DMA_CYCLIC, + DMA_INTERLEAVE, + DMA_COMPLETION_NO_ORDER, + DMA_REPEAT, + DMA_LOAD_EOT, +/* last transaction type for creation of the capabilities mask */ + DMA_TX_TYPE_END, +}; + +/** + * enum dma_transfer_direction - dma transfer mode and direction indicator + * @DMA_MEM_TO_MEM: Async/Memcpy mode + * @DMA_MEM_TO_DEV: Slave mode & From Memory to Device + * @DMA_DEV_TO_MEM: Slave mode & From Device to Memory + * @DMA_DEV_TO_DEV: Slave mode & From Device to Device + */ +enum dma_transfer_direction { + DMA_MEM_TO_MEM, + DMA_MEM_TO_DEV, + DMA_DEV_TO_MEM, + DMA_DEV_TO_DEV, + DMA_TRANS_NONE, +}; + +/** + * Interleaved Transfer Request + * ---------------------------- + * A chunk is collection of contiguous bytes to be transferred. + * The gap(in bytes) between two chunks is called inter-chunk-gap(ICG). + * ICGs may or may not change between chunks. + * A FRAME is the smallest series of contiguous {chunk,icg} pairs, + * that when repeated an integral number of times, specifies the transfer. + * A transfer template is specification of a Frame, the number of times + * it is to be repeated and other per-transfer attributes. + * + * Practically, a client driver would have ready a template for each + * type of transfer it is going to need during its lifetime and + * set only 'src_start' and 'dst_start' before submitting the requests. + * + * + * | Frame-1 | Frame-2 | ~ | Frame-'numf' | + * |====....==.===...=...|====....==.===...=...| ~ |====....==.===...=...| + * + * == Chunk size + * ... ICG + */ + +/** + * struct data_chunk - Element of scatter-gather list that makes a frame. + * @size: Number of bytes to read from source. + * size_dst := fn(op, size_src), so doesn't mean much for destination. + * @icg: Number of bytes to jump after last src/dst address of this + * chunk and before first src/dst address for next chunk. + * Ignored for dst(assumed 0), if dst_inc is true and dst_sgl is false. + * Ignored for src(assumed 0), if src_inc is true and src_sgl is false. + * @dst_icg: Number of bytes to jump after last dst address of this + * chunk and before the first dst address for next chunk. + * Ignored if dst_inc is true and dst_sgl is false. + * @src_icg: Number of bytes to jump after last src address of this + * chunk and before the first src address for next chunk. + * Ignored if src_inc is true and src_sgl is false. + */ +struct data_chunk { + size_t size; + size_t icg; + size_t dst_icg; + size_t src_icg; +}; + +/** + * struct dma_interleaved_template - Template to convey DMAC the transfer pattern + * and attributes. + * @src_start: Bus address of source for the first chunk. + * @dst_start: Bus address of destination for the first chunk. + * @dir: Specifies the type of Source and Destination. + * @src_inc: If the source address increments after reading from it. + * @dst_inc: If the destination address increments after writing to it. + * @src_sgl: If the 'icg' of sgl[] applies to Source (scattered read). + * Otherwise, source is read contiguously (icg ignored). + * Ignored if src_inc is false. + * @dst_sgl: If the 'icg' of sgl[] applies to Destination (scattered write). + * Otherwise, destination is filled contiguously (icg ignored). + * Ignored if dst_inc is false. + * @numf: Number of frames in this template. + * @frame_size: Number of chunks in a frame i.e, size of sgl[]. + * @sgl: Array of {chunk,icg} pairs that make up a frame. + */ +struct dma_interleaved_template { + dma_addr_t src_start; + dma_addr_t dst_start; + enum dma_transfer_direction dir; + bool src_inc; + bool dst_inc; + bool src_sgl; + bool dst_sgl; + size_t numf; + size_t frame_size; + struct data_chunk sgl[]; +}; + +/** + * enum dma_ctrl_flags - DMA flags to augment operation preparation, + * control completion, and communicate status. + * @DMA_PREP_INTERRUPT - trigger an interrupt (callback) upon completion of + * this transaction + * @DMA_CTRL_ACK - if clear, the descriptor cannot be reused until the client + * acknowledges receipt, i.e. has a chance to establish any dependency + * chains + * @DMA_PREP_PQ_DISABLE_P - prevent generation of P while generating Q + * @DMA_PREP_PQ_DISABLE_Q - prevent generation of Q while generating P + * @DMA_PREP_CONTINUE - indicate to a driver that it is reusing buffers as + * sources that were the result of a previous operation, in the case of a PQ + * operation it continues the calculation with new sources + * @DMA_PREP_FENCE - tell the driver that subsequent operations depend + * on the result of this operation + * @DMA_CTRL_REUSE: client can reuse the descriptor and submit again till + * cleared or freed + * @DMA_PREP_CMD: tell the driver that the data passed to DMA API is command + * data and the descriptor should be in different format from normal + * data descriptors. + * @DMA_PREP_REPEAT: tell the driver that the transaction shall be automatically + * repeated when it ends until a transaction is issued on the same channel + * with the DMA_PREP_LOAD_EOT flag set. This flag is only applicable to + * interleaved transactions and is ignored for all other transaction types. + * @DMA_PREP_LOAD_EOT: tell the driver that the transaction shall replace any + * active repeated (as indicated by DMA_PREP_REPEAT) transaction when the + * repeated transaction ends. Not setting this flag when the previously queued + * transaction is marked with DMA_PREP_REPEAT will cause the new transaction + * to never be processed and stay in the issued queue forever. The flag is + * ignored if the previous transaction is not a repeated transaction. + */ +enum dma_ctrl_flags { + DMA_PREP_INTERRUPT = (1 << 0), + DMA_CTRL_ACK = (1 << 1), + DMA_PREP_PQ_DISABLE_P = (1 << 2), + DMA_PREP_PQ_DISABLE_Q = (1 << 3), + DMA_PREP_CONTINUE = (1 << 4), + DMA_PREP_FENCE = (1 << 5), + DMA_CTRL_REUSE = (1 << 6), + DMA_PREP_CMD = (1 << 7), + DMA_PREP_REPEAT = (1 << 8), + DMA_PREP_LOAD_EOT = (1 << 9), +}; + +/** + * enum sum_check_bits - bit position of pq_check_flags + */ +enum sum_check_bits { + SUM_CHECK_P = 0, + SUM_CHECK_Q = 1, +}; + +/** + * enum pq_check_flags - result of async_{xor,pq}_zero_sum operations + * @SUM_CHECK_P_RESULT - 1 if xor zero sum error, 0 otherwise + * @SUM_CHECK_Q_RESULT - 1 if reed-solomon zero sum error, 0 otherwise + */ +enum sum_check_flags { + SUM_CHECK_P_RESULT = (1 << SUM_CHECK_P), + SUM_CHECK_Q_RESULT = (1 << SUM_CHECK_Q), +}; + + +/** + * dma_cap_mask_t - capabilities bitmap modeled after cpumask_t. + * See linux/cpumask.h + */ +typedef struct { DECLARE_BITMAP(bits, DMA_TX_TYPE_END); } dma_cap_mask_t; + +/** + * enum dma_desc_metadata_mode - per descriptor metadata mode types supported + * @DESC_METADATA_CLIENT - the metadata buffer is allocated/provided by the + * client driver and it is attached (via the dmaengine_desc_attach_metadata() + * helper) to the descriptor. + * + * Client drivers interested to use this mode can follow: + * - DMA_MEM_TO_DEV / DEV_MEM_TO_MEM: + * 1. prepare the descriptor (dmaengine_prep_*) + * construct the metadata in the client's buffer + * 2. use dmaengine_desc_attach_metadata() to attach the buffer to the + * descriptor + * 3. submit the transfer + * - DMA_DEV_TO_MEM: + * 1. prepare the descriptor (dmaengine_prep_*) + * 2. use dmaengine_desc_attach_metadata() to attach the buffer to the + * descriptor + * 3. submit the transfer + * 4. when the transfer is completed, the metadata should be available in the + * attached buffer + * + * @DESC_METADATA_ENGINE - the metadata buffer is allocated/managed by the DMA + * driver. The client driver can ask for the pointer, maximum size and the + * currently used size of the metadata and can directly update or read it. + * dmaengine_desc_get_metadata_ptr() and dmaengine_desc_set_metadata_len() is + * provided as helper functions. + * + * Note: the metadata area for the descriptor is no longer valid after the + * transfer has been completed (valid up to the point when the completion + * callback returns if used). + * + * Client drivers interested to use this mode can follow: + * - DMA_MEM_TO_DEV / DEV_MEM_TO_MEM: + * 1. prepare the descriptor (dmaengine_prep_*) + * 2. use dmaengine_desc_get_metadata_ptr() to get the pointer to the engine's + * metadata area + * 3. update the metadata at the pointer + * 4. use dmaengine_desc_set_metadata_len() to tell the DMA engine the amount + * of data the client has placed into the metadata buffer + * 5. submit the transfer + * - DMA_DEV_TO_MEM: + * 1. prepare the descriptor (dmaengine_prep_*) + * 2. submit the transfer + * 3. on transfer completion, use dmaengine_desc_get_metadata_ptr() to get the + * pointer to the engine's metadata area + * 4. Read out the metadata from the pointer + * + * Note: the two mode is not compatible and clients must use one mode for a + * descriptor. + */ +enum dma_desc_metadata_mode { + DESC_METADATA_NONE = 0, + DESC_METADATA_CLIENT = BIT(0), + DESC_METADATA_ENGINE = BIT(1), +}; + +/** + * struct dma_chan_percpu - the per-CPU part of struct dma_chan + * @memcpy_count: transaction counter + * @bytes_transferred: byte counter + */ +struct dma_chan_percpu { + /* stats */ + unsigned long memcpy_count; + unsigned long bytes_transferred; +}; + +/** + * struct dma_router - DMA router structure + * @dev: pointer to the DMA router device + * @route_free: function to be called when the route can be disconnected + */ +struct dma_router { + struct device *dev; + void (*route_free)(struct device *dev, void *route_data); +}; + +/** + * struct dma_chan - devices supply DMA channels, clients use them + * @device: ptr to the dma device who supplies this channel, always !%NULL + * @slave: ptr to the device using this channel + * @cookie: last cookie value returned to client + * @completed_cookie: last completed cookie for this channel + * @chan_id: channel ID for sysfs + * @dev: class device for sysfs + * @name: backlink name for sysfs + * @dbg_client_name: slave name for debugfs in format: + * dev_name(requester's dev):channel name, for example: "2b00000.mcasp:tx" + * @device_node: used to add this to the device chan list + * @local: per-cpu pointer to a struct dma_chan_percpu + * @client_count: how many clients are using this channel + * @table_count: number of appearances in the mem-to-mem allocation table + * @router: pointer to the DMA router structure + * @route_data: channel specific data for the router + * @private: private data for certain client-channel associations + */ +struct dma_chan { + struct dma_device *device; + struct device *slave; + dma_cookie_t cookie; + dma_cookie_t completed_cookie; + + /* sysfs */ + int chan_id; + struct dma_chan_dev *dev; + const char *name; +#ifdef CONFIG_DEBUG_FS + char *dbg_client_name; +#endif + + struct list_head device_node; + struct dma_chan_percpu __percpu *local; + int client_count; + int table_count; + + /* DMA router */ + struct dma_router *router; + void *route_data; + + void *private; +}; + +/** + * struct dma_chan_dev - relate sysfs device node to backing channel device + * @chan: driver channel device + * @device: sysfs device + * @dev_id: parent dma_device dev_id + * @chan_dma_dev: The channel is using custom/different dma-mapping + * compared to the parent dma_device + */ +struct dma_chan_dev { + struct dma_chan *chan; + struct device device; + int dev_id; + bool chan_dma_dev; +}; + +/** + * enum dma_slave_buswidth - defines bus width of the DMA slave + * device, source or target buses + */ +enum dma_slave_buswidth { + DMA_SLAVE_BUSWIDTH_UNDEFINED = 0, + DMA_SLAVE_BUSWIDTH_1_BYTE = 1, + DMA_SLAVE_BUSWIDTH_2_BYTES = 2, + DMA_SLAVE_BUSWIDTH_3_BYTES = 3, + DMA_SLAVE_BUSWIDTH_4_BYTES = 4, + DMA_SLAVE_BUSWIDTH_8_BYTES = 8, + DMA_SLAVE_BUSWIDTH_16_BYTES = 16, + DMA_SLAVE_BUSWIDTH_32_BYTES = 32, + DMA_SLAVE_BUSWIDTH_64_BYTES = 64, + DMA_SLAVE_BUSWIDTH_128_BYTES = 128, +}; + +/** + * struct dma_slave_config - dma slave channel runtime config + * @direction: whether the data shall go in or out on this slave + * channel, right now. DMA_MEM_TO_DEV and DMA_DEV_TO_MEM are + * legal values. DEPRECATED, drivers should use the direction argument + * to the device_prep_slave_sg and device_prep_dma_cyclic functions or + * the dir field in the dma_interleaved_template structure. + * @src_addr: this is the physical address where DMA slave data + * should be read (RX), if the source is memory this argument is + * ignored. + * @dst_addr: this is the physical address where DMA slave data + * should be written (TX), if the destination is memory this argument + * is ignored. + * @src_addr_width: this is the width in bytes of the source (RX) + * register where DMA data shall be read. If the source + * is memory this may be ignored depending on architecture. + * Legal values: 1, 2, 3, 4, 8, 16, 32, 64, 128. + * @dst_addr_width: same as src_addr_width but for destination + * target (TX) mutatis mutandis. + * @src_maxburst: the maximum number of words (note: words, as in + * units of the src_addr_width member, not bytes) that can be sent + * in one burst to the device. Typically something like half the + * FIFO depth on I/O peripherals so you don't overflow it. This + * may or may not be applicable on memory sources. + * @dst_maxburst: same as src_maxburst but for destination target + * mutatis mutandis. + * @src_port_window_size: The length of the register area in words the data need + * to be accessed on the device side. It is only used for devices which is using + * an area instead of a single register to receive the data. Typically the DMA + * loops in this area in order to transfer the data. + * @dst_port_window_size: same as src_port_window_size but for the destination + * port. + * @device_fc: Flow Controller Settings. Only valid for slave channels. Fill + * with 'true' if peripheral should be flow controller. Direction will be + * selected at Runtime. + * @peripheral_config: peripheral configuration for programming peripheral + * for dmaengine transfer + * @peripheral_size: peripheral configuration buffer size + * + * This struct is passed in as configuration data to a DMA engine + * in order to set up a certain channel for DMA transport at runtime. + * The DMA device/engine has to provide support for an additional + * callback in the dma_device structure, device_config and this struct + * will then be passed in as an argument to the function. + * + * The rationale for adding configuration information to this struct is as + * follows: if it is likely that more than one DMA slave controllers in + * the world will support the configuration option, then make it generic. + * If not: if it is fixed so that it be sent in static from the platform + * data, then prefer to do that. + */ +struct dma_slave_config { + enum dma_transfer_direction direction; + phys_addr_t src_addr; + phys_addr_t dst_addr; + enum dma_slave_buswidth src_addr_width; + enum dma_slave_buswidth dst_addr_width; + u32 src_maxburst; + u32 dst_maxburst; + u32 src_port_window_size; + u32 dst_port_window_size; + bool device_fc; + void *peripheral_config; + size_t peripheral_size; +}; + +/** + * enum dma_residue_granularity - Granularity of the reported transfer residue + * @DMA_RESIDUE_GRANULARITY_DESCRIPTOR: Residue reporting is not support. The + * DMA channel is only able to tell whether a descriptor has been completed or + * not, which means residue reporting is not supported by this channel. The + * residue field of the dma_tx_state field will always be 0. + * @DMA_RESIDUE_GRANULARITY_SEGMENT: Residue is updated after each successfully + * completed segment of the transfer (For cyclic transfers this is after each + * period). This is typically implemented by having the hardware generate an + * interrupt after each transferred segment and then the drivers updates the + * outstanding residue by the size of the segment. Another possibility is if + * the hardware supports scatter-gather and the segment descriptor has a field + * which gets set after the segment has been completed. The driver then counts + * the number of segments without the flag set to compute the residue. + * @DMA_RESIDUE_GRANULARITY_BURST: Residue is updated after each transferred + * burst. This is typically only supported if the hardware has a progress + * register of some sort (E.g. a register with the current read/write address + * or a register with the amount of bursts/beats/bytes that have been + * transferred or still need to be transferred). + */ +enum dma_residue_granularity { + DMA_RESIDUE_GRANULARITY_DESCRIPTOR = 0, + DMA_RESIDUE_GRANULARITY_SEGMENT = 1, + DMA_RESIDUE_GRANULARITY_BURST = 2, +}; + +/** + * struct dma_slave_caps - expose capabilities of a slave channel only + * @src_addr_widths: bit mask of src addr widths the channel supports. + * Width is specified in bytes, e.g. for a channel supporting + * a width of 4 the mask should have BIT(4) set. + * @dst_addr_widths: bit mask of dst addr widths the channel supports + * @directions: bit mask of slave directions the channel supports. + * Since the enum dma_transfer_direction is not defined as bit flag for + * each type, the dma controller should set BIT(<TYPE>) and same + * should be checked by controller as well + * @min_burst: min burst capability per-transfer + * @max_burst: max burst capability per-transfer + * @max_sg_burst: max number of SG list entries executed in a single burst + * DMA tansaction with no software intervention for reinitialization. + * Zero value means unlimited number of entries. + * @cmd_pause: true, if pause is supported (i.e. for reading residue or + * for resume later) + * @cmd_resume: true, if resume is supported + * @cmd_terminate: true, if terminate cmd is supported + * @residue_granularity: granularity of the reported transfer residue + * @descriptor_reuse: if a descriptor can be reused by client and + * resubmitted multiple times + */ +struct dma_slave_caps { + u32 src_addr_widths; + u32 dst_addr_widths; + u32 directions; + u32 min_burst; + u32 max_burst; + u32 max_sg_burst; + bool cmd_pause; + bool cmd_resume; + bool cmd_terminate; + enum dma_residue_granularity residue_granularity; + bool descriptor_reuse; +}; + +static inline const char *dma_chan_name(struct dma_chan *chan) +{ + return dev_name(&chan->dev->device); +} + +void dma_chan_cleanup(struct kref *kref); + +/** + * typedef dma_filter_fn - callback filter for dma_request_channel + * @chan: channel to be reviewed + * @filter_param: opaque parameter passed through dma_request_channel + * + * When this optional parameter is specified in a call to dma_request_channel a + * suitable channel is passed to this routine for further dispositioning before + * being returned. Where 'suitable' indicates a non-busy channel that + * satisfies the given capability mask. It returns 'true' to indicate that the + * channel is suitable. + */ +typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param); + +typedef void (*dma_async_tx_callback)(void *dma_async_param); + +enum dmaengine_tx_result { + DMA_TRANS_NOERROR = 0, /* SUCCESS */ + DMA_TRANS_READ_FAILED, /* Source DMA read failed */ + DMA_TRANS_WRITE_FAILED, /* Destination DMA write failed */ + DMA_TRANS_ABORTED, /* Op never submitted / aborted */ +}; + +struct dmaengine_result { + enum dmaengine_tx_result result; + u32 residue; +}; + +typedef void (*dma_async_tx_callback_result)(void *dma_async_param, + const struct dmaengine_result *result); + +struct dmaengine_unmap_data { +#if IS_ENABLED(CONFIG_DMA_ENGINE_RAID) + u16 map_cnt; +#else + u8 map_cnt; +#endif + u8 to_cnt; + u8 from_cnt; + u8 bidi_cnt; + struct device *dev; + struct kref kref; + size_t len; + dma_addr_t addr[]; +}; + +struct dma_async_tx_descriptor; + +struct dma_descriptor_metadata_ops { + int (*attach)(struct dma_async_tx_descriptor *desc, void *data, + size_t len); + + void *(*get_ptr)(struct dma_async_tx_descriptor *desc, + size_t *payload_len, size_t *max_len); + int (*set_len)(struct dma_async_tx_descriptor *desc, + size_t payload_len); +}; + +/** + * struct dma_async_tx_descriptor - async transaction descriptor + * ---dma generic offload fields--- + * @cookie: tracking cookie for this transaction, set to -EBUSY if + * this tx is sitting on a dependency list + * @flags: flags to augment operation preparation, control completion, and + * communicate status + * @phys: physical address of the descriptor + * @chan: target channel for this operation + * @tx_submit: accept the descriptor, assign ordered cookie and mark the + * descriptor pending. To be pushed on .issue_pending() call + * @callback: routine to call after this operation is complete + * @callback_param: general parameter to pass to the callback routine + * @desc_metadata_mode: core managed metadata mode to protect mixed use of + * DESC_METADATA_CLIENT or DESC_METADATA_ENGINE. Otherwise + * DESC_METADATA_NONE + * @metadata_ops: DMA driver provided metadata mode ops, need to be set by the + * DMA driver if metadata mode is supported with the descriptor + * ---async_tx api specific fields--- + * @next: at completion submit this descriptor + * @parent: pointer to the next level up in the dependency chain + * @lock: protect the parent and next pointers + */ +struct dma_async_tx_descriptor { + dma_cookie_t cookie; + enum dma_ctrl_flags flags; /* not a 'long' to pack with cookie */ + dma_addr_t phys; + struct dma_chan *chan; + dma_cookie_t (*tx_submit)(struct dma_async_tx_descriptor *tx); + int (*desc_free)(struct dma_async_tx_descriptor *tx); + dma_async_tx_callback callback; + dma_async_tx_callback_result callback_result; + void *callback_param; + struct dmaengine_unmap_data *unmap; + enum dma_desc_metadata_mode desc_metadata_mode; + struct dma_descriptor_metadata_ops *metadata_ops; +#ifdef CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH + struct dma_async_tx_descriptor *next; + struct dma_async_tx_descriptor *parent; + spinlock_t lock; +#endif +}; + +#ifdef CONFIG_DMA_ENGINE +static inline void dma_set_unmap(struct dma_async_tx_descriptor *tx, + struct dmaengine_unmap_data *unmap) +{ + kref_get(&unmap->kref); + tx->unmap = unmap; +} + +struct dmaengine_unmap_data * +dmaengine_get_unmap_data(struct device *dev, int nr, gfp_t flags); +void dmaengine_unmap_put(struct dmaengine_unmap_data *unmap); +#else +static inline void dma_set_unmap(struct dma_async_tx_descriptor *tx, + struct dmaengine_unmap_data *unmap) +{ +} +static inline struct dmaengine_unmap_data * +dmaengine_get_unmap_data(struct device *dev, int nr, gfp_t flags) +{ + return NULL; +} +static inline void dmaengine_unmap_put(struct dmaengine_unmap_data *unmap) +{ +} +#endif + +static inline void dma_descriptor_unmap(struct dma_async_tx_descriptor *tx) +{ + if (!tx->unmap) + return; + + dmaengine_unmap_put(tx->unmap); + tx->unmap = NULL; +} + +#ifndef CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH +static inline void txd_lock(struct dma_async_tx_descriptor *txd) +{ +} +static inline void txd_unlock(struct dma_async_tx_descriptor *txd) +{ +} +static inline void txd_chain(struct dma_async_tx_descriptor *txd, struct dma_async_tx_descriptor *next) +{ + BUG(); +} +static inline void txd_clear_parent(struct dma_async_tx_descriptor *txd) +{ +} +static inline void txd_clear_next(struct dma_async_tx_descriptor *txd) +{ +} +static inline struct dma_async_tx_descriptor *txd_next(struct dma_async_tx_descriptor *txd) +{ + return NULL; +} +static inline struct dma_async_tx_descriptor *txd_parent(struct dma_async_tx_descriptor *txd) +{ + return NULL; +} + +#else +static inline void txd_lock(struct dma_async_tx_descriptor *txd) +{ + spin_lock_bh(&txd->lock); +} +static inline void txd_unlock(struct dma_async_tx_descriptor *txd) +{ + spin_unlock_bh(&txd->lock); +} +static inline void txd_chain(struct dma_async_tx_descriptor *txd, struct dma_async_tx_descriptor *next) +{ + txd->next = next; + next->parent = txd; +} +static inline void txd_clear_parent(struct dma_async_tx_descriptor *txd) +{ + txd->parent = NULL; +} +static inline void txd_clear_next(struct dma_async_tx_descriptor *txd) +{ + txd->next = NULL; +} +static inline struct dma_async_tx_descriptor *txd_parent(struct dma_async_tx_descriptor *txd) +{ + return txd->parent; +} +static inline struct dma_async_tx_descriptor *txd_next(struct dma_async_tx_descriptor *txd) +{ + return txd->next; +} +#endif + +/** + * struct dma_tx_state - filled in to report the status of + * a transfer. + * @last: last completed DMA cookie + * @used: last issued DMA cookie (i.e. the one in progress) + * @residue: the remaining number of bytes left to transmit + * on the selected transfer for states DMA_IN_PROGRESS and + * DMA_PAUSED if this is implemented in the driver, else 0 + * @in_flight_bytes: amount of data in bytes cached by the DMA. + */ +struct dma_tx_state { + dma_cookie_t last; + dma_cookie_t used; + u32 residue; + u32 in_flight_bytes; +}; + +/** + * enum dmaengine_alignment - defines alignment of the DMA async tx + * buffers + */ +enum dmaengine_alignment { + DMAENGINE_ALIGN_1_BYTE = 0, + DMAENGINE_ALIGN_2_BYTES = 1, + DMAENGINE_ALIGN_4_BYTES = 2, + DMAENGINE_ALIGN_8_BYTES = 3, + DMAENGINE_ALIGN_16_BYTES = 4, + DMAENGINE_ALIGN_32_BYTES = 5, + DMAENGINE_ALIGN_64_BYTES = 6, + DMAENGINE_ALIGN_128_BYTES = 7, + DMAENGINE_ALIGN_256_BYTES = 8, +}; + +/** + * struct dma_slave_map - associates slave device and it's slave channel with + * parameter to be used by a filter function + * @devname: name of the device + * @slave: slave channel name + * @param: opaque parameter to pass to struct dma_filter.fn + */ +struct dma_slave_map { + const char *devname; + const char *slave; + void *param; +}; + +/** + * struct dma_filter - information for slave device/channel to filter_fn/param + * mapping + * @fn: filter function callback + * @mapcnt: number of slave device/channel in the map + * @map: array of channel to filter mapping data + */ +struct dma_filter { + dma_filter_fn fn; + int mapcnt; + const struct dma_slave_map *map; +}; + +/** + * struct dma_device - info on the entity supplying DMA services + * @ref: reference is taken and put every time a channel is allocated or freed + * @chancnt: how many DMA channels are supported + * @privatecnt: how many DMA channels are requested by dma_request_channel + * @channels: the list of struct dma_chan + * @global_node: list_head for global dma_device_list + * @filter: information for device/slave to filter function/param mapping + * @cap_mask: one or more dma_capability flags + * @desc_metadata_modes: supported metadata modes by the DMA device + * @max_xor: maximum number of xor sources, 0 if no capability + * @max_pq: maximum number of PQ sources and PQ-continue capability + * @copy_align: alignment shift for memcpy operations + * @xor_align: alignment shift for xor operations + * @pq_align: alignment shift for pq operations + * @fill_align: alignment shift for memset operations + * @dev_id: unique device ID + * @dev: struct device reference for dma mapping api + * @owner: owner module (automatically set based on the provided dev) + * @chan_ida: unique channel ID + * @src_addr_widths: bit mask of src addr widths the device supports + * Width is specified in bytes, e.g. for a device supporting + * a width of 4 the mask should have BIT(4) set. + * @dst_addr_widths: bit mask of dst addr widths the device supports + * @directions: bit mask of slave directions the device supports. + * Since the enum dma_transfer_direction is not defined as bit flag for + * each type, the dma controller should set BIT(<TYPE>) and same + * should be checked by controller as well + * @min_burst: min burst capability per-transfer + * @max_burst: max burst capability per-transfer + * @max_sg_burst: max number of SG list entries executed in a single burst + * DMA tansaction with no software intervention for reinitialization. + * Zero value means unlimited number of entries. + * @descriptor_reuse: a submitted transfer can be resubmitted after completion + * @residue_granularity: granularity of the transfer residue reported + * by tx_status + * @device_alloc_chan_resources: allocate resources and return the + * number of allocated descriptors + * @device_router_config: optional callback for DMA router configuration + * @device_free_chan_resources: release DMA channel's resources + * @device_prep_dma_memcpy: prepares a memcpy operation + * @device_prep_dma_xor: prepares a xor operation + * @device_prep_dma_xor_val: prepares a xor validation operation + * @device_prep_dma_pq: prepares a pq operation + * @device_prep_dma_pq_val: prepares a pqzero_sum operation + * @device_prep_dma_memset: prepares a memset operation + * @device_prep_dma_memset_sg: prepares a memset operation over a scatter list + * @device_prep_dma_interrupt: prepares an end of chain interrupt operation + * @device_prep_slave_sg: prepares a slave dma operation + * @device_prep_dma_cyclic: prepare a cyclic dma operation suitable for audio. + * The function takes a buffer of size buf_len. The callback function will + * be called after period_len bytes have been transferred. + * @device_prep_interleaved_dma: Transfer expression in a generic way. + * @device_prep_dma_imm_data: DMA's 8 byte immediate data to the dst address + * @device_caps: May be used to override the generic DMA slave capabilities + * with per-channel specific ones + * @device_config: Pushes a new configuration to a channel, return 0 or an error + * code + * @device_pause: Pauses any transfer happening on a channel. Returns + * 0 or an error code + * @device_resume: Resumes any transfer on a channel previously + * paused. Returns 0 or an error code + * @device_terminate_all: Aborts all transfers on a channel. Returns 0 + * or an error code + * @device_synchronize: Synchronizes the termination of a transfers to the + * current context. + * @device_tx_status: poll for transaction completion, the optional + * txstate parameter can be supplied with a pointer to get a + * struct with auxiliary transfer status information, otherwise the call + * will just return a simple status code + * @device_issue_pending: push pending transactions to hardware + * @device_release: called sometime atfer dma_async_device_unregister() is + * called and there are no further references to this structure. This + * must be implemented to free resources however many existing drivers + * do not and are therefore not safe to unbind while in use. + * @dbg_summary_show: optional routine to show contents in debugfs; default code + * will be used when this is omitted, but custom code can show extra, + * controller specific information. + * @dbg_dev_root: the root folder in debugfs for this device + */ +struct dma_device { + struct kref ref; + unsigned int chancnt; + unsigned int privatecnt; + struct list_head channels; + struct list_head global_node; + struct dma_filter filter; + dma_cap_mask_t cap_mask; + enum dma_desc_metadata_mode desc_metadata_modes; + unsigned short max_xor; + unsigned short max_pq; + enum dmaengine_alignment copy_align; + enum dmaengine_alignment xor_align; + enum dmaengine_alignment pq_align; + enum dmaengine_alignment fill_align; + #define DMA_HAS_PQ_CONTINUE (1 << 15) + + int dev_id; + struct device *dev; + struct module *owner; + struct ida chan_ida; + + u32 src_addr_widths; + u32 dst_addr_widths; + u32 directions; + u32 min_burst; + u32 max_burst; + u32 max_sg_burst; + bool descriptor_reuse; + enum dma_residue_granularity residue_granularity; + + int (*device_alloc_chan_resources)(struct dma_chan *chan); + int (*device_router_config)(struct dma_chan *chan); + void (*device_free_chan_resources)(struct dma_chan *chan); + + struct dma_async_tx_descriptor *(*device_prep_dma_memcpy)( + struct dma_chan *chan, dma_addr_t dst, dma_addr_t src, + size_t len, unsigned long flags); + struct dma_async_tx_descriptor *(*device_prep_dma_xor)( + struct dma_chan *chan, dma_addr_t dst, dma_addr_t *src, + unsigned int src_cnt, size_t len, unsigned long flags); + struct dma_async_tx_descriptor *(*device_prep_dma_xor_val)( + struct dma_chan *chan, dma_addr_t *src, unsigned int src_cnt, + size_t len, enum sum_check_flags *result, unsigned long flags); + struct dma_async_tx_descriptor *(*device_prep_dma_pq)( + struct dma_chan *chan, dma_addr_t *dst, dma_addr_t *src, + unsigned int src_cnt, const unsigned char *scf, + size_t len, unsigned long flags); + struct dma_async_tx_descriptor *(*device_prep_dma_pq_val)( + struct dma_chan *chan, dma_addr_t *pq, dma_addr_t *src, + unsigned int src_cnt, const unsigned char *scf, size_t len, + enum sum_check_flags *pqres, unsigned long flags); + struct dma_async_tx_descriptor *(*device_prep_dma_memset)( + struct dma_chan *chan, dma_addr_t dest, int value, size_t len, + unsigned long flags); + struct dma_async_tx_descriptor *(*device_prep_dma_memset_sg)( + struct dma_chan *chan, struct scatterlist *sg, + unsigned int nents, int value, unsigned long flags); + struct dma_async_tx_descriptor *(*device_prep_dma_interrupt)( + struct dma_chan *chan, unsigned long flags); + + struct dma_async_tx_descriptor *(*device_prep_slave_sg)( + struct dma_chan *chan, struct scatterlist *sgl, + unsigned int sg_len, enum dma_transfer_direction direction, + unsigned long flags, void *context); + struct dma_async_tx_descriptor *(*device_prep_dma_cyclic)( + struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, + size_t period_len, enum dma_transfer_direction direction, + unsigned long flags); + struct dma_async_tx_descriptor *(*device_prep_interleaved_dma)( + struct dma_chan *chan, struct dma_interleaved_template *xt, + unsigned long flags); + struct dma_async_tx_descriptor *(*device_prep_dma_imm_data)( + struct dma_chan *chan, dma_addr_t dst, u64 data, + unsigned long flags); + + void (*device_caps)(struct dma_chan *chan, struct dma_slave_caps *caps); + int (*device_config)(struct dma_chan *chan, struct dma_slave_config *config); + int (*device_pause)(struct dma_chan *chan); + int (*device_resume)(struct dma_chan *chan); + int (*device_terminate_all)(struct dma_chan *chan); + void (*device_synchronize)(struct dma_chan *chan); + + enum dma_status (*device_tx_status)(struct dma_chan *chan, + dma_cookie_t cookie, + struct dma_tx_state *txstate); + void (*device_issue_pending)(struct dma_chan *chan); + void (*device_release)(struct dma_device *dev); + /* debugfs support */ + void (*dbg_summary_show)(struct seq_file *s, struct dma_device *dev); + struct dentry *dbg_dev_root; +}; + +static inline int dmaengine_slave_config(struct dma_chan *chan, + struct dma_slave_config *config) +{ + if (chan->device->device_config) + return chan->device->device_config(chan, config); + + return -ENOSYS; +} + +static inline bool is_slave_direction(enum dma_transfer_direction direction) +{ + return (direction == DMA_MEM_TO_DEV) || (direction == DMA_DEV_TO_MEM); +} + +static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_single( + struct dma_chan *chan, dma_addr_t buf, size_t len, + enum dma_transfer_direction dir, unsigned long flags) +{ + struct scatterlist sg; + sg_init_table(&sg, 1); + sg_dma_address(&sg) = buf; + sg_dma_len(&sg) = len; + + if (!chan || !chan->device || !chan->device->device_prep_slave_sg) + return NULL; + + return chan->device->device_prep_slave_sg(chan, &sg, 1, + dir, flags, NULL); +} + +static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_sg( + struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, + enum dma_transfer_direction dir, unsigned long flags) +{ + if (!chan || !chan->device || !chan->device->device_prep_slave_sg) + return NULL; + + return chan->device->device_prep_slave_sg(chan, sgl, sg_len, + dir, flags, NULL); +} + +#ifdef CONFIG_RAPIDIO_DMA_ENGINE +struct rio_dma_ext; +static inline struct dma_async_tx_descriptor *dmaengine_prep_rio_sg( + struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, + enum dma_transfer_direction dir, unsigned long flags, + struct rio_dma_ext *rio_ext) +{ + if (!chan || !chan->device || !chan->device->device_prep_slave_sg) + return NULL; + + return chan->device->device_prep_slave_sg(chan, sgl, sg_len, + dir, flags, rio_ext); +} +#endif + +static inline struct dma_async_tx_descriptor *dmaengine_prep_dma_cyclic( + struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, + size_t period_len, enum dma_transfer_direction dir, + unsigned long flags) +{ + if (!chan || !chan->device || !chan->device->device_prep_dma_cyclic) + return NULL; + + return chan->device->device_prep_dma_cyclic(chan, buf_addr, buf_len, + period_len, dir, flags); +} + +static inline struct dma_async_tx_descriptor *dmaengine_prep_interleaved_dma( + struct dma_chan *chan, struct dma_interleaved_template *xt, + unsigned long flags) +{ + if (!chan || !chan->device || !chan->device->device_prep_interleaved_dma) + return NULL; + if (flags & DMA_PREP_REPEAT && + !test_bit(DMA_REPEAT, chan->device->cap_mask.bits)) + return NULL; + + return chan->device->device_prep_interleaved_dma(chan, xt, flags); +} + +/** + * dmaengine_prep_dma_memset() - Prepare a DMA memset descriptor. + * @chan: The channel to be used for this descriptor + * @dest: Address of buffer to be set + * @value: Treated as a single byte value that fills the destination buffer + * @len: The total size of dest + * @flags: DMA engine flags + */ +static inline struct dma_async_tx_descriptor *dmaengine_prep_dma_memset( + struct dma_chan *chan, dma_addr_t dest, int value, size_t len, + unsigned long flags) +{ + if (!chan || !chan->device || !chan->device->device_prep_dma_memset) + return NULL; + + return chan->device->device_prep_dma_memset(chan, dest, value, + len, flags); +} + +static inline struct dma_async_tx_descriptor *dmaengine_prep_dma_memcpy( + struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, + size_t len, unsigned long flags) +{ + if (!chan || !chan->device || !chan->device->device_prep_dma_memcpy) + return NULL; + + return chan->device->device_prep_dma_memcpy(chan, dest, src, + len, flags); +} + +static inline bool dmaengine_is_metadata_mode_supported(struct dma_chan *chan, + enum dma_desc_metadata_mode mode) +{ + if (!chan) + return false; + + return !!(chan->device->desc_metadata_modes & mode); +} + +#ifdef CONFIG_DMA_ENGINE +int dmaengine_desc_attach_metadata(struct dma_async_tx_descriptor *desc, + void *data, size_t len); +void *dmaengine_desc_get_metadata_ptr(struct dma_async_tx_descriptor *desc, + size_t *payload_len, size_t *max_len); +int dmaengine_desc_set_metadata_len(struct dma_async_tx_descriptor *desc, + size_t payload_len); +#else /* CONFIG_DMA_ENGINE */ +static inline int dmaengine_desc_attach_metadata( + struct dma_async_tx_descriptor *desc, void *data, size_t len) +{ + return -EINVAL; +} +static inline void *dmaengine_desc_get_metadata_ptr( + struct dma_async_tx_descriptor *desc, size_t *payload_len, + size_t *max_len) +{ + return NULL; +} +static inline int dmaengine_desc_set_metadata_len( + struct dma_async_tx_descriptor *desc, size_t payload_len) +{ + return -EINVAL; +} +#endif /* CONFIG_DMA_ENGINE */ + +/** + * dmaengine_terminate_all() - Terminate all active DMA transfers + * @chan: The channel for which to terminate the transfers + * + * This function is DEPRECATED use either dmaengine_terminate_sync() or + * dmaengine_terminate_async() instead. + */ +static inline int dmaengine_terminate_all(struct dma_chan *chan) +{ + if (chan->device->device_terminate_all) + return chan->device->device_terminate_all(chan); + + return -ENOSYS; +} + +/** + * dmaengine_terminate_async() - Terminate all active DMA transfers + * @chan: The channel for which to terminate the transfers + * + * Calling this function will terminate all active and pending descriptors + * that have previously been submitted to the channel. It is not guaranteed + * though that the transfer for the active descriptor has stopped when the + * function returns. Furthermore it is possible the complete callback of a + * submitted transfer is still running when this function returns. + * + * dmaengine_synchronize() needs to be called before it is safe to free + * any memory that is accessed by previously submitted descriptors or before + * freeing any resources accessed from within the completion callback of any + * previously submitted descriptors. + * + * This function can be called from atomic context as well as from within a + * complete callback of a descriptor submitted on the same channel. + * + * If none of the two conditions above apply consider using + * dmaengine_terminate_sync() instead. + */ +static inline int dmaengine_terminate_async(struct dma_chan *chan) +{ + if (chan->device->device_terminate_all) + return chan->device->device_terminate_all(chan); + + return -EINVAL; +} + +/** + * dmaengine_synchronize() - Synchronize DMA channel termination + * @chan: The channel to synchronize + * + * Synchronizes to the DMA channel termination to the current context. When this + * function returns it is guaranteed that all transfers for previously issued + * descriptors have stopped and it is safe to free the memory associated + * with them. Furthermore it is guaranteed that all complete callback functions + * for a previously submitted descriptor have finished running and it is safe to + * free resources accessed from within the complete callbacks. + * + * The behavior of this function is undefined if dma_async_issue_pending() has + * been called between dmaengine_terminate_async() and this function. + * + * This function must only be called from non-atomic context and must not be + * called from within a complete callback of a descriptor submitted on the same + * channel. + */ +static inline void dmaengine_synchronize(struct dma_chan *chan) +{ + might_sleep(); + + if (chan->device->device_synchronize) + chan->device->device_synchronize(chan); +} + +/** + * dmaengine_terminate_sync() - Terminate all active DMA transfers + * @chan: The channel for which to terminate the transfers + * + * Calling this function will terminate all active and pending transfers + * that have previously been submitted to the channel. It is similar to + * dmaengine_terminate_async() but guarantees that the DMA transfer has actually + * stopped and that all complete callbacks have finished running when the + * function returns. + * + * This function must only be called from non-atomic context and must not be + * called from within a complete callback of a descriptor submitted on the same + * channel. + */ +static inline int dmaengine_terminate_sync(struct dma_chan *chan) +{ + int ret; + + ret = dmaengine_terminate_async(chan); + if (ret) + return ret; + + dmaengine_synchronize(chan); + + return 0; +} + +static inline int dmaengine_pause(struct dma_chan *chan) +{ + if (chan->device->device_pause) + return chan->device->device_pause(chan); + + return -ENOSYS; +} + +static inline int dmaengine_resume(struct dma_chan *chan) +{ + if (chan->device->device_resume) + return chan->device->device_resume(chan); + + return -ENOSYS; +} + +static inline enum dma_status dmaengine_tx_status(struct dma_chan *chan, + dma_cookie_t cookie, struct dma_tx_state *state) +{ + return chan->device->device_tx_status(chan, cookie, state); +} + +static inline dma_cookie_t dmaengine_submit(struct dma_async_tx_descriptor *desc) +{ + return desc->tx_submit(desc); +} + +static inline bool dmaengine_check_align(enum dmaengine_alignment align, + size_t off1, size_t off2, size_t len) +{ + return !(((1 << align) - 1) & (off1 | off2 | len)); +} + +static inline bool is_dma_copy_aligned(struct dma_device *dev, size_t off1, + size_t off2, size_t len) +{ + return dmaengine_check_align(dev->copy_align, off1, off2, len); +} + +static inline bool is_dma_xor_aligned(struct dma_device *dev, size_t off1, + size_t off2, size_t len) +{ + return dmaengine_check_align(dev->xor_align, off1, off2, len); +} + +static inline bool is_dma_pq_aligned(struct dma_device *dev, size_t off1, + size_t off2, size_t len) +{ + return dmaengine_check_align(dev->pq_align, off1, off2, len); +} + +static inline bool is_dma_fill_aligned(struct dma_device *dev, size_t off1, + size_t off2, size_t len) +{ + return dmaengine_check_align(dev->fill_align, off1, off2, len); +} + +static inline void +dma_set_maxpq(struct dma_device *dma, int maxpq, int has_pq_continue) +{ + dma->max_pq = maxpq; + if (has_pq_continue) + dma->max_pq |= DMA_HAS_PQ_CONTINUE; +} + +static inline bool dmaf_continue(enum dma_ctrl_flags flags) +{ + return (flags & DMA_PREP_CONTINUE) == DMA_PREP_CONTINUE; +} + +static inline bool dmaf_p_disabled_continue(enum dma_ctrl_flags flags) +{ + enum dma_ctrl_flags mask = DMA_PREP_CONTINUE | DMA_PREP_PQ_DISABLE_P; + + return (flags & mask) == mask; +} + +static inline bool dma_dev_has_pq_continue(struct dma_device *dma) +{ + return (dma->max_pq & DMA_HAS_PQ_CONTINUE) == DMA_HAS_PQ_CONTINUE; +} + +static inline unsigned short dma_dev_to_maxpq(struct dma_device *dma) +{ + return dma->max_pq & ~DMA_HAS_PQ_CONTINUE; +} + +/* dma_maxpq - reduce maxpq in the face of continued operations + * @dma - dma device with PQ capability + * @flags - to check if DMA_PREP_CONTINUE and DMA_PREP_PQ_DISABLE_P are set + * + * When an engine does not support native continuation we need 3 extra + * source slots to reuse P and Q with the following coefficients: + * 1/ {00} * P : remove P from Q', but use it as a source for P' + * 2/ {01} * Q : use Q to continue Q' calculation + * 3/ {00} * Q : subtract Q from P' to cancel (2) + * + * In the case where P is disabled we only need 1 extra source: + * 1/ {01} * Q : use Q to continue Q' calculation + */ +static inline int dma_maxpq(struct dma_device *dma, enum dma_ctrl_flags flags) +{ + if (dma_dev_has_pq_continue(dma) || !dmaf_continue(flags)) + return dma_dev_to_maxpq(dma); + if (dmaf_p_disabled_continue(flags)) + return dma_dev_to_maxpq(dma) - 1; + if (dmaf_continue(flags)) + return dma_dev_to_maxpq(dma) - 3; + BUG(); +} + +static inline size_t dmaengine_get_icg(bool inc, bool sgl, size_t icg, + size_t dir_icg) +{ + if (inc) { + if (dir_icg) + return dir_icg; + if (sgl) + return icg; + } + + return 0; +} + +static inline size_t dmaengine_get_dst_icg(struct dma_interleaved_template *xt, + struct data_chunk *chunk) +{ + return dmaengine_get_icg(xt->dst_inc, xt->dst_sgl, + chunk->icg, chunk->dst_icg); +} + +static inline size_t dmaengine_get_src_icg(struct dma_interleaved_template *xt, + struct data_chunk *chunk) +{ + return dmaengine_get_icg(xt->src_inc, xt->src_sgl, + chunk->icg, chunk->src_icg); +} + +/* --- public DMA engine API --- */ + +#ifdef CONFIG_DMA_ENGINE +void dmaengine_get(void); +void dmaengine_put(void); +#else +static inline void dmaengine_get(void) +{ +} +static inline void dmaengine_put(void) +{ +} +#endif + +#ifdef CONFIG_ASYNC_TX_DMA +#define async_dmaengine_get() dmaengine_get() +#define async_dmaengine_put() dmaengine_put() +#ifndef CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH +#define async_dma_find_channel(type) dma_find_channel(DMA_ASYNC_TX) +#else +#define async_dma_find_channel(type) dma_find_channel(type) +#endif /* CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH */ +#else +static inline void async_dmaengine_get(void) +{ +} +static inline void async_dmaengine_put(void) +{ +} +static inline struct dma_chan * +async_dma_find_channel(enum dma_transaction_type type) +{ + return NULL; +} +#endif /* CONFIG_ASYNC_TX_DMA */ +void dma_async_tx_descriptor_init(struct dma_async_tx_descriptor *tx, + struct dma_chan *chan); + +static inline void async_tx_ack(struct dma_async_tx_descriptor *tx) +{ + tx->flags |= DMA_CTRL_ACK; +} + +static inline void async_tx_clear_ack(struct dma_async_tx_descriptor *tx) +{ + tx->flags &= ~DMA_CTRL_ACK; +} + +static inline bool async_tx_test_ack(struct dma_async_tx_descriptor *tx) +{ + return (tx->flags & DMA_CTRL_ACK) == DMA_CTRL_ACK; +} + +#define dma_cap_set(tx, mask) __dma_cap_set((tx), &(mask)) +static inline void +__dma_cap_set(enum dma_transaction_type tx_type, dma_cap_mask_t *dstp) +{ + set_bit(tx_type, dstp->bits); +} + +#define dma_cap_clear(tx, mask) __dma_cap_clear((tx), &(mask)) +static inline void +__dma_cap_clear(enum dma_transaction_type tx_type, dma_cap_mask_t *dstp) +{ + clear_bit(tx_type, dstp->bits); +} + +#define dma_cap_zero(mask) __dma_cap_zero(&(mask)) +static inline void __dma_cap_zero(dma_cap_mask_t *dstp) +{ + bitmap_zero(dstp->bits, DMA_TX_TYPE_END); +} + +#define dma_has_cap(tx, mask) __dma_has_cap((tx), &(mask)) +static inline int +__dma_has_cap(enum dma_transaction_type tx_type, dma_cap_mask_t *srcp) +{ + return test_bit(tx_type, srcp->bits); +} + +#define for_each_dma_cap_mask(cap, mask) \ + for_each_set_bit(cap, mask.bits, DMA_TX_TYPE_END) + +/** + * dma_async_issue_pending - flush pending transactions to HW + * @chan: target DMA channel + * + * This allows drivers to push copies to HW in batches, + * reducing MMIO writes where possible. + */ +static inline void dma_async_issue_pending(struct dma_chan *chan) +{ + chan->device->device_issue_pending(chan); +} + +/** + * dma_async_is_tx_complete - poll for transaction completion + * @chan: DMA channel + * @cookie: transaction identifier to check status of + * @last: returns last completed cookie, can be NULL + * @used: returns last issued cookie, can be NULL + * + * If @last and @used are passed in, upon return they reflect the driver + * internal state and can be used with dma_async_is_complete() to check + * the status of multiple cookies without re-checking hardware state. + */ +static inline enum dma_status dma_async_is_tx_complete(struct dma_chan *chan, + dma_cookie_t cookie, dma_cookie_t *last, dma_cookie_t *used) +{ + struct dma_tx_state state; + enum dma_status status; + + status = chan->device->device_tx_status(chan, cookie, &state); + if (last) + *last = state.last; + if (used) + *used = state.used; + return status; +} + +/** + * dma_async_is_complete - test a cookie against chan state + * @cookie: transaction identifier to test status of + * @last_complete: last know completed transaction + * @last_used: last cookie value handed out + * + * dma_async_is_complete() is used in dma_async_is_tx_complete() + * the test logic is separated for lightweight testing of multiple cookies + */ +static inline enum dma_status dma_async_is_complete(dma_cookie_t cookie, + dma_cookie_t last_complete, dma_cookie_t last_used) +{ + if (last_complete <= last_used) { + if ((cookie <= last_complete) || (cookie > last_used)) + return DMA_COMPLETE; + } else { + if ((cookie <= last_complete) && (cookie > last_used)) + return DMA_COMPLETE; + } + return DMA_IN_PROGRESS; +} + +static inline void +dma_set_tx_state(struct dma_tx_state *st, dma_cookie_t last, dma_cookie_t used, u32 residue) +{ + if (!st) + return; + + st->last = last; + st->used = used; + st->residue = residue; +} + +#ifdef CONFIG_DMA_ENGINE +struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type); +enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie); +enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx); +void dma_issue_pending_all(void); +struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask, + dma_filter_fn fn, void *fn_param, + struct device_node *np); + +struct dma_chan *dma_request_chan(struct device *dev, const char *name); +struct dma_chan *dma_request_chan_by_mask(const dma_cap_mask_t *mask); + +void dma_release_channel(struct dma_chan *chan); +int dma_get_slave_caps(struct dma_chan *chan, struct dma_slave_caps *caps); +#else +static inline struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type) +{ + return NULL; +} +static inline enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie) +{ + return DMA_COMPLETE; +} +static inline enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx) +{ + return DMA_COMPLETE; +} +static inline void dma_issue_pending_all(void) +{ +} +static inline struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask, + dma_filter_fn fn, + void *fn_param, + struct device_node *np) +{ + return NULL; +} +static inline struct dma_chan *dma_request_chan(struct device *dev, + const char *name) +{ + return ERR_PTR(-ENODEV); +} +static inline struct dma_chan *dma_request_chan_by_mask( + const dma_cap_mask_t *mask) +{ + return ERR_PTR(-ENODEV); +} +static inline void dma_release_channel(struct dma_chan *chan) +{ +} +static inline int dma_get_slave_caps(struct dma_chan *chan, + struct dma_slave_caps *caps) +{ + return -ENXIO; +} +#endif + +static inline int dmaengine_desc_set_reuse(struct dma_async_tx_descriptor *tx) +{ + struct dma_slave_caps caps; + int ret; + + ret = dma_get_slave_caps(tx->chan, &caps); + if (ret) + return ret; + + if (!caps.descriptor_reuse) + return -EPERM; + + tx->flags |= DMA_CTRL_REUSE; + return 0; +} + +static inline void dmaengine_desc_clear_reuse(struct dma_async_tx_descriptor *tx) +{ + tx->flags &= ~DMA_CTRL_REUSE; +} + +static inline bool dmaengine_desc_test_reuse(struct dma_async_tx_descriptor *tx) +{ + return (tx->flags & DMA_CTRL_REUSE) == DMA_CTRL_REUSE; +} + +static inline int dmaengine_desc_free(struct dma_async_tx_descriptor *desc) +{ + /* this is supported for reusable desc, so check that */ + if (!dmaengine_desc_test_reuse(desc)) + return -EPERM; + + return desc->desc_free(desc); +} + +/* --- DMA device --- */ + +int dma_async_device_register(struct dma_device *device); +int dmaenginem_async_device_register(struct dma_device *device); +void dma_async_device_unregister(struct dma_device *device); +int dma_async_device_channel_register(struct dma_device *device, + struct dma_chan *chan); +void dma_async_device_channel_unregister(struct dma_device *device, + struct dma_chan *chan); +void dma_run_dependencies(struct dma_async_tx_descriptor *tx); +#define dma_request_channel(mask, x, y) \ + __dma_request_channel(&(mask), x, y, NULL) + +/* Deprecated, please use dma_request_chan() directly */ +static inline struct dma_chan * __deprecated +dma_request_slave_channel(struct device *dev, const char *name) +{ + struct dma_chan *ch = dma_request_chan(dev, name); + + return IS_ERR(ch) ? NULL : ch; +} + +static inline struct dma_chan +*dma_request_slave_channel_compat(const dma_cap_mask_t mask, + dma_filter_fn fn, void *fn_param, + struct device *dev, const char *name) +{ + struct dma_chan *chan; + + chan = dma_request_slave_channel(dev, name); + if (chan) + return chan; + + if (!fn || !fn_param) + return NULL; + + return __dma_request_channel(&mask, fn, fn_param, NULL); +} + +static inline char * +dmaengine_get_direction_text(enum dma_transfer_direction dir) +{ + switch (dir) { + case DMA_DEV_TO_MEM: + return "DEV_TO_MEM"; + case DMA_MEM_TO_DEV: + return "MEM_TO_DEV"; + case DMA_MEM_TO_MEM: + return "MEM_TO_MEM"; + case DMA_DEV_TO_DEV: + return "DEV_TO_DEV"; + default: + return "invalid"; + } +} + +static inline struct device *dmaengine_get_dma_device(struct dma_chan *chan) +{ + if (chan->dev->chan_dma_dev) + return &chan->dev->device; + + return chan->device->dev; +} + +#endif /* DMAENGINE_H */ diff --git a/snd-alpx-dkms/snd-alpx/regmap-mmio.c b/snd-alpx-dkms/snd-alpx/regmap-mmio.c new file mode 100644 index 0000000..59c2007 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/regmap-mmio.c @@ -0,0 +1,9 @@ +#include <linux/version.h> + +#if KERNEL_VERSION(5, 14, 0) == LINUX_VERSION_CODE +#include "core/generic/5.14/regmap-mmio.c" +#elif KERNEL_VERSION(4, 19, 0) == LINUX_VERSION_CODE +#include "core/generic/4.19/regmap-mmio.c" +#else +#error "Unsupported kernel version, backporting another version of regmap-mmio is required" +#endif diff --git a/snd-alpx-dkms/snd-alpx/snd_alpx_xdma.c b/snd-alpx-dkms/snd-alpx/snd_alpx_xdma.c new file mode 100644 index 0000000..2941793 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/snd_alpx_xdma.c @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* +* Support for Digigram AlpX PCI-e boards +* +* Copyright (c) 2024 Digigram Digital (info@digigram.com) +*/ + +#include <linux/version.h> +#include <linux/module.h> + + +/* Defined an exported symbol to allow dependency use */ +const char* SND_ALPX_XDMA_DEP(void) +{ + return "snd_alpx_xdma support"; +} +EXPORT_SYMBOL(SND_ALPX_XDMA_DEP); + + +/* + * Use the in-kernel driver if enabled and recent enough. Otherwise, use the + * mainline kernel driver backported locally and improved with cyclic transfers + * support (6.7 code) + */ +#if IS_ENABLED(CONFIG_XILINX_XDMA) && (KERNEL_VERSION(6, 7, 0) <= LINUX_VERSION_CODE) + /* EMPTY MODULE !!! */ + #include "alpx_version.h" + #warning "Use Kernel's XDMA" + + /* MODULE meta required for build only */ + MODULE_DESCRIPTION("AlpX XDMA support module placeholder"); + MODULE_AUTHOR("Digigram Digital"); + MODULE_VERSION("ALPX_MODULE_VERSION"); + MODULE_LICENSE("GPL"); + +#else +/* Need our module BUT with the right version !! */ + #if KERNEL_VERSION(6, 3, 0) > LINUX_VERSION_CODE + + #warning 6.2 + #include "core/generic/6.2/xilinx/xdma.c" + + #elif KERNEL_VERSION(6, 7, 0) > LINUX_VERSION_CODE + + #warning 6.3 + #include "core/generic/6.3/xilinx/xdma.c" + + #endif +#endif /* IS_ENABLED(CONFIG_XILINX_XDMA) && (KERNEL_VERSION(6, 7, 0) >= LINUX_VERSION_CODE) */ diff --git a/snd-alpx-dkms/snd-alpx/snd_alpx_xdma.h b/snd-alpx-dkms/snd-alpx/snd_alpx_xdma.h new file mode 100644 index 0000000..5acba24 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/snd_alpx_xdma.h @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* +* Support for Digigram AlpX PCI-e boards +* +* Copyright (c) 2024 Digigram Digital (info@digigram.com) +*/ +#ifndef _SND_ALPX_XDMA_H_ +#define _SND_ALPX_XDMA_H_ + +/* dependency check support */ +#if (!IS_ENABLED(CONFIG_XILINX_XDMA)) || \ + (KERNEL_VERSION(6, 7, 0) > LINUX_VERSION_CODE) +#warning "USE Package's XDMA module" + /* snd-alpx-xdma dependency */ + const char* SND_ALPX_XDMA_DEP(void); +#else +/* NO dependency SO required local define*/ +static const char* SND_ALPX_XDMA_DEP(void) +{ + return "Internal XDMA support"; +} +#endif + +#endif /*_SND_ALPX_XDMA_H_*/ diff --git a/snd-alpx-dkms/snd-alpx/tools/audio_card_update_firmware.sh b/snd-alpx-dkms/snd-alpx/tools/audio_card_update_firmware.sh new file mode 100755 index 0000000..9dfa0c7 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/tools/audio_card_update_firmware.sh @@ -0,0 +1,99 @@ +#!/bin/bash + + +# This script is used to update the firmware of the card FOR Audio card only (Alpxxy) with x and y are numbers. +# Param 1 : mtd partition number of the "fw-user-updatable", see /proc/mtd file and select +# the one of the to be updated card. +#Param 2 : firmware complete filepath + +#NOTE : use BASH read, SH read : follow https://stackoverflow.com/questions/226703/how-do-i-prompt-for-yes-no-cancel-input-in-a-linux-shell-script + + +user_manual(){ + echo "Param 1 : mtd partition number of the \"fw-user-updatable\", see /proc/mtd file and select" + echo "Param 2 : firmware complete filepath" + echo "Check user can write to the mtd partition's file" + return 0 +} + + +## MAIN ## +# warn about supported card +#Warn about the card supported model : Alp Audio card. +read -r -n 1 -p "WARNING: This is only for AUDIO based Alp cards (ie Alp222, Alp882 and Alp442) update ? [y/N]:" user_resp + +echo # (optional) move to a new line +if [[ ! "$user_resp" =~ ^[Yy]$ ]] +then + # handle exits from shell or function but don't exit interactive shell + [[ "$0" = "$BASH_SOURCE" ]] && echo "CANCELED by User" && exit 1 || return 1 +fi + + +#Check parameters +[ "$#" -ne "2" ] && user_manual && exit 1 + +fw_partition_path="$1" +source_fw_file="$2" + + + +# /dev/mtd is a character device +[ ! -c "$fw_partition_path" ] && echo "$fw_partition_path Not a C Device" && exit 2 +#Write access ? +[ ! -w "$fw_partition_path" ] && echo "Not writeable" && exit 2 + +# firmware file condition +[ ! -e "$source_fw_file" ] && user_manual && exit 2 +[ ! -f "$source_fw_file" ] && user_manual && exit 2 +[ ! -s "$source_fw_file" ] && user_manual && exit 2 +[ ! -r "$source_fw_file" ] && user_manual && exit 2 + +#Check available space !! TODO +# It Requires firmware size + 4kB for the extracted HEADER. + +#read : BASH extensions used ! +read -r -n 1 -p Writing\ "$source_fw_file"\ to\ "$fw_partition_path ? [y/N]: " user_resp + +echo # (optional) move to a new line +if [[ ! "$user_resp" =~ ^[Yy]$ ]] +then + # handle exits from shell or function but don't exit interactive shell + [[ "$0" = "$BASH_SOURCE" ]] && echo "CANCELED by User" && exit 1 || return 1 +fi + +dd if="$source_fw_file" of=fw_header.bin bs=4096 count=1 status=none +if [ "$?" -ne "0" ] ; then + echo "Error when preparing the firmware, check disk size please." + exit 4; +fi + +dd if="$source_fw_file" of=fw_body.bin bs=4096 skip=1 seek=1 status=none +if [ "$?" -ne "0" ] ; then + echo "Error when preparing the firmware, check disk size please." + exit 4; +fi + + +echo "Updating first phase ..." +cat fw_body.bin > "$fw_partition_path" +if [ "$?" -ne "0" ] ; then + echo "!! Update failed DON'T poweroff, correct to retry." + rm -f fw_body.bin fw_header.bin + exit 3; +fi + +echo "Updating second phase ..." +cat fw_header.bin > "$fw_partition_path" + +if [ "$?" -ne "0" ] ; then + echo "!! Update failed DON'T poweroff, correct to retry." + rm -f fw_body.bin fw_header.bin + exit 3; +fi + +echo "Update SUCCEEDED" + +rm -f fw_body.bin fw_header.bin + +exit 0 diff --git a/snd-alpx-dkms/snd-alpx/tools/build-load-script.sh b/snd-alpx-dkms/snd-alpx/tools/build-load-script.sh new file mode 100755 index 0000000..76e0174 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/tools/build-load-script.sh @@ -0,0 +1,111 @@ +#!/bin/bash +#This script will build the manual launch script for the Alpx cards' driver. + +TEXT_BOLD="\e[1m" +TEXT_BLUE="\e[34m" +TEXT_RED="\e[31m" +TEXT_RESET="\e[0m" + +manual_load_script_name="$1" +ALPX_SOUND_DRIVER_NAME="snd-alpx.ko" +ALPX_DMA_DRIVER_NAME="snd-alpx-xdma.ko" + +OPTIONS_REQUIRED=("CONFIG_MTD" "CONFIG_DMA_VIRTUAL_CHANNELS" "CONFIG_SND_PCM") +OPTIONS_OPTIONAL=("CONFIG_SND_DMAENGINE_PCM") + +module_for_option() +{ + option=$1 + + case $option in + "CONFIG_MTD") + echo "mtd" + ;; + "CONFIG_DMA_VIRTUAL_CHANNELS") + echo "virt-dma" + ;; + "CONFIG_SND_DMAENGINE_PCM") + echo "snd-pcm-dmaengine" + ;; + "CONFIG_SND_PCM") + echo "snd-pcm" + ;; + esac +} + +required_module_entry() +{ + option=$1 + module_name=$( module_for_option "$option" ) + + echo -e $TEXT_BOLD$TEXT_BLUE"Option $option was built as a module and will be loaded" + echo -e "echo 'loading required module : $module_name'" >> $manual_load_script_name + echo -e "modprobe $module_name" >> $manual_load_script_name +} + +build_launch_script() +{ + list=$( cat - ) + + if [ -f "$manual_load_script_name" ] + then + rm "$manual_load_script_name" + echo -e "#!/bin/bash" >> $manual_load_script_name + fi + + for option in ${OPTIONS_REQUIRED[@]} + do + match_y=$( echo "$list" | grep -P "^$option=y" ) + match_m=$( echo "$list" | grep -P "^$option=m" ) + + if [ -z "$match_y" ] && [ -z "$match_m" ] + then + echo -e $TEXT_BOLD$TEXT_RED"Missing required option $option!"$TEXT_RESET + return 1 + fi + + if [ -n "$match_m" ] + then + required_module_entry "$option" + fi + done + + for option in ${OPTIONS_OPTIONAL[@]} + do + match_m=$( echo "$list" | grep -P "^$option=m" ) + + if [ -n "$match_m" ] + then + required_module_entry "$option" + fi + done + + + + if [ -f "$manual_load_script_name" ] + then + chmod u+x "$manual_load_script_name" + fi + + #NO> add the drivers entries themselves + echo -e "echo 'loading the dma driver : $ALPX_DMA_DRIVER_NAME '" >> $manual_load_script_name + echo -e "insmod $ALPX_DMA_DRIVER_NAME" >> $manual_load_script_name + echo -e "echo 'loading the sound driver : $ALPX_SOUND_DRIVER_NAME '" >> $manual_load_script_name + echo -e "insmod $ALPX_SOUND_DRIVER_NAME" >> $manual_load_script_name + + + echo -e $TEXT_RESET +} + +config_path="/boot/config"-$( uname -r ) + +if [ -f "/proc/config.gz" ] +then + cat /proc/config.gz | gunzip | build_launch_script +elif [ -f "$config_path" ] +then + cat "$config_path" | build_launch_script +else + echo "No config path found, unable to check!" >&2 + exit 1 +fi diff --git a/snd-alpx-dkms/snd-alpx/tools/build_driver_pkg.sh b/snd-alpx-dkms/snd-alpx/tools/build_driver_pkg.sh new file mode 100755 index 0000000..ef568bd --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/tools/build_driver_pkg.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +#This script will create the driver source archive with the given tag, name compilant with dkms +# and put it in the destination dir + +print_help() { + echo -e "This script requires 2 parameters : \n\t 1: version tag \n\t 2: destination directory" +} + +## MAIN ## +#Check parameters +echo "starting $0 with $#" + +[ ! "$#" -eq "2" ] && print_help && exit 1 + +version_tag=$1 +dest_dir=$2 + +##Handle HEAD as a Special value +if [ "$version_tag" == "HEAD" ] +then + version=$version_tag +else + version=${version_tag:2} +fi + +echo "get ready for the archive V: $version_tag, from tag: $version_tag to $dest_dir/snd-alpx-$version.zip ..." +git archive --format=zip -9 --prefix="snd-alpx-$version/" "$version_tag" > "$dest_dir/snd-alpx-$version.zip" diff --git a/snd-alpx-dkms/snd-alpx/tools/build_virtual_board_alsa_conf.sh b/snd-alpx-dkms/snd-alpx/tools/build_virtual_board_alsa_conf.sh new file mode 100755 index 0000000..3e8a605 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/tools/build_virtual_board_alsa_conf.sh @@ -0,0 +1,79 @@ +#!/bin/bash +## This script will print an asoundrc stream which add virtual boards from one physical board. +## Output must be directed into a file to be stored + +### FUNCTIONS ### +user_manual() { + echo "Required Parameters + 1. Phy board id like "hw:CARD=Alp882e,DEV=0" + 2. Phy board channels quantity + 3. Virtual boards base name like : \"Emulated analog Alp222\" + 4. Virtual boards channels quantities (2: stéréo, ...)" >&2 +} + + +build_phy_node() { + node_type=$1 + card_id=$2 + channels_qty=$3 + echo -e "pcm_slave.$node_type { \n pcm \"$card_id\"\n channels $channels_qty\n }\n" +} + +build_virtual_node() { +node_alias=$1 +node_type=$2 +node_id=$3 +ipc_key=$4 +phy_name=$5 +phy_channels_base=$6 +phy_channels_qty=$7 +description=$8 +direction=$9 + +echo -e "pcm.$node_alias$node_id { + type $node_type + ipc_key $ipc_key + ipc_key_add_uid true + slave $phy_name" + + for channel_id in $(seq 0 "$(($phy_channels_qty-1))") + do + echo -e "\tbindings.$channel_id $(($channel_id+$phy_channels_base))" + done + + + echo -e "\thint.description" \"$description \#$node_id $direction\" + echo -e "}\n" +} + +### MAIN ### + +[ "$#" -ne "4" ] && user_manual && exit 1 + +ipc_key=$(date +%N) +card_id=$1 +channels_qty=$2 +virtual_basename=$3 +stream_width=$4 +virt_qty=$(($channels_qty / $stream_width)) + +echo "#Building Alsa sound RC file for $virt_qty virtual boards of $stream_width channels from physical board $card_id with $channels_qty." + +##Build the entries first +build_phy_node "ins" "$card_id" "$channels_qty" + +for entry_idx in $(seq 0 $(($virt_qty-1))) +do + build_virtual_node "mic" "dsnoop" "$entry_idx" "$ipc_key" "ins" "$(($stream_width * $entry_idx))" "$stream_width" "virtual Alp-$stream_width" "in" +done + +##Now the outpus +build_phy_node "outs" "$card_id" "$channels_qty" + +ipc_key=$(date +%N) + +for entry_idx in $(seq 0 $(($virt_qty-1))) +do + build_virtual_node "out" "dshare" "$entry_idx" "$ipc_key" "outs" "$(($stream_width * $entry_idx))" "$stream_width" "virtual Alp-$stream_width" "out" +done + diff --git a/snd-alpx-dkms/snd-alpx/udev/88-pulseaudio-no-alp.rules b/snd-alpx-dkms/snd-alpx/udev/88-pulseaudio-no-alp.rules new file mode 100644 index 0000000..89e01c5 --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/udev/88-pulseaudio-no-alp.rules @@ -0,0 +1 @@ +ATTRS{vendor}=="0x1369", ATTRS{device}=="0x0002", ATTRS{subsystem_vendor}=="0x1369", ENV{PULSE_IGNORE}="1" |