aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/ctxfi
diff options
context:
space:
mode:
authorWai Yew CHAY <wychay@ctl.creative.com>2009-05-14 02:05:58 -0400
committerTakashi Iwai <tiwai@suse.de>2009-05-14 02:24:10 -0400
commit8cc72361481f00253f1e468ade5795427386d593 (patch)
treeec6f3ea304f90fa9c99abb1bf2354fc5d357db27 /sound/pci/ctxfi
parent091bf7624d1c90cec9e578a18529f615213ff847 (diff)
ALSA: SB X-Fi driver merge
The Sound Blaster X-Fi driver supports Creative solutions based on 20K1 and 20K2 chipsets. Supported hardware : Creative Sound Blaster X-Fi Titanium Fatal1ty® Champion Series Creative Sound Blaster X-Fi Titanium Fatal1ty Professional Series Creative Sound Blaster X-Fi Titanium Professional Audio Creative Sound Blaster X-Fi Titanium Creative Sound Blaster X-Fi Elite Pro Creative Sound Blaster X-Fi Platinum Creative Sound Blaster X-Fi Fatal1ty Creative Sound Blaster X-Fi XtremeGamer Creative Sound Blaster X-Fi XtremeMusic Current release features: * ALSA PCM Playback * ALSA Record * ALSA Mixer Note: * External I/O modules detection not included. Signed-off-by: Wai Yew CHAY <wychay@ctl.creative.com> Singed-off-by: Ryan RICHARDS <ryan_richards@creativelabs.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/ctxfi')
-rw-r--r--sound/pci/ctxfi/Makefile5
-rw-r--r--sound/pci/ctxfi/ct20k1reg.h634
-rw-r--r--sound/pci/ctxfi/ct20k2reg.h85
-rw-r--r--sound/pci/ctxfi/ctamixer.c488
-rw-r--r--sound/pci/ctxfi/ctamixer.h96
-rw-r--r--sound/pci/ctxfi/ctatc.c1605
-rw-r--r--sound/pci/ctxfi/ctatc.h155
-rw-r--r--sound/pci/ctxfi/ctdaio.c769
-rw-r--r--sound/pci/ctxfi/ctdaio.h122
-rw-r--r--sound/pci/ctxfi/ctdrv.h30
-rw-r--r--sound/pci/ctxfi/cthardware.c108
-rw-r--r--sound/pci/ctxfi/cthardware.h160
-rw-r--r--sound/pci/ctxfi/cthw20k1.c2230
-rw-r--r--sound/pci/ctxfi/cthw20k1.h26
-rw-r--r--sound/pci/ctxfi/cthw20k2.c2133
-rw-r--r--sound/pci/ctxfi/cthw20k2.h26
-rw-r--r--sound/pci/ctxfi/ctimap.c112
-rw-r--r--sound/pci/ctxfi/ctimap.h40
-rw-r--r--sound/pci/ctxfi/ctmixer.c1108
-rw-r--r--sound/pci/ctxfi/ctmixer.h67
-rw-r--r--sound/pci/ctxfi/ctpcm.c499
-rw-r--r--sound/pci/ctxfi/ctpcm.h27
-rw-r--r--sound/pci/ctxfi/ctresource.c297
-rw-r--r--sound/pci/ctxfi/ctresource.h72
-rw-r--r--sound/pci/ctxfi/ctsrc.c886
-rw-r--r--sound/pci/ctxfi/ctsrc.h149
-rw-r--r--sound/pci/ctxfi/ctvmem.c254
-rw-r--r--sound/pci/ctxfi/ctvmem.h49
-rw-r--r--sound/pci/ctxfi/xfi.c125
29 files changed, 12357 insertions, 0 deletions
diff --git a/sound/pci/ctxfi/Makefile b/sound/pci/ctxfi/Makefile
new file mode 100644
index 000000000000..29043237f9f8
--- /dev/null
+++ b/sound/pci/ctxfi/Makefile
@@ -0,0 +1,5 @@
1snd-ctxfi-objs := xfi.o ctatc.o ctvmem.o ctpcm.o ctmixer.o ctresource.o \
2 ctsrc.o ctamixer.o ctdaio.o ctimap.o cthardware.o \
3 cthw20k2.o cthw20k1.o
4
5obj-$(CONFIG_SND_CTXFI) += snd-ctxfi.o
diff --git a/sound/pci/ctxfi/ct20k1reg.h b/sound/pci/ctxfi/ct20k1reg.h
new file mode 100644
index 000000000000..c62e6775dab3
--- /dev/null
+++ b/sound/pci/ctxfi/ct20k1reg.h
@@ -0,0 +1,634 @@
1/**
2 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
3 *
4 * This source file is released under GPL v2 license (no other versions).
5 * See the COPYING file included in the main directory of this source
6 * distribution for the license terms and conditions.
7 */
8
9#ifndef CT20K1REG_H
10#define CT20k1REG_H
11
12/* 20k1 registers */
13#define DSPXRAM_START 0x000000
14#define DSPXRAM_END 0x013FFC
15#define DSPAXRAM_START 0x020000
16#define DSPAXRAM_END 0x023FFC
17#define DSPYRAM_START 0x040000
18#define DSPYRAM_END 0x04FFFC
19#define DSPAYRAM_START 0x020000
20#define DSPAYRAM_END 0x063FFC
21#define DSPMICRO_START 0x080000
22#define DSPMICRO_END 0x0B3FFC
23#define DSP0IO_START 0x100000
24#define DSP0IO_END 0x101FFC
25#define AUDIORINGIPDSP0_START 0x100000
26#define AUDIORINGIPDSP0_END 0x1003FC
27#define AUDIORINGOPDSP0_START 0x100400
28#define AUDIORINGOPDSP0_END 0x1007FC
29#define AUDPARARINGIODSP0_START 0x100800
30#define AUDPARARINGIODSP0_END 0x100BFC
31#define DSP0LOCALHWREG_START 0x100C00
32#define DSP0LOCALHWREG_END 0x100C3C
33#define DSP0XYRAMAGINDEX_START 0x100C40
34#define DSP0XYRAMAGINDEX_END 0x100C5C
35#define DSP0XYRAMAGMDFR_START 0x100C60
36#define DSP0XYRAMAGMDFR_END 0x100C7C
37#define DSP0INTCONTLVEC_START 0x100C80
38#define DSP0INTCONTLVEC_END 0x100CD8
39#define INTCONTLGLOBALREG_START 0x100D1C
40#define INTCONTLGLOBALREG_END 0x100D3C
41#define HOSTINTFPORTADDRCONTDSP0 0x100D40
42#define HOSTINTFPORTDATADSP0 0x100D44
43#define TIME0PERENBDSP0 0x100D60
44#define TIME0COUNTERDSP0 0x100D64
45#define TIME1PERENBDSP0 0x100D68
46#define TIME1COUNTERDSP0 0x100D6C
47#define TIME2PERENBDSP0 0x100D70
48#define TIME2COUNTERDSP0 0x100D74
49#define TIME3PERENBDSP0 0x100D78
50#define TIME3COUNTERDSP0 0x100D7C
51#define XRAMINDOPERREFNOUP_STARTDSP0 0x100D80
52#define XRAMINDOPERREFNOUP_ENDDSP0 0x100D9C
53#define XRAMINDOPERREFUP_STARTDSP0 0x100DA0
54#define XRAMINDOPERREFUP_ENDDSP0 0x100DBC
55#define YRAMINDOPERREFNOUP_STARTDSP0 0x100DC0
56#define YRAMINDOPERREFNOUP_ENDDSP0 0x100DDC
57#define YRAMINDOPERREFUP_STARTDSP0 0x100DE0
58#define YRAMINDOPERREFUP_ENDDSP0 0x100DFC
59#define DSP0CONDCODE 0x100E00
60#define DSP0STACKFLAG 0x100E04
61#define DSP0PROGCOUNTSTACKPTREG 0x100E08
62#define DSP0PROGCOUNTSTACKDATAREG 0x100E0C
63#define DSP0CURLOOPADDRREG 0x100E10
64#define DSP0CURLOOPCOUNT 0x100E14
65#define DSP0TOPLOOPCOUNTSTACK 0x100E18
66#define DSP0TOPLOOPADDRSTACK 0x100E1C
67#define DSP0LOOPSTACKPTR 0x100E20
68#define DSP0STASSTACKDATAREG 0x100E24
69#define DSP0STASSTACKPTR 0x100E28
70#define DSP0PROGCOUNT 0x100E2C
71#define GLOBDSPDEBGREG 0x100E30
72#define GLOBDSPBREPTRREG 0x100E30
73#define DSP0XYRAMBASE_START 0x100EA0
74#define DSP0XYRAMBASE_END 0x100EBC
75#define DSP0XYRAMLENG_START 0x100EC0
76#define DSP0XYRAMLENG_END 0x100EDC
77#define SEMAPHOREREGDSP0 0x100EE0
78#define DSP0INTCONTMASKREG 0x100EE4
79#define DSP0INTCONTPENDREG 0x100EE8
80#define DSP0INTCONTSERVINT 0x100EEC
81#define DSPINTCONTEXTINTMODREG 0x100EEC
82#define GPIODSP0 0x100EFC
83#define DMADSPBASEADDRREG_STARTDSP0 0x100F00
84#define DMADSPBASEADDRREG_ENDDSP0 0x100F1C
85#define DMAHOSTBASEADDRREG_STARTDSP0 0x100F20
86#define DMAHOSTBASEADDRREG_ENDDSP0 0x100F3C
87#define DMADSPCURADDRREG_STARTDSP0 0x100F40
88#define DMADSPCURADDRREG_ENDDSP0 0x100F5C
89#define DMAHOSTCURADDRREG_STARTDSP0 0x100F60
90#define DMAHOSTCURADDRREG_ENDDSP0 0x100F7C
91#define DMATANXCOUNTREG_STARTDSP0 0x100F80
92#define DMATANXCOUNTREG_ENDDSP0 0x100F9C
93#define DMATIMEBUGREG_STARTDSP0 0x100FA0
94#define DMATIMEBUGREG_ENDDSP0 0x100FAC
95#define DMACNTLMODFREG_STARTDSP0 0x100FA0
96#define DMACNTLMODFREG_ENDDSP0 0x100FAC
97
98#define DMAGLOBSTATSREGDSP0 0x100FEC
99#define DSP0XGPRAM_START 0x101000
100#define DSP0XGPRAM_END 0x1017FC
101#define DSP0YGPRAM_START 0x101800
102#define DSP0YGPRAM_END 0x101FFC
103
104
105
106
107#define AUDIORINGIPDSP1_START 0x102000
108#define AUDIORINGIPDSP1_END 0x1023FC
109#define AUDIORINGOPDSP1_START 0x102400
110#define AUDIORINGOPDSP1_END 0x1027FC
111#define AUDPARARINGIODSP1_START 0x102800
112#define AUDPARARINGIODSP1_END 0x102BFC
113#define DSP1LOCALHWREG_START 0x102C00
114#define DSP1LOCALHWREG_END 0x102C3C
115#define DSP1XYRAMAGINDEX_START 0x102C40
116#define DSP1XYRAMAGINDEX_END 0x102C5C
117#define DSP1XYRAMAGMDFR_START 0x102C60
118#define DSP1XYRAMAGMDFR_END 0x102C7C
119#define DSP1INTCONTLVEC_START 0x102C80
120#define DSP1INTCONTLVEC_END 0x102CD8
121#define HOSTINTFPORTADDRCONTDSP1 0x102D40
122#define HOSTINTFPORTDATADSP1 0x102D44
123#define TIME0PERENBDSP1 0x102D60
124#define TIME0COUNTERDSP1 0x102D64
125#define TIME1PERENBDSP1 0x102D68
126#define TIME1COUNTERDSP1 0x102D6C
127#define TIME2PERENBDSP1 0x102D70
128#define TIME2COUNTERDSP1 0x102D74
129#define TIME3PERENBDSP1 0x102D78
130#define TIME3COUNTERDSP1 0x102D7C
131#define XRAMINDOPERREFNOUP_STARTDSP1 0x102D80
132#define XRAMINDOPERREFNOUP_ENDDSP1 0x102D9C
133#define XRAMINDOPERREFUP_STARTDSP1 0x102DA0
134#define XRAMINDOPERREFUP_ENDDSP1 0x102DBC
135#define YRAMINDOPERREFNOUP_STARTDSP1 0x102DC0
136#define YRAMINDOPERREFNOUP_ENDDSP1 0x102DDC
137#define YRAMINDOPERREFUP_STARTDSP1 0x102DE0
138#define YRAMINDOPERREFUP_ENDDSP1 0x102DFC
139
140#define DSP1CONDCODE 0x102E00
141#define DSP1STACKFLAG 0x102E04
142#define DSP1PROGCOUNTSTACKPTREG 0x102E08
143#define DSP1PROGCOUNTSTACKDATAREG 0x102E0C
144#define DSP1CURLOOPADDRREG 0x102E10
145#define DSP1CURLOOPCOUNT 0x102E14
146#define DSP1TOPLOOPCOUNTSTACK 0x102E18
147#define DSP1TOPLOOPADDRSTACK 0x102E1C
148#define DSP1LOOPSTACKPTR 0x102E20
149#define DSP1STASSTACKDATAREG 0x102E24
150#define DSP1STASSTACKPTR 0x102E28
151#define DSP1PROGCOUNT 0x102E2C
152#define DSP1XYRAMBASE_START 0x102EA0
153#define DSP1XYRAMBASE_END 0x102EBC
154#define DSP1XYRAMLENG_START 0x102EC0
155#define DSP1XYRAMLENG_END 0x102EDC
156#define SEMAPHOREREGDSP1 0x102EE0
157#define DSP1INTCONTMASKREG 0x102EE4
158#define DSP1INTCONTPENDREG 0x102EE8
159#define DSP1INTCONTSERVINT 0x102EEC
160#define GPIODSP1 0x102EFC
161#define DMADSPBASEADDRREG_STARTDSP1 0x102F00
162#define DMADSPBASEADDRREG_ENDDSP1 0x102F1C
163#define DMAHOSTBASEADDRREG_STARTDSP1 0x102F20
164#define DMAHOSTBASEADDRREG_ENDDSP1 0x102F3C
165#define DMADSPCURADDRREG_STARTDSP1 0x102F40
166#define DMADSPCURADDRREG_ENDDSP1 0x102F5C
167#define DMAHOSTCURADDRREG_STARTDSP1 0x102F60
168#define DMAHOSTCURADDRREG_ENDDSP1 0x102F7C
169#define DMATANXCOUNTREG_STARTDSP1 0x102F80
170#define DMATANXCOUNTREG_ENDDSP1 0x102F9C
171#define DMATIMEBUGREG_STARTDSP1 0x102FA0
172#define DMATIMEBUGREG_ENDDSP1 0x102FAC
173#define DMACNTLMODFREG_STARTDSP1 0x102FA0
174#define DMACNTLMODFREG_ENDDSP1 0x102FAC
175
176#define DMAGLOBSTATSREGDSP1 0x102FEC
177#define DSP1XGPRAM_START 0x103000
178#define DSP1XGPRAM_END 0x1033FC
179#define DSP1YGPRAM_START 0x103400
180#define DSP1YGPRAM_END 0x1037FC
181
182
183
184#define AUDIORINGIPDSP2_START 0x104000
185#define AUDIORINGIPDSP2_END 0x1043FC
186#define AUDIORINGOPDSP2_START 0x104400
187#define AUDIORINGOPDSP2_END 0x1047FC
188#define AUDPARARINGIODSP2_START 0x104800
189#define AUDPARARINGIODSP2_END 0x104BFC
190#define DSP2LOCALHWREG_START 0x104C00
191#define DSP2LOCALHWREG_END 0x104C3C
192#define DSP2XYRAMAGINDEX_START 0x104C40
193#define DSP2XYRAMAGINDEX_END 0x104C5C
194#define DSP2XYRAMAGMDFR_START 0x104C60
195#define DSP2XYRAMAGMDFR_END 0x104C7C
196#define DSP2INTCONTLVEC_START 0x104C80
197#define DSP2INTCONTLVEC_END 0x104CD8
198#define HOSTINTFPORTADDRCONTDSP2 0x104D40
199#define HOSTINTFPORTDATADSP2 0x104D44
200#define TIME0PERENBDSP2 0x104D60
201#define TIME0COUNTERDSP2 0x104D64
202#define TIME1PERENBDSP2 0x104D68
203#define TIME1COUNTERDSP2 0x104D6C
204#define TIME2PERENBDSP2 0x104D70
205#define TIME2COUNTERDSP2 0x104D74
206#define TIME3PERENBDSP2 0x104D78
207#define TIME3COUNTERDSP2 0x104D7C
208#define XRAMINDOPERREFNOUP_STARTDSP2 0x104D80
209#define XRAMINDOPERREFNOUP_ENDDSP2 0x104D9C
210#define XRAMINDOPERREFUP_STARTDSP2 0x104DA0
211#define XRAMINDOPERREFUP_ENDDSP2 0x104DBC
212#define YRAMINDOPERREFNOUP_STARTDSP2 0x104DC0
213#define YRAMINDOPERREFNOUP_ENDDSP2 0x104DDC
214#define YRAMINDOPERREFUP_STARTDSP2 0x104DE0
215#define YRAMINDOPERREFUP_ENDDSP2 0x104DFC
216#define DSP2CONDCODE 0x104E00
217#define DSP2STACKFLAG 0x104E04
218#define DSP2PROGCOUNTSTACKPTREG 0x104E08
219#define DSP2PROGCOUNTSTACKDATAREG 0x104E0C
220#define DSP2CURLOOPADDRREG 0x104E10
221#define DSP2CURLOOPCOUNT 0x104E14
222#define DSP2TOPLOOPCOUNTSTACK 0x104E18
223#define DSP2TOPLOOPADDRSTACK 0x104E1C
224#define DSP2LOOPSTACKPTR 0x104E20
225#define DSP2STASSTACKDATAREG 0x104E24
226#define DSP2STASSTACKPTR 0x104E28
227#define DSP2PROGCOUNT 0x104E2C
228#define DSP2XYRAMBASE_START 0x104EA0
229#define DSP2XYRAMBASE_END 0x104EBC
230#define DSP2XYRAMLENG_START 0x104EC0
231#define DSP2XYRAMLENG_END 0x104EDC
232#define SEMAPHOREREGDSP2 0x104EE0
233#define DSP2INTCONTMASKREG 0x104EE4
234#define DSP2INTCONTPENDREG 0x104EE8
235#define DSP2INTCONTSERVINT 0x104EEC
236#define GPIODSP2 0x104EFC
237#define DMADSPBASEADDRREG_STARTDSP2 0x104F00
238#define DMADSPBASEADDRREG_ENDDSP2 0x104F1C
239#define DMAHOSTBASEADDRREG_STARTDSP2 0x104F20
240#define DMAHOSTBASEADDRREG_ENDDSP2 0x104F3C
241#define DMADSPCURADDRREG_STARTDSP2 0x104F40
242#define DMADSPCURADDRREG_ENDDSP2 0x104F5C
243#define DMAHOSTCURADDRREG_STARTDSP2 0x104F60
244#define DMAHOSTCURADDRREG_ENDDSP2 0x104F7C
245#define DMATANXCOUNTREG_STARTDSP2 0x104F80
246#define DMATANXCOUNTREG_ENDDSP2 0x104F9C
247#define DMATIMEBUGREG_STARTDSP2 0x104FA0
248#define DMATIMEBUGREG_ENDDSP2 0x104FAC
249#define DMACNTLMODFREG_STARTDSP2 0x104FA0
250#define DMACNTLMODFREG_ENDDSP2 0x104FAC
251
252#define DMAGLOBSTATSREGDSP2 0x104FEC
253#define DSP2XGPRAM_START 0x105000
254#define DSP2XGPRAM_END 0x1051FC
255#define DSP2YGPRAM_START 0x105800
256#define DSP2YGPRAM_END 0x1059FC
257
258
259
260#define AUDIORINGIPDSP3_START 0x106000
261#define AUDIORINGIPDSP3_END 0x1063FC
262#define AUDIORINGOPDSP3_START 0x106400
263#define AUDIORINGOPDSP3_END 0x1067FC
264#define AUDPARARINGIODSP3_START 0x106800
265#define AUDPARARINGIODSP3_END 0x106BFC
266#define DSP3LOCALHWREG_START 0x106C00
267#define DSP3LOCALHWREG_END 0x106C3C
268#define DSP3XYRAMAGINDEX_START 0x106C40
269#define DSP3XYRAMAGINDEX_END 0x106C5C
270#define DSP3XYRAMAGMDFR_START 0x106C60
271#define DSP3XYRAMAGMDFR_END 0x106C7C
272#define DSP3INTCONTLVEC_START 0x106C80
273#define DSP3INTCONTLVEC_END 0x106CD8
274#define HOSTINTFPORTADDRCONTDSP3 0x106D40
275#define HOSTINTFPORTDATADSP3 0x106D44
276#define TIME0PERENBDSP3 0x106D60
277#define TIME0COUNTERDSP3 0x106D64
278#define TIME1PERENBDSP3 0x106D68
279#define TIME1COUNTERDSP3 0x106D6C
280#define TIME2PERENBDSP3 0x106D70
281#define TIME2COUNTERDSP3 0x106D74
282#define TIME3PERENBDSP3 0x106D78
283#define TIME3COUNTERDSP3 0x106D7C
284#define XRAMINDOPERREFNOUP_STARTDSP3 0x106D80
285#define XRAMINDOPERREFNOUP_ENDDSP3 0x106D9C
286#define XRAMINDOPERREFUP_STARTDSP3 0x106DA0
287#define XRAMINDOPERREFUP_ENDDSP3 0x106DBC
288#define YRAMINDOPERREFNOUP_STARTDSP3 0x106DC0
289#define YRAMINDOPERREFNOUP_ENDDSP3 0x106DDC
290#define YRAMINDOPERREFUP_STARTDSP3 0x106DE0
291#define YRAMINDOPERREFUP_ENDDSP3 0x100DFC
292
293#define DSP3CONDCODE 0x106E00
294#define DSP3STACKFLAG 0x106E04
295#define DSP3PROGCOUNTSTACKPTREG 0x106E08
296#define DSP3PROGCOUNTSTACKDATAREG 0x106E0C
297#define DSP3CURLOOPADDRREG 0x106E10
298#define DSP3CURLOOPCOUNT 0x106E14
299#define DSP3TOPLOOPCOUNTSTACK 0x106E18
300#define DSP3TOPLOOPADDRSTACK 0x106E1C
301#define DSP3LOOPSTACKPTR 0x106E20
302#define DSP3STASSTACKDATAREG 0x106E24
303#define DSP3STASSTACKPTR 0x106E28
304#define DSP3PROGCOUNT 0x106E2C
305#define DSP3XYRAMBASE_START 0x106EA0
306#define DSP3XYRAMBASE_END 0x106EBC
307#define DSP3XYRAMLENG_START 0x106EC0
308#define DSP3XYRAMLENG_END 0x106EDC
309#define SEMAPHOREREGDSP3 0x106EE0
310#define DSP3INTCONTMASKREG 0x106EE4
311#define DSP3INTCONTPENDREG 0x106EE8
312#define DSP3INTCONTSERVINT 0x106EEC
313#define GPIODSP3 0x106EFC
314#define DMADSPBASEADDRREG_STARTDSP3 0x106F00
315#define DMADSPBASEADDRREG_ENDDSP3 0x106F1C
316#define DMAHOSTBASEADDRREG_STARTDSP3 0x106F20
317#define DMAHOSTBASEADDRREG_ENDDSP3 0x106F3C
318#define DMADSPCURADDRREG_STARTDSP3 0x106F40
319#define DMADSPCURADDRREG_ENDDSP3 0x106F5C
320#define DMAHOSTCURADDRREG_STARTDSP3 0x106F60
321#define DMAHOSTCURADDRREG_ENDDSP3 0x106F7C
322#define DMATANXCOUNTREG_STARTDSP3 0x106F80
323#define DMATANXCOUNTREG_ENDDSP3 0x106F9C
324#define DMATIMEBUGREG_STARTDSP3 0x106FA0
325#define DMATIMEBUGREG_ENDDSP3 0x106FAC
326#define DMACNTLMODFREG_STARTDSP3 0x106FA0
327#define DMACNTLMODFREG_ENDDSP3 0x106FAC
328
329#define DMAGLOBSTATSREGDSP3 0x106FEC
330#define DSP3XGPRAM_START 0x107000
331#define DSP3XGPRAM_END 0x1071FC
332#define DSP3YGPRAM_START 0x107800
333#define DSP3YGPRAM_END 0x1079FC
334
335/* end of DSP reg definitions */
336
337#define DSPAIMAP_START 0x108000
338#define DSPAIMAP_END 0x1083FC
339#define DSPPIMAP_START 0x108400
340#define DSPPIMAP_END 0x1087FC
341#define DSPPOMAP_START 0x108800
342#define DSPPOMAP_END 0x108BFC
343#define DSPPOCTL 0x108C00
344#define TKCTL_START 0x110000
345#define TKCTL_END 0x110FFC
346#define TKCC_START 0x111000
347#define TKCC_END 0x111FFC
348#define TKIMAP_START 0x112000
349#define TKIMAP_END 0x112FFC
350#define TKDCTR16 0x113000
351#define TKPB16 0x113004
352#define TKBS16 0x113008
353#define TKDCTR32 0x11300C
354#define TKPB32 0x113010
355#define TKBS32 0x113014
356#define ICDCTR16 0x113018
357#define ITBS16 0x11301C
358#define ICDCTR32 0x113020
359#define ITBS32 0x113024
360#define ITSTART 0x113028
361#define TKSQ 0x11302C
362
363#define TKSCCTL_START 0x114000
364#define TKSCCTL_END 0x11403C
365#define TKSCADR_START 0x114100
366#define TKSCADR_END 0x11413C
367#define TKSCDATAX_START 0x114800
368#define TKSCDATAX_END 0x1149FC
369#define TKPCDATAX_START 0x120000
370#define TKPCDATAX_END 0x12FFFC
371
372#define MALSA 0x130000
373#define MAPPHA 0x130004
374#define MAPPLA 0x130008
375#define MALSB 0x130010
376#define MAPPHB 0x130014
377#define MAPPLB 0x130018
378
379#define TANSPORTMAPABREGS_START 0x130020
380#define TANSPORTMAPABREGS_END 0x13A2FC
381
382#define PTPAHX 0x13B000
383#define PTPALX 0x13B004
384
385#define TANSPPAGETABLEPHYADDR015_START 0x13B008
386#define TANSPPAGETABLEPHYADDR015_END 0x13B07C
387#define TRNQADRX_START 0x13B100
388#define TRNQADRX_END 0x13B13C
389#define TRNQTIMX_START 0x13B200
390#define TRNQTIMX_END 0x13B23C
391#define TRNQAPARMX_START 0x13B300
392#define TRNQAPARMX_END 0x13B33C
393
394#define TRNQCNT 0x13B400
395#define TRNCTL 0x13B404
396#define TRNIS 0x13B408
397#define TRNCURTS 0x13B40C
398
399#define AMOP_START 0x140000
400#define AMOPLO 0x140000
401#define AMOPHI 0x140004
402#define AMOP_END 0x147FFC
403#define PMOP_START 0x148000
404#define PMOPLO 0x148000
405#define PMOPHI 0x148004
406#define PMOP_END 0x14FFFC
407#define PCURR_START 0x150000
408#define PCURR_END 0x153FFC
409#define PTRAG_START 0x154000
410#define PTRAG_END 0x157FFC
411#define PSR_START 0x158000
412#define PSR_END 0x15BFFC
413
414#define PFSTAT4SEG_START 0x160000
415#define PFSTAT4SEG_END 0x160BFC
416#define PFSTAT2SEG_START 0x160C00
417#define PFSTAT2SEG_END 0x1617FC
418#define PFTARG4SEG_START 0x164000
419#define PFTARG4SEG_END 0x164BFC
420#define PFTARG2SEG_START 0x164C00
421#define PFTARG2SEG_END 0x1657FC
422#define PFSR4SEG_START 0x168000
423#define PFSR4SEG_END 0x168BFC
424#define PFSR2SEG_START 0x168C00
425#define PFSR2SEG_END 0x1697FC
426#define PCURRMS4SEG_START 0x16C000
427#define PCURRMS4SEG_END 0x16CCFC
428#define PCURRMS2SEG_START 0x16CC00
429#define PCURRMS2SEG_END 0x16D7FC
430#define PTARGMS4SEG_START 0x170000
431#define PTARGMS4SEG_END 0x172FFC
432#define PTARGMS2SEG_START 0x173000
433#define PTARGMS2SEG_END 0x1747FC
434#define PSRMS4SEG_START 0x170000
435#define PSRMS4SEG_END 0x172FFC
436#define PSRMS2SEG_START 0x173000
437#define PSRMS2SEG_END 0x1747FC
438
439#define PRING_LO_START 0x190000
440#define PRING_LO_END 0x193FFC
441#define PRING_HI_START 0x194000
442#define PRING_HI_END 0x197FFC
443#define PRING_LO_HI_START 0x198000
444#define PRING_LO_HI 0x198000
445#define PRING_LO_HI_END 0x19BFFC
446
447#define PINTFIFO 0x1A0000
448#define SRCCTL 0x1B0000
449#define SRCCCR 0x1B0004
450#define SRCIMAP 0x1B0008
451#define SRCODDC 0x1B000C
452#define SRCCA 0x1B0010
453#define SRCCF 0x1B0014
454#define SRCSA 0x1B0018
455#define SRCLA 0x1B001C
456#define SRCCTLSWR 0x1B0020
457
458/* SRC HERE */
459#define SRCALBA 0x1B002C
460#define SRCMCTL 0x1B012C
461#define SRCCERR 0x1B022C
462#define SRCITB 0x1B032C
463#define SRCIPM 0x1B082C
464#define SRCIP 0x1B102C
465#define SRCENBSTAT 0x1B202C
466#define SRCENBLO 0x1B212C
467#define SRCENBHI 0x1B222C
468#define SRCENBS 0x1B232C
469#define SRCENB 0x1B282C
470#define SRCENB07 0x1B282C
471#define SRCENBS07 0x1B302C
472
473#define SRCDN0Z 0x1B0030
474#define SRCDN0Z0 0x1B0030
475#define SRCDN0Z1 0x1B0034
476#define SRCDN0Z2 0x1B0038
477#define SRCDN0Z3 0x1B003C
478#define SRCDN1Z 0x1B0040
479#define SRCDN1Z0 0x1B0040
480#define SRCDN1Z1 0x1B0044
481#define SRCDN1Z2 0x1B0048
482#define SRCDN1Z3 0x1B004C
483#define SRCDN1Z4 0x1B0050
484#define SRCDN1Z5 0x1B0054
485#define SRCDN1Z6 0x1B0058
486#define SRCDN1Z7 0x1B005C
487#define SRCUPZ 0x1B0060
488#define SRCUPZ0 0x1B0060
489#define SRCUPZ1 0x1B0064
490#define SRCUPZ2 0x1B0068
491#define SRCUPZ3 0x1B006C
492#define SRCUPZ4 0x1B0070
493#define SRCUPZ5 0x1B0074
494#define SRCUPZ6 0x1B0078
495#define SRCUPZ7 0x1B007C
496#define SRCCD0 0x1B0080
497#define SRCCD1 0x1B0084
498#define SRCCD2 0x1B0088
499#define SRCCD3 0x1B008C
500#define SRCCD4 0x1B0090
501#define SRCCD5 0x1B0094
502#define SRCCD6 0x1B0098
503#define SRCCD7 0x1B009C
504#define SRCCD8 0x1B00A0
505#define SRCCD9 0x1B00A4
506#define SRCCDA 0x1B00A8
507#define SRCCDB 0x1B00AC
508#define SRCCDC 0x1B00B0
509#define SRCCDD 0x1B00B4
510#define SRCCDE 0x1B00B8
511#define SRCCDF 0x1B00BC
512#define SRCCD10 0x1B00C0
513#define SRCCD11 0x1B00C4
514#define SRCCD12 0x1B00C8
515#define SRCCD13 0x1B00CC
516#define SRCCD14 0x1B00D0
517#define SRCCD15 0x1B00D4
518#define SRCCD16 0x1B00D8
519#define SRCCD17 0x1B00DC
520#define SRCCD18 0x1B00E0
521#define SRCCD19 0x1B00E4
522#define SRCCD1A 0x1B00E8
523#define SRCCD1B 0x1B00EC
524#define SRCCD1C 0x1B00F0
525#define SRCCD1D 0x1B00F4
526#define SRCCD1E 0x1B00F8
527#define SRCCD1F 0x1B00FC
528
529#define SRCCONTRBLOCK_START 0x1B0100
530#define SRCCONTRBLOCK_END 0x1BFFFC
531#define FILTOP_START 0x1C0000
532#define FILTOP_END 0x1C05FC
533#define FILTIMAP_START 0x1C0800
534#define FILTIMAP_END 0x1C0DFC
535#define FILTZ1_START 0x1C1000
536#define FILTZ1_END 0x1C15FC
537#define FILTZ2_START 0x1C1800
538#define FILTZ2_END 0x1C1DFC
539#define DAOIMAP_START 0x1C5000
540#define DAOIMAP 0x1C5000
541#define DAOIMAP_END 0x1C5124
542
543#define AC97D 0x1C5400
544#define AC97A 0x1C5404
545#define AC97CTL 0x1C5408
546#define I2SCTL 0x1C5420
547
548#define SPOS 0x1C5440
549#define SPOSA 0x1C5440
550#define SPOSB 0x1C5444
551#define SPOSC 0x1C5448
552#define SPOSD 0x1C544C
553
554#define SPISA 0x1C5450
555#define SPISB 0x1C5454
556#define SPISC 0x1C5458
557#define SPISD 0x1C545C
558
559#define SPFSCTL 0x1C5460
560
561#define SPFS0 0x1C5468
562#define SPFS1 0x1C546C
563#define SPFS2 0x1C5470
564#define SPFS3 0x1C5474
565#define SPFS4 0x1C5478
566#define SPFS5 0x1C547C
567
568#define SPOCTL 0x1C5480
569#define SPICTL 0x1C5484
570#define SPISTS 0x1C5488
571#define SPINTP 0x1C548C
572#define SPINTE 0x1C5490
573#define SPUTCTLAB 0x1C5494
574#define SPUTCTLCD 0x1C5498
575
576#define SRTSPA 0x1C54C0
577#define SRTSPB 0x1C54C4
578#define SRTSPC 0x1C54C8
579#define SRTSPD 0x1C54CC
580
581#define SRTSCTL 0x1C54D0
582#define SRTSCTLA 0x1C54D0
583#define SRTSCTLB 0x1C54D4
584#define SRTSCTLC 0x1C54D8
585#define SRTSCTLD 0x1C54DC
586
587#define SRTI2S 0x1C54E0
588#define SRTICTL 0x1C54F0
589
590#define WC 0x1C6000
591#define TIMR 0x1C6004
592
593#define GIP 0x1C6010
594#define GIE 0x1C6014
595#define DIE 0x1C6018
596#define DIC 0x1C601C
597#define GPIO 0x1C6020
598#define GPIOCTL 0x1C6024
599#define GPIP 0x1C6028
600#define GPIE 0x1C602C
601#define DSPINT0 0x1C6030
602#define DSPEIOC 0x1C6034
603#define MUADAT 0x1C6040
604#define MUACMD 0x1C6044
605#define MUASTAT 0x1C6044
606#define MUBDAT 0x1C6048
607#define MUBCMD 0x1C604C
608#define MUBSTAT 0x1C604C
609#define UARTCMA 0x1C6050
610#define UARTCMB 0x1C6054
611#define UARTIP 0x1C6058
612#define UARTIE 0x1C605C
613#define PLLCTL 0x1C6060
614#define PLLDCD 0x1C6064
615#define GCTL 0x1C6070
616#define ID0 0x1C6080
617#define ID1 0x1C6084
618#define ID2 0x1C6088
619#define ID3 0x1C608C
620#define SDRCTL 0x1C7000
621
622
623#define I2SA_L 0x0L
624#define I2SA_R 0x1L
625#define I2SB_L 0x8L
626#define I2SB_R 0x9L
627#define I2SC_L 0x10L
628#define I2SC_R 0x11L
629#define I2SD_L 0x18L
630#define I2SD_R 0x19L
631
632#endif /* CT20K1REG_H */
633
634
diff --git a/sound/pci/ctxfi/ct20k2reg.h b/sound/pci/ctxfi/ct20k2reg.h
new file mode 100644
index 000000000000..2d07986f57cc
--- /dev/null
+++ b/sound/pci/ctxfi/ct20k2reg.h
@@ -0,0 +1,85 @@
1/**
2 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
3 *
4 * This source file is released under GPL v2 license (no other versions).
5 * See the COPYING file included in the main directory of this source
6 * distribution for the license terms and conditions.
7 */
8
9#ifndef _20K2REGISTERS_H_
10#define _20K2REGISTERS_H_
11
12
13/* Timer Registers */
14#define TIMER_TIMR 0x1B7004
15#define INTERRUPT_GIP 0x1B7010
16#define INTERRUPT_GIE 0x1B7014
17
18/* I2C Registers */
19#define I2C_IF_ADDRESS 0x1B9000
20#define I2C_IF_WDATA 0x1B9004
21#define I2C_IF_RDATA 0x1B9008
22#define I2C_IF_STATUS 0x1B900C
23#define I2C_IF_WLOCK 0x1B9010
24
25/* Global Control Registers */
26#define GLOBAL_CNTL_GCTL 0x1B7090
27
28/* PLL Registers */
29#define PLL_CTL 0x1B7080
30#define PLL_STAT 0x1B7084
31#define PLL_ENB 0x1B7088
32
33/* SRC Registers */
34#define SRC_CTL 0x1A0000 /* 0x1A0000 + (256 * Chn) */
35#define SRC_CCR 0x1A0004 /* 0x1A0004 + (256 * Chn) */
36#define SRC_IMAP 0x1A0008 /* 0x1A0008 + (256 * Chn) */
37#define SRC_CA 0x1A0010 /* 0x1A0010 + (256 * Chn) */
38#define SRC_CF 0x1A0014 /* 0x1A0014 + (256 * Chn) */
39#define SRC_SA 0x1A0018 /* 0x1A0018 + (256 * Chn) */
40#define SRC_LA 0x1A001C /* 0x1A001C + (256 * Chn) */
41#define SRC_CTLSWR 0x1A0020 /* 0x1A0020 + (256 * Chn) */
42#define SRC_CD 0x1A0080 /* 0x1A0080 + (256 * Chn) + (4 * Regn) */
43#define SRC_MCTL 0x1A012C
44#define SRC_IP 0x1A102C /* 0x1A102C + (256 * Regn) */
45#define SRC_ENB 0x1A282C /* 0x1A282C + (256 * Regn) */
46#define SRC_ENBSTAT 0x1A202C
47#define SRC_ENBSA 0x1A232C
48#define SRC_DN0Z 0x1A0030
49#define SRC_DN1Z 0x1A0040
50#define SRC_UPZ 0x1A0060
51
52/* GPIO Registers */
53#define GPIO_DATA 0x1B7020
54#define GPIO_CTRL 0x1B7024
55
56/* Virtual memory registers */
57#define VMEM_PTPAL 0x1C6300 /* 0x1C6300 + (16 * Chn) */
58#define VMEM_PTPAH 0x1C6304 /* 0x1C6304 + (16 * Chn) */
59#define VMEM_CTL 0x1C7000
60
61/* Transport Registers */
62#define TRANSPORT_ENB 0x1B6000
63#define TRANSPORT_CTL 0x1B6004
64#define TRANSPORT_INT 0x1B6008
65
66/* Audio IO */
67#define AUDIO_IO_AIM 0x1B5000 /* 0x1B5000 + (0x04 * Chn) */
68#define AUDIO_IO_TX_CTL 0x1B5400 /* 0x1B5400 + (0x40 * Chn) */
69#define AUDIO_IO_TX_CSTAT_L 0x1B5408 /* 0x1B5408 + (0x40 * Chn) */
70#define AUDIO_IO_TX_CSTAT_H 0x1B540C /* 0x1B540C + (0x40 * Chn) */
71#define AUDIO_IO_RX_CTL 0x1B5410 /* 0x1B5410 + (0x40 * Chn) */
72#define AUDIO_IO_RX_SRT_CTL 0x1B5420 /* 0x1B5420 + (0x40 * Chn) */
73#define AUDIO_IO_MCLK 0x1B5600
74#define AUDIO_IO_TX_BLRCLK 0x1B5604
75#define AUDIO_IO_RX_BLRCLK 0x1B5608
76
77/* Mixer */
78#define MIXER_AMOPLO 0x130000 /* 0x130000 + (8 * Chn) [4095 : 0] */
79#define MIXER_AMOPHI 0x130004 /* 0x130004 + (8 * Chn) [4095 : 0] */
80#define MIXER_PRING_LO_HI 0x188000 /* 0x188000 + (4 * Chn) [4095 : 0] */
81#define MIXER_PMOPLO 0x138000 /* 0x138000 + (8 * Chn) [4095 : 0] */
82#define MIXER_PMOPHI 0x138004 /* 0x138004 + (8 * Chn) [4095 : 0] */
83#define MIXER_AR_ENABLE 0x19000C
84
85#endif
diff --git a/sound/pci/ctxfi/ctamixer.c b/sound/pci/ctxfi/ctamixer.c
new file mode 100644
index 000000000000..119791aa70eb
--- /dev/null
+++ b/sound/pci/ctxfi/ctamixer.c
@@ -0,0 +1,488 @@
1/**
2 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
3 *
4 * This source file is released under GPL v2 license (no other versions).
5 * See the COPYING file included in the main directory of this source
6 * distribution for the license terms and conditions.
7 *
8 * @File ctamixer.c
9 *
10 * @Brief
11 * This file contains the implementation of the Audio Mixer
12 * resource management object.
13 *
14 * @Author Liu Chun
15 * @Date May 21 2008
16 *
17 */
18
19#include "ctamixer.h"
20#include "cthardware.h"
21#include <linux/slab.h>
22
23#define AMIXER_RESOURCE_NUM 256
24#define SUM_RESOURCE_NUM 256
25
26#define AMIXER_Y_IMMEDIATE 1
27
28#define BLANK_SLOT 4094
29
30static int amixer_master(struct rsc *rsc)
31{
32 rsc->conj = 0;
33 return rsc->idx = container_of(rsc, struct amixer, rsc)->idx[0];
34}
35
36static int amixer_next_conj(struct rsc *rsc)
37{
38 rsc->conj++;
39 return container_of(rsc, struct amixer, rsc)->idx[rsc->conj];
40}
41
42static int amixer_index(const struct rsc *rsc)
43{
44 return container_of(rsc, struct amixer, rsc)->idx[rsc->conj];
45}
46
47static int amixer_output_slot(const struct rsc *rsc)
48{
49 return (amixer_index(rsc) << 4) + 0x4;
50}
51
52static struct rsc_ops amixer_basic_rsc_ops = {
53 .master = amixer_master,
54 .next_conj = amixer_next_conj,
55 .index = amixer_index,
56 .output_slot = amixer_output_slot,
57};
58
59static int amixer_set_input(struct amixer *amixer, struct rsc *rsc)
60{
61 struct hw *hw = NULL;
62
63 hw = (struct hw *)amixer->rsc.hw;
64 hw->amixer_set_mode(amixer->rsc.ctrl_blk, AMIXER_Y_IMMEDIATE);
65 amixer->input = rsc;
66 if (NULL == rsc)
67 hw->amixer_set_x(amixer->rsc.ctrl_blk, BLANK_SLOT);
68 else
69 hw->amixer_set_x(amixer->rsc.ctrl_blk,
70 rsc->ops->output_slot(rsc));
71
72 return 0;
73}
74
75/* y is a 14-bit immediate constant */
76static int amixer_set_y(struct amixer *amixer, unsigned int y)
77{
78 struct hw *hw = NULL;
79
80 hw = (struct hw *)amixer->rsc.hw;
81 hw->amixer_set_y(amixer->rsc.ctrl_blk, y);
82
83 return 0;
84}
85
86static int amixer_set_invalid_squash(struct amixer *amixer, unsigned int iv)
87{
88 struct hw *hw = NULL;
89
90 hw = (struct hw *)amixer->rsc.hw;
91 hw->amixer_set_iv(amixer->rsc.ctrl_blk, iv);
92
93 return 0;
94}
95
96static int amixer_set_sum(struct amixer *amixer, struct sum *sum)
97{
98 struct hw *hw = NULL;
99
100 hw = (struct hw *)amixer->rsc.hw;
101 amixer->sum = sum;
102 if (NULL == sum) {
103 hw->amixer_set_se(amixer->rsc.ctrl_blk, 0);
104 } else {
105 hw->amixer_set_se(amixer->rsc.ctrl_blk, 1);
106 hw->amixer_set_sadr(amixer->rsc.ctrl_blk,
107 sum->rsc.ops->index(&sum->rsc));
108 }
109
110 return 0;
111}
112
113static int amixer_commit_write(struct amixer *amixer)
114{
115 struct hw *hw = NULL;
116 unsigned int index = 0;
117 int i = 0;
118 struct rsc *input = NULL;
119 struct sum *sum = NULL;
120
121 hw = (struct hw *)amixer->rsc.hw;
122 input = amixer->input;
123 sum = amixer->sum;
124
125 /* Program master and conjugate resources */
126 amixer->rsc.ops->master(&amixer->rsc);
127 if (NULL != input)
128 input->ops->master(input);
129
130 if (NULL != sum)
131 sum->rsc.ops->master(&sum->rsc);
132
133 for (i = 0; i < amixer->rsc.msr; i++) {
134 hw->amixer_set_dirty_all(amixer->rsc.ctrl_blk);
135 if (NULL != input) {
136 hw->amixer_set_x(amixer->rsc.ctrl_blk,
137 input->ops->output_slot(input));
138 input->ops->next_conj(input);
139 }
140 if (NULL != sum) {
141 hw->amixer_set_sadr(amixer->rsc.ctrl_blk,
142 sum->rsc.ops->index(&sum->rsc));
143 sum->rsc.ops->next_conj(&sum->rsc);
144 }
145 index = amixer->rsc.ops->output_slot(&amixer->rsc);
146 hw->amixer_commit_write(hw, index, amixer->rsc.ctrl_blk);
147 amixer->rsc.ops->next_conj(&amixer->rsc);
148 }
149 amixer->rsc.ops->master(&amixer->rsc);
150 if (NULL != input)
151 input->ops->master(input);
152
153 if (NULL != sum)
154 sum->rsc.ops->master(&sum->rsc);
155
156 return 0;
157}
158
159static int amixer_commit_raw_write(struct amixer *amixer)
160{
161 struct hw *hw = NULL;
162 unsigned int index = 0;
163
164 hw = (struct hw *)amixer->rsc.hw;
165 index = amixer->rsc.ops->output_slot(&amixer->rsc);
166 hw->amixer_commit_write(hw, index, amixer->rsc.ctrl_blk);
167
168 return 0;
169}
170
171static int amixer_get_y(struct amixer *amixer)
172{
173 struct hw *hw = NULL;
174
175 hw = (struct hw *)amixer->rsc.hw;
176 return hw->amixer_get_y(amixer->rsc.ctrl_blk);
177}
178
179static int amixer_setup(struct amixer *amixer, struct rsc *input,
180 unsigned int scale, struct sum *sum)
181{
182 amixer_set_input(amixer, input);
183 amixer_set_y(amixer, scale);
184 amixer_set_sum(amixer, sum);
185 amixer_commit_write(amixer);
186 return 0;
187}
188
189static struct amixer_rsc_ops amixer_ops = {
190 .set_input = amixer_set_input,
191 .set_invalid_squash = amixer_set_invalid_squash,
192 .set_scale = amixer_set_y,
193 .set_sum = amixer_set_sum,
194 .commit_write = amixer_commit_write,
195 .commit_raw_write = amixer_commit_raw_write,
196 .setup = amixer_setup,
197 .get_scale = amixer_get_y,
198};
199
200static int amixer_rsc_init(struct amixer *amixer,
201 const struct amixer_desc *desc,
202 struct amixer_mgr *mgr)
203{
204 int err = 0;
205
206 err = rsc_init(&amixer->rsc, amixer->idx[0],
207 AMIXER, desc->msr, mgr->mgr.hw);
208 if (err)
209 return err;
210
211 /* Set amixer specific operations */
212 amixer->rsc.ops = &amixer_basic_rsc_ops;
213 amixer->ops = &amixer_ops;
214 amixer->input = NULL;
215 amixer->sum = NULL;
216
217 amixer_setup(amixer, NULL, 0, NULL);
218
219 return 0;
220}
221
222static int amixer_rsc_uninit(struct amixer *amixer)
223{
224 amixer_setup(amixer, NULL, 0, NULL);
225 rsc_uninit(&amixer->rsc);
226 amixer->ops = NULL;
227 amixer->input = NULL;
228 amixer->sum = NULL;
229 return 0;
230}
231
232static int get_amixer_rsc(struct amixer_mgr *mgr,
233 const struct amixer_desc *desc,
234 struct amixer **ramixer)
235{
236 int err = 0, i = 0;
237 unsigned int idx = 0;
238 struct amixer *amixer = NULL;
239 unsigned long flags;
240
241 *ramixer = NULL;
242
243 /* Allocate mem for amixer resource */
244 amixer = kzalloc(sizeof(*amixer), GFP_KERNEL);
245 if (NULL == amixer) {
246 err = -ENOMEM;
247 return err;
248 }
249
250 /* Check whether there are sufficient
251 * amixer resources to meet request. */
252 spin_lock_irqsave(&mgr->mgr_lock, flags);
253 for (i = 0; i < desc->msr; i++) {
254 err = mgr_get_resource(&mgr->mgr, 1, &idx);
255 if (err)
256 break;
257
258 amixer->idx[i] = idx;
259 }
260 spin_unlock_irqrestore(&mgr->mgr_lock, flags);
261 if (err) {
262 printk(KERN_ERR "Can't meet AMIXER resource request!\n");
263 goto error;
264 }
265
266 err = amixer_rsc_init(amixer, desc, mgr);
267 if (err)
268 goto error;
269
270 *ramixer = amixer;
271
272 return 0;
273
274error:
275 spin_lock_irqsave(&mgr->mgr_lock, flags);
276 for (i--; i >= 0; i--)
277 mgr_put_resource(&mgr->mgr, 1, amixer->idx[i]);
278
279 spin_unlock_irqrestore(&mgr->mgr_lock, flags);
280 kfree(amixer);
281 return err;
282}
283
284static int put_amixer_rsc(struct amixer_mgr *mgr, struct amixer *amixer)
285{
286 unsigned long flags;
287 int i = 0;
288
289 spin_lock_irqsave(&mgr->mgr_lock, flags);
290 for (i = 0; i < amixer->rsc.msr; i++)
291 mgr_put_resource(&mgr->mgr, 1, amixer->idx[i]);
292
293 spin_unlock_irqrestore(&mgr->mgr_lock, flags);
294 amixer_rsc_uninit(amixer);
295 kfree(amixer);
296
297 return 0;
298}
299
300int amixer_mgr_create(void *hw, struct amixer_mgr **ramixer_mgr)
301{
302 int err = 0;
303 struct amixer_mgr *amixer_mgr;
304
305 *ramixer_mgr = NULL;
306 amixer_mgr = kzalloc(sizeof(*amixer_mgr), GFP_KERNEL);
307 if (NULL == amixer_mgr)
308 return -ENOMEM;
309
310 err = rsc_mgr_init(&amixer_mgr->mgr, AMIXER, AMIXER_RESOURCE_NUM, hw);
311 if (err)
312 goto error;
313
314 spin_lock_init(&amixer_mgr->mgr_lock);
315
316 amixer_mgr->get_amixer = get_amixer_rsc;
317 amixer_mgr->put_amixer = put_amixer_rsc;
318
319 *ramixer_mgr = amixer_mgr;
320
321 return 0;
322
323error:
324 kfree(amixer_mgr);
325 return err;
326}
327
328int amixer_mgr_destroy(struct amixer_mgr *amixer_mgr)
329{
330 rsc_mgr_uninit(&amixer_mgr->mgr);
331 kfree(amixer_mgr);
332 return 0;
333}
334
335/* SUM resource management */
336
337static int sum_master(struct rsc *rsc)
338{
339 rsc->conj = 0;
340 return rsc->idx = container_of(rsc, struct sum, rsc)->idx[0];
341}
342
343static int sum_next_conj(struct rsc *rsc)
344{
345 rsc->conj++;
346 return container_of(rsc, struct sum, rsc)->idx[rsc->conj];
347}
348
349static int sum_index(const struct rsc *rsc)
350{
351 return container_of(rsc, struct sum, rsc)->idx[rsc->conj];
352}
353
354static int sum_output_slot(const struct rsc *rsc)
355{
356 return (sum_index(rsc) << 4) + 0xc;
357}
358
359static struct rsc_ops sum_basic_rsc_ops = {
360 .master = sum_master,
361 .next_conj = sum_next_conj,
362 .index = sum_index,
363 .output_slot = sum_output_slot,
364};
365
366static int sum_rsc_init(struct sum *sum,
367 const struct sum_desc *desc,
368 struct sum_mgr *mgr)
369{
370 int err = 0;
371
372 err = rsc_init(&sum->rsc, sum->idx[0], SUM, desc->msr, mgr->mgr.hw);
373 if (err)
374 return err;
375
376 sum->rsc.ops = &sum_basic_rsc_ops;
377
378 return 0;
379}
380
381static int sum_rsc_uninit(struct sum *sum)
382{
383 rsc_uninit(&sum->rsc);
384 return 0;
385}
386
387static int get_sum_rsc(struct sum_mgr *mgr,
388 const struct sum_desc *desc,
389 struct sum **rsum)
390{
391 int err = 0, i = 0;
392 unsigned int idx = 0;
393 struct sum *sum = NULL;
394 unsigned long flags;
395
396 *rsum = NULL;
397
398 /* Allocate mem for sum resource */
399 sum = kzalloc(sizeof(*sum), GFP_KERNEL);
400 if (NULL == sum) {
401 err = -ENOMEM;
402 return err;
403 }
404
405 /* Check whether there are sufficient sum resources to meet request. */
406 spin_lock_irqsave(&mgr->mgr_lock, flags);
407 for (i = 0; i < desc->msr; i++) {
408 err = mgr_get_resource(&mgr->mgr, 1, &idx);
409 if (err)
410 break;
411
412 sum->idx[i] = idx;
413 }
414 spin_unlock_irqrestore(&mgr->mgr_lock, flags);
415 if (err) {
416 printk(KERN_ERR "Can't meet SUM resource request!\n");
417 goto error;
418 }
419
420 err = sum_rsc_init(sum, desc, mgr);
421 if (err)
422 goto error;
423
424 *rsum = sum;
425
426 return 0;
427
428error:
429 spin_lock_irqsave(&mgr->mgr_lock, flags);
430 for (i--; i >= 0; i--)
431 mgr_put_resource(&mgr->mgr, 1, sum->idx[i]);
432
433 spin_unlock_irqrestore(&mgr->mgr_lock, flags);
434 kfree(sum);
435 return err;
436}
437
438static int put_sum_rsc(struct sum_mgr *mgr, struct sum *sum)
439{
440 unsigned long flags;
441 int i = 0;
442
443 spin_lock_irqsave(&mgr->mgr_lock, flags);
444 for (i = 0; i < sum->rsc.msr; i++)
445 mgr_put_resource(&mgr->mgr, 1, sum->idx[i]);
446
447 spin_unlock_irqrestore(&mgr->mgr_lock, flags);
448 sum_rsc_uninit(sum);
449 kfree(sum);
450
451 return 0;
452}
453
454int sum_mgr_create(void *hw, struct sum_mgr **rsum_mgr)
455{
456 int err = 0;
457 struct sum_mgr *sum_mgr;
458
459 *rsum_mgr = NULL;
460 sum_mgr = kzalloc(sizeof(*sum_mgr), GFP_KERNEL);
461 if (NULL == sum_mgr)
462 return -ENOMEM;
463
464 err = rsc_mgr_init(&sum_mgr->mgr, SUM, SUM_RESOURCE_NUM, hw);
465 if (err)
466 goto error;
467
468 spin_lock_init(&sum_mgr->mgr_lock);
469
470 sum_mgr->get_sum = get_sum_rsc;
471 sum_mgr->put_sum = put_sum_rsc;
472
473 *rsum_mgr = sum_mgr;
474
475 return 0;
476
477error:
478 kfree(sum_mgr);
479 return err;
480}
481
482int sum_mgr_destroy(struct sum_mgr *sum_mgr)
483{
484 rsc_mgr_uninit(&sum_mgr->mgr);
485 kfree(sum_mgr);
486 return 0;
487}
488
diff --git a/sound/pci/ctxfi/ctamixer.h b/sound/pci/ctxfi/ctamixer.h
new file mode 100644
index 000000000000..cc49e5ab4750
--- /dev/null
+++ b/sound/pci/ctxfi/ctamixer.h
@@ -0,0 +1,96 @@
1/**
2 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
3 *
4 * This source file is released under GPL v2 license (no other versions).
5 * See the COPYING file included in the main directory of this source
6 * distribution for the license terms and conditions.
7 *
8 * @File ctamixer.h
9 *
10 * @Brief
11 * This file contains the definition of the Audio Mixer
12 * resource management object.
13 *
14 * @Author Liu Chun
15 * @Date May 21 2008
16 *
17 */
18
19#ifndef CTAMIXER_H
20#define CTAMIXER_H
21
22#include "ctresource.h"
23#include <linux/spinlock.h>
24
25/* Define the descriptor of a summation node resource */
26struct sum {
27 struct rsc rsc; /* Basic resource info */
28 unsigned char idx[8];
29};
30
31/* Define sum resource request description info */
32struct sum_desc {
33 unsigned int msr;
34};
35
36struct sum_mgr {
37 struct rsc_mgr mgr; /* Basic resource manager info */
38 spinlock_t mgr_lock;
39
40 /* request one sum resource */
41 int (*get_sum)(struct sum_mgr *mgr,
42 const struct sum_desc *desc, struct sum **rsum);
43 /* return one sum resource */
44 int (*put_sum)(struct sum_mgr *mgr, struct sum *sum);
45};
46
47/* Constructor and destructor of daio resource manager */
48int sum_mgr_create(void *hw, struct sum_mgr **rsum_mgr);
49int sum_mgr_destroy(struct sum_mgr *sum_mgr);
50
51/* Define the descriptor of a amixer resource */
52struct amixer_rsc_ops;
53
54struct amixer {
55 struct rsc rsc; /* Basic resource info */
56 unsigned char idx[8];
57 struct rsc *input; /* pointer to a resource acting as source */
58 struct sum *sum; /* Put amixer output to this summation node */
59 struct amixer_rsc_ops *ops; /* AMixer specific operations */
60};
61
62struct amixer_rsc_ops {
63 int (*set_input)(struct amixer *amixer, struct rsc *rsc);
64 int (*set_scale)(struct amixer *amixer, unsigned int scale);
65 int (*set_invalid_squash)(struct amixer *amixer, unsigned int iv);
66 int (*set_sum)(struct amixer *amixer, struct sum *sum);
67 int (*commit_write)(struct amixer *amixer);
68 /* Only for interleaved recording */
69 int (*commit_raw_write)(struct amixer *amixer);
70 int (*setup)(struct amixer *amixer, struct rsc *input,
71 unsigned int scale, struct sum *sum);
72 int (*get_scale)(struct amixer *amixer);
73};
74
75/* Define amixer resource request description info */
76struct amixer_desc {
77 unsigned int msr;
78};
79
80struct amixer_mgr {
81 struct rsc_mgr mgr; /* Basic resource manager info */
82 spinlock_t mgr_lock;
83
84 /* request one amixer resource */
85 int (*get_amixer)(struct amixer_mgr *mgr,
86 const struct amixer_desc *desc,
87 struct amixer **ramixer);
88 /* return one amixer resource */
89 int (*put_amixer)(struct amixer_mgr *mgr, struct amixer *amixer);
90};
91
92/* Constructor and destructor of amixer resource manager */
93int amixer_mgr_create(void *hw, struct amixer_mgr **ramixer_mgr);
94int amixer_mgr_destroy(struct amixer_mgr *amixer_mgr);
95
96#endif /* CTAMIXER_H */
diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c
new file mode 100644
index 000000000000..5f35374863fb
--- /dev/null
+++ b/sound/pci/ctxfi/ctatc.c
@@ -0,0 +1,1605 @@
1/**
2 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
3 *
4 * This source file is released under GPL v2 license (no other versions).
5 * See the COPYING file included in the main directory of this source
6 * distribution for the license terms and conditions.
7 *
8 * @File ctatc.c
9 *
10 * @Brief
11 * This file contains the implementation of the device resource management
12 * object.
13 *
14 * @Author Liu Chun
15 * @Date Mar 28 2008
16 */
17
18#include "ctatc.h"
19#include "ctpcm.h"
20#include "ctmixer.h"
21#include "ctdrv.h"
22#include "cthardware.h"
23#include "ctsrc.h"
24#include "ctamixer.h"
25#include "ctdaio.h"
26#include <linux/delay.h>
27#include <sound/pcm.h>
28#include <sound/control.h>
29#include <sound/asoundef.h>
30
31#define MONO_SUM_SCALE 0x19a8 /* 2^(-0.5) in 14-bit floating format */
32#define DAIONUM 7
33#define MAX_MULTI_CHN 8
34
35#define IEC958_DEFAULT_CON ((IEC958_AES0_NONAUDIO \
36 | IEC958_AES0_CON_NOT_COPYRIGHT) \
37 | ((IEC958_AES1_CON_MIXER \
38 | IEC958_AES1_CON_ORIGINAL) << 8) \
39 | (0x10 << 16) \
40 | ((IEC958_AES3_CON_FS_48000) << 24))
41
42static const struct ct_atc_chip_sub_details atc_sub_details[NUM_CTCARDS] = {
43 [CTSB0760] = {.subsys = PCI_SUBSYS_CREATIVE_SB0760,
44 .nm_model = "SB076x"},
45 [CTHENDRIX] = {.subsys = PCI_SUBSYS_CREATIVE_HENDRIX,
46 .nm_model = "Hendrix"},
47 [CTSB08801] = {.subsys = PCI_SUBSYS_CREATIVE_SB08801,
48 .nm_model = "SB0880"},
49 [CTSB08802] = {.subsys = PCI_SUBSYS_CREATIVE_SB08802,
50 .nm_model = "SB0880"},
51 [CTSB08803] = {.subsys = PCI_SUBSYS_CREATIVE_SB08803,
52 .nm_model = "SB0880"}
53};
54
55static struct ct_atc_chip_details atc_chip_details[] = {
56 {.vendor = PCI_VENDOR_CREATIVE, .device = PCI_DEVICE_CREATIVE_20K1,
57 .sub_details = NULL,
58 .nm_card = "X-Fi 20k1"},
59 {.vendor = PCI_VENDOR_CREATIVE, .device = PCI_DEVICE_CREATIVE_20K2,
60 .sub_details = atc_sub_details,
61 .nm_card = "X-Fi 20k2"},
62 {} /* terminator */
63};
64
65static struct {
66 int (*create)(struct ct_atc *atc,
67 enum CTALSADEVS device, const char *device_name);
68 int (*destroy)(void *alsa_dev);
69 const char *public_name;
70} alsa_dev_funcs[NUM_CTALSADEVS] = {
71 [FRONT] = { .create = ct_alsa_pcm_create,
72 .destroy = NULL,
73 .public_name = "Front/WaveIn"},
74 [REAR] = { .create = ct_alsa_pcm_create,
75 .destroy = NULL,
76 .public_name = "Rear"},
77 [CLFE] = { .create = ct_alsa_pcm_create,
78 .destroy = NULL,
79 .public_name = "Center/LFE"},
80 [SURROUND] = { .create = ct_alsa_pcm_create,
81 .destroy = NULL,
82 .public_name = "Surround"},
83 [IEC958] = { .create = ct_alsa_pcm_create,
84 .destroy = NULL,
85 .public_name = "IEC958 Non-audio"},
86
87 [MIXER] = { .create = ct_alsa_mix_create,
88 .destroy = NULL,
89 .public_name = "Mixer"}
90};
91
92typedef int (*create_t)(void *, void **);
93typedef int (*destroy_t)(void *);
94
95static struct {
96 int (*create)(void *hw, void **rmgr);
97 int (*destroy)(void *mgr);
98} rsc_mgr_funcs[NUM_RSCTYP] = {
99 [SRC] = { .create = (create_t)src_mgr_create,
100 .destroy = (destroy_t)src_mgr_destroy },
101 [SRCIMP] = { .create = (create_t)srcimp_mgr_create,
102 .destroy = (destroy_t)srcimp_mgr_destroy },
103 [AMIXER] = { .create = (create_t)amixer_mgr_create,
104 .destroy = (destroy_t)amixer_mgr_destroy },
105 [SUM] = { .create = (create_t)sum_mgr_create,
106 .destroy = (destroy_t)sum_mgr_destroy },
107 [DAIO] = { .create = (create_t)daio_mgr_create,
108 .destroy = (destroy_t)daio_mgr_destroy }
109};
110
111static int
112atc_pcm_release_resources(struct ct_atc *atc, struct ct_atc_pcm *apcm);
113
114/* *
115 * Only mono and interleaved modes are supported now.
116 * Always allocates a contiguous channel block.
117 * */
118
119static int ct_map_audio_buffer(struct ct_atc *atc, struct ct_atc_pcm *apcm)
120{
121 unsigned long flags;
122 struct snd_pcm_runtime *runtime;
123 struct ct_vm *vm;
124
125 if (NULL == apcm->substream)
126 return 0;
127
128 runtime = apcm->substream->runtime;
129 vm = atc->vm;
130
131 spin_lock_irqsave(&atc->vm_lock, flags);
132 apcm->vm_block = vm->map(vm, runtime->dma_area, runtime->dma_bytes);
133 spin_unlock_irqrestore(&atc->vm_lock, flags);
134
135 if (NULL == apcm->vm_block)
136 return -ENOENT;
137
138 return 0;
139}
140
141static void ct_unmap_audio_buffer(struct ct_atc *atc, struct ct_atc_pcm *apcm)
142{
143 unsigned long flags;
144 struct ct_vm *vm;
145
146 if (NULL == apcm->vm_block)
147 return;
148
149 vm = atc->vm;
150
151 spin_lock_irqsave(&atc->vm_lock, flags);
152 vm->unmap(vm, apcm->vm_block);
153 spin_unlock_irqrestore(&atc->vm_lock, flags);
154
155 apcm->vm_block = NULL;
156}
157
158static unsigned long atc_get_ptp_phys(struct ct_atc *atc, int index)
159{
160 struct ct_vm *vm;
161 void *kvirt_addr;
162 unsigned long phys_addr;
163 unsigned long flags;
164
165 spin_lock_irqsave(&atc->vm_lock, flags);
166 vm = atc->vm;
167 kvirt_addr = vm->get_ptp_virt(vm, index);
168 if (kvirt_addr == NULL)
169 phys_addr = (~0UL);
170 else
171 phys_addr = virt_to_phys(kvirt_addr);
172
173 spin_unlock_irqrestore(&atc->vm_lock, flags);
174
175 return phys_addr;
176}
177
178static unsigned int convert_format(snd_pcm_format_t snd_format)
179{
180 switch (snd_format) {
181 case SNDRV_PCM_FORMAT_U8:
182 case SNDRV_PCM_FORMAT_S8:
183 return SRC_SF_U8;
184 case SNDRV_PCM_FORMAT_S16_LE:
185 case SNDRV_PCM_FORMAT_U16_LE:
186 return SRC_SF_S16;
187 case SNDRV_PCM_FORMAT_S24_3LE:
188 return SRC_SF_S24;
189 case SNDRV_PCM_FORMAT_S24_LE:
190 case SNDRV_PCM_FORMAT_S32_LE:
191 return SRC_SF_S32;
192 default:
193 printk(KERN_ERR "not recognized snd format is %d \n",
194 snd_format);
195 return SRC_SF_S16;
196 }
197}
198
199static unsigned int
200atc_get_pitch(unsigned int input_rate, unsigned int output_rate)
201{
202 unsigned int pitch = 0;
203 int b = 0;
204
205 /* get pitch and convert to fixed-point 8.24 format. */
206 pitch = (input_rate / output_rate) << 24;
207 input_rate %= output_rate;
208 input_rate /= 100;
209 output_rate /= 100;
210 for (b = 31; ((b >= 0) && !(input_rate >> b)); )
211 b--;
212
213 if (b >= 0) {
214 input_rate <<= (31 - b);
215 input_rate /= output_rate;
216 b = 24 - (31 - b);
217 if (b >= 0)
218 input_rate <<= b;
219 else
220 input_rate >>= -b;
221
222 pitch |= input_rate;
223 }
224
225 return pitch;
226}
227
228static int select_rom(unsigned int pitch)
229{
230 if ((pitch > 0x00428f5c) && (pitch < 0x01b851ec)) {
231 /* 0.26 <= pitch <= 1.72 */
232 return 1;
233 } else if ((0x01d66666 == pitch) || (0x01d66667 == pitch)) {
234 /* pitch == 1.8375 */
235 return 2;
236 } else if (0x02000000 == pitch) {
237 /* pitch == 2 */
238 return 3;
239 } else if ((pitch >= 0x0) && (pitch <= 0x08000000)) {
240 /* 0 <= pitch <= 8 */
241 return 0;
242 } else {
243 return -ENOENT;
244 }
245}
246
247static int atc_pcm_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm)
248{
249 struct src_mgr *src_mgr = atc->rsc_mgrs[SRC];
250 struct amixer_mgr *amixer_mgr = atc->rsc_mgrs[AMIXER];
251 struct src_desc desc = {0};
252 struct amixer_desc mix_dsc = {0};
253 struct src *src = NULL;
254 struct amixer *amixer = NULL;
255 int err = 0;
256 int n_amixer = apcm->substream->runtime->channels, i = 0;
257 int device = apcm->substream->pcm->device;
258 unsigned int pitch = 0;
259 unsigned long flags;
260
261 if (NULL != apcm->src) {
262 /* Prepared pcm playback */
263 return 0;
264 }
265
266 /* Get SRC resource */
267 desc.multi = apcm->substream->runtime->channels;
268 desc.msr = atc->msr;
269 desc.mode = MEMRD;
270 err = src_mgr->get_src(src_mgr, &desc, (struct src **)&apcm->src);
271 if (err)
272 goto error1;
273
274 pitch = atc_get_pitch(apcm->substream->runtime->rate,
275 (atc->rsr * atc->msr));
276 src = apcm->src;
277 src->ops->set_pitch(src, pitch);
278 src->ops->set_rom(src, select_rom(pitch));
279 src->ops->set_sf(src, convert_format(apcm->substream->runtime->format));
280 src->ops->set_pm(src, (src->ops->next_interleave(src) != NULL));
281
282 /* Get AMIXER resource */
283 n_amixer = (n_amixer < 2) ? 2 : n_amixer;
284 apcm->amixers = kzalloc(sizeof(void *)*n_amixer, GFP_KERNEL);
285 if (NULL == apcm->amixers) {
286 err = -ENOMEM;
287 goto error1;
288 }
289 mix_dsc.msr = atc->msr;
290 for (i = 0, apcm->n_amixer = 0; i < n_amixer; i++) {
291 err = amixer_mgr->get_amixer(amixer_mgr, &mix_dsc,
292 (struct amixer **)&apcm->amixers[i]);
293 if (err)
294 goto error1;
295
296 apcm->n_amixer++;
297 }
298
299 /* Set up device virtual mem map */
300 err = ct_map_audio_buffer(atc, apcm);
301 if (err < 0)
302 goto error1;
303
304 /* Connect resources */
305 src = apcm->src;
306 for (i = 0; i < n_amixer; i++) {
307 amixer = apcm->amixers[i];
308 spin_lock_irqsave(&atc->atc_lock, flags);
309 amixer->ops->setup(amixer, &src->rsc,
310 INIT_VOL, atc->pcm[i+device*2]);
311 spin_unlock_irqrestore(&atc->atc_lock, flags);
312 src = src->ops->next_interleave(src);
313 if (NULL == src)
314 src = apcm->src;
315 }
316
317 return 0;
318
319error1:
320 atc_pcm_release_resources(atc, apcm);
321 return err;
322}
323
324static int
325atc_pcm_release_resources(struct ct_atc *atc, struct ct_atc_pcm *apcm)
326{
327 struct src_mgr *src_mgr = atc->rsc_mgrs[SRC];
328 struct srcimp_mgr *srcimp_mgr = atc->rsc_mgrs[SRCIMP];
329 struct amixer_mgr *amixer_mgr = atc->rsc_mgrs[AMIXER];
330 struct sum_mgr *sum_mgr = atc->rsc_mgrs[SUM];
331 struct srcimp *srcimp = NULL;
332 int i = 0;
333
334 if (NULL != apcm->srcimps) {
335 for (i = 0; i < apcm->n_srcimp; i++) {
336 srcimp = apcm->srcimps[i];
337 srcimp->ops->unmap(srcimp);
338 srcimp_mgr->put_srcimp(srcimp_mgr, srcimp);
339 apcm->srcimps[i] = NULL;
340 }
341 kfree(apcm->srcimps);
342 apcm->srcimps = NULL;
343 }
344
345 if (NULL != apcm->srccs) {
346 for (i = 0; i < apcm->n_srcc; i++) {
347 src_mgr->put_src(src_mgr, apcm->srccs[i]);
348 apcm->srccs[i] = NULL;
349 }
350 kfree(apcm->srccs);
351 apcm->srccs = NULL;
352 }
353
354 if (NULL != apcm->amixers) {
355 for (i = 0; i < apcm->n_amixer; i++) {
356 amixer_mgr->put_amixer(amixer_mgr, apcm->amixers[i]);
357 apcm->amixers[i] = NULL;
358 }
359 kfree(apcm->amixers);
360 apcm->amixers = NULL;
361 }
362
363 if (NULL != apcm->mono) {
364 sum_mgr->put_sum(sum_mgr, apcm->mono);
365 apcm->mono = NULL;
366 }
367
368 if (NULL != apcm->src) {
369 src_mgr->put_src(src_mgr, apcm->src);
370 apcm->src = NULL;
371 }
372
373 if (NULL != apcm->vm_block) {
374 /* Undo device virtual mem map */
375 ct_unmap_audio_buffer(atc, apcm);
376 apcm->vm_block = NULL;
377 }
378
379 return 0;
380}
381
382static int atc_pcm_playback_start(struct ct_atc *atc, struct ct_atc_pcm *apcm)
383{
384 unsigned int max_cisz = 0;
385 struct src *src = apcm->src;
386
387 max_cisz = src->multi * src->rsc.msr;
388 max_cisz = 0x80 * (max_cisz < 8 ? max_cisz : 8);
389
390 src->ops->set_sa(src, apcm->vm_block->addr);
391 src->ops->set_la(src, apcm->vm_block->addr + apcm->vm_block->size);
392 src->ops->set_ca(src, apcm->vm_block->addr + max_cisz);
393 src->ops->set_cisz(src, max_cisz);
394
395 src->ops->set_bm(src, 1);
396 src->ops->set_state(src, SRC_STATE_INIT);
397 src->ops->commit_write(src);
398
399 return 0;
400}
401
402static int atc_pcm_stop(struct ct_atc *atc, struct ct_atc_pcm *apcm)
403{
404 struct src *src = NULL;
405 int i = 0;
406
407 src = apcm->src;
408 src->ops->set_bm(src, 0);
409 src->ops->set_state(src, SRC_STATE_OFF);
410 src->ops->commit_write(src);
411
412 if (NULL != apcm->srccs) {
413 for (i = 0; i < apcm->n_srcc; i++) {
414 src = apcm->srccs[i];
415 src->ops->set_bm(src, 0);
416 src->ops->set_state(src, SRC_STATE_OFF);
417 src->ops->commit_write(src);
418 }
419 }
420
421 apcm->started = 0;
422
423 return 0;
424}
425
426static int
427atc_pcm_playback_position(struct ct_atc *atc, struct ct_atc_pcm *apcm)
428{
429 struct src *src = apcm->src;
430 u32 size = 0, max_cisz = 0;
431 int position = 0;
432
433 position = src->ops->get_ca(src);
434
435 size = apcm->vm_block->size;
436 max_cisz = src->multi * src->rsc.msr;
437 max_cisz = 128 * (max_cisz < 8 ? max_cisz : 8);
438
439 return (position + size - max_cisz - apcm->vm_block->addr) % size;
440}
441
442struct src_node_conf_t {
443 unsigned int pitch;
444 unsigned int msr:8;
445 unsigned int mix_msr:8;
446 unsigned int imp_msr:8;
447 unsigned int vo:1;
448};
449
450static void setup_src_node_conf(struct ct_atc *atc, struct ct_atc_pcm *apcm,
451 struct src_node_conf_t *conf, int *n_srcc)
452{
453 unsigned int pitch = 0;
454
455 /* get pitch and convert to fixed-point 8.24 format. */
456 pitch = atc_get_pitch((atc->rsr * atc->msr),
457 apcm->substream->runtime->rate);
458 *n_srcc = 0;
459
460 if (1 == atc->msr) {
461 *n_srcc = apcm->substream->runtime->channels;
462 conf[0].pitch = pitch;
463 conf[0].mix_msr = conf[0].imp_msr = conf[0].msr = 1;
464 conf[0].vo = 1;
465 } else if (2 == atc->msr) {
466 if (0x8000000 < pitch) {
467 /* Need two-stage SRCs, SRCIMPs and
468 * AMIXERs for converting format */
469 conf[0].pitch = (atc->msr << 24);
470 conf[0].msr = conf[0].mix_msr = 1;
471 conf[0].imp_msr = atc->msr;
472 conf[0].vo = 0;
473 conf[1].pitch = atc_get_pitch(atc->rsr,
474 apcm->substream->runtime->rate);
475 conf[1].msr = conf[1].mix_msr = conf[1].imp_msr = 1;
476 conf[1].vo = 1;
477 *n_srcc = apcm->substream->runtime->channels * 2;
478 } else if (0x1000000 < pitch) {
479 /* Need one-stage SRCs, SRCIMPs and
480 * AMIXERs for converting format */
481 conf[0].pitch = pitch;
482 conf[0].msr = conf[0].mix_msr
483 = conf[0].imp_msr = atc->msr;
484 conf[0].vo = 1;
485 *n_srcc = apcm->substream->runtime->channels;
486 }
487 }
488}
489
490static int
491atc_pcm_capture_get_resources(struct ct_atc *atc, struct ct_atc_pcm *apcm)
492{
493 struct src_mgr *src_mgr = atc->rsc_mgrs[SRC];
494 struct srcimp_mgr *srcimp_mgr = atc->rsc_mgrs[SRCIMP];
495 struct amixer_mgr *amixer_mgr = atc->rsc_mgrs[AMIXER];
496 struct sum_mgr *sum_mgr = atc->rsc_mgrs[SUM];
497 struct src_desc src_dsc = {0};
498 struct src *src = NULL;
499 struct srcimp_desc srcimp_dsc = {0};
500 struct srcimp *srcimp = NULL;
501 struct amixer_desc mix_dsc = {0};
502 struct sum_desc sum_dsc = {0};
503 unsigned int pitch = 0;
504 int multi = 0, err = 0, i = 0;
505 int n_srcimp = 0, n_amixer = 0, n_srcc = 0, n_sum = 0;
506 struct src_node_conf_t src_node_conf[2] = {{0} };
507
508 /* The numbers of converting SRCs and SRCIMPs should be determined
509 * by pitch value. */
510
511 multi = apcm->substream->runtime->channels;
512
513 /* get pitch and convert to fixed-point 8.24 format. */
514 pitch = atc_get_pitch((atc->rsr * atc->msr),
515 apcm->substream->runtime->rate);
516
517 setup_src_node_conf(atc, apcm, src_node_conf, &n_srcc);
518 n_sum = (1 == multi) ? 1 : 0;
519 n_amixer += n_sum * 2 + n_srcc;
520 n_srcimp += n_srcc;
521 if ((multi > 1) && (0x8000000 >= pitch)) {
522 /* Need extra AMIXERs and SRCIMPs for special treatment
523 * of interleaved recording of conjugate channels */
524 n_amixer += multi * atc->msr;
525 n_srcimp += multi * atc->msr;
526 } else {
527 n_srcimp += multi;
528 }
529
530 if (n_srcc) {
531 apcm->srccs = kzalloc(sizeof(void *)*n_srcc, GFP_KERNEL);
532 if (NULL == apcm->srccs)
533 return -ENOMEM;
534 }
535 if (n_amixer) {
536 apcm->amixers = kzalloc(sizeof(void *)*n_amixer, GFP_KERNEL);
537 if (NULL == apcm->amixers) {
538 err = -ENOMEM;
539 goto error1;
540 }
541 }
542 apcm->srcimps = kzalloc(sizeof(void *)*n_srcimp, GFP_KERNEL);
543 if (NULL == apcm->srcimps) {
544 err = -ENOMEM;
545 goto error1;
546 }
547
548 /* Allocate SRCs for sample rate conversion if needed */
549 src_dsc.multi = 1;
550 src_dsc.mode = ARCRW;
551 for (i = 0, apcm->n_srcc = 0; i < n_srcc; i++) {
552 src_dsc.msr = src_node_conf[i/multi].msr;
553 err = src_mgr->get_src(src_mgr, &src_dsc,
554 (struct src **)&apcm->srccs[i]);
555 if (err)
556 goto error1;
557
558 src = apcm->srccs[i];
559 pitch = src_node_conf[i/multi].pitch;
560 src->ops->set_pitch(src, pitch);
561 src->ops->set_rom(src, select_rom(pitch));
562 src->ops->set_vo(src, src_node_conf[i/multi].vo);
563
564 apcm->n_srcc++;
565 }
566
567 /* Allocate AMIXERs for routing SRCs of conversion if needed */
568 for (i = 0, apcm->n_amixer = 0; i < n_amixer; i++) {
569 if (i < (n_sum*2))
570 mix_dsc.msr = atc->msr;
571 else if (i < (n_sum*2+n_srcc))
572 mix_dsc.msr = src_node_conf[(i-n_sum*2)/multi].mix_msr;
573 else
574 mix_dsc.msr = 1;
575
576 err = amixer_mgr->get_amixer(amixer_mgr, &mix_dsc,
577 (struct amixer **)&apcm->amixers[i]);
578 if (err)
579 goto error1;
580
581 apcm->n_amixer++;
582 }
583
584 /* Allocate a SUM resource to mix all input channels together */
585 sum_dsc.msr = atc->msr;
586 err = sum_mgr->get_sum(sum_mgr, &sum_dsc, (struct sum **)&apcm->mono);
587 if (err)
588 goto error1;
589
590 pitch = atc_get_pitch((atc->rsr * atc->msr),
591 apcm->substream->runtime->rate);
592 /* Allocate SRCIMP resources */
593 for (i = 0, apcm->n_srcimp = 0; i < n_srcimp; i++) {
594 if (i < (n_srcc))
595 srcimp_dsc.msr = src_node_conf[i/multi].imp_msr;
596 else if (1 == multi)
597 srcimp_dsc.msr = (pitch <= 0x8000000) ? atc->msr : 1;
598 else
599 srcimp_dsc.msr = 1;
600
601 err = srcimp_mgr->get_srcimp(srcimp_mgr, &srcimp_dsc, &srcimp);
602 if (err)
603 goto error1;
604
605 apcm->srcimps[i] = srcimp;
606 apcm->n_srcimp++;
607 }
608
609 /* Allocate a SRC for writing data to host memory */
610 src_dsc.multi = apcm->substream->runtime->channels;
611 src_dsc.msr = 1;
612 src_dsc.mode = MEMWR;
613 err = src_mgr->get_src(src_mgr, &src_dsc, (struct src **)&apcm->src);
614 if (err)
615 goto error1;
616
617 src = apcm->src;
618 src->ops->set_pitch(src, pitch);
619
620 /* Set up device virtual mem map */
621 err = ct_map_audio_buffer(atc, apcm);
622 if (err < 0)
623 goto error1;
624
625 return 0;
626
627error1:
628 atc_pcm_release_resources(atc, apcm);
629 return err;
630}
631
632static int atc_pcm_capture_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm)
633{
634 struct src *src = NULL;
635 struct amixer *amixer = NULL;
636 struct srcimp *srcimp = NULL;
637 struct ct_mixer *mixer = atc->mixer;
638 struct sum *mono = NULL;
639 struct rsc *out_ports[8] = {NULL};
640 int err = 0, i = 0, j = 0, n_sum = 0, multi = 0;
641 unsigned int pitch = 0;
642 int mix_base = 0, imp_base = 0;
643
644 if (NULL != apcm->src) {
645 /* Prepared pcm capture */
646 return 0;
647 }
648
649 /* Get needed resources. */
650 err = atc_pcm_capture_get_resources(atc, apcm);
651 if (err)
652 return err;
653
654 /* Connect resources */
655 mixer->get_output_ports(mixer, MIX_PCMO_FRONT,
656 &out_ports[0], &out_ports[1]);
657
658 multi = apcm->substream->runtime->channels;
659 if (1 == multi) {
660 mono = apcm->mono;
661 for (i = 0; i < 2; i++) {
662 amixer = apcm->amixers[i];
663 amixer->ops->setup(amixer, out_ports[i],
664 MONO_SUM_SCALE, mono);
665 }
666 out_ports[0] = &mono->rsc;
667 n_sum = 1;
668 mix_base = n_sum * 2;
669 }
670
671 for (i = 0; i < apcm->n_srcc; i++) {
672 src = apcm->srccs[i];
673 srcimp = apcm->srcimps[imp_base+i];
674 amixer = apcm->amixers[mix_base+i];
675 srcimp->ops->map(srcimp, src, out_ports[i%multi]);
676 amixer->ops->setup(amixer, &src->rsc, INIT_VOL, NULL);
677 out_ports[i%multi] = &amixer->rsc;
678 }
679
680 pitch = atc_get_pitch((atc->rsr * atc->msr),
681 apcm->substream->runtime->rate);
682
683 if ((multi > 1) && (pitch <= 0x8000000)) {
684 /* Special connection for interleaved
685 * recording with conjugate channels */
686 for (i = 0; i < multi; i++) {
687 out_ports[i]->ops->master(out_ports[i]);
688 for (j = 0; j < atc->msr; j++) {
689 amixer = apcm->amixers[apcm->n_srcc+j*multi+i];
690 amixer->ops->set_input(amixer, out_ports[i]);
691 amixer->ops->set_scale(amixer, INIT_VOL);
692 amixer->ops->set_sum(amixer, NULL);
693 amixer->ops->commit_raw_write(amixer);
694 out_ports[i]->ops->next_conj(out_ports[i]);
695
696 srcimp = apcm->srcimps[apcm->n_srcc+j*multi+i];
697 srcimp->ops->map(srcimp, apcm->src,
698 &amixer->rsc);
699 }
700 }
701 } else {
702 for (i = 0; i < multi; i++) {
703 srcimp = apcm->srcimps[apcm->n_srcc+i];
704 srcimp->ops->map(srcimp, apcm->src, out_ports[i]);
705 }
706 }
707
708 return 0;
709}
710
711static int atc_pcm_capture_start(struct ct_atc *atc, struct ct_atc_pcm *apcm)
712{
713 struct src *src = NULL;
714 struct src_mgr *src_mgr = atc->rsc_mgrs[SRC];
715 int i = 0, multi = 0;
716
717 if (apcm->started)
718 return 0;
719
720 apcm->started = 1;
721 multi = apcm->substream->runtime->channels;
722 /* Set up converting SRCs */
723 for (i = 0; i < apcm->n_srcc; i++) {
724 src = apcm->srccs[i];
725 src->ops->set_pm(src, ((i%multi) != (multi-1)));
726 src_mgr->src_disable(src_mgr, src);
727 }
728
729 /* Set up recording SRC */
730 src = apcm->src;
731 src->ops->set_sf(src, convert_format(apcm->substream->runtime->format));
732 src->ops->set_sa(src, apcm->vm_block->addr);
733 src->ops->set_la(src, apcm->vm_block->addr + apcm->vm_block->size);
734 src->ops->set_ca(src, apcm->vm_block->addr);
735 src_mgr->src_disable(src_mgr, src);
736
737 /* Disable relevant SRCs firstly */
738 src_mgr->commit_write(src_mgr);
739
740 /* Enable SRCs respectively */
741 for (i = 0; i < apcm->n_srcc; i++) {
742 src = apcm->srccs[i];
743 src->ops->set_state(src, SRC_STATE_RUN);
744 src->ops->commit_write(src);
745 src_mgr->src_enable_s(src_mgr, src);
746 }
747 src = apcm->src;
748 src->ops->set_bm(src, 1);
749 src->ops->set_state(src, SRC_STATE_RUN);
750 src->ops->commit_write(src);
751 src_mgr->src_enable_s(src_mgr, src);
752
753 /* Enable relevant SRCs synchronously */
754 src_mgr->commit_write(src_mgr);
755
756 return 0;
757}
758
759static int
760atc_pcm_capture_position(struct ct_atc *atc, struct ct_atc_pcm *apcm)
761{
762 struct src *src = apcm->src;
763
764 return src->ops->get_ca(src) - apcm->vm_block->addr;
765}
766
767static int spdif_passthru_playback_get_resources(struct ct_atc *atc,
768 struct ct_atc_pcm *apcm)
769{
770 struct src_mgr *src_mgr = atc->rsc_mgrs[SRC];
771 struct amixer_mgr *amixer_mgr = atc->rsc_mgrs[AMIXER];
772 struct src_desc desc = {0};
773 struct amixer_desc mix_dsc = {0};
774 struct src *src = NULL;
775 int err = 0;
776 int n_amixer = apcm->substream->runtime->channels, i = 0;
777 unsigned int pitch = 0, rsr = atc->pll_rate;
778
779 /* Get SRC resource */
780 desc.multi = apcm->substream->runtime->channels;
781 desc.msr = 1;
782 while (apcm->substream->runtime->rate > (rsr * desc.msr))
783 desc.msr <<= 1;
784
785 desc.mode = MEMRD;
786 err = src_mgr->get_src(src_mgr, &desc, (struct src **)&apcm->src);
787 if (err)
788 goto error1;
789
790 pitch = atc_get_pitch(apcm->substream->runtime->rate, (rsr * desc.msr));
791 src = apcm->src;
792 src->ops->set_pitch(src, pitch);
793 src->ops->set_rom(src, select_rom(pitch));
794 src->ops->set_sf(src, convert_format(apcm->substream->runtime->format));
795 src->ops->set_pm(src, (src->ops->next_interleave(src) != NULL));
796 src->ops->set_bp(src, 1);
797
798 /* Get AMIXER resource */
799 n_amixer = (n_amixer < 2) ? 2 : n_amixer;
800 apcm->amixers = kzalloc(sizeof(void *)*n_amixer, GFP_KERNEL);
801 if (NULL == apcm->amixers) {
802 err = -ENOMEM;
803 goto error1;
804 }
805 mix_dsc.msr = desc.msr;
806 for (i = 0, apcm->n_amixer = 0; i < n_amixer; i++) {
807 err = amixer_mgr->get_amixer(amixer_mgr, &mix_dsc,
808 (struct amixer **)&apcm->amixers[i]);
809 if (err)
810 goto error1;
811
812 apcm->n_amixer++;
813 }
814
815 /* Set up device virtual mem map */
816 err = ct_map_audio_buffer(atc, apcm);
817 if (err < 0)
818 goto error1;
819
820 return 0;
821
822error1:
823 atc_pcm_release_resources(atc, apcm);
824 return err;
825}
826
827static int
828spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm)
829{
830 struct dao *dao = container_of(atc->daios[SPDIFOO], struct dao, daio);
831 unsigned long flags;
832 unsigned int rate = apcm->substream->runtime->rate;
833 unsigned int status = 0;
834 int err = 0;
835 unsigned char iec958_con_fs = 0;
836
837 switch (rate) {
838 case 48000:
839 iec958_con_fs = IEC958_AES3_CON_FS_48000;
840 break;
841 case 44100:
842 iec958_con_fs = IEC958_AES3_CON_FS_44100;
843 break;
844 case 32000:
845 iec958_con_fs = IEC958_AES3_CON_FS_32000;
846 break;
847 default:
848 return -ENOENT;
849 }
850
851 spin_lock_irqsave(&atc->atc_lock, flags);
852 dao->ops->get_spos(dao, &status);
853 if (((status >> 24) & IEC958_AES3_CON_FS) != iec958_con_fs) {
854 status &= ((~IEC958_AES3_CON_FS) << 24);
855 status |= (iec958_con_fs << 24);
856 dao->ops->set_spos(dao, status);
857 dao->ops->commit_write(dao);
858 }
859 if ((rate != atc->pll_rate) && (32000 != rate)) {
860 err = ((struct hw *)atc->hw)->pll_init(atc->hw, rate);
861 atc->pll_rate = err ? 0 : rate;
862 }
863 spin_unlock_irqrestore(&atc->atc_lock, flags);
864
865 return err;
866}
867
868static int
869spdif_passthru_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm)
870{
871 struct src *src = NULL;
872 struct amixer *amixer = NULL;
873 struct dao *dao = NULL;
874 int err = 0;
875 int i = 0;
876 unsigned long flags;
877
878 if (NULL != apcm->src)
879 return 0;
880
881 /* Configure SPDIFOO and PLL to passthrough mode;
882 * determine pll_rate. */
883 err = spdif_passthru_playback_setup(atc, apcm);
884 if (err)
885 return err;
886
887 /* Get needed resources. */
888 err = spdif_passthru_playback_get_resources(atc, apcm);
889 if (err)
890 return err;
891
892 /* Connect resources */
893 src = apcm->src;
894 for (i = 0; i < apcm->n_amixer; i++) {
895 amixer = apcm->amixers[i];
896 amixer->ops->setup(amixer, &src->rsc, INIT_VOL, NULL);
897 src = src->ops->next_interleave(src);
898 if (NULL == src)
899 src = apcm->src;
900 }
901 /* Connect to SPDIFOO */
902 spin_lock_irqsave(&atc->atc_lock, flags);
903 dao = container_of(atc->daios[SPDIFOO], struct dao, daio);
904 amixer = apcm->amixers[0];
905 dao->ops->set_left_input(dao, &amixer->rsc);
906 amixer = apcm->amixers[1];
907 dao->ops->set_right_input(dao, &amixer->rsc);
908 spin_unlock_irqrestore(&atc->atc_lock, flags);
909
910 return 0;
911}
912
913static int atc_select_line_in(struct ct_atc *atc)
914{
915 struct hw *hw = atc->hw;
916 struct ct_mixer *mixer = atc->mixer;
917 struct src *src = NULL;
918
919 if (hw->is_adc_source_selected(hw, ADC_LINEIN))
920 return 0;
921
922 mixer->set_input_left(mixer, MIX_MIC_IN, NULL);
923 mixer->set_input_right(mixer, MIX_MIC_IN, NULL);
924
925 hw->select_adc_source(hw, ADC_LINEIN);
926
927 src = atc->srcs[2];
928 mixer->set_input_left(mixer, MIX_LINE_IN, &src->rsc);
929 src = atc->srcs[3];
930 mixer->set_input_right(mixer, MIX_LINE_IN, &src->rsc);
931
932 return 0;
933}
934
935static int atc_select_mic_in(struct ct_atc *atc)
936{
937 struct hw *hw = atc->hw;
938 struct ct_mixer *mixer = atc->mixer;
939 struct src *src = NULL;
940
941 if (hw->is_adc_source_selected(hw, ADC_MICIN))
942 return 0;
943
944 mixer->set_input_left(mixer, MIX_LINE_IN, NULL);
945 mixer->set_input_right(mixer, MIX_LINE_IN, NULL);
946
947 hw->select_adc_source(hw, ADC_MICIN);
948
949 src = atc->srcs[2];
950 mixer->set_input_left(mixer, MIX_MIC_IN, &src->rsc);
951 src = atc->srcs[3];
952 mixer->set_input_right(mixer, MIX_MIC_IN, &src->rsc);
953
954 return 0;
955}
956
957static int atc_have_digit_io_switch(struct ct_atc *atc)
958{
959 struct hw *hw = atc->hw;
960
961 return hw->have_digit_io_switch(hw);
962}
963
964static int atc_select_digit_io(struct ct_atc *atc)
965{
966 struct hw *hw = atc->hw;
967
968 if (hw->is_adc_source_selected(hw, ADC_NONE))
969 return 0;
970
971 hw->select_adc_source(hw, ADC_NONE);
972
973 return 0;
974}
975
976static int atc_daio_unmute(struct ct_atc *atc, unsigned char state, int type)
977{
978 struct daio_mgr *daio_mgr = atc->rsc_mgrs[DAIO];
979
980 if (state)
981 daio_mgr->daio_enable(daio_mgr, atc->daios[type]);
982 else
983 daio_mgr->daio_disable(daio_mgr, atc->daios[type]);
984
985 daio_mgr->commit_write(daio_mgr);
986
987 return 0;
988}
989
990static int
991atc_dao_get_status(struct ct_atc *atc, unsigned int *status, int type)
992{
993 struct dao *dao = container_of(atc->daios[type], struct dao, daio);
994 return dao->ops->get_spos(dao, status);
995}
996
997static int
998atc_dao_set_status(struct ct_atc *atc, unsigned int status, int type)
999{
1000 struct dao *dao = container_of(atc->daios[type], struct dao, daio);
1001
1002 dao->ops->set_spos(dao, status);
1003 dao->ops->commit_write(dao);
1004 return 0;
1005}
1006
1007static int atc_line_front_unmute(struct ct_atc *atc, unsigned char state)
1008{
1009 return atc_daio_unmute(atc, state, LINEO1);
1010}
1011
1012static int atc_line_surround_unmute(struct ct_atc *atc, unsigned char state)
1013{
1014 return atc_daio_unmute(atc, state, LINEO4);
1015}
1016
1017static int atc_line_clfe_unmute(struct ct_atc *atc, unsigned char state)
1018{
1019 return atc_daio_unmute(atc, state, LINEO3);
1020}
1021
1022static int atc_line_rear_unmute(struct ct_atc *atc, unsigned char state)
1023{
1024 return atc_daio_unmute(atc, state, LINEO2);
1025}
1026
1027static int atc_line_in_unmute(struct ct_atc *atc, unsigned char state)
1028{
1029 return atc_daio_unmute(atc, state, LINEIM);
1030}
1031
1032static int atc_spdif_out_unmute(struct ct_atc *atc, unsigned char state)
1033{
1034 return atc_daio_unmute(atc, state, SPDIFOO);
1035}
1036
1037static int atc_spdif_in_unmute(struct ct_atc *atc, unsigned char state)
1038{
1039 return atc_daio_unmute(atc, state, SPDIFIO);
1040}
1041
1042static int atc_spdif_out_get_status(struct ct_atc *atc, unsigned int *status)
1043{
1044 return atc_dao_get_status(atc, status, SPDIFOO);
1045}
1046
1047static int atc_spdif_out_set_status(struct ct_atc *atc, unsigned int status)
1048{
1049 return atc_dao_set_status(atc, status, SPDIFOO);
1050}
1051
1052static int atc_spdif_out_passthru(struct ct_atc *atc, unsigned char state)
1053{
1054 unsigned long flags;
1055 struct dao_desc da_dsc = {0};
1056 struct dao *dao = NULL;
1057 int err = 0;
1058 struct ct_mixer *mixer = atc->mixer;
1059 struct rsc *rscs[2] = {NULL};
1060 unsigned int spos = 0;
1061
1062 spin_lock_irqsave(&atc->atc_lock, flags);
1063 dao = container_of(atc->daios[SPDIFOO], struct dao, daio);
1064 da_dsc.msr = state ? 1 : atc->msr;
1065 da_dsc.passthru = state ? 1 : 0;
1066 err = dao->ops->reinit(dao, &da_dsc);
1067 if (state) {
1068 spos = IEC958_DEFAULT_CON;
1069 } else {
1070 mixer->get_output_ports(mixer, MIX_SPDIF_OUT,
1071 &rscs[0], &rscs[1]);
1072 dao->ops->set_left_input(dao, rscs[0]);
1073 dao->ops->set_right_input(dao, rscs[1]);
1074 /* Restore PLL to atc->rsr if needed. */
1075 if (atc->pll_rate != atc->rsr) {
1076 err = ((struct hw *)atc->hw)->pll_init(atc->hw,
1077 atc->rsr);
1078 atc->pll_rate = err ? 0 : atc->rsr;
1079 }
1080 }
1081 dao->ops->set_spos(dao, spos);
1082 dao->ops->commit_write(dao);
1083 spin_unlock_irqrestore(&atc->atc_lock, flags);
1084
1085 return err;
1086}
1087
1088static int ct_atc_destroy(struct ct_atc *atc)
1089{
1090 struct daio_mgr *daio_mgr = NULL;
1091 struct dao *dao = NULL;
1092 struct dai *dai = NULL;
1093 struct daio *daio = NULL;
1094 struct sum_mgr *sum_mgr = NULL;
1095 struct src_mgr *src_mgr = NULL;
1096 struct srcimp_mgr *srcimp_mgr = NULL;
1097 struct srcimp *srcimp = NULL;
1098 struct ct_mixer *mixer = NULL;
1099 int i = 0;
1100
1101 if (NULL == atc)
1102 return 0;
1103
1104 /* Stop hardware and disable all interrupts */
1105 if (NULL != atc->hw)
1106 ((struct hw *)atc->hw)->card_stop(atc->hw);
1107
1108 /* Destroy internal mixer objects */
1109 if (NULL != atc->mixer) {
1110 mixer = atc->mixer;
1111 mixer->set_input_left(mixer, MIX_LINE_IN, NULL);
1112 mixer->set_input_right(mixer, MIX_LINE_IN, NULL);
1113 mixer->set_input_left(mixer, MIX_MIC_IN, NULL);
1114 mixer->set_input_right(mixer, MIX_MIC_IN, NULL);
1115 mixer->set_input_left(mixer, MIX_SPDIF_IN, NULL);
1116 mixer->set_input_right(mixer, MIX_SPDIF_IN, NULL);
1117 ct_mixer_destroy(atc->mixer);
1118 }
1119
1120 if (NULL != atc->daios) {
1121 daio_mgr = (struct daio_mgr *)atc->rsc_mgrs[DAIO];
1122 for (i = 0; i < atc->n_daio; i++) {
1123 daio = atc->daios[i];
1124 if (daio->type < LINEIM) {
1125 dao = container_of(daio, struct dao, daio);
1126 dao->ops->clear_left_input(dao);
1127 dao->ops->clear_right_input(dao);
1128 } else {
1129 dai = container_of(daio, struct dai, daio);
1130 /* some thing to do for dai ... */
1131 }
1132 daio_mgr->put_daio(daio_mgr, daio);
1133 }
1134 kfree(atc->daios);
1135 }
1136
1137 if (NULL != atc->pcm) {
1138 sum_mgr = atc->rsc_mgrs[SUM];
1139 for (i = 0; i < atc->n_pcm; i++)
1140 sum_mgr->put_sum(sum_mgr, atc->pcm[i]);
1141
1142 kfree(atc->pcm);
1143 }
1144
1145 if (NULL != atc->srcs) {
1146 src_mgr = atc->rsc_mgrs[SRC];
1147 for (i = 0; i < atc->n_src; i++)
1148 src_mgr->put_src(src_mgr, atc->srcs[i]);
1149
1150 kfree(atc->srcs);
1151 }
1152
1153 if (NULL != atc->srcimps) {
1154 srcimp_mgr = atc->rsc_mgrs[SRCIMP];
1155 for (i = 0; i < atc->n_srcimp; i++) {
1156 srcimp = atc->srcimps[i];
1157 srcimp->ops->unmap(srcimp);
1158 srcimp_mgr->put_srcimp(srcimp_mgr, atc->srcimps[i]);
1159 }
1160 kfree(atc->srcimps);
1161 }
1162
1163 for (i = 0; i < NUM_RSCTYP; i++) {
1164 if ((NULL != rsc_mgr_funcs[i].destroy) &&
1165 (NULL != atc->rsc_mgrs[i]))
1166 rsc_mgr_funcs[i].destroy(atc->rsc_mgrs[i]);
1167
1168 }
1169
1170 if (NULL != atc->hw)
1171 destroy_hw_obj((struct hw *)atc->hw);
1172
1173 /* Destroy device virtual memory manager object */
1174 if (NULL != atc->vm) {
1175 ct_vm_destroy(atc->vm);
1176 atc->vm = NULL;
1177 }
1178
1179 kfree(atc);
1180
1181 return 0;
1182}
1183
1184static int atc_dev_free(struct snd_device *dev)
1185{
1186 struct ct_atc *atc = dev->device_data;
1187 return ct_atc_destroy(atc);
1188}
1189
1190static int atc_identify_card(struct ct_atc *atc)
1191{
1192 u16 subsys = 0;
1193 u8 revision = 0;
1194 struct pci_dev *pci = atc->pci;
1195 const struct ct_atc_chip_details *d;
1196 enum CTCARDS i;
1197
1198 pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &subsys);
1199 pci_read_config_byte(pci, PCI_REVISION_ID, &revision);
1200 atc->chip_details = NULL;
1201 atc->model = NUM_CTCARDS;
1202 for (d = atc_chip_details; d->vendor; d++) {
1203 if (d->vendor != pci->vendor || d->device != pci->device)
1204 continue;
1205
1206 if (NULL == d->sub_details) {
1207 atc->chip_details = d;
1208 break;
1209 }
1210 for (i = 0; i < NUM_CTCARDS; i++) {
1211 if ((d->sub_details[i].subsys == subsys) ||
1212 (((subsys & 0x6000) == 0x6000) &&
1213 ((d->sub_details[i].subsys & 0x6000) == 0x6000))) {
1214 atc->model = i;
1215 break;
1216 }
1217 }
1218 if (i >= NUM_CTCARDS)
1219 continue;
1220
1221 atc->chip_details = d;
1222 break;
1223 /* not take revision into consideration now */
1224 }
1225 if (!d->vendor)
1226 return -ENOENT;
1227
1228 return 0;
1229}
1230
1231static int ct_create_alsa_devs(struct ct_atc *atc)
1232{
1233 enum CTALSADEVS i;
1234 struct hw *hw = atc->hw;
1235 int err;
1236
1237 switch (hw->get_chip_type(hw)) {
1238 case ATC20K1:
1239 alsa_dev_funcs[MIXER].public_name = "20K1";
1240 break;
1241 case ATC20K2:
1242 alsa_dev_funcs[MIXER].public_name = "20K2";
1243 break;
1244 default:
1245 alsa_dev_funcs[MIXER].public_name = "Unknown";
1246 break;
1247 }
1248
1249 for (i = 0; i < NUM_CTALSADEVS; i++) {
1250 if (NULL == alsa_dev_funcs[i].create)
1251 continue;
1252
1253 err = alsa_dev_funcs[i].create(atc, i,
1254 alsa_dev_funcs[i].public_name);
1255 if (err) {
1256 printk(KERN_ERR "Creating alsa device %d failed!\n", i);
1257 return err;
1258 }
1259 }
1260
1261 return 0;
1262}
1263
1264static int atc_create_hw_devs(struct ct_atc *atc)
1265{
1266 struct hw *hw = NULL;
1267 struct card_conf info = {0};
1268 int i = 0, err = 0;
1269
1270 err = create_hw_obj(atc->pci, &hw);
1271 if (err) {
1272 printk(KERN_ERR "Failed to create hw obj!!!\n");
1273 return err;
1274 }
1275 atc->hw = hw;
1276
1277 /* Initialize card hardware. */
1278 info.rsr = atc->rsr;
1279 info.msr = atc->msr;
1280 info.vm_pgt_phys = atc_get_ptp_phys(atc, 0);
1281 err = hw->card_init(hw, &info);
1282 if (err < 0)
1283 return err;
1284
1285 for (i = 0; i < NUM_RSCTYP; i++) {
1286 if (NULL == rsc_mgr_funcs[i].create)
1287 continue;
1288
1289 err = rsc_mgr_funcs[i].create(atc->hw, &atc->rsc_mgrs[i]);
1290 if (err) {
1291 printk(KERN_ERR "Failed to create rsc_mgr %d!!!\n", i);
1292 return err;
1293 }
1294 }
1295
1296 return 0;
1297}
1298
1299static int atc_get_resources(struct ct_atc *atc)
1300{
1301 struct daio_desc da_desc = {0};
1302 struct daio_mgr *daio_mgr = NULL;
1303 struct src_desc src_dsc = {0};
1304 struct src_mgr *src_mgr = NULL;
1305 struct srcimp_desc srcimp_dsc = {0};
1306 struct srcimp_mgr *srcimp_mgr = NULL;
1307 struct sum_desc sum_dsc = {0};
1308 struct sum_mgr *sum_mgr = NULL;
1309 int err = 0, i = 0;
1310 unsigned short subsys_id = 0;
1311
1312 atc->daios = kzalloc(sizeof(void *)*(DAIONUM), GFP_KERNEL);
1313 if (NULL == atc->daios)
1314 return -ENOMEM;
1315
1316 atc->srcs = kzalloc(sizeof(void *)*(2*2), GFP_KERNEL);
1317 if (NULL == atc->srcs)
1318 return -ENOMEM;
1319
1320 atc->srcimps = kzalloc(sizeof(void *)*(2*2), GFP_KERNEL);
1321 if (NULL == atc->srcimps)
1322 return -ENOMEM;
1323
1324 atc->pcm = kzalloc(sizeof(void *)*(2*4), GFP_KERNEL);
1325 if (NULL == atc->pcm)
1326 return -ENOMEM;
1327
1328 daio_mgr = (struct daio_mgr *)atc->rsc_mgrs[DAIO];
1329 da_desc.msr = atc->msr;
1330 for (i = 0, atc->n_daio = 0; i < DAIONUM-1; i++) {
1331 da_desc.type = i;
1332 err = daio_mgr->get_daio(daio_mgr, &da_desc,
1333 (struct daio **)&atc->daios[i]);
1334 if (err) {
1335 printk(KERN_ERR "Failed to get DAIO "
1336 "resource %d!!!\n", i);
1337 return err;
1338 }
1339 atc->n_daio++;
1340 }
1341 pci_read_config_word(atc->pci, PCI_SUBSYSTEM_ID, &subsys_id);
1342 if ((subsys_id == 0x0029) || (subsys_id == 0x0031)) {
1343 /* SB073x cards */
1344 da_desc.type = SPDIFI1;
1345 } else {
1346 da_desc.type = SPDIFIO;
1347 }
1348 err = daio_mgr->get_daio(daio_mgr, &da_desc,
1349 (struct daio **)&atc->daios[i]);
1350 if (err) {
1351 printk(KERN_ERR "Failed to get S/PDIF-in resource!!!\n");
1352 return err;
1353 }
1354 atc->n_daio++;
1355
1356 src_mgr = atc->rsc_mgrs[SRC];
1357 src_dsc.multi = 1;
1358 src_dsc.msr = atc->msr;
1359 src_dsc.mode = ARCRW;
1360 for (i = 0, atc->n_src = 0; i < (2*2); i++) {
1361 err = src_mgr->get_src(src_mgr, &src_dsc,
1362 (struct src **)&atc->srcs[i]);
1363 if (err)
1364 return err;
1365
1366 atc->n_src++;
1367 }
1368
1369 srcimp_mgr = atc->rsc_mgrs[SRCIMP];
1370 srcimp_dsc.msr = 8; /* SRCIMPs for S/PDIFIn SRT */
1371 for (i = 0, atc->n_srcimp = 0; i < (2*1); i++) {
1372 err = srcimp_mgr->get_srcimp(srcimp_mgr, &srcimp_dsc,
1373 (struct srcimp **)&atc->srcimps[i]);
1374 if (err)
1375 return err;
1376
1377 atc->n_srcimp++;
1378 }
1379 srcimp_dsc.msr = 8; /* SRCIMPs for LINE/MICIn SRT */
1380 for (i = 0; i < (2*1); i++) {
1381 err = srcimp_mgr->get_srcimp(srcimp_mgr, &srcimp_dsc,
1382 (struct srcimp **)&atc->srcimps[2*1+i]);
1383 if (err)
1384 return err;
1385
1386 atc->n_srcimp++;
1387 }
1388
1389 sum_mgr = atc->rsc_mgrs[SUM];
1390 sum_dsc.msr = atc->msr;
1391 for (i = 0, atc->n_pcm = 0; i < (2*4); i++) {
1392 err = sum_mgr->get_sum(sum_mgr, &sum_dsc,
1393 (struct sum **)&atc->pcm[i]);
1394 if (err)
1395 return err;
1396
1397 atc->n_pcm++;
1398 }
1399
1400 err = ct_mixer_create(atc, (struct ct_mixer **)&atc->mixer);
1401 if (err) {
1402 printk(KERN_ERR "Failed to create mixer obj!!!\n");
1403 return err;
1404 }
1405
1406 return 0;
1407}
1408
1409static void
1410atc_connect_dai(struct src_mgr *src_mgr, struct dai *dai,
1411 struct src **srcs, struct srcimp **srcimps)
1412{
1413 struct rsc *rscs[2] = {NULL};
1414 struct src *src = NULL;
1415 struct srcimp *srcimp = NULL;
1416 int i = 0;
1417
1418 rscs[0] = &dai->daio.rscl;
1419 rscs[1] = &dai->daio.rscr;
1420 for (i = 0; i < 2; i++) {
1421 src = srcs[i];
1422 srcimp = srcimps[i];
1423 srcimp->ops->map(srcimp, src, rscs[i]);
1424 src_mgr->src_disable(src_mgr, src);
1425 }
1426
1427 src_mgr->commit_write(src_mgr); /* Actually disable SRCs */
1428
1429 src = srcs[0];
1430 src->ops->set_pm(src, 1);
1431 for (i = 0; i < 2; i++) {
1432 src = srcs[i];
1433 src->ops->set_state(src, SRC_STATE_RUN);
1434 src->ops->commit_write(src);
1435 src_mgr->src_enable_s(src_mgr, src);
1436 }
1437
1438 dai->ops->set_srt_srcl(dai, &(srcs[0]->rsc));
1439 dai->ops->set_srt_srcr(dai, &(srcs[1]->rsc));
1440
1441 dai->ops->set_enb_src(dai, 1);
1442 dai->ops->set_enb_srt(dai, 1);
1443 dai->ops->commit_write(dai);
1444
1445 src_mgr->commit_write(src_mgr); /* Synchronously enable SRCs */
1446}
1447
1448static void atc_connect_resources(struct ct_atc *atc)
1449{
1450 struct dai *dai = NULL;
1451 struct dao *dao = NULL;
1452 struct src *src = NULL;
1453 struct sum *sum = NULL;
1454 struct ct_mixer *mixer = NULL;
1455 struct rsc *rscs[2] = {NULL};
1456 int i = 0, j = 0;
1457
1458 mixer = atc->mixer;
1459
1460 for (i = MIX_WAVE_FRONT, j = LINEO1; i <= MIX_SPDIF_OUT; i++, j++) {
1461 mixer->get_output_ports(mixer, i, &rscs[0], &rscs[1]);
1462 dao = container_of(atc->daios[j], struct dao, daio);
1463 dao->ops->set_left_input(dao, rscs[0]);
1464 dao->ops->set_right_input(dao, rscs[1]);
1465 }
1466
1467 dai = container_of(atc->daios[LINEIM], struct dai, daio);
1468 atc_connect_dai(atc->rsc_mgrs[SRC], dai,
1469 (struct src **)&atc->srcs[2],
1470 (struct srcimp **)&atc->srcimps[2]);
1471 src = atc->srcs[2];
1472 mixer->set_input_left(mixer, MIX_LINE_IN, &src->rsc);
1473 src = atc->srcs[3];
1474 mixer->set_input_right(mixer, MIX_LINE_IN, &src->rsc);
1475
1476 dai = container_of(atc->daios[SPDIFIO], struct dai, daio);
1477 atc_connect_dai(atc->rsc_mgrs[SRC], dai,
1478 (struct src **)&atc->srcs[0],
1479 (struct srcimp **)&atc->srcimps[0]);
1480
1481 src = atc->srcs[0];
1482 mixer->set_input_left(mixer, MIX_SPDIF_IN, &src->rsc);
1483 src = atc->srcs[1];
1484 mixer->set_input_right(mixer, MIX_SPDIF_IN, &src->rsc);
1485
1486 for (i = MIX_PCMI_FRONT, j = 0; i <= MIX_PCMI_SURROUND; i++, j += 2) {
1487 sum = atc->pcm[j];
1488 mixer->set_input_left(mixer, i, &sum->rsc);
1489 sum = atc->pcm[j+1];
1490 mixer->set_input_right(mixer, i, &sum->rsc);
1491 }
1492}
1493
1494static void atc_set_ops(struct ct_atc *atc)
1495{
1496 /* Set operations */
1497 atc->map_audio_buffer = ct_map_audio_buffer;
1498 atc->unmap_audio_buffer = ct_unmap_audio_buffer;
1499 atc->pcm_playback_prepare = atc_pcm_playback_prepare;
1500 atc->pcm_release_resources = atc_pcm_release_resources;
1501 atc->pcm_playback_start = atc_pcm_playback_start;
1502 atc->pcm_playback_stop = atc_pcm_stop;
1503 atc->pcm_playback_position = atc_pcm_playback_position;
1504 atc->pcm_capture_prepare = atc_pcm_capture_prepare;
1505 atc->pcm_capture_start = atc_pcm_capture_start;
1506 atc->pcm_capture_stop = atc_pcm_stop;
1507 atc->pcm_capture_position = atc_pcm_capture_position;
1508 atc->spdif_passthru_playback_prepare = spdif_passthru_playback_prepare;
1509 atc->get_ptp_phys = atc_get_ptp_phys;
1510 atc->select_line_in = atc_select_line_in;
1511 atc->select_mic_in = atc_select_mic_in;
1512 atc->select_digit_io = atc_select_digit_io;
1513 atc->line_front_unmute = atc_line_front_unmute;
1514 atc->line_surround_unmute = atc_line_surround_unmute;
1515 atc->line_clfe_unmute = atc_line_clfe_unmute;
1516 atc->line_rear_unmute = atc_line_rear_unmute;
1517 atc->line_in_unmute = atc_line_in_unmute;
1518 atc->spdif_out_unmute = atc_spdif_out_unmute;
1519 atc->spdif_in_unmute = atc_spdif_in_unmute;
1520 atc->spdif_out_get_status = atc_spdif_out_get_status;
1521 atc->spdif_out_set_status = atc_spdif_out_set_status;
1522 atc->spdif_out_passthru = atc_spdif_out_passthru;
1523 atc->have_digit_io_switch = atc_have_digit_io_switch;
1524}
1525
1526/**
1527 * ct_atc_create - create and initialize a hardware manager
1528 * @card: corresponding alsa card object
1529 * @pci: corresponding kernel pci device object
1530 * @ratc: return created object address in it
1531 *
1532 * Creates and initializes a hardware manager.
1533 *
1534 * Creates kmallocated ct_atc structure. Initializes hardware.
1535 * Returns 0 if suceeds, or negative error code if fails.
1536 */
1537
1538int ct_atc_create(struct snd_card *card, struct pci_dev *pci,
1539 unsigned int rsr, unsigned int msr, struct ct_atc **ratc)
1540{
1541 struct ct_atc *atc = NULL;
1542 static struct snd_device_ops ops = {
1543 .dev_free = atc_dev_free,
1544 };
1545 int err = 0;
1546
1547 *ratc = NULL;
1548
1549 atc = kzalloc(sizeof(*atc), GFP_KERNEL);
1550 if (NULL == atc)
1551 return -ENOMEM;
1552
1553 atc->card = card;
1554 atc->pci = pci;
1555 atc->rsr = rsr;
1556 atc->msr = msr;
1557
1558 /* Set operations */
1559 atc_set_ops(atc);
1560
1561 spin_lock_init(&atc->atc_lock);
1562 spin_lock_init(&atc->vm_lock);
1563
1564 /* Find card model */
1565 err = atc_identify_card(atc);
1566 if (err < 0) {
1567 printk(KERN_ERR "ctatc: Card not recognised\n");
1568 goto error1;
1569 }
1570
1571 /* Set up device virtual memory management object */
1572 err = ct_vm_create(&atc->vm);
1573 if (err < 0)
1574 goto error1;
1575
1576 /* Create all atc hw devices */
1577 err = atc_create_hw_devs(atc);
1578 if (err < 0)
1579 goto error1;
1580
1581 /* Get resources */
1582 err = atc_get_resources(atc);
1583 if (err < 0)
1584 goto error1;
1585
1586 /* Build topology */
1587 atc_connect_resources(atc);
1588
1589 atc->create_alsa_devs = ct_create_alsa_devs;
1590
1591 err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, atc, &ops);
1592 if (err < 0)
1593 goto error1;
1594
1595 snd_card_set_dev(card, &pci->dev);
1596
1597 *ratc = atc;
1598 return 0;
1599
1600error1:
1601 ct_atc_destroy(atc);
1602 printk(KERN_ERR "Something wrong!!!\n");
1603 return err;
1604}
1605
diff --git a/sound/pci/ctxfi/ctatc.h b/sound/pci/ctxfi/ctatc.h
new file mode 100644
index 000000000000..286c993d461a
--- /dev/null
+++ b/sound/pci/ctxfi/ctatc.h
@@ -0,0 +1,155 @@
1/**
2 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
3 *
4 * This source file is released under GPL v2 license (no other versions).
5 * See the COPYING file included in the main directory of this source
6 * distribution for the license terms and conditions.
7 *
8 * @File ctatc.h
9 *
10 * @Brief
11 * This file contains the definition of the device resource management object.
12 *
13 * @Author Liu Chun
14 * @Date Mar 28 2008
15 *
16 */
17
18#ifndef CTATC_H
19#define CTATC_H
20
21#include <linux/types.h>
22#include <linux/spinlock_types.h>
23#include <linux/pci.h>
24#include <linux/timer.h>
25#include <sound/core.h>
26
27#include "ctvmem.h"
28#include "ctresource.h"
29
30enum CTALSADEVS { /* Types of alsa devices */
31 FRONT,
32 REAR,
33 CLFE,
34 SURROUND,
35 IEC958,
36 MIXER,
37 NUM_CTALSADEVS /* This should always be the last */
38};
39
40enum CTCARDS {
41 CTSB0760,
42 CTHENDRIX,
43 CTSB08801,
44 CTSB08802,
45 CTSB08803,
46 NUM_CTCARDS /* This should always be the last */
47};
48
49struct ct_atc_chip_sub_details {
50 u16 subsys;
51 const char *nm_model;
52};
53
54struct ct_atc_chip_details {
55 u16 vendor;
56 u16 device;
57 const struct ct_atc_chip_sub_details *sub_details;
58 const char *nm_card;
59};
60
61struct ct_atc;
62
63/* alsa pcm stream descriptor */
64struct ct_atc_pcm {
65 struct snd_pcm_substream *substream;
66 void (*interrupt)(struct ct_atc_pcm *apcm);
67 unsigned int started:1;
68 unsigned int stop_timer:1;
69 struct timer_list timer;
70 spinlock_t timer_lock;
71 unsigned int position;
72
73 /* Only mono and interleaved modes are supported now. */
74 struct ct_vm_block *vm_block;
75 void *src; /* SRC for interacting with host memory */
76 void **srccs; /* SRCs for sample rate conversion */
77 void **srcimps; /* SRC Input Mappers */
78 void **amixers; /* AMIXERs for routing converted data */
79 void *mono; /* A SUM resource for mixing chs to one */
80 unsigned char n_srcc; /* Number of converting SRCs */
81 unsigned char n_srcimp; /* Number of SRC Input Mappers */
82 unsigned char n_amixer; /* Number of AMIXERs */
83};
84
85/* Chip resource management object */
86struct ct_atc {
87 struct pci_dev *pci;
88 struct snd_card *card;
89 unsigned int rsr; /* reference sample rate in Hz */
90 unsigned int msr; /* master sample rate in rsr */
91 unsigned int pll_rate; /* current rate of Phase Lock Loop */
92
93 const struct ct_atc_chip_details *chip_details;
94 enum CTCARDS model;
95 /* Create all alsa devices */
96 int (*create_alsa_devs)(struct ct_atc *atc);
97
98 struct ct_vm *vm; /* device virtual memory manager for this card */
99 int (*map_audio_buffer)(struct ct_atc *atc, struct ct_atc_pcm *apcm);
100 void (*unmap_audio_buffer)(struct ct_atc *atc, struct ct_atc_pcm *apcm);
101 unsigned long (*get_ptp_phys)(struct ct_atc *atc, int index);
102
103 spinlock_t atc_lock;
104 spinlock_t vm_lock;
105
106 int (*pcm_playback_prepare)(struct ct_atc *atc,
107 struct ct_atc_pcm *apcm);
108 int (*pcm_playback_start)(struct ct_atc *atc, struct ct_atc_pcm *apcm);
109 int (*pcm_playback_stop)(struct ct_atc *atc, struct ct_atc_pcm *apcm);
110 int (*pcm_playback_position)(struct ct_atc *atc,
111 struct ct_atc_pcm *apcm);
112 int (*spdif_passthru_playback_prepare)(struct ct_atc *atc,
113 struct ct_atc_pcm *apcm);
114 int (*pcm_capture_prepare)(struct ct_atc *atc, struct ct_atc_pcm *apcm);
115 int (*pcm_capture_start)(struct ct_atc *atc, struct ct_atc_pcm *apcm);
116 int (*pcm_capture_stop)(struct ct_atc *atc, struct ct_atc_pcm *apcm);
117 int (*pcm_capture_position)(struct ct_atc *atc,
118 struct ct_atc_pcm *apcm);
119 int (*pcm_release_resources)(struct ct_atc *atc,
120 struct ct_atc_pcm *apcm);
121 int (*select_line_in)(struct ct_atc *atc);
122 int (*select_mic_in)(struct ct_atc *atc);
123 int (*select_digit_io)(struct ct_atc *atc);
124 int (*line_front_unmute)(struct ct_atc *atc, unsigned char state);
125 int (*line_surround_unmute)(struct ct_atc *atc, unsigned char state);
126 int (*line_clfe_unmute)(struct ct_atc *atc, unsigned char state);
127 int (*line_rear_unmute)(struct ct_atc *atc, unsigned char state);
128 int (*line_in_unmute)(struct ct_atc *atc, unsigned char state);
129 int (*spdif_out_unmute)(struct ct_atc *atc, unsigned char state);
130 int (*spdif_in_unmute)(struct ct_atc *atc, unsigned char state);
131 int (*spdif_out_get_status)(struct ct_atc *atc, unsigned int *status);
132 int (*spdif_out_set_status)(struct ct_atc *atc, unsigned int status);
133 int (*spdif_out_passthru)(struct ct_atc *atc, unsigned char state);
134 int (*have_digit_io_switch)(struct ct_atc *atc);
135
136 /* Don't touch! Used for internal object. */
137 void *rsc_mgrs[NUM_RSCTYP]; /* chip resource managers */
138 void *mixer; /* internal mixer object */
139 void *hw; /* chip specific hardware access object */
140 void **daios; /* digital audio io resources */
141 void **pcm; /* SUMs for collecting all pcm stream */
142 void **srcs; /* Sample Rate Converters for input signal */
143 void **srcimps; /* input mappers for SRCs */
144 unsigned char n_daio;
145 unsigned char n_src;
146 unsigned char n_srcimp;
147 unsigned char n_pcm;
148};
149
150
151int __devinit ct_atc_create(struct snd_card *card, struct pci_dev *pci,
152 unsigned int rsr, unsigned int msr,
153 struct ct_atc **ratc);
154
155#endif /* CTATC_H */
diff --git a/sound/pci/ctxfi/ctdaio.c b/sound/pci/ctxfi/ctdaio.c
new file mode 100644
index 000000000000..a2aea399eba1
--- /dev/null
+++ b/sound/pci/ctxfi/ctdaio.c
@@ -0,0 +1,769 @@
1/**
2 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
3 *
4 * This source file is released under GPL v2 license (no other versions).
5 * See the COPYING file included in the main directory of this source
6 * distribution for the license terms and conditions.
7 *
8 * @File ctdaio.c
9 *
10 * @Brief
11 * This file contains the implementation of Digital Audio Input Output
12 * resource management object.
13 *
14 * @Author Liu Chun
15 * @Date May 23 2008
16 *
17 */
18
19#include "ctdaio.h"
20#include "cthardware.h"
21#include "ctimap.h"
22#include <linux/slab.h>
23#include <linux/kernel.h>
24
25#define DAIO_RESOURCE_NUM NUM_DAIOTYP
26#define DAIO_OUT_MAX SPDIFOO
27
28union daio_usage {
29 struct {
30 unsigned short lineo1:1;
31 unsigned short lineo2:1;
32 unsigned short lineo3:1;
33 unsigned short lineo4:1;
34 unsigned short spdifoo:1;
35 unsigned short lineim:1;
36 unsigned short spdifio:1;
37 unsigned short spdifi1:1;
38 } bf;
39 unsigned short data;
40};
41
42struct daio_rsc_idx {
43 unsigned short left;
44 unsigned short right;
45};
46
47struct daio_rsc_idx idx_20k1[NUM_DAIOTYP] = {
48 [LINEO1] = {.left = 0x00, .right = 0x01},
49 [LINEO2] = {.left = 0x18, .right = 0x19},
50 [LINEO3] = {.left = 0x08, .right = 0x09},
51 [LINEO4] = {.left = 0x10, .right = 0x11},
52 [LINEIM] = {.left = 0x1b5, .right = 0x1bd},
53 [SPDIFOO] = {.left = 0x20, .right = 0x21},
54 [SPDIFIO] = {.left = 0x15, .right = 0x1d},
55 [SPDIFI1] = {.left = 0x95, .right = 0x9d},
56};
57
58struct daio_rsc_idx idx_20k2[NUM_DAIOTYP] = {
59 [LINEO1] = {.left = 0x40, .right = 0x41},
60 [LINEO2] = {.left = 0x70, .right = 0x71},
61 [LINEO3] = {.left = 0x50, .right = 0x51},
62 [LINEO4] = {.left = 0x60, .right = 0x61},
63 [LINEIM] = {.left = 0x45, .right = 0xc5},
64 [SPDIFOO] = {.left = 0x00, .right = 0x01},
65 [SPDIFIO] = {.left = 0x05, .right = 0x85},
66};
67
68static int daio_master(struct rsc *rsc)
69{
70 /* Actually, this is not the resource index of DAIO.
71 * For DAO, it is the input mapper index. And, for DAI,
72 * it is the output time-slot index. */
73 return rsc->conj = rsc->idx;
74}
75
76static int daio_index(const struct rsc *rsc)
77{
78 return rsc->conj;
79}
80
81static int daio_out_next_conj(struct rsc *rsc)
82{
83 return rsc->conj += 2;
84}
85
86static int daio_in_next_conj_20k1(struct rsc *rsc)
87{
88 return rsc->conj += 0x200;
89}
90
91static int daio_in_next_conj_20k2(struct rsc *rsc)
92{
93 return rsc->conj += 0x100;
94}
95
96static struct rsc_ops daio_out_rsc_ops = {
97 .master = daio_master,
98 .next_conj = daio_out_next_conj,
99 .index = daio_index,
100 .output_slot = NULL,
101};
102
103static struct rsc_ops daio_in_rsc_ops_20k1 = {
104 .master = daio_master,
105 .next_conj = daio_in_next_conj_20k1,
106 .index = NULL,
107 .output_slot = daio_index,
108};
109
110static struct rsc_ops daio_in_rsc_ops_20k2 = {
111 .master = daio_master,
112 .next_conj = daio_in_next_conj_20k2,
113 .index = NULL,
114 .output_slot = daio_index,
115};
116
117static unsigned int daio_device_index(enum DAIOTYP type, struct hw *hw)
118{
119 switch (hw->get_chip_type(hw)) {
120 case ATC20K1:
121 switch (type) {
122 case SPDIFOO: return 0;
123 case SPDIFIO: return 0;
124 case SPDIFI1: return 1;
125 case LINEO1: return 4;
126 case LINEO2: return 7;
127 case LINEO3: return 5;
128 case LINEO4: return 6;
129 case LINEIM: return 7;
130 default: return -EINVAL;
131 }
132 case ATC20K2:
133 switch (type) {
134 case SPDIFOO: return 0;
135 case SPDIFIO: return 0;
136 case LINEO1: return 4;
137 case LINEO2: return 7;
138 case LINEO3: return 5;
139 case LINEO4: return 6;
140 case LINEIM: return 4;
141 default: return -EINVAL;
142 }
143 default:
144 return -EINVAL;
145 }
146}
147
148static int dao_rsc_reinit(struct dao *dao, const struct dao_desc *desc);
149
150static int dao_spdif_get_spos(struct dao *dao, unsigned int *spos)
151{
152 ((struct hw *)dao->hw)->dao_get_spos(dao->ctrl_blk, spos);
153 return 0;
154}
155
156static int dao_spdif_set_spos(struct dao *dao, unsigned int spos)
157{
158 ((struct hw *)dao->hw)->dao_set_spos(dao->ctrl_blk, spos);
159 return 0;
160}
161
162static int dao_commit_write(struct dao *dao)
163{
164 ((struct hw *)dao->hw)->dao_commit_write(dao->hw,
165 daio_device_index(dao->daio.type, dao->hw), dao->ctrl_blk);
166 return 0;
167}
168
169static int dao_set_left_input(struct dao *dao, struct rsc *input)
170{
171 struct imapper *entry = NULL;
172 struct daio *daio = &dao->daio;
173 int i = 0;
174
175 entry = kzalloc((sizeof(*entry) * daio->rscl.msr), GFP_KERNEL);
176 if (NULL == entry)
177 return -ENOMEM;
178
179 /* Program master and conjugate resources */
180 input->ops->master(input);
181 daio->rscl.ops->master(&daio->rscl);
182 for (i = 0; i < daio->rscl.msr; i++, entry++) {
183 entry->slot = input->ops->output_slot(input);
184 entry->user = entry->addr = daio->rscl.ops->index(&daio->rscl);
185 dao->mgr->imap_add(dao->mgr, entry);
186 dao->imappers[i] = entry;
187
188 input->ops->next_conj(input);
189 daio->rscl.ops->next_conj(&daio->rscl);
190 }
191 input->ops->master(input);
192 daio->rscl.ops->master(&daio->rscl);
193
194 return 0;
195}
196
197static int dao_set_right_input(struct dao *dao, struct rsc *input)
198{
199 struct imapper *entry = NULL;
200 struct daio *daio = &dao->daio;
201 int i = 0;
202
203 entry = kzalloc((sizeof(*entry) * daio->rscr.msr), GFP_KERNEL);
204 if (NULL == entry)
205 return -ENOMEM;
206
207 /* Program master and conjugate resources */
208 input->ops->master(input);
209 daio->rscr.ops->master(&daio->rscr);
210 for (i = 0; i < daio->rscr.msr; i++, entry++) {
211 entry->slot = input->ops->output_slot(input);
212 entry->user = entry->addr = daio->rscr.ops->index(&daio->rscr);
213 dao->mgr->imap_add(dao->mgr, entry);
214 dao->imappers[daio->rscl.msr + i] = entry;
215
216 input->ops->next_conj(input);
217 daio->rscr.ops->next_conj(&daio->rscr);
218 }
219 input->ops->master(input);
220 daio->rscr.ops->master(&daio->rscr);
221
222 return 0;
223}
224
225static int dao_clear_left_input(struct dao *dao)
226{
227 struct imapper *entry = NULL;
228 struct daio *daio = &dao->daio;
229 int i = 0;
230
231 if (NULL == dao->imappers[0])
232 return 0;
233
234 entry = dao->imappers[0];
235 dao->mgr->imap_delete(dao->mgr, entry);
236 /* Program conjugate resources */
237 for (i = 1; i < daio->rscl.msr; i++) {
238 entry = dao->imappers[i];
239 dao->mgr->imap_delete(dao->mgr, entry);
240 dao->imappers[i] = NULL;
241 }
242
243 kfree(dao->imappers[0]);
244 dao->imappers[0] = NULL;
245
246 return 0;
247}
248
249static int dao_clear_right_input(struct dao *dao)
250{
251 struct imapper *entry = NULL;
252 struct daio *daio = &dao->daio;
253 int i = 0;
254
255 if (NULL == dao->imappers[daio->rscl.msr])
256 return 0;
257
258 entry = dao->imappers[daio->rscl.msr];
259 dao->mgr->imap_delete(dao->mgr, entry);
260 /* Program conjugate resources */
261 for (i = 1; i < daio->rscr.msr; i++) {
262 entry = dao->imappers[daio->rscl.msr + i];
263 dao->mgr->imap_delete(dao->mgr, entry);
264 dao->imappers[daio->rscl.msr + i] = NULL;
265 }
266
267 kfree(dao->imappers[daio->rscl.msr]);
268 dao->imappers[daio->rscl.msr] = NULL;
269
270 return 0;
271}
272
273static struct dao_rsc_ops dao_ops = {
274 .set_spos = dao_spdif_set_spos,
275 .commit_write = dao_commit_write,
276 .get_spos = dao_spdif_get_spos,
277 .reinit = dao_rsc_reinit,
278 .set_left_input = dao_set_left_input,
279 .set_right_input = dao_set_right_input,
280 .clear_left_input = dao_clear_left_input,
281 .clear_right_input = dao_clear_right_input,
282};
283
284static int dai_set_srt_srcl(struct dai *dai, struct rsc *src)
285{
286 src->ops->master(src);
287 ((struct hw *)dai->hw)->dai_srt_set_srcm(dai->ctrl_blk,
288 src->ops->index(src));
289 return 0;
290}
291
292static int dai_set_srt_srcr(struct dai *dai, struct rsc *src)
293{
294 src->ops->master(src);
295 ((struct hw *)dai->hw)->dai_srt_set_srco(dai->ctrl_blk,
296 src->ops->index(src));
297 return 0;
298}
299
300static int dai_set_srt_msr(struct dai *dai, unsigned int msr)
301{
302 unsigned int rsr = 0;
303
304 for (rsr = 0; msr > 1; msr >>= 1)
305 rsr++;
306
307 ((struct hw *)dai->hw)->dai_srt_set_rsr(dai->ctrl_blk, rsr);
308 return 0;
309}
310
311static int dai_set_enb_src(struct dai *dai, unsigned int enb)
312{
313 ((struct hw *)dai->hw)->dai_srt_set_ec(dai->ctrl_blk, enb);
314 return 0;
315}
316
317static int dai_set_enb_srt(struct dai *dai, unsigned int enb)
318{
319 ((struct hw *)dai->hw)->dai_srt_set_et(dai->ctrl_blk, enb);
320 return 0;
321}
322
323static int dai_commit_write(struct dai *dai)
324{
325 ((struct hw *)dai->hw)->dai_commit_write(dai->hw,
326 daio_device_index(dai->daio.type, dai->hw), dai->ctrl_blk);
327 return 0;
328}
329
330static struct dai_rsc_ops dai_ops = {
331 .set_srt_srcl = dai_set_srt_srcl,
332 .set_srt_srcr = dai_set_srt_srcr,
333 .set_srt_msr = dai_set_srt_msr,
334 .set_enb_src = dai_set_enb_src,
335 .set_enb_srt = dai_set_enb_srt,
336 .commit_write = dai_commit_write,
337};
338
339static int daio_rsc_init(struct daio *daio,
340 const struct daio_desc *desc,
341 void *hw)
342{
343 int err = 0;
344 unsigned int idx_l = 0, idx_r = 0;
345
346 switch (((struct hw *)hw)->get_chip_type(hw)) {
347 case ATC20K1:
348 idx_l = idx_20k1[desc->type].left;
349 idx_r = idx_20k1[desc->type].right;
350 break;
351 case ATC20K2:
352 idx_l = idx_20k2[desc->type].left;
353 idx_r = idx_20k2[desc->type].right;
354 break;
355 default:
356 return -EINVAL;
357 }
358 err = rsc_init(&daio->rscl, idx_l, DAIO, desc->msr, hw);
359 if (err)
360 return err;
361
362 err = rsc_init(&daio->rscr, idx_r, DAIO, desc->msr, hw);
363 if (err)
364 goto error1;
365
366 /* Set daio->rscl/r->ops to daio specific ones */
367 if (desc->type <= DAIO_OUT_MAX) {
368 daio->rscl.ops = daio->rscr.ops = &daio_out_rsc_ops;
369 } else {
370 switch (((struct hw *)hw)->get_chip_type(hw)) {
371 case ATC20K1:
372 daio->rscl.ops = daio->rscr.ops = &daio_in_rsc_ops_20k1;
373 break;
374 case ATC20K2:
375 daio->rscl.ops = daio->rscr.ops = &daio_in_rsc_ops_20k2;
376 break;
377 default:
378 break;
379 }
380 }
381 daio->type = desc->type;
382
383 return 0;
384
385error1:
386 rsc_uninit(&daio->rscl);
387 return err;
388}
389
390static int daio_rsc_uninit(struct daio *daio)
391{
392 rsc_uninit(&daio->rscl);
393 rsc_uninit(&daio->rscr);
394
395 return 0;
396}
397
398static int dao_rsc_init(struct dao *dao,
399 const struct daio_desc *desc,
400 struct daio_mgr *mgr)
401{
402 struct hw *hw = mgr->mgr.hw;
403 unsigned int conf = 0;
404 int err = 0;
405
406 err = daio_rsc_init(&dao->daio, desc, mgr->mgr.hw);
407 if (err)
408 return err;
409
410 dao->imappers = kzalloc(sizeof(void *)*desc->msr*2, GFP_KERNEL);
411 if (NULL == dao->imappers) {
412 err = -ENOMEM;
413 goto error1;
414 }
415 dao->ops = &dao_ops;
416 dao->mgr = mgr;
417 dao->hw = hw;
418 err = hw->dao_get_ctrl_blk(&dao->ctrl_blk);
419 if (err)
420 goto error2;
421
422 hw->daio_mgr_dsb_dao(mgr->mgr.ctrl_blk,
423 daio_device_index(dao->daio.type, hw));
424 hw->daio_mgr_commit_write(hw, mgr->mgr.ctrl_blk);
425
426 conf |= (desc->msr & 0x7) | (desc->passthru << 3);
427 hw->daio_mgr_dao_init(mgr->mgr.ctrl_blk,
428 daio_device_index(dao->daio.type, hw), conf);
429 hw->daio_mgr_enb_dao(mgr->mgr.ctrl_blk,
430 daio_device_index(dao->daio.type, hw));
431 hw->daio_mgr_commit_write(hw, mgr->mgr.ctrl_blk);
432
433 return 0;
434
435error2:
436 kfree(dao->imappers);
437 dao->imappers = NULL;
438error1:
439 daio_rsc_uninit(&dao->daio);
440 return err;
441}
442
443static int dao_rsc_uninit(struct dao *dao)
444{
445 if (NULL != dao->imappers) {
446 if (NULL != dao->imappers[0])
447 dao_clear_left_input(dao);
448
449 if (NULL != dao->imappers[dao->daio.rscl.msr])
450 dao_clear_right_input(dao);
451
452 kfree(dao->imappers);
453 dao->imappers = NULL;
454 }
455 ((struct hw *)dao->hw)->dao_put_ctrl_blk(dao->ctrl_blk);
456 dao->hw = dao->ctrl_blk = NULL;
457 daio_rsc_uninit(&dao->daio);
458
459 return 0;
460}
461
462static int dao_rsc_reinit(struct dao *dao, const struct dao_desc *desc)
463{
464 struct daio_mgr *mgr = dao->mgr;
465 struct daio_desc dsc = {0};
466
467 dsc.type = dao->daio.type;
468 dsc.msr = desc->msr;
469 dsc.passthru = desc->passthru;
470 dao_rsc_uninit(dao);
471 return dao_rsc_init(dao, &dsc, mgr);
472}
473
474static int dai_rsc_init(struct dai *dai,
475 const struct daio_desc *desc,
476 struct daio_mgr *mgr)
477{
478 int err = 0;
479 struct hw *hw = mgr->mgr.hw;
480 unsigned int rsr = 0, msr = 0;
481
482 err = daio_rsc_init(&dai->daio, desc, mgr->mgr.hw);
483 if (err)
484 return err;
485
486 dai->ops = &dai_ops;
487 dai->hw = mgr->mgr.hw;
488 err = hw->dai_get_ctrl_blk(&dai->ctrl_blk);
489 if (err)
490 goto error1;
491
492 for (rsr = 0, msr = desc->msr; msr > 1; msr >>= 1)
493 rsr++;
494
495 hw->dai_srt_set_rsr(dai->ctrl_blk, rsr);
496 hw->dai_srt_set_drat(dai->ctrl_blk, 0);
497 /* default to disabling control of a SRC */
498 hw->dai_srt_set_ec(dai->ctrl_blk, 0);
499 hw->dai_srt_set_et(dai->ctrl_blk, 0); /* default to disabling SRT */
500 hw->dai_commit_write(hw,
501 daio_device_index(dai->daio.type, dai->hw), dai->ctrl_blk);
502
503 return 0;
504
505error1:
506 daio_rsc_uninit(&dai->daio);
507 return err;
508}
509
510static int dai_rsc_uninit(struct dai *dai)
511{
512 ((struct hw *)dai->hw)->dai_put_ctrl_blk(dai->ctrl_blk);
513 dai->hw = dai->ctrl_blk = NULL;
514 daio_rsc_uninit(&dai->daio);
515 return 0;
516}
517
518static int daio_mgr_get_rsc(struct rsc_mgr *mgr, enum DAIOTYP type)
519{
520 if (((union daio_usage *)mgr->rscs)->data & (0x1 << type))
521 return -ENOENT;
522
523 ((union daio_usage *)mgr->rscs)->data |= (0x1 << type);
524
525 return 0;
526}
527
528static int daio_mgr_put_rsc(struct rsc_mgr *mgr, enum DAIOTYP type)
529{
530 ((union daio_usage *)mgr->rscs)->data &= ~(0x1 << type);
531
532 return 0;
533}
534
535static int get_daio_rsc(struct daio_mgr *mgr,
536 const struct daio_desc *desc,
537 struct daio **rdaio)
538{
539 int err = 0;
540 struct dai *dai = NULL;
541 struct dao *dao = NULL;
542 unsigned long flags;
543
544 *rdaio = NULL;
545
546 /* Check whether there are sufficient daio resources to meet request. */
547 spin_lock_irqsave(&mgr->mgr_lock, flags);
548 err = daio_mgr_get_rsc(&mgr->mgr, desc->type);
549 spin_unlock_irqrestore(&mgr->mgr_lock, flags);
550 if (err) {
551 printk(KERN_ERR "Can't meet DAIO resource request!\n");
552 return err;
553 }
554
555 /* Allocate mem for daio resource */
556 if (desc->type <= DAIO_OUT_MAX) {
557 dao = kzalloc(sizeof(*dao), GFP_KERNEL);
558 if (NULL == dao) {
559 err = -ENOMEM;
560 goto error;
561 }
562 err = dao_rsc_init(dao, desc, mgr);
563 if (err)
564 goto error;
565
566 *rdaio = &dao->daio;
567 } else {
568 dai = kzalloc(sizeof(*dai), GFP_KERNEL);
569 if (NULL == dai) {
570 err = -ENOMEM;
571 goto error;
572 }
573 err = dai_rsc_init(dai, desc, mgr);
574 if (err)
575 goto error;
576
577 *rdaio = &dai->daio;
578 }
579
580 mgr->daio_enable(mgr, *rdaio);
581 mgr->commit_write(mgr);
582
583 return 0;
584
585error:
586 if (NULL != dao)
587 kfree(dao);
588 else if (NULL != dai)
589 kfree(dai);
590
591 spin_lock_irqsave(&mgr->mgr_lock, flags);
592 daio_mgr_put_rsc(&mgr->mgr, desc->type);
593 spin_unlock_irqrestore(&mgr->mgr_lock, flags);
594 return err;
595}
596
597static int put_daio_rsc(struct daio_mgr *mgr, struct daio *daio)
598{
599 unsigned long flags;
600
601 mgr->daio_disable(mgr, daio);
602 mgr->commit_write(mgr);
603
604 spin_lock_irqsave(&mgr->mgr_lock, flags);
605 daio_mgr_put_rsc(&mgr->mgr, daio->type);
606 spin_unlock_irqrestore(&mgr->mgr_lock, flags);
607
608 if (daio->type <= DAIO_OUT_MAX) {
609 dao_rsc_uninit(container_of(daio, struct dao, daio));
610 kfree(container_of(daio, struct dao, daio));
611 } else {
612 dai_rsc_uninit(container_of(daio, struct dai, daio));
613 kfree(container_of(daio, struct dai, daio));
614 }
615
616 return 0;
617}
618
619static int daio_mgr_enb_daio(struct daio_mgr *mgr, struct daio *daio)
620{
621 struct hw *hw = mgr->mgr.hw;
622
623 if (DAIO_OUT_MAX >= daio->type) {
624 hw->daio_mgr_enb_dao(mgr->mgr.ctrl_blk,
625 daio_device_index(daio->type, hw));
626 } else {
627 hw->daio_mgr_enb_dai(mgr->mgr.ctrl_blk,
628 daio_device_index(daio->type, hw));
629 }
630 return 0;
631}
632
633static int daio_mgr_dsb_daio(struct daio_mgr *mgr, struct daio *daio)
634{
635 struct hw *hw = mgr->mgr.hw;
636
637 if (DAIO_OUT_MAX >= daio->type) {
638 hw->daio_mgr_dsb_dao(mgr->mgr.ctrl_blk,
639 daio_device_index(daio->type, hw));
640 } else {
641 hw->daio_mgr_dsb_dai(mgr->mgr.ctrl_blk,
642 daio_device_index(daio->type, hw));
643 }
644 return 0;
645}
646
647static int daio_map_op(void *data, struct imapper *entry)
648{
649 struct rsc_mgr *mgr = &((struct daio_mgr *)data)->mgr;
650 struct hw *hw = mgr->hw;
651
652 hw->daio_mgr_set_imaparc(mgr->ctrl_blk, entry->slot);
653 hw->daio_mgr_set_imapnxt(mgr->ctrl_blk, entry->next);
654 hw->daio_mgr_set_imapaddr(mgr->ctrl_blk, entry->addr);
655 hw->daio_mgr_commit_write(mgr->hw, mgr->ctrl_blk);
656
657 return 0;
658}
659
660static int daio_imap_add(struct daio_mgr *mgr, struct imapper *entry)
661{
662 unsigned long flags;
663 int err = 0;
664
665 spin_lock_irqsave(&mgr->imap_lock, flags);
666 if ((0 == entry->addr) && (mgr->init_imap_added)) {
667 input_mapper_delete(&mgr->imappers, mgr->init_imap,
668 daio_map_op, mgr);
669 mgr->init_imap_added = 0;
670 }
671 err = input_mapper_add(&mgr->imappers, entry, daio_map_op, mgr);
672 spin_unlock_irqrestore(&mgr->imap_lock, flags);
673
674 return err;
675}
676
677static int daio_imap_delete(struct daio_mgr *mgr, struct imapper *entry)
678{
679 unsigned long flags;
680 int err = 0;
681
682 spin_lock_irqsave(&mgr->imap_lock, flags);
683 err = input_mapper_delete(&mgr->imappers, entry, daio_map_op, mgr);
684 if (list_empty(&mgr->imappers)) {
685 input_mapper_add(&mgr->imappers, mgr->init_imap,
686 daio_map_op, mgr);
687 mgr->init_imap_added = 1;
688 }
689 spin_unlock_irqrestore(&mgr->imap_lock, flags);
690
691 return err;
692}
693
694static int daio_mgr_commit_write(struct daio_mgr *mgr)
695{
696 struct hw *hw = mgr->mgr.hw;
697
698 hw->daio_mgr_commit_write(hw, mgr->mgr.ctrl_blk);
699 return 0;
700}
701
702int daio_mgr_create(void *hw, struct daio_mgr **rdaio_mgr)
703{
704 int err = 0, i = 0;
705 struct daio_mgr *daio_mgr;
706 struct imapper *entry;
707
708 *rdaio_mgr = NULL;
709 daio_mgr = kzalloc(sizeof(*daio_mgr), GFP_KERNEL);
710 if (NULL == daio_mgr)
711 return -ENOMEM;
712
713 err = rsc_mgr_init(&daio_mgr->mgr, DAIO, DAIO_RESOURCE_NUM, hw);
714 if (err)
715 goto error1;
716
717 spin_lock_init(&daio_mgr->mgr_lock);
718 spin_lock_init(&daio_mgr->imap_lock);
719 INIT_LIST_HEAD(&daio_mgr->imappers);
720 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
721 if (NULL == entry) {
722 err = -ENOMEM;
723 goto error2;
724 }
725 entry->slot = entry->addr = entry->next = entry->user = 0;
726 list_add(&entry->list, &daio_mgr->imappers);
727 daio_mgr->init_imap = entry;
728 daio_mgr->init_imap_added = 1;
729
730 daio_mgr->get_daio = get_daio_rsc;
731 daio_mgr->put_daio = put_daio_rsc;
732 daio_mgr->daio_enable = daio_mgr_enb_daio;
733 daio_mgr->daio_disable = daio_mgr_dsb_daio;
734 daio_mgr->imap_add = daio_imap_add;
735 daio_mgr->imap_delete = daio_imap_delete;
736 daio_mgr->commit_write = daio_mgr_commit_write;
737
738 for (i = 0; i < 8; i++) {
739 ((struct hw *)hw)->daio_mgr_dsb_dao(daio_mgr->mgr.ctrl_blk, i);
740 ((struct hw *)hw)->daio_mgr_dsb_dai(daio_mgr->mgr.ctrl_blk, i);
741 }
742 ((struct hw *)hw)->daio_mgr_commit_write(hw, daio_mgr->mgr.ctrl_blk);
743
744 *rdaio_mgr = daio_mgr;
745
746 return 0;
747
748error2:
749 rsc_mgr_uninit(&daio_mgr->mgr);
750error1:
751 kfree(daio_mgr);
752 return err;
753}
754
755int daio_mgr_destroy(struct daio_mgr *daio_mgr)
756{
757 unsigned long flags;
758
759 /* free daio input mapper list */
760 spin_lock_irqsave(&daio_mgr->imap_lock, flags);
761 free_input_mapper_list(&daio_mgr->imappers);
762 spin_unlock_irqrestore(&daio_mgr->imap_lock, flags);
763
764 rsc_mgr_uninit(&daio_mgr->mgr);
765 kfree(daio_mgr);
766
767 return 0;
768}
769
diff --git a/sound/pci/ctxfi/ctdaio.h b/sound/pci/ctxfi/ctdaio.h
new file mode 100644
index 000000000000..0f52ce571ee8
--- /dev/null
+++ b/sound/pci/ctxfi/ctdaio.h
@@ -0,0 +1,122 @@
1/**
2 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
3 *
4 * This source file is released under GPL v2 license (no other versions).
5 * See the COPYING file included in the main directory of this source
6 * distribution for the license terms and conditions.
7 *
8 * @File ctdaio.h
9 *
10 * @Brief
11 * This file contains the definition of Digital Audio Input Output
12 * resource management object.
13 *
14 * @Author Liu Chun
15 * @Date May 23 2008
16 *
17 */
18
19#ifndef CTDAIO_H
20#define CTDAIO_H
21
22#include "ctresource.h"
23#include "ctimap.h"
24#include <linux/spinlock.h>
25#include <linux/list.h>
26
27/* Define the descriptor of a daio resource */
28enum DAIOTYP {
29 LINEO1,
30 LINEO2,
31 LINEO3,
32 LINEO4,
33 SPDIFOO, /* S/PDIF Out (Flexijack/Optical) */
34 LINEIM,
35 SPDIFIO, /* S/PDIF In (Flexijack/Optical) on the card */
36 SPDIFI1, /* S/PDIF In on internal Drive Bay */
37 NUM_DAIOTYP
38};
39
40struct dao_rsc_ops;
41struct dai_rsc_ops;
42struct daio_mgr;
43
44struct daio {
45 struct rsc rscl; /* Basic resource info for left TX/RX */
46 struct rsc rscr; /* Basic resource info for right TX/RX */
47 enum DAIOTYP type;
48};
49
50struct dao {
51 struct daio daio;
52 struct dao_rsc_ops *ops; /* DAO specific operations */
53 struct imapper **imappers;
54 struct daio_mgr *mgr;
55 void *hw;
56 void *ctrl_blk;
57};
58
59struct dai {
60 struct daio daio;
61 struct dai_rsc_ops *ops; /* DAI specific operations */
62 void *hw;
63 void *ctrl_blk;
64};
65
66struct dao_desc {
67 unsigned int msr:4;
68 unsigned int passthru:1;
69};
70
71struct dao_rsc_ops {
72 int (*set_spos)(struct dao *dao, unsigned int spos);
73 int (*commit_write)(struct dao *dao);
74 int (*get_spos)(struct dao *dao, unsigned int *spos);
75 int (*reinit)(struct dao *dao, const struct dao_desc *desc);
76 int (*set_left_input)(struct dao *dao, struct rsc *input);
77 int (*set_right_input)(struct dao *dao, struct rsc *input);
78 int (*clear_left_input)(struct dao *dao);
79 int (*clear_right_input)(struct dao *dao);
80};
81
82struct dai_rsc_ops {
83 int (*set_srt_srcl)(struct dai *dai, struct rsc *src);
84 int (*set_srt_srcr)(struct dai *dai, struct rsc *src);
85 int (*set_srt_msr)(struct dai *dai, unsigned int msr);
86 int (*set_enb_src)(struct dai *dai, unsigned int enb);
87 int (*set_enb_srt)(struct dai *dai, unsigned int enb);
88 int (*commit_write)(struct dai *dai);
89};
90
91/* Define daio resource request description info */
92struct daio_desc {
93 unsigned int type:4;
94 unsigned int msr:4;
95 unsigned int passthru:1;
96};
97
98struct daio_mgr {
99 struct rsc_mgr mgr; /* Basic resource manager info */
100 spinlock_t mgr_lock;
101 spinlock_t imap_lock;
102 struct list_head imappers;
103 struct imapper *init_imap;
104 unsigned int init_imap_added;
105
106 /* request one daio resource */
107 int (*get_daio)(struct daio_mgr *mgr,
108 const struct daio_desc *desc, struct daio **rdaio);
109 /* return one daio resource */
110 int (*put_daio)(struct daio_mgr *mgr, struct daio *daio);
111 int (*daio_enable)(struct daio_mgr *mgr, struct daio *daio);
112 int (*daio_disable)(struct daio_mgr *mgr, struct daio *daio);
113 int (*imap_add)(struct daio_mgr *mgr, struct imapper *entry);
114 int (*imap_delete)(struct daio_mgr *mgr, struct imapper *entry);
115 int (*commit_write)(struct daio_mgr *mgr);
116};
117
118/* Constructor and destructor of daio resource manager */
119int daio_mgr_create(void *hw, struct daio_mgr **rdaio_mgr);
120int daio_mgr_destroy(struct daio_mgr *daio_mgr);
121
122#endif /* CTDAIO_H */
diff --git a/sound/pci/ctxfi/ctdrv.h b/sound/pci/ctxfi/ctdrv.h
new file mode 100644
index 000000000000..f776a44f52cf
--- /dev/null
+++ b/sound/pci/ctxfi/ctdrv.h
@@ -0,0 +1,30 @@
1/**
2 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
3 *
4 * This source file is released under GPL v2 license (no other versions).
5 * See the COPYING file included in the main directory of this source
6 * distribution for the license terms and conditions.
7 *
8 * @file ctdrv.h
9 *
10 * @breaf
11 * This file contains the definition of card IDs supported by this driver.
12 *
13 * @author Liu Chun
14 *
15 */
16
17#ifndef CTDRV_H
18#define CTDRV_H
19
20#define PCI_VENDOR_CREATIVE 0x1102
21#define PCI_DEVICE_CREATIVE_20K1 0x0005
22#define PCI_DEVICE_CREATIVE_20K2 0x000B
23#define PCI_SUBVENDOR_CREATIVE 0x1102
24#define PCI_SUBSYS_CREATIVE_SB0760 0x0024
25#define PCI_SUBSYS_CREATIVE_SB08801 0x0041
26#define PCI_SUBSYS_CREATIVE_SB08802 0x0042
27#define PCI_SUBSYS_CREATIVE_SB08803 0x0043
28#define PCI_SUBSYS_CREATIVE_HENDRIX 0x6000
29
30#endif /* CTDRV_H */
diff --git a/sound/pci/ctxfi/cthardware.c b/sound/pci/ctxfi/cthardware.c
new file mode 100644
index 000000000000..8e58860f641c
--- /dev/null
+++ b/sound/pci/ctxfi/cthardware.c
@@ -0,0 +1,108 @@
1/**
2 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
3 *
4 * This source file is released under GPL v2 license (no other versions).
5 * See the COPYING file included in the main directory of this source
6 * distribution for the license terms and conditions.
7 *
8 * @File cthardware.c
9 *
10 * @Brief
11 * This file contains the implementation of hardware access methord.
12 *
13 * @Author Liu Chun
14 * @Date Jun 26 2008
15 *
16 */
17
18#include "cthardware.h"
19#include "cthw20k1.h"
20#include "cthw20k2.h"
21#include <linux/bug.h>
22
23static enum CHIPTYP get_chip_type(struct hw *hw)
24{
25 enum CHIPTYP type = ATCNONE;
26
27 switch (hw->pci->device) {
28 case 0x0005: /* 20k1 device */
29 type = ATC20K1;
30 break;
31 case 0x000B: /* 20k2 device */
32 type = ATC20K2;
33 break;
34 default:
35 type = ATCNONE;
36 break;
37 }
38
39 return type;
40}
41
42int create_hw_obj(struct pci_dev *pci, struct hw **rhw)
43{
44 int err = 0;
45
46 switch (pci->device) {
47 case 0x0005: /* 20k1 device */
48 err = create_20k1_hw_obj(rhw);
49 break;
50 case 0x000B: /* 20k2 device */
51 err = create_20k2_hw_obj(rhw);
52 break;
53 default:
54 err = -ENODEV;
55 break;
56 }
57 if (err)
58 return err;
59
60 (*rhw)->pci = pci;
61 (*rhw)->get_chip_type = get_chip_type;
62
63 return 0;
64}
65
66int destroy_hw_obj(struct hw *hw)
67{
68 int err = 0;
69
70 switch (hw->pci->device) {
71 case 0x0005: /* 20k1 device */
72 err = destroy_20k1_hw_obj(hw);
73 break;
74 case 0x000B: /* 20k2 device */
75 err = destroy_20k2_hw_obj(hw);
76 break;
77 default:
78 err = -ENODEV;
79 break;
80 }
81
82 return err;
83}
84
85unsigned int get_field(unsigned int data, unsigned int field)
86{
87 int i;
88
89 BUG_ON(!field);
90 /* @field should always be greater than 0 */
91 for (i = 0; !(field & (1 << i)); )
92 i++;
93
94 return (data & field) >> i;
95}
96
97void set_field(unsigned int *data, unsigned int field, unsigned int value)
98{
99 int i;
100
101 BUG_ON(!field);
102 /* @field should always be greater than 0 */
103 for (i = 0; !(field & (1 << i)); )
104 i++;
105
106 *data = (*data & (~field)) | ((value << i) & field);
107}
108
diff --git a/sound/pci/ctxfi/cthardware.h b/sound/pci/ctxfi/cthardware.h
new file mode 100644
index 000000000000..b0512df8b334
--- /dev/null
+++ b/sound/pci/ctxfi/cthardware.h
@@ -0,0 +1,160 @@
1/**
2 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
3 *
4 * This source file is released under GPL v2 license (no other versions).
5 * See the COPYING file included in the main directory of this source
6 * distribution for the license terms and conditions.
7 *
8 * @File cthardware.h
9 *
10 * @Brief
11 * This file contains the definition of hardware access methord.
12 *
13 * @Author Liu Chun
14 * @Date May 13 2008
15 *
16 */
17
18#ifndef CTHARDWARE_H
19#define CTHARDWARE_H
20
21#include <linux/types.h>
22#include <linux/pci.h>
23
24enum CHIPTYP {
25 ATC20K1,
26 ATC20K2,
27 ATCNONE
28};
29
30/* Type of input source for ADC */
31enum ADCSRC{
32 ADC_MICIN,
33 ADC_LINEIN,
34 ADC_VIDEO,
35 ADC_AUX,
36 ADC_NONE /* Switch to digital input */
37};
38
39struct card_conf {
40 /* device virtual mem page table page physical addr
41 * (supporting one page table page now) */
42 unsigned long vm_pgt_phys;
43 unsigned int rsr; /* reference sample rate in Hzs*/
44 unsigned int msr; /* master sample rate in rsrs */
45};
46
47struct hw {
48 int (*card_init)(struct hw *hw, struct card_conf *info);
49 int (*card_stop)(struct hw *hw);
50 int (*pll_init)(struct hw *hw, unsigned int rsr);
51 enum CHIPTYP (*get_chip_type)(struct hw *hw);
52 int (*is_adc_source_selected)(struct hw *hw, enum ADCSRC source);
53 int (*select_adc_source)(struct hw *hw, enum ADCSRC source);
54 int (*have_digit_io_switch)(struct hw *hw);
55
56 /* SRC operations */
57 int (*src_rsc_get_ctrl_blk)(void **rblk);
58 int (*src_rsc_put_ctrl_blk)(void *blk);
59 int (*src_set_state)(void *blk, unsigned int state);
60 int (*src_set_bm)(void *blk, unsigned int bm);
61 int (*src_set_rsr)(void *blk, unsigned int rsr);
62 int (*src_set_sf)(void *blk, unsigned int sf);
63 int (*src_set_wr)(void *blk, unsigned int wr);
64 int (*src_set_pm)(void *blk, unsigned int pm);
65 int (*src_set_rom)(void *blk, unsigned int rom);
66 int (*src_set_vo)(void *blk, unsigned int vo);
67 int (*src_set_st)(void *blk, unsigned int st);
68 int (*src_set_ie)(void *blk, unsigned int ie);
69 int (*src_set_ilsz)(void *blk, unsigned int ilsz);
70 int (*src_set_bp)(void *blk, unsigned int bp);
71 int (*src_set_cisz)(void *blk, unsigned int cisz);
72 int (*src_set_ca)(void *blk, unsigned int ca);
73 int (*src_set_sa)(void *blk, unsigned int sa);
74 int (*src_set_la)(void *blk, unsigned int la);
75 int (*src_set_pitch)(void *blk, unsigned int pitch);
76 int (*src_set_clear_zbufs)(void *blk, unsigned int clear);
77 int (*src_set_dirty)(void *blk, unsigned int flags);
78 int (*src_set_dirty_all)(void *blk);
79 int (*src_commit_write)(struct hw *hw, unsigned int idx, void *blk);
80 int (*src_get_ca)(struct hw *hw, unsigned int idx, void *blk);
81 unsigned int (*src_get_dirty)(void *blk);
82 unsigned int (*src_dirty_conj_mask)(void);
83 int (*src_mgr_get_ctrl_blk)(void **rblk);
84 int (*src_mgr_put_ctrl_blk)(void *blk);
85 /* syncly enable src @idx */
86 int (*src_mgr_enbs_src)(void *blk, unsigned int idx);
87 /* enable src @idx */
88 int (*src_mgr_enb_src)(void *blk, unsigned int idx);
89 /* disable src @idx */
90 int (*src_mgr_dsb_src)(void *blk, unsigned int idx);
91 int (*src_mgr_commit_write)(struct hw *hw, void *blk);
92
93 /* SRC Input Mapper operations */
94 int (*srcimp_mgr_get_ctrl_blk)(void **rblk);
95 int (*srcimp_mgr_put_ctrl_blk)(void *blk);
96 int (*srcimp_mgr_set_imaparc)(void *blk, unsigned int slot);
97 int (*srcimp_mgr_set_imapuser)(void *blk, unsigned int user);
98 int (*srcimp_mgr_set_imapnxt)(void *blk, unsigned int next);
99 int (*srcimp_mgr_set_imapaddr)(void *blk, unsigned int addr);
100 int (*srcimp_mgr_commit_write)(struct hw *hw, void *blk);
101
102 /* AMIXER operations */
103 int (*amixer_rsc_get_ctrl_blk)(void **rblk);
104 int (*amixer_rsc_put_ctrl_blk)(void *blk);
105 int (*amixer_mgr_get_ctrl_blk)(void **rblk);
106 int (*amixer_mgr_put_ctrl_blk)(void *blk);
107 int (*amixer_set_mode)(void *blk, unsigned int mode);
108 int (*amixer_set_iv)(void *blk, unsigned int iv);
109 int (*amixer_set_x)(void *blk, unsigned int x);
110 int (*amixer_set_y)(void *blk, unsigned int y);
111 int (*amixer_set_sadr)(void *blk, unsigned int sadr);
112 int (*amixer_set_se)(void *blk, unsigned int se);
113 int (*amixer_set_dirty)(void *blk, unsigned int flags);
114 int (*amixer_set_dirty_all)(void *blk);
115 int (*amixer_commit_write)(struct hw *hw, unsigned int idx, void *blk);
116 int (*amixer_get_y)(void *blk);
117 unsigned int (*amixer_get_dirty)(void *blk);
118
119 /* DAIO operations */
120 int (*dai_get_ctrl_blk)(void **rblk);
121 int (*dai_put_ctrl_blk)(void *blk);
122 int (*dai_srt_set_srco)(void *blk, unsigned int src);
123 int (*dai_srt_set_srcm)(void *blk, unsigned int src);
124 int (*dai_srt_set_rsr)(void *blk, unsigned int rsr);
125 int (*dai_srt_set_drat)(void *blk, unsigned int drat);
126 int (*dai_srt_set_ec)(void *blk, unsigned int ec);
127 int (*dai_srt_set_et)(void *blk, unsigned int et);
128 int (*dai_commit_write)(struct hw *hw, unsigned int idx, void *blk);
129 int (*dao_get_ctrl_blk)(void **rblk);
130 int (*dao_put_ctrl_blk)(void *blk);
131 int (*dao_set_spos)(void *blk, unsigned int spos);
132 int (*dao_commit_write)(struct hw *hw, unsigned int idx, void *blk);
133 int (*dao_get_spos)(void *blk, unsigned int *spos);
134
135 int (*daio_mgr_get_ctrl_blk)(struct hw *hw, void **rblk);
136 int (*daio_mgr_put_ctrl_blk)(void *blk);
137 int (*daio_mgr_enb_dai)(void *blk, unsigned int idx);
138 int (*daio_mgr_dsb_dai)(void *blk, unsigned int idx);
139 int (*daio_mgr_enb_dao)(void *blk, unsigned int idx);
140 int (*daio_mgr_dsb_dao)(void *blk, unsigned int idx);
141 int (*daio_mgr_dao_init)(void *blk, unsigned int idx,
142 unsigned int conf);
143 int (*daio_mgr_set_imaparc)(void *blk, unsigned int slot);
144 int (*daio_mgr_set_imapnxt)(void *blk, unsigned int next);
145 int (*daio_mgr_set_imapaddr)(void *blk, unsigned int addr);
146 int (*daio_mgr_commit_write)(struct hw *hw, void *blk);
147
148 struct pci_dev *pci; /* the pci kernel structure of this card */
149 int irq;
150 unsigned long io_base;
151 unsigned long mem_base;
152};
153
154int create_hw_obj(struct pci_dev *pci, struct hw **rhw);
155int destroy_hw_obj(struct hw *hw);
156
157unsigned int get_field(unsigned int data, unsigned int field);
158void set_field(unsigned int *data, unsigned int field, unsigned int value);
159
160#endif /* CTHARDWARE_H */
diff --git a/sound/pci/ctxfi/cthw20k1.c b/sound/pci/ctxfi/cthw20k1.c
new file mode 100644
index 000000000000..53572d92ef5d
--- /dev/null
+++ b/sound/pci/ctxfi/cthw20k1.c
@@ -0,0 +1,2230 @@
1/**
2 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
3 *
4 * This source file is released under GPL v2 license (no other versions).
5 * See the COPYING file included in the main directory of this source
6 * distribution for the license terms and conditions.
7 *
8 * @File cthw20k1.c
9 *
10 * @Brief
11 * This file contains the implementation of hardware access methord for 20k1.
12 *
13 * @Author Liu Chun
14 * @Date Jun 24 2008
15 *
16 */
17
18#include "cthw20k1.h"
19#include "ct20k1reg.h"
20#include <linux/types.h>
21#include <linux/slab.h>
22#include <linux/pci.h>
23#include <linux/io.h>
24#include <linux/string.h>
25#include <linux/spinlock.h>
26#include <linux/kernel.h>
27#include <linux/interrupt.h>
28
29#define CT_XFI_DMA_MASK DMA_BIT_MASK(32) /* 32 bits */
30
31struct hw20k1 {
32 struct hw hw;
33 spinlock_t reg_20k1_lock;
34 spinlock_t reg_pci_lock;
35};
36
37static u32 hw_read_20kx(struct hw *hw, u32 reg);
38static void hw_write_20kx(struct hw *hw, u32 reg, u32 data);
39static u32 hw_read_pci(struct hw *hw, u32 reg);
40static void hw_write_pci(struct hw *hw, u32 reg, u32 data);
41
42/*
43 * Type definition block.
44 * The layout of control structures can be directly applied on 20k2 chip.
45 */
46
47/*
48 * SRC control block definitions.
49 */
50
51/* SRC resource control block */
52#define SRCCTL_STATE 0x00000007
53#define SRCCTL_BM 0x00000008
54#define SRCCTL_RSR 0x00000030
55#define SRCCTL_SF 0x000001C0
56#define SRCCTL_WR 0x00000200
57#define SRCCTL_PM 0x00000400
58#define SRCCTL_ROM 0x00001800
59#define SRCCTL_VO 0x00002000
60#define SRCCTL_ST 0x00004000
61#define SRCCTL_IE 0x00008000
62#define SRCCTL_ILSZ 0x000F0000
63#define SRCCTL_BP 0x00100000
64
65#define SRCCCR_CISZ 0x000007FF
66#define SRCCCR_CWA 0x001FF800
67#define SRCCCR_D 0x00200000
68#define SRCCCR_RS 0x01C00000
69#define SRCCCR_NAL 0x3E000000
70#define SRCCCR_RA 0xC0000000
71
72#define SRCCA_CA 0x03FFFFFF
73#define SRCCA_RS 0x1C000000
74#define SRCCA_NAL 0xE0000000
75
76#define SRCSA_SA 0x03FFFFFF
77
78#define SRCLA_LA 0x03FFFFFF
79
80/* Mixer Parameter Ring ram Low and Hight register.
81 * Fixed-point value in 8.24 format for parameter channel */
82#define MPRLH_PITCH 0xFFFFFFFF
83
84/* SRC resource register dirty flags */
85union src_dirty {
86 struct {
87 u16 ctl:1;
88 u16 ccr:1;
89 u16 sa:1;
90 u16 la:1;
91 u16 ca:1;
92 u16 mpr:1;
93 u16 czbfs:1; /* Clear Z-Buffers */
94 u16 rsv:9;
95 } bf;
96 u16 data;
97};
98
99struct src_rsc_ctrl_blk {
100 unsigned int ctl;
101 unsigned int ccr;
102 unsigned int ca;
103 unsigned int sa;
104 unsigned int la;
105 unsigned int mpr;
106 union src_dirty dirty;
107};
108
109/* SRC manager control block */
110union src_mgr_dirty {
111 struct {
112 u16 enb0:1;
113 u16 enb1:1;
114 u16 enb2:1;
115 u16 enb3:1;
116 u16 enb4:1;
117 u16 enb5:1;
118 u16 enb6:1;
119 u16 enb7:1;
120 u16 enbsa:1;
121 u16 rsv:7;
122 } bf;
123 u16 data;
124};
125
126struct src_mgr_ctrl_blk {
127 unsigned int enbsa;
128 unsigned int enb[8];
129 union src_mgr_dirty dirty;
130};
131
132/* SRCIMP manager control block */
133#define SRCAIM_ARC 0x00000FFF
134#define SRCAIM_NXT 0x00FF0000
135#define SRCAIM_SRC 0xFF000000
136
137struct srcimap {
138 unsigned int srcaim;
139 unsigned int idx;
140};
141
142/* SRCIMP manager register dirty flags */
143union srcimp_mgr_dirty {
144 struct {
145 u16 srcimap:1;
146 u16 rsv:15;
147 } bf;
148 u16 data;
149};
150
151struct srcimp_mgr_ctrl_blk {
152 struct srcimap srcimap;
153 union srcimp_mgr_dirty dirty;
154};
155
156/*
157 * Function implementation block.
158 */
159
160static int src_get_rsc_ctrl_blk(void **rblk)
161{
162 struct src_rsc_ctrl_blk *blk;
163
164 *rblk = NULL;
165 blk = kzalloc(sizeof(*blk), GFP_KERNEL);
166 if (NULL == blk)
167 return -ENOMEM;
168
169 *rblk = blk;
170
171 return 0;
172}
173
174static int src_put_rsc_ctrl_blk(void *blk)
175{
176 kfree((struct src_rsc_ctrl_blk *)blk);
177
178 return 0;
179}
180
181static int src_set_state(void *blk, unsigned int state)
182{
183 struct src_rsc_ctrl_blk *ctl = blk;
184
185 set_field(&ctl->ctl, SRCCTL_STATE, state);
186 ctl->dirty.bf.ctl = 1;
187 return 0;
188}
189
190static int src_set_bm(void *blk, unsigned int bm)
191{
192 struct src_rsc_ctrl_blk *ctl = blk;
193
194 set_field(&ctl->ctl, SRCCTL_BM, bm);
195 ctl->dirty.bf.ctl = 1;
196 return 0;
197}
198
199static int src_set_rsr(void *blk, unsigned int rsr)
200{
201 struct src_rsc_ctrl_blk *ctl = blk;
202
203 set_field(&ctl->ctl, SRCCTL_RSR, rsr);
204 ctl->dirty.bf.ctl = 1;
205 return 0;
206}
207
208static int src_set_sf(void *blk, unsigned int sf)
209{
210 struct src_rsc_ctrl_blk *ctl = blk;
211
212 set_field(&ctl->ctl, SRCCTL_SF, sf);
213 ctl->dirty.bf.ctl = 1;
214 return 0;
215}
216
217static int src_set_wr(void *blk, unsigned int wr)
218{
219 struct src_rsc_ctrl_blk *ctl = blk;
220
221 set_field(&ctl->ctl, SRCCTL_WR, wr);
222 ctl->dirty.bf.ctl = 1;
223 return 0;
224}
225
226static int src_set_pm(void *blk, unsigned int pm)
227{
228 struct src_rsc_ctrl_blk *ctl = blk;
229
230 set_field(&ctl->ctl, SRCCTL_PM, pm);
231 ctl->dirty.bf.ctl = 1;
232 return 0;
233}
234
235static int src_set_rom(void *blk, unsigned int rom)
236{
237 struct src_rsc_ctrl_blk *ctl = blk;
238
239 set_field(&ctl->ctl, SRCCTL_ROM, rom);
240 ctl->dirty.bf.ctl = 1;
241 return 0;
242}
243
244static int src_set_vo(void *blk, unsigned int vo)
245{
246 struct src_rsc_ctrl_blk *ctl = blk;
247
248 set_field(&ctl->ctl, SRCCTL_VO, vo);
249 ctl->dirty.bf.ctl = 1;
250 return 0;
251}
252
253static int src_set_st(void *blk, unsigned int st)
254{
255 struct src_rsc_ctrl_blk *ctl = blk;
256
257 set_field(&ctl->ctl, SRCCTL_ST, st);
258 ctl->dirty.bf.ctl = 1;
259 return 0;
260}
261
262static int src_set_ie(void *blk, unsigned int ie)
263{
264 struct src_rsc_ctrl_blk *ctl = blk;
265
266 set_field(&ctl->ctl, SRCCTL_IE, ie);
267 ctl->dirty.bf.ctl = 1;
268 return 0;
269}
270
271static int src_set_ilsz(void *blk, unsigned int ilsz)
272{
273 struct src_rsc_ctrl_blk *ctl = blk;
274
275 set_field(&ctl->ctl, SRCCTL_ILSZ, ilsz);
276 ctl->dirty.bf.ctl = 1;
277 return 0;
278}
279
280static int src_set_bp(void *blk, unsigned int bp)
281{
282 struct src_rsc_ctrl_blk *ctl = blk;
283
284 set_field(&ctl->ctl, SRCCTL_BP, bp);
285 ctl->dirty.bf.ctl = 1;
286 return 0;
287}
288
289static int src_set_cisz(void *blk, unsigned int cisz)
290{
291 struct src_rsc_ctrl_blk *ctl = blk;
292
293 set_field(&ctl->ccr, SRCCCR_CISZ, cisz);
294 ctl->dirty.bf.ccr = 1;
295 return 0;
296}
297
298static int src_set_ca(void *blk, unsigned int ca)
299{
300 struct src_rsc_ctrl_blk *ctl = blk;
301
302 set_field(&ctl->ca, SRCCA_CA, ca);
303 ctl->dirty.bf.ca = 1;
304 return 0;
305}
306
307static int src_set_sa(void *blk, unsigned int sa)
308{
309 struct src_rsc_ctrl_blk *ctl = blk;
310
311 set_field(&ctl->sa, SRCSA_SA, sa);
312 ctl->dirty.bf.sa = 1;
313 return 0;
314}
315
316static int src_set_la(void *blk, unsigned int la)
317{
318 struct src_rsc_ctrl_blk *ctl = blk;
319
320 set_field(&ctl->la, SRCLA_LA, la);
321 ctl->dirty.bf.la = 1;
322 return 0;
323}
324
325static int src_set_pitch(void *blk, unsigned int pitch)
326{
327 struct src_rsc_ctrl_blk *ctl = blk;
328
329 set_field(&ctl->mpr, MPRLH_PITCH, pitch);
330 ctl->dirty.bf.mpr = 1;
331 return 0;
332}
333
334static int src_set_clear_zbufs(void *blk, unsigned int clear)
335{
336 ((struct src_rsc_ctrl_blk *)blk)->dirty.bf.czbfs = (clear ? 1 : 0);
337 return 0;
338}
339
340static int src_set_dirty(void *blk, unsigned int flags)
341{
342 ((struct src_rsc_ctrl_blk *)blk)->dirty.data = (flags & 0xffff);
343 return 0;
344}
345
346static int src_set_dirty_all(void *blk)
347{
348 ((struct src_rsc_ctrl_blk *)blk)->dirty.data = ~(0x0);
349 return 0;
350}
351
352#define AR_SLOT_SIZE 4096
353#define AR_SLOT_BLOCK_SIZE 16
354#define AR_PTS_PITCH 6
355#define AR_PARAM_SRC_OFFSET 0x60
356
357static unsigned int src_param_pitch_mixer(unsigned int src_idx)
358{
359 return ((src_idx << 4) + AR_PTS_PITCH + AR_SLOT_SIZE
360 - AR_PARAM_SRC_OFFSET) % AR_SLOT_SIZE;
361
362}
363
364static int src_commit_write(struct hw *hw, unsigned int idx, void *blk)
365{
366 struct src_rsc_ctrl_blk *ctl = blk;
367 int i = 0;
368
369 if (ctl->dirty.bf.czbfs) {
370 /* Clear Z-Buffer registers */
371 for (i = 0; i < 8; i++)
372 hw_write_20kx(hw, SRCUPZ+idx*0x100+i*0x4, 0);
373
374 for (i = 0; i < 4; i++)
375 hw_write_20kx(hw, SRCDN0Z+idx*0x100+i*0x4, 0);
376
377 for (i = 0; i < 8; i++)
378 hw_write_20kx(hw, SRCDN1Z+idx*0x100+i*0x4, 0);
379
380 ctl->dirty.bf.czbfs = 0;
381 }
382 if (ctl->dirty.bf.mpr) {
383 /* Take the parameter mixer resource in the same group as that
384 * the idx src is in for simplicity. Unlike src, all conjugate
385 * parameter mixer resources must be programmed for
386 * corresponding conjugate src resources. */
387 unsigned int pm_idx = src_param_pitch_mixer(idx);
388 hw_write_20kx(hw, PRING_LO_HI+4*pm_idx, ctl->mpr);
389 hw_write_20kx(hw, PMOPLO+8*pm_idx, 0x3);
390 hw_write_20kx(hw, PMOPHI+8*pm_idx, 0x0);
391 ctl->dirty.bf.mpr = 0;
392 }
393 if (ctl->dirty.bf.sa) {
394 hw_write_20kx(hw, SRCSA+idx*0x100, ctl->sa);
395 ctl->dirty.bf.sa = 0;
396 }
397 if (ctl->dirty.bf.la) {
398 hw_write_20kx(hw, SRCLA+idx*0x100, ctl->la);
399 ctl->dirty.bf.la = 0;
400 }
401 if (ctl->dirty.bf.ca) {
402 hw_write_20kx(hw, SRCCA+idx*0x100, ctl->ca);
403 ctl->dirty.bf.ca = 0;
404 }
405
406 /* Write srccf register */
407 hw_write_20kx(hw, SRCCF+idx*0x100, 0x0);
408
409 if (ctl->dirty.bf.ccr) {
410 hw_write_20kx(hw, SRCCCR+idx*0x100, ctl->ccr);
411 ctl->dirty.bf.ccr = 0;
412 }
413 if (ctl->dirty.bf.ctl) {
414 hw_write_20kx(hw, SRCCTL+idx*0x100, ctl->ctl);
415 ctl->dirty.bf.ctl = 0;
416 }
417
418 return 0;
419}
420
421static int src_get_ca(struct hw *hw, unsigned int idx, void *blk)
422{
423 struct src_rsc_ctrl_blk *ctl = blk;
424
425 ctl->ca = hw_read_20kx(hw, SRCCA+idx*0x100);
426 ctl->dirty.bf.ca = 0;
427
428 return get_field(ctl->ca, SRCCA_CA);
429}
430
431static unsigned int src_get_dirty(void *blk)
432{
433 return ((struct src_rsc_ctrl_blk *)blk)->dirty.data;
434}
435
436static unsigned int src_dirty_conj_mask(void)
437{
438 return 0x20;
439}
440
441static int src_mgr_enbs_src(void *blk, unsigned int idx)
442{
443 ((struct src_mgr_ctrl_blk *)blk)->enbsa = ~(0x0);
444 ((struct src_mgr_ctrl_blk *)blk)->dirty.bf.enbsa = 1;
445 ((struct src_mgr_ctrl_blk *)blk)->enb[idx/32] |= (0x1 << (idx%32));
446 return 0;
447}
448
449static int src_mgr_enb_src(void *blk, unsigned int idx)
450{
451 ((struct src_mgr_ctrl_blk *)blk)->enb[idx/32] |= (0x1 << (idx%32));
452 ((struct src_mgr_ctrl_blk *)blk)->dirty.data |= (0x1 << (idx/32));
453 return 0;
454}
455
456static int src_mgr_dsb_src(void *blk, unsigned int idx)
457{
458 ((struct src_mgr_ctrl_blk *)blk)->enb[idx/32] &= ~(0x1 << (idx%32));
459 ((struct src_mgr_ctrl_blk *)blk)->dirty.data |= (0x1 << (idx/32));
460 return 0;
461}
462
463static int src_mgr_commit_write(struct hw *hw, void *blk)
464{
465 struct src_mgr_ctrl_blk *ctl = blk;
466 int i = 0;
467 unsigned int ret = 0;
468
469 if (ctl->dirty.bf.enbsa) {
470 do {
471 ret = hw_read_20kx(hw, SRCENBSTAT);
472 } while (ret & 0x1);
473 hw_write_20kx(hw, SRCENBS, ctl->enbsa);
474 ctl->dirty.bf.enbsa = 0;
475 }
476 for (i = 0; i < 8; i++) {
477 if ((ctl->dirty.data & (0x1 << i))) {
478 hw_write_20kx(hw, SRCENB+(i*0x100), ctl->enb[i]);
479 ctl->dirty.data &= ~(0x1 << i);
480 }
481 }
482
483 return 0;
484}
485
486static int src_mgr_get_ctrl_blk(void **rblk)
487{
488 struct src_mgr_ctrl_blk *blk;
489
490 *rblk = NULL;
491 blk = kzalloc(sizeof(*blk), GFP_KERNEL);
492 if (NULL == blk)
493 return -ENOMEM;
494
495 *rblk = blk;
496
497 return 0;
498}
499
500static int src_mgr_put_ctrl_blk(void *blk)
501{
502 kfree((struct src_mgr_ctrl_blk *)blk);
503
504 return 0;
505}
506
507static int srcimp_mgr_get_ctrl_blk(void **rblk)
508{
509 struct srcimp_mgr_ctrl_blk *blk;
510
511 *rblk = NULL;
512 blk = kzalloc(sizeof(*blk), GFP_KERNEL);
513 if (NULL == blk)
514 return -ENOMEM;
515
516 *rblk = blk;
517
518 return 0;
519}
520
521static int srcimp_mgr_put_ctrl_blk(void *blk)
522{
523 kfree((struct srcimp_mgr_ctrl_blk *)blk);
524
525 return 0;
526}
527
528static int srcimp_mgr_set_imaparc(void *blk, unsigned int slot)
529{
530 struct srcimp_mgr_ctrl_blk *ctl = blk;
531
532 set_field(&ctl->srcimap.srcaim, SRCAIM_ARC, slot);
533 ctl->dirty.bf.srcimap = 1;
534 return 0;
535}
536
537static int srcimp_mgr_set_imapuser(void *blk, unsigned int user)
538{
539 struct srcimp_mgr_ctrl_blk *ctl = blk;
540
541 set_field(&ctl->srcimap.srcaim, SRCAIM_SRC, user);
542 ctl->dirty.bf.srcimap = 1;
543 return 0;
544}
545
546static int srcimp_mgr_set_imapnxt(void *blk, unsigned int next)
547{
548 struct srcimp_mgr_ctrl_blk *ctl = blk;
549
550 set_field(&ctl->srcimap.srcaim, SRCAIM_NXT, next);
551 ctl->dirty.bf.srcimap = 1;
552 return 0;
553}
554
555static int srcimp_mgr_set_imapaddr(void *blk, unsigned int addr)
556{
557 struct srcimp_mgr_ctrl_blk *ctl = blk;
558
559 ctl->srcimap.idx = addr;
560 ctl->dirty.bf.srcimap = 1;
561 return 0;
562}
563
564static int srcimp_mgr_commit_write(struct hw *hw, void *blk)
565{
566 struct srcimp_mgr_ctrl_blk *ctl = blk;
567
568 if (ctl->dirty.bf.srcimap) {
569 hw_write_20kx(hw, SRCIMAP+ctl->srcimap.idx*0x100,
570 ctl->srcimap.srcaim);
571 ctl->dirty.bf.srcimap = 0;
572 }
573
574 return 0;
575}
576
577/*
578 * AMIXER control block definitions.
579 */
580
581#define AMOPLO_M 0x00000003
582#define AMOPLO_X 0x0003FFF0
583#define AMOPLO_Y 0xFFFC0000
584
585#define AMOPHI_SADR 0x000000FF
586#define AMOPHI_SE 0x80000000
587
588/* AMIXER resource register dirty flags */
589union amixer_dirty {
590 struct {
591 u16 amoplo:1;
592 u16 amophi:1;
593 u16 rsv:14;
594 } bf;
595 u16 data;
596};
597
598/* AMIXER resource control block */
599struct amixer_rsc_ctrl_blk {
600 unsigned int amoplo;
601 unsigned int amophi;
602 union amixer_dirty dirty;
603};
604
605static int amixer_set_mode(void *blk, unsigned int mode)
606{
607 struct amixer_rsc_ctrl_blk *ctl = blk;
608
609 set_field(&ctl->amoplo, AMOPLO_M, mode);
610 ctl->dirty.bf.amoplo = 1;
611 return 0;
612}
613
614static int amixer_set_iv(void *blk, unsigned int iv)
615{
616 /* 20k1 amixer does not have this field */
617 return 0;
618}
619
620static int amixer_set_x(void *blk, unsigned int x)
621{
622 struct amixer_rsc_ctrl_blk *ctl = blk;
623
624 set_field(&ctl->amoplo, AMOPLO_X, x);
625 ctl->dirty.bf.amoplo = 1;
626 return 0;
627}
628
629static int amixer_set_y(void *blk, unsigned int y)
630{
631 struct amixer_rsc_ctrl_blk *ctl = blk;
632
633 set_field(&ctl->amoplo, AMOPLO_Y, y);
634 ctl->dirty.bf.amoplo = 1;
635 return 0;
636}
637
638static int amixer_set_sadr(void *blk, unsigned int sadr)
639{
640 struct amixer_rsc_ctrl_blk *ctl = blk;
641
642 set_field(&ctl->amophi, AMOPHI_SADR, sadr);
643 ctl->dirty.bf.amophi = 1;
644 return 0;
645}
646
647static int amixer_set_se(void *blk, unsigned int se)
648{
649 struct amixer_rsc_ctrl_blk *ctl = blk;
650
651 set_field(&ctl->amophi, AMOPHI_SE, se);
652 ctl->dirty.bf.amophi = 1;
653 return 0;
654}
655
656static int amixer_set_dirty(void *blk, unsigned int flags)
657{
658 ((struct amixer_rsc_ctrl_blk *)blk)->dirty.data = (flags & 0xffff);
659 return 0;
660}
661
662static int amixer_set_dirty_all(void *blk)
663{
664 ((struct amixer_rsc_ctrl_blk *)blk)->dirty.data = ~(0x0);
665 return 0;
666}
667
668static int amixer_commit_write(struct hw *hw, unsigned int idx, void *blk)
669{
670 struct amixer_rsc_ctrl_blk *ctl = blk;
671
672 if (ctl->dirty.bf.amoplo || ctl->dirty.bf.amophi) {
673 hw_write_20kx(hw, AMOPLO+idx*8, ctl->amoplo);
674 ctl->dirty.bf.amoplo = 0;
675 hw_write_20kx(hw, AMOPHI+idx*8, ctl->amophi);
676 ctl->dirty.bf.amophi = 0;
677 }
678
679 return 0;
680}
681
682static int amixer_get_y(void *blk)
683{
684 struct amixer_rsc_ctrl_blk *ctl = blk;
685
686 return get_field(ctl->amoplo, AMOPLO_Y);
687}
688
689static unsigned int amixer_get_dirty(void *blk)
690{
691 return ((struct amixer_rsc_ctrl_blk *)blk)->dirty.data;
692}
693
694static int amixer_rsc_get_ctrl_blk(void **rblk)
695{
696 struct amixer_rsc_ctrl_blk *blk;
697
698 *rblk = NULL;
699 blk = kzalloc(sizeof(*blk), GFP_KERNEL);
700 if (NULL == blk)
701 return -ENOMEM;
702
703 *rblk = blk;
704
705 return 0;
706}
707
708static int amixer_rsc_put_ctrl_blk(void *blk)
709{
710 kfree((struct amixer_rsc_ctrl_blk *)blk);
711
712 return 0;
713}
714
715static int amixer_mgr_get_ctrl_blk(void **rblk)
716{
717 /*amixer_mgr_ctrl_blk_t *blk;*/
718
719 *rblk = NULL;
720 /*blk = kzalloc(sizeof(*blk), GFP_KERNEL);
721 if (NULL == blk)
722 return -ENOMEM;
723
724 *rblk = blk;*/
725
726 return 0;
727}
728
729static int amixer_mgr_put_ctrl_blk(void *blk)
730{
731 /*kfree((amixer_mgr_ctrl_blk_t *)blk);*/
732
733 return 0;
734}
735
736/*
737 * DAIO control block definitions.
738 */
739
740/* Receiver Sample Rate Tracker Control register */
741#define SRTCTL_SRCR 0x000000FF
742#define SRTCTL_SRCL 0x0000FF00
743#define SRTCTL_RSR 0x00030000
744#define SRTCTL_DRAT 0x000C0000
745#define SRTCTL_RLE 0x10000000
746#define SRTCTL_RLP 0x20000000
747#define SRTCTL_EC 0x40000000
748#define SRTCTL_ET 0x80000000
749
750/* DAIO Receiver register dirty flags */
751union dai_dirty {
752 struct {
753 u16 srtctl:1;
754 u16 rsv:15;
755 } bf;
756 u16 data;
757};
758
759/* DAIO Receiver control block */
760struct dai_ctrl_blk {
761 unsigned int srtctl;
762 union dai_dirty dirty;
763};
764
765/* S/PDIF Transmitter register dirty flags */
766union dao_dirty {
767 struct {
768 u16 spos:1;
769 u16 rsv:15;
770 } bf;
771 u16 data;
772};
773
774/* S/PDIF Transmitter control block */
775struct dao_ctrl_blk {
776 unsigned int spos; /* S/PDIF Output Channel Status Register */
777 union dao_dirty dirty;
778};
779
780/* Audio Input Mapper RAM */
781#define AIM_ARC 0x00000FFF
782#define AIM_NXT 0x007F0000
783
784struct daoimap {
785 unsigned int aim;
786 unsigned int idx;
787};
788
789/* I2S Transmitter/Receiver Control register */
790#define I2SCTL_EA 0x00000004
791#define I2SCTL_EI 0x00000010
792
793/* S/PDIF Transmitter Control register */
794#define SPOCTL_OE 0x00000001
795#define SPOCTL_OS 0x0000000E
796#define SPOCTL_RIV 0x00000010
797#define SPOCTL_LIV 0x00000020
798#define SPOCTL_SR 0x000000C0
799
800/* S/PDIF Receiver Control register */
801#define SPICTL_EN 0x00000001
802#define SPICTL_I24 0x00000002
803#define SPICTL_IB 0x00000004
804#define SPICTL_SM 0x00000008
805#define SPICTL_VM 0x00000010
806
807/* DAIO manager register dirty flags */
808union daio_mgr_dirty {
809 struct {
810 u32 i2soctl:4;
811 u32 i2sictl:4;
812 u32 spoctl:4;
813 u32 spictl:4;
814 u32 daoimap:1;
815 u32 rsv:15;
816 } bf;
817 u32 data;
818};
819
820/* DAIO manager control block */
821struct daio_mgr_ctrl_blk {
822 unsigned int i2sctl;
823 unsigned int spoctl;
824 unsigned int spictl;
825 struct daoimap daoimap;
826 union daio_mgr_dirty dirty;
827};
828
829static int dai_srt_set_srcr(void *blk, unsigned int src)
830{
831 struct dai_ctrl_blk *ctl = blk;
832
833 set_field(&ctl->srtctl, SRTCTL_SRCR, src);
834 ctl->dirty.bf.srtctl = 1;
835 return 0;
836}
837
838static int dai_srt_set_srcl(void *blk, unsigned int src)
839{
840 struct dai_ctrl_blk *ctl = blk;
841
842 set_field(&ctl->srtctl, SRTCTL_SRCL, src);
843 ctl->dirty.bf.srtctl = 1;
844 return 0;
845}
846
847static int dai_srt_set_rsr(void *blk, unsigned int rsr)
848{
849 struct dai_ctrl_blk *ctl = blk;
850
851 set_field(&ctl->srtctl, SRTCTL_RSR, rsr);
852 ctl->dirty.bf.srtctl = 1;
853 return 0;
854}
855
856static int dai_srt_set_drat(void *blk, unsigned int drat)
857{
858 struct dai_ctrl_blk *ctl = blk;
859
860 set_field(&ctl->srtctl, SRTCTL_DRAT, drat);
861 ctl->dirty.bf.srtctl = 1;
862 return 0;
863}
864
865static int dai_srt_set_ec(void *blk, unsigned int ec)
866{
867 struct dai_ctrl_blk *ctl = blk;
868
869 set_field(&ctl->srtctl, SRTCTL_EC, ec ? 1 : 0);
870 ctl->dirty.bf.srtctl = 1;
871 return 0;
872}
873
874static int dai_srt_set_et(void *blk, unsigned int et)
875{
876 struct dai_ctrl_blk *ctl = blk;
877
878 set_field(&ctl->srtctl, SRTCTL_ET, et ? 1 : 0);
879 ctl->dirty.bf.srtctl = 1;
880 return 0;
881}
882
883static int dai_commit_write(struct hw *hw, unsigned int idx, void *blk)
884{
885 struct dai_ctrl_blk *ctl = blk;
886
887 if (ctl->dirty.bf.srtctl) {
888 if (idx < 4) {
889 /* S/PDIF SRTs */
890 hw_write_20kx(hw, SRTSCTL+0x4*idx, ctl->srtctl);
891 } else {
892 /* I2S SRT */
893 hw_write_20kx(hw, SRTICTL, ctl->srtctl);
894 }
895 ctl->dirty.bf.srtctl = 0;
896 }
897
898 return 0;
899}
900
901static int dai_get_ctrl_blk(void **rblk)
902{
903 struct dai_ctrl_blk *blk;
904
905 *rblk = NULL;
906 blk = kzalloc(sizeof(*blk), GFP_KERNEL);
907 if (NULL == blk)
908 return -ENOMEM;
909
910 *rblk = blk;
911
912 return 0;
913}
914
915static int dai_put_ctrl_blk(void *blk)
916{
917 kfree((struct dai_ctrl_blk *)blk);
918
919 return 0;
920}
921
922static int dao_set_spos(void *blk, unsigned int spos)
923{
924 ((struct dao_ctrl_blk *)blk)->spos = spos;
925 ((struct dao_ctrl_blk *)blk)->dirty.bf.spos = 1;
926 return 0;
927}
928
929static int dao_commit_write(struct hw *hw, unsigned int idx, void *blk)
930{
931 struct dao_ctrl_blk *ctl = blk;
932
933 if (ctl->dirty.bf.spos) {
934 if (idx < 4) {
935 /* S/PDIF SPOSx */
936 hw_write_20kx(hw, SPOS+0x4*idx, ctl->spos);
937 }
938 ctl->dirty.bf.spos = 0;
939 }
940
941 return 0;
942}
943
944static int dao_get_spos(void *blk, unsigned int *spos)
945{
946 *spos = ((struct dao_ctrl_blk *)blk)->spos;
947 return 0;
948}
949
950static int dao_get_ctrl_blk(void **rblk)
951{
952 struct dao_ctrl_blk *blk;
953
954 *rblk = NULL;
955 blk = kzalloc(sizeof(*blk), GFP_KERNEL);
956 if (NULL == blk)
957 return -ENOMEM;
958
959 *rblk = blk;
960
961 return 0;
962}
963
964static int dao_put_ctrl_blk(void *blk)
965{
966 kfree((struct dao_ctrl_blk *)blk);
967
968 return 0;
969}
970
971static int daio_mgr_enb_dai(void *blk, unsigned int idx)
972{
973 struct daio_mgr_ctrl_blk *ctl = blk;
974
975 if (idx < 4) {
976 /* S/PDIF input */
977 set_field(&ctl->spictl, SPICTL_EN << (idx*8), 1);
978 ctl->dirty.bf.spictl |= (0x1 << idx);
979 } else {
980 /* I2S input */
981 idx %= 4;
982 set_field(&ctl->i2sctl, I2SCTL_EI << (idx*8), 1);
983 ctl->dirty.bf.i2sictl |= (0x1 << idx);
984 }
985 return 0;
986}
987
988static int daio_mgr_dsb_dai(void *blk, unsigned int idx)
989{
990 struct daio_mgr_ctrl_blk *ctl = blk;
991
992 if (idx < 4) {
993 /* S/PDIF input */
994 set_field(&ctl->spictl, SPICTL_EN << (idx*8), 0);
995 ctl->dirty.bf.spictl |= (0x1 << idx);
996 } else {
997 /* I2S input */
998 idx %= 4;
999 set_field(&ctl->i2sctl, I2SCTL_EI << (idx*8), 0);
1000 ctl->dirty.bf.i2sictl |= (0x1 << idx);
1001 }
1002 return 0;
1003}
1004
1005static int daio_mgr_enb_dao(void *blk, unsigned int idx)
1006{
1007 struct daio_mgr_ctrl_blk *ctl = blk;
1008
1009 if (idx < 4) {
1010 /* S/PDIF output */
1011 set_field(&ctl->spoctl, SPOCTL_OE << (idx*8), 1);
1012 ctl->dirty.bf.spoctl |= (0x1 << idx);
1013 } else {
1014 /* I2S output */
1015 idx %= 4;
1016 set_field(&ctl->i2sctl, I2SCTL_EA << (idx*8), 1);
1017 ctl->dirty.bf.i2soctl |= (0x1 << idx);
1018 }
1019 return 0;
1020}
1021
1022static int daio_mgr_dsb_dao(void *blk, unsigned int idx)
1023{
1024 struct daio_mgr_ctrl_blk *ctl = blk;
1025
1026 if (idx < 4) {
1027 /* S/PDIF output */
1028 set_field(&ctl->spoctl, SPOCTL_OE << (idx*8), 0);
1029 ctl->dirty.bf.spoctl |= (0x1 << idx);
1030 } else {
1031 /* I2S output */
1032 idx %= 4;
1033 set_field(&ctl->i2sctl, I2SCTL_EA << (idx*8), 0);
1034 ctl->dirty.bf.i2soctl |= (0x1 << idx);
1035 }
1036 return 0;
1037}
1038
1039static int daio_mgr_dao_init(void *blk, unsigned int idx, unsigned int conf)
1040{
1041 struct daio_mgr_ctrl_blk *ctl = blk;
1042
1043 if (idx < 4) {
1044 /* S/PDIF output */
1045 switch ((conf & 0x7)) {
1046 case 0:
1047 set_field(&ctl->spoctl, SPOCTL_SR << (idx*8), 3);
1048 break; /* CDIF */
1049 case 1:
1050 set_field(&ctl->spoctl, SPOCTL_SR << (idx*8), 0);
1051 break;
1052 case 2:
1053 set_field(&ctl->spoctl, SPOCTL_SR << (idx*8), 1);
1054 break;
1055 case 4:
1056 set_field(&ctl->spoctl, SPOCTL_SR << (idx*8), 2);
1057 break;
1058 default:
1059 break;
1060 }
1061 set_field(&ctl->spoctl, SPOCTL_LIV << (idx*8),
1062 (conf >> 4) & 0x1); /* Non-audio */
1063 set_field(&ctl->spoctl, SPOCTL_RIV << (idx*8),
1064 (conf >> 4) & 0x1); /* Non-audio */
1065 set_field(&ctl->spoctl, SPOCTL_OS << (idx*8),
1066 ((conf >> 3) & 0x1) ? 2 : 2); /* Raw */
1067
1068 ctl->dirty.bf.spoctl |= (0x1 << idx);
1069 } else {
1070 /* I2S output */
1071 /*idx %= 4; */
1072 }
1073 return 0;
1074}
1075
1076static int daio_mgr_set_imaparc(void *blk, unsigned int slot)
1077{
1078 struct daio_mgr_ctrl_blk *ctl = blk;
1079
1080 set_field(&ctl->daoimap.aim, AIM_ARC, slot);
1081 ctl->dirty.bf.daoimap = 1;
1082 return 0;
1083}
1084
1085static int daio_mgr_set_imapnxt(void *blk, unsigned int next)
1086{
1087 struct daio_mgr_ctrl_blk *ctl = blk;
1088
1089 set_field(&ctl->daoimap.aim, AIM_NXT, next);
1090 ctl->dirty.bf.daoimap = 1;
1091 return 0;
1092}
1093
1094static int daio_mgr_set_imapaddr(void *blk, unsigned int addr)
1095{
1096 struct daio_mgr_ctrl_blk *ctl = blk;
1097
1098 ctl->daoimap.idx = addr;
1099 ctl->dirty.bf.daoimap = 1;
1100 return 0;
1101}
1102
1103static int daio_mgr_commit_write(struct hw *hw, void *blk)
1104{
1105 struct daio_mgr_ctrl_blk *ctl = blk;
1106 int i = 0;
1107
1108 if (ctl->dirty.bf.i2sictl || ctl->dirty.bf.i2soctl) {
1109 for (i = 0; i < 4; i++) {
1110 if ((ctl->dirty.bf.i2sictl & (0x1 << i)))
1111 ctl->dirty.bf.i2sictl &= ~(0x1 << i);
1112
1113 if ((ctl->dirty.bf.i2soctl & (0x1 << i)))
1114 ctl->dirty.bf.i2soctl &= ~(0x1 << i);
1115 }
1116 hw_write_20kx(hw, I2SCTL, ctl->i2sctl);
1117 mdelay(1);
1118 }
1119 if (ctl->dirty.bf.spoctl) {
1120 for (i = 0; i < 4; i++) {
1121 if ((ctl->dirty.bf.spoctl & (0x1 << i)))
1122 ctl->dirty.bf.spoctl &= ~(0x1 << i);
1123 }
1124 hw_write_20kx(hw, SPOCTL, ctl->spoctl);
1125 mdelay(1);
1126 }
1127 if (ctl->dirty.bf.spictl) {
1128 for (i = 0; i < 4; i++) {
1129 if ((ctl->dirty.bf.spictl & (0x1 << i)))
1130 ctl->dirty.bf.spictl &= ~(0x1 << i);
1131 }
1132 hw_write_20kx(hw, SPICTL, ctl->spictl);
1133 mdelay(1);
1134 }
1135 if (ctl->dirty.bf.daoimap) {
1136 hw_write_20kx(hw, DAOIMAP+ctl->daoimap.idx*4,
1137 ctl->daoimap.aim);
1138 ctl->dirty.bf.daoimap = 0;
1139 }
1140
1141 return 0;
1142}
1143
1144static int daio_mgr_get_ctrl_blk(struct hw *hw, void **rblk)
1145{
1146 struct daio_mgr_ctrl_blk *blk;
1147
1148 *rblk = NULL;
1149 blk = kzalloc(sizeof(*blk), GFP_KERNEL);
1150 if (NULL == blk)
1151 return -ENOMEM;
1152
1153 blk->i2sctl = hw_read_20kx(hw, I2SCTL);
1154 blk->spoctl = hw_read_20kx(hw, SPOCTL);
1155 blk->spictl = hw_read_20kx(hw, SPICTL);
1156
1157 *rblk = blk;
1158
1159 return 0;
1160}
1161
1162static int daio_mgr_put_ctrl_blk(void *blk)
1163{
1164 kfree((struct daio_mgr_ctrl_blk *)blk);
1165
1166 return 0;
1167}
1168
1169/* Card hardware initialization block */
1170struct dac_conf {
1171 unsigned int msr; /* master sample rate in rsrs */
1172};
1173
1174struct adc_conf {
1175 unsigned int msr; /* master sample rate in rsrs */
1176 unsigned char input; /* the input source of ADC */
1177 unsigned char mic20db; /* boost mic by 20db if input is microphone */
1178};
1179
1180struct daio_conf {
1181 unsigned int msr; /* master sample rate in rsrs */
1182};
1183
1184struct trn_conf {
1185 unsigned long vm_pgt_phys;
1186};
1187
1188static int hw_daio_init(struct hw *hw, const struct daio_conf *info)
1189{
1190 u32 i2sorg = 0;
1191 u32 spdorg = 0;
1192
1193 /* Read I2S CTL. Keep original value. */
1194 /*i2sorg = hw_read_20kx(hw, I2SCTL);*/
1195 i2sorg = 0x94040404; /* enable all audio out and I2S-D input */
1196 /* Program I2S with proper master sample rate and enable
1197 * the correct I2S channel. */
1198 i2sorg &= 0xfffffffc;
1199
1200 /* Enable S/PDIF-out-A in fixed 24-bit data
1201 * format and default to 48kHz. */
1202 /* Disable all before doing any changes. */
1203 hw_write_20kx(hw, SPOCTL, 0x0);
1204 spdorg = 0x05;
1205
1206 switch (info->msr) {
1207 case 1:
1208 i2sorg |= 1;
1209 spdorg |= (0x0 << 6);
1210 break;
1211 case 2:
1212 i2sorg |= 2;
1213 spdorg |= (0x1 << 6);
1214 break;
1215 case 4:
1216 i2sorg |= 3;
1217 spdorg |= (0x2 << 6);
1218 break;
1219 default:
1220 i2sorg |= 1;
1221 break;
1222 }
1223
1224 hw_write_20kx(hw, I2SCTL, i2sorg);
1225 hw_write_20kx(hw, SPOCTL, spdorg);
1226
1227 /* Enable S/PDIF-in-A in fixed 24-bit data format. */
1228 /* Disable all before doing any changes. */
1229 hw_write_20kx(hw, SPICTL, 0x0);
1230 mdelay(1);
1231 spdorg = 0x0a0a0a0a;
1232 hw_write_20kx(hw, SPICTL, spdorg);
1233 mdelay(1);
1234
1235 return 0;
1236}
1237
1238/* TRANSPORT operations */
1239static int hw_trn_init(struct hw *hw, const struct trn_conf *info)
1240{
1241 u32 trnctl = 0;
1242 unsigned long ptp_phys_low = 0, ptp_phys_high = 0;
1243
1244 /* Set up device page table */
1245 if ((~0UL) == info->vm_pgt_phys) {
1246 printk(KERN_ERR "Wrong device page table page address!\n");
1247 return -1;
1248 }
1249
1250 trnctl = 0x13; /* 32-bit, 4k-size page */
1251#if BITS_PER_LONG == 64
1252 ptp_phys_low = info->vm_pgt_phys & ((1UL<<32)-1);
1253 ptp_phys_high = (info->vm_pgt_phys>>32) & ((1UL<<32)-1);
1254 trnctl |= (1<<2);
1255#elif BITS_PER_LONG == 32
1256 ptp_phys_low = info->vm_pgt_phys & (~0UL);
1257 ptp_phys_high = 0;
1258#else
1259# error "Unknown BITS_PER_LONG!"
1260#endif
1261#if PAGE_SIZE == 8192
1262 trnctl |= (1<<5);
1263#endif
1264 hw_write_20kx(hw, PTPALX, ptp_phys_low);
1265 hw_write_20kx(hw, PTPAHX, ptp_phys_high);
1266 hw_write_20kx(hw, TRNCTL, trnctl);
1267 hw_write_20kx(hw, TRNIS, 0x200c01); /* realy needed? */
1268
1269 return 0;
1270}
1271
1272/* Card initialization */
1273#define GCTL_EAC 0x00000001
1274#define GCTL_EAI 0x00000002
1275#define GCTL_BEP 0x00000004
1276#define GCTL_BES 0x00000008
1277#define GCTL_DSP 0x00000010
1278#define GCTL_DBP 0x00000020
1279#define GCTL_ABP 0x00000040
1280#define GCTL_TBP 0x00000080
1281#define GCTL_SBP 0x00000100
1282#define GCTL_FBP 0x00000200
1283#define GCTL_XA 0x00000400
1284#define GCTL_ET 0x00000800
1285#define GCTL_PR 0x00001000
1286#define GCTL_MRL 0x00002000
1287#define GCTL_SDE 0x00004000
1288#define GCTL_SDI 0x00008000
1289#define GCTL_SM 0x00010000
1290#define GCTL_SR 0x00020000
1291#define GCTL_SD 0x00040000
1292#define GCTL_SE 0x00080000
1293#define GCTL_AID 0x00100000
1294
1295static int hw_pll_init(struct hw *hw, unsigned int rsr)
1296{
1297 unsigned int pllctl;
1298 int i = 0;
1299
1300 pllctl = (48000 == rsr) ? 0x1480a001 : 0x1480a731;
1301 for (i = 0; i < 3; i++) {
1302 if (hw_read_20kx(hw, PLLCTL) == pllctl)
1303 break;
1304
1305 hw_write_20kx(hw, PLLCTL, pllctl);
1306 mdelay(40);
1307 }
1308 if (i >= 3) {
1309 printk(KERN_ALERT "PLL initialization failed!!!\n");
1310 return -EBUSY;
1311 }
1312
1313 return 0;
1314}
1315
1316static int hw_auto_init(struct hw *hw)
1317{
1318 unsigned int gctl;
1319 int i;
1320
1321 gctl = hw_read_20kx(hw, GCTL);
1322 set_field(&gctl, GCTL_EAI, 0);
1323 hw_write_20kx(hw, GCTL, gctl);
1324 set_field(&gctl, GCTL_EAI, 1);
1325 hw_write_20kx(hw, GCTL, gctl);
1326 mdelay(10);
1327 for (i = 0; i < 400000; i++) {
1328 gctl = hw_read_20kx(hw, GCTL);
1329 if (get_field(gctl, GCTL_AID))
1330 break;
1331 }
1332 if (!get_field(gctl, GCTL_AID)) {
1333 printk(KERN_ALERT "Card Auto-init failed!!!\n");
1334 return -EBUSY;
1335 }
1336
1337 return 0;
1338}
1339
1340static int i2c_unlock(struct hw *hw)
1341{
1342 if ((hw_read_pci(hw, 0xcc) & 0xff) == 0xaa)
1343 return 0;
1344
1345 hw_write_pci(hw, 0xcc, 0x8c);
1346 hw_write_pci(hw, 0xcc, 0x0e);
1347 if ((hw_read_pci(hw, 0xcc) & 0xff) == 0xaa)
1348 return 0;
1349
1350 hw_write_pci(hw, 0xcc, 0xee);
1351 hw_write_pci(hw, 0xcc, 0xaa);
1352 if ((hw_read_pci(hw, 0xcc) & 0xff) == 0xaa)
1353 return 0;
1354
1355 return -1;
1356}
1357
1358static void i2c_lock(struct hw *hw)
1359{
1360 if ((hw_read_pci(hw, 0xcc) & 0xff) == 0xaa)
1361 hw_write_pci(hw, 0xcc, 0x00);
1362}
1363
1364static void i2c_write(struct hw *hw, u32 device, u32 addr, u32 data)
1365{
1366 unsigned int ret = 0;
1367
1368 do {
1369 ret = hw_read_pci(hw, 0xEC);
1370 } while (!(ret & 0x800000));
1371 hw_write_pci(hw, 0xE0, device);
1372 hw_write_pci(hw, 0xE4, (data << 8) | (addr & 0xff));
1373}
1374
1375/* DAC operations */
1376
1377static int hw_reset_dac(struct hw *hw)
1378{
1379 u32 i = 0;
1380 u16 gpioorg = 0;
1381 unsigned int ret = 0;
1382
1383 if (i2c_unlock(hw))
1384 return -1;
1385
1386 do {
1387 ret = hw_read_pci(hw, 0xEC);
1388 } while (!(ret & 0x800000));
1389 hw_write_pci(hw, 0xEC, 0x05); /* write to i2c status control */
1390
1391 /* To be effective, need to reset the DAC twice. */
1392 for (i = 0; i < 2; i++) {
1393 /* set gpio */
1394 mdelay(100);
1395 gpioorg = (u16)hw_read_20kx(hw, GPIO);
1396 gpioorg &= 0xfffd;
1397 hw_write_20kx(hw, GPIO, gpioorg);
1398 mdelay(1);
1399 hw_write_20kx(hw, GPIO, gpioorg | 0x2);
1400 }
1401
1402 i2c_write(hw, 0x00180080, 0x01, 0x80);
1403 i2c_write(hw, 0x00180080, 0x02, 0x10);
1404
1405 i2c_lock(hw);
1406
1407 return 0;
1408}
1409
1410static int hw_dac_init(struct hw *hw, const struct dac_conf *info)
1411{
1412 u32 data = 0;
1413 u16 gpioorg = 0;
1414 u16 subsys_id = 0;
1415 unsigned int ret = 0;
1416
1417 pci_read_config_word(hw->pci, PCI_SUBSYSTEM_ID, &subsys_id);
1418 if ((subsys_id == 0x0022) || (subsys_id == 0x002F)) {
1419 /* SB055x, unmute outputs */
1420 gpioorg = (u16)hw_read_20kx(hw, GPIO);
1421 gpioorg &= 0xffbf; /* set GPIO6 to low */
1422 gpioorg |= 2; /* set GPIO1 to high */
1423 hw_write_20kx(hw, GPIO, gpioorg);
1424 return 0;
1425 }
1426
1427 /* mute outputs */
1428 gpioorg = (u16)hw_read_20kx(hw, GPIO);
1429 gpioorg &= 0xffbf;
1430 hw_write_20kx(hw, GPIO, gpioorg);
1431
1432 hw_reset_dac(hw);
1433
1434 if (i2c_unlock(hw))
1435 return -1;
1436
1437 hw_write_pci(hw, 0xEC, 0x05); /* write to i2c status control */
1438 do {
1439 ret = hw_read_pci(hw, 0xEC);
1440 } while (!(ret & 0x800000));
1441
1442 switch (info->msr) {
1443 case 1:
1444 data = 0x24;
1445 break;
1446 case 2:
1447 data = 0x25;
1448 break;
1449 case 4:
1450 data = 0x26;
1451 break;
1452 default:
1453 data = 0x24;
1454 break;
1455 }
1456
1457 i2c_write(hw, 0x00180080, 0x06, data);
1458 i2c_write(hw, 0x00180080, 0x09, data);
1459 i2c_write(hw, 0x00180080, 0x0c, data);
1460 i2c_write(hw, 0x00180080, 0x0f, data);
1461
1462 i2c_lock(hw);
1463
1464 /* unmute outputs */
1465 gpioorg = (u16)hw_read_20kx(hw, GPIO);
1466 gpioorg = gpioorg | 0x40;
1467 hw_write_20kx(hw, GPIO, gpioorg);
1468
1469 return 0;
1470}
1471
1472/* ADC operations */
1473
1474static int is_adc_input_selected_SB055x(struct hw *hw, enum ADCSRC type)
1475{
1476 u32 data = 0;
1477 return data;
1478}
1479
1480static int is_adc_input_selected_SBx(struct hw *hw, enum ADCSRC type)
1481{
1482 u32 data = 0;
1483
1484 data = hw_read_20kx(hw, GPIO);
1485 switch (type) {
1486 case ADC_MICIN:
1487 data = ((data & (0x1<<7)) && (data & (0x1<<8)));
1488 break;
1489 case ADC_LINEIN:
1490 data = (!(data & (0x1<<7)) && (data & (0x1<<8)));
1491 break;
1492 case ADC_NONE: /* Digital I/O */
1493 data = (!(data & (0x1<<8)));
1494 break;
1495 default:
1496 data = 0;
1497 }
1498 return data;
1499}
1500
1501static int is_adc_input_selected_hendrix(struct hw *hw, enum ADCSRC type)
1502{
1503 u32 data = 0;
1504
1505 data = hw_read_20kx(hw, GPIO);
1506 switch (type) {
1507 case ADC_MICIN:
1508 data = (data & (0x1 << 7)) ? 1 : 0;
1509 break;
1510 case ADC_LINEIN:
1511 data = (data & (0x1 << 7)) ? 0 : 1;
1512 break;
1513 default:
1514 data = 0;
1515 }
1516 return data;
1517}
1518
1519static int hw_is_adc_input_selected(struct hw *hw, enum ADCSRC type)
1520{
1521 u16 subsys_id = 0;
1522
1523 pci_read_config_word(hw->pci, PCI_SUBSYSTEM_ID, &subsys_id);
1524 if ((subsys_id == 0x0022) || (subsys_id == 0x002F)) {
1525 /* SB055x cards */
1526 return is_adc_input_selected_SB055x(hw, type);
1527 } else if ((subsys_id == 0x0029) || (subsys_id == 0x0031)) {
1528 /* SB073x cards */
1529 return is_adc_input_selected_hendrix(hw, type);
1530 } else if ((subsys_id & 0xf000) == 0x6000) {
1531 /* Vista compatible cards */
1532 return is_adc_input_selected_hendrix(hw, type);
1533 } else {
1534 return is_adc_input_selected_SBx(hw, type);
1535 }
1536}
1537
1538static int
1539adc_input_select_SB055x(struct hw *hw, enum ADCSRC type, unsigned char boost)
1540{
1541 u32 data = 0;
1542
1543 /*
1544 * check and set the following GPIO bits accordingly
1545 * ADC_Gain = GPIO2
1546 * DRM_off = GPIO3
1547 * Mic_Pwr_on = GPIO7
1548 * Digital_IO_Sel = GPIO8
1549 * Mic_Sw = GPIO9
1550 * Aux/MicLine_Sw = GPIO12
1551 */
1552 data = hw_read_20kx(hw, GPIO);
1553 data &= 0xec73;
1554 switch (type) {
1555 case ADC_MICIN:
1556 data |= (0x1<<7) | (0x1<<8) | (0x1<<9) ;
1557 data |= boost ? (0x1<<2) : 0;
1558 break;
1559 case ADC_LINEIN:
1560 data |= (0x1<<8);
1561 break;
1562 case ADC_AUX:
1563 data |= (0x1<<8) | (0x1<<12);
1564 break;
1565 case ADC_NONE:
1566 data |= (0x1<<12); /* set to digital */
1567 break;
1568 default:
1569 return -1;
1570 }
1571
1572 hw_write_20kx(hw, GPIO, data);
1573
1574 return 0;
1575}
1576
1577
1578static int
1579adc_input_select_SBx(struct hw *hw, enum ADCSRC type, unsigned char boost)
1580{
1581 u32 data = 0;
1582 u32 i2c_data = 0;
1583 unsigned int ret = 0;
1584
1585 if (i2c_unlock(hw))
1586 return -1;
1587
1588 do {
1589 ret = hw_read_pci(hw, 0xEC);
1590 } while (!(ret & 0x800000)); /* i2c ready poll */
1591 /* set i2c access mode as Direct Control */
1592 hw_write_pci(hw, 0xEC, 0x05);
1593
1594 data = hw_read_20kx(hw, GPIO);
1595 switch (type) {
1596 case ADC_MICIN:
1597 data |= ((0x1 << 7) | (0x1 << 8));
1598 i2c_data = 0x1; /* Mic-in */
1599 break;
1600 case ADC_LINEIN:
1601 data &= ~(0x1 << 7);
1602 data |= (0x1 << 8);
1603 i2c_data = 0x2; /* Line-in */
1604 break;
1605 case ADC_NONE:
1606 data &= ~(0x1 << 8);
1607 i2c_data = 0x0; /* set to Digital */
1608 break;
1609 default:
1610 i2c_lock(hw);
1611 return -1;
1612 }
1613 hw_write_20kx(hw, GPIO, data);
1614 i2c_write(hw, 0x001a0080, 0x2a, i2c_data);
1615 if (boost) {
1616 i2c_write(hw, 0x001a0080, 0x1c, 0xe7); /* +12dB boost */
1617 i2c_write(hw, 0x001a0080, 0x1e, 0xe7); /* +12dB boost */
1618 } else {
1619 i2c_write(hw, 0x001a0080, 0x1c, 0xcf); /* No boost */
1620 i2c_write(hw, 0x001a0080, 0x1e, 0xcf); /* No boost */
1621 }
1622
1623 i2c_lock(hw);
1624
1625 return 0;
1626}
1627
1628static int
1629adc_input_select_hendrix(struct hw *hw, enum ADCSRC type, unsigned char boost)
1630{
1631 u32 data = 0;
1632 u32 i2c_data = 0;
1633 unsigned int ret = 0;
1634
1635 if (i2c_unlock(hw))
1636 return -1;
1637
1638 do {
1639 ret = hw_read_pci(hw, 0xEC);
1640 } while (!(ret & 0x800000)); /* i2c ready poll */
1641 /* set i2c access mode as Direct Control */
1642 hw_write_pci(hw, 0xEC, 0x05);
1643
1644 data = hw_read_20kx(hw, GPIO);
1645 switch (type) {
1646 case ADC_MICIN:
1647 data |= (0x1 << 7);
1648 i2c_data = 0x1; /* Mic-in */
1649 break;
1650 case ADC_LINEIN:
1651 data &= ~(0x1 << 7);
1652 i2c_data = 0x2; /* Line-in */
1653 break;
1654 default:
1655 i2c_lock(hw);
1656 return -1;
1657 }
1658 hw_write_20kx(hw, GPIO, data);
1659 i2c_write(hw, 0x001a0080, 0x2a, i2c_data);
1660 if (boost) {
1661 i2c_write(hw, 0x001a0080, 0x1c, 0xe7); /* +12dB boost */
1662 i2c_write(hw, 0x001a0080, 0x1e, 0xe7); /* +12dB boost */
1663 } else {
1664 i2c_write(hw, 0x001a0080, 0x1c, 0xcf); /* No boost */
1665 i2c_write(hw, 0x001a0080, 0x1e, 0xcf); /* No boost */
1666 }
1667
1668 i2c_lock(hw);
1669
1670 return 0;
1671}
1672
1673static int hw_adc_input_select(struct hw *hw, enum ADCSRC type)
1674{
1675 u16 subsys_id = 0;
1676
1677 pci_read_config_word(hw->pci, PCI_SUBSYSTEM_ID, &subsys_id);
1678 if ((subsys_id == 0x0022) || (subsys_id == 0x002F)) {
1679 /* SB055x cards */
1680 return adc_input_select_SB055x(hw, type, (ADC_MICIN == type));
1681 } else if ((subsys_id == 0x0029) || (subsys_id == 0x0031)) {
1682 /* SB073x cards */
1683 return adc_input_select_hendrix(hw, type, (ADC_MICIN == type));
1684 } else if ((subsys_id & 0xf000) == 0x6000) {
1685 /* Vista compatible cards */
1686 return adc_input_select_hendrix(hw, type, (ADC_MICIN == type));
1687 } else {
1688 return adc_input_select_SBx(hw, type, (ADC_MICIN == type));
1689 }
1690}
1691
1692static int adc_init_SB055x(struct hw *hw, int input, int mic20db)
1693{
1694 return adc_input_select_SB055x(hw, input, mic20db);
1695}
1696
1697static int adc_init_SBx(struct hw *hw, int input, int mic20db)
1698{
1699 u16 gpioorg;
1700 u16 input_source;
1701 u32 adcdata = 0;
1702 unsigned int ret = 0;
1703
1704 input_source = 0x100; /* default to analog */
1705 switch (input) {
1706 case ADC_MICIN:
1707 adcdata = 0x1;
1708 input_source = 0x180; /* set GPIO7 to select Mic */
1709 break;
1710 case ADC_LINEIN:
1711 adcdata = 0x2;
1712 break;
1713 case ADC_VIDEO:
1714 adcdata = 0x4;
1715 break;
1716 case ADC_AUX:
1717 adcdata = 0x8;
1718 break;
1719 case ADC_NONE:
1720 adcdata = 0x0;
1721 input_source = 0x0; /* set to Digital */
1722 break;
1723 default:
1724 break;
1725 }
1726
1727 if (i2c_unlock(hw))
1728 return -1;
1729
1730 do {
1731 ret = hw_read_pci(hw, 0xEC);
1732 } while (!(ret & 0x800000)); /* i2c ready poll */
1733 hw_write_pci(hw, 0xEC, 0x05); /* write to i2c status control */
1734
1735 i2c_write(hw, 0x001a0080, 0x0e, 0x08);
1736 i2c_write(hw, 0x001a0080, 0x18, 0x0a);
1737 i2c_write(hw, 0x001a0080, 0x28, 0x86);
1738 i2c_write(hw, 0x001a0080, 0x2a, adcdata);
1739
1740 if (mic20db) {
1741 i2c_write(hw, 0x001a0080, 0x1c, 0xf7);
1742 i2c_write(hw, 0x001a0080, 0x1e, 0xf7);
1743 } else {
1744 i2c_write(hw, 0x001a0080, 0x1c, 0xcf);
1745 i2c_write(hw, 0x001a0080, 0x1e, 0xcf);
1746 }
1747
1748 if (!(hw_read_20kx(hw, ID0) & 0x100))
1749 i2c_write(hw, 0x001a0080, 0x16, 0x26);
1750
1751 i2c_lock(hw);
1752
1753 gpioorg = (u16)hw_read_20kx(hw, GPIO);
1754 gpioorg &= 0xfe7f;
1755 gpioorg |= input_source;
1756 hw_write_20kx(hw, GPIO, gpioorg);
1757
1758 return 0;
1759}
1760
1761static int hw_adc_init(struct hw *hw, const struct adc_conf *info)
1762{
1763 int err = 0;
1764 u16 subsys_id = 0;
1765
1766 pci_read_config_word(hw->pci, PCI_SUBSYSTEM_ID, &subsys_id);
1767 if ((subsys_id == 0x0022) || (subsys_id == 0x002F)) {
1768 /* Sb055x card */
1769 err = adc_init_SB055x(hw, info->input, info->mic20db);
1770 } else {
1771 err = adc_init_SBx(hw, info->input, info->mic20db);
1772 }
1773
1774 return err;
1775}
1776
1777static int hw_have_digit_io_switch(struct hw *hw)
1778{
1779 u16 subsys_id = 0;
1780
1781 pci_read_config_word(hw->pci, PCI_SUBSYSTEM_ID, &subsys_id);
1782 /* SB073x and Vista compatible cards have no digit IO switch */
1783 return !((subsys_id == 0x0029) || (subsys_id == 0x0031)
1784 || ((subsys_id & 0xf000) == 0x6000));
1785}
1786
1787#define UAA_CFG_PWRSTATUS 0x44
1788#define UAA_CFG_SPACE_FLAG 0xA0
1789#define UAA_CORE_CHANGE 0x3FFC
1790static int uaa_to_xfi(struct pci_dev *pci)
1791{
1792 unsigned int bar0, bar1, bar2, bar3, bar4, bar5;
1793 unsigned int cmd, irq, cl_size, l_timer, pwr;
1794 unsigned int CTLA, CTLZ, CTLL, CTLX, CTL_, CTLF, CTLi;
1795 unsigned int is_uaa = 0;
1796 unsigned int data[4] = {0};
1797 unsigned int io_base;
1798 void *mem_base;
1799 int i = 0;
1800
1801 /* By default, Hendrix card UAA Bar0 should be using memory... */
1802 io_base = pci_resource_start(pci, 0);
1803 mem_base = ioremap(io_base, pci_resource_len(pci, 0));
1804 if (NULL == mem_base)
1805 return -ENOENT;
1806
1807 CTLX = ___constant_swab32(*((unsigned int *)"CTLX"));
1808 CTL_ = ___constant_swab32(*((unsigned int *)"CTL-"));
1809 CTLF = ___constant_swab32(*((unsigned int *)"CTLF"));
1810 CTLi = ___constant_swab32(*((unsigned int *)"CTLi"));
1811 CTLA = ___constant_swab32(*((unsigned int *)"CTLA"));
1812 CTLZ = ___constant_swab32(*((unsigned int *)"CTLZ"));
1813 CTLL = ___constant_swab32(*((unsigned int *)"CTLL"));
1814
1815 /* Read current mode from Mode Change Register */
1816 for (i = 0; i < 4; i++)
1817 data[i] = readl(mem_base + UAA_CORE_CHANGE);
1818
1819 /* Determine current mode... */
1820 if (data[0] == CTLA) {
1821 is_uaa = ((data[1] == CTLZ && data[2] == CTLL
1822 && data[3] == CTLA) || (data[1] == CTLA
1823 && data[2] == CTLZ && data[3] == CTLL));
1824 } else if (data[0] == CTLZ) {
1825 is_uaa = (data[1] == CTLL
1826 && data[2] == CTLA && data[3] == CTLA);
1827 } else if (data[0] == CTLL) {
1828 is_uaa = (data[1] == CTLA
1829 && data[2] == CTLA && data[3] == CTLZ);
1830 } else {
1831 is_uaa = 0;
1832 }
1833
1834 if (!is_uaa) {
1835 /* Not in UAA mode currently. Return directly. */
1836 iounmap(mem_base);
1837 return 0;
1838 }
1839
1840 pci_read_config_dword(pci, PCI_BASE_ADDRESS_0, &bar0);
1841 pci_read_config_dword(pci, PCI_BASE_ADDRESS_1, &bar1);
1842 pci_read_config_dword(pci, PCI_BASE_ADDRESS_2, &bar2);
1843 pci_read_config_dword(pci, PCI_BASE_ADDRESS_3, &bar3);
1844 pci_read_config_dword(pci, PCI_BASE_ADDRESS_4, &bar4);
1845 pci_read_config_dword(pci, PCI_BASE_ADDRESS_5, &bar5);
1846 pci_read_config_dword(pci, PCI_INTERRUPT_LINE, &irq);
1847 pci_read_config_dword(pci, PCI_CACHE_LINE_SIZE, &cl_size);
1848 pci_read_config_dword(pci, PCI_LATENCY_TIMER, &l_timer);
1849 pci_read_config_dword(pci, UAA_CFG_PWRSTATUS, &pwr);
1850 pci_read_config_dword(pci, PCI_COMMAND, &cmd);
1851
1852 /* Set up X-Fi core PCI configuration space. */
1853 /* Switch to X-Fi config space with BAR0 exposed. */
1854 pci_write_config_dword(pci, UAA_CFG_SPACE_FLAG, 0x87654321);
1855 /* Copy UAA's BAR5 into X-Fi BAR0 */
1856 pci_write_config_dword(pci, PCI_BASE_ADDRESS_0, bar5);
1857 /* Switch to X-Fi config space without BAR0 exposed. */
1858 pci_write_config_dword(pci, UAA_CFG_SPACE_FLAG, 0x12345678);
1859 pci_write_config_dword(pci, PCI_BASE_ADDRESS_1, bar1);
1860 pci_write_config_dword(pci, PCI_BASE_ADDRESS_2, bar2);
1861 pci_write_config_dword(pci, PCI_BASE_ADDRESS_3, bar3);
1862 pci_write_config_dword(pci, PCI_BASE_ADDRESS_4, bar4);
1863 pci_write_config_dword(pci, PCI_INTERRUPT_LINE, irq);
1864 pci_write_config_dword(pci, PCI_CACHE_LINE_SIZE, cl_size);
1865 pci_write_config_dword(pci, PCI_LATENCY_TIMER, l_timer);
1866 pci_write_config_dword(pci, UAA_CFG_PWRSTATUS, pwr);
1867 pci_write_config_dword(pci, PCI_COMMAND, cmd);
1868
1869 /* Switch to X-Fi mode */
1870 writel(CTLX, (mem_base + UAA_CORE_CHANGE));
1871 writel(CTL_, (mem_base + UAA_CORE_CHANGE));
1872 writel(CTLF, (mem_base + UAA_CORE_CHANGE));
1873 writel(CTLi, (mem_base + UAA_CORE_CHANGE));
1874
1875 iounmap(mem_base);
1876
1877 return 0;
1878}
1879
1880static int hw_card_start(struct hw *hw)
1881{
1882 int err = 0;
1883 struct pci_dev *pci = hw->pci;
1884 u16 subsys_id = 0;
1885 unsigned int dma_mask = 0;
1886
1887 err = pci_enable_device(pci);
1888 if (err < 0)
1889 return err;
1890
1891 /* Set DMA transfer mask */
1892 dma_mask = CT_XFI_DMA_MASK;
1893 if (pci_set_dma_mask(pci, dma_mask) < 0 ||
1894 pci_set_consistent_dma_mask(pci, dma_mask) < 0) {
1895 printk(KERN_ERR "architecture does not support PCI "
1896 "busmaster DMA with mask 0x%x\n", dma_mask);
1897 err = -ENXIO;
1898 goto error1;
1899 }
1900
1901 err = pci_request_regions(pci, "XFi");
1902 if (err < 0)
1903 goto error1;
1904
1905 /* Switch to X-Fi mode from UAA mode if neeeded */
1906 pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &subsys_id);
1907 if ((0x5 == pci->device) && (0x6000 == (subsys_id & 0x6000))) {
1908 err = uaa_to_xfi(pci);
1909 if (err)
1910 goto error2;
1911
1912 hw->io_base = pci_resource_start(pci, 5);
1913 } else {
1914 hw->io_base = pci_resource_start(pci, 0);
1915 }
1916
1917 /*if ((err = request_irq(pci->irq, ct_atc_interrupt, IRQF_SHARED,
1918 atc->chip_details->nm_card, hw))) {
1919 goto error2;
1920 }
1921 hw->irq = pci->irq;
1922 */
1923
1924 pci_set_master(pci);
1925
1926 return 0;
1927
1928error2:
1929 pci_release_regions(pci);
1930 hw->io_base = 0;
1931error1:
1932 pci_disable_device(pci);
1933 return err;
1934}
1935
1936static int hw_card_stop(struct hw *hw)
1937{
1938 /* TODO: Disable interrupt and so on... */
1939 return 0;
1940}
1941
1942static int hw_card_shutdown(struct hw *hw)
1943{
1944 if (hw->irq >= 0)
1945 free_irq(hw->irq, hw);
1946
1947 hw->irq = -1;
1948
1949 if (NULL != ((void *)hw->mem_base))
1950 iounmap((void *)hw->mem_base);
1951
1952 hw->mem_base = (unsigned long)NULL;
1953
1954 if (hw->io_base)
1955 pci_release_regions(hw->pci);
1956
1957 hw->io_base = 0;
1958
1959 pci_disable_device(hw->pci);
1960
1961 return 0;
1962}
1963
1964static int hw_card_init(struct hw *hw, struct card_conf *info)
1965{
1966 int err;
1967 unsigned int gctl;
1968 u16 subsys_id = 0;
1969 u32 data = 0;
1970 struct dac_conf dac_info = {0};
1971 struct adc_conf adc_info = {0};
1972 struct daio_conf daio_info = {0};
1973 struct trn_conf trn_info = {0};
1974
1975 /* Get PCI io port base address and do Hendrix switch if needed. */
1976 if (!hw->io_base) {
1977 err = hw_card_start(hw);
1978 if (err)
1979 return err;
1980 }
1981
1982 /* PLL init */
1983 err = hw_pll_init(hw, info->rsr);
1984 if (err < 0)
1985 return err;
1986
1987 /* kick off auto-init */
1988 err = hw_auto_init(hw);
1989 if (err < 0)
1990 return err;
1991
1992 /* Enable audio ring */
1993 gctl = hw_read_20kx(hw, GCTL);
1994 set_field(&gctl, GCTL_EAC, 1);
1995 set_field(&gctl, GCTL_DBP, 1);
1996 set_field(&gctl, GCTL_TBP, 1);
1997 set_field(&gctl, GCTL_FBP, 1);
1998 set_field(&gctl, GCTL_ET, 1);
1999 hw_write_20kx(hw, GCTL, gctl);
2000 mdelay(10);
2001
2002 /* Reset all global pending interrupts */
2003 hw_write_20kx(hw, GIE, 0);
2004 /* Reset all SRC pending interrupts */
2005 hw_write_20kx(hw, SRCIP, 0);
2006 mdelay(30);
2007
2008 pci_read_config_word(hw->pci, PCI_SUBSYSTEM_ID, &subsys_id);
2009 /* Detect the card ID and configure GPIO accordingly. */
2010 if ((subsys_id == 0x0022) || (subsys_id == 0x002F)) {
2011 /* SB055x cards */
2012 hw_write_20kx(hw, GPIOCTL, 0x13fe);
2013 } else if ((subsys_id == 0x0029) || (subsys_id == 0x0031)) {
2014 /* SB073x cards */
2015 hw_write_20kx(hw, GPIOCTL, 0x00e6);
2016 } else if ((subsys_id & 0xf000) == 0x6000) {
2017 /* Vista compatible cards */
2018 hw_write_20kx(hw, GPIOCTL, 0x00c2);
2019 } else {
2020 hw_write_20kx(hw, GPIOCTL, 0x01e6);
2021 }
2022
2023 trn_info.vm_pgt_phys = info->vm_pgt_phys;
2024 err = hw_trn_init(hw, &trn_info);
2025 if (err < 0)
2026 return err;
2027
2028 daio_info.msr = info->msr;
2029 err = hw_daio_init(hw, &daio_info);
2030 if (err < 0)
2031 return err;
2032
2033 dac_info.msr = info->msr;
2034 err = hw_dac_init(hw, &dac_info);
2035 if (err < 0)
2036 return err;
2037
2038 adc_info.msr = info->msr;
2039 adc_info.input = ADC_LINEIN;
2040 adc_info.mic20db = 0;
2041 err = hw_adc_init(hw, &adc_info);
2042 if (err < 0)
2043 return err;
2044
2045 data = hw_read_20kx(hw, SRCMCTL);
2046 data |= 0x1; /* Enables input from the audio ring */
2047 hw_write_20kx(hw, SRCMCTL, data);
2048
2049 return 0;
2050}
2051
2052static u32 hw_read_20kx(struct hw *hw, u32 reg)
2053{
2054 u32 value;
2055 unsigned long flags;
2056
2057 spin_lock_irqsave(
2058 &container_of(hw, struct hw20k1, hw)->reg_20k1_lock, flags);
2059 outl(reg, hw->io_base + 0x0);
2060 value = inl(hw->io_base + 0x4);
2061 spin_unlock_irqrestore(
2062 &container_of(hw, struct hw20k1, hw)->reg_20k1_lock, flags);
2063
2064 return value;
2065}
2066
2067static void hw_write_20kx(struct hw *hw, u32 reg, u32 data)
2068{
2069 unsigned long flags;
2070
2071 spin_lock_irqsave(
2072 &container_of(hw, struct hw20k1, hw)->reg_20k1_lock, flags);
2073 outl(reg, hw->io_base + 0x0);
2074 outl(data, hw->io_base + 0x4);
2075 spin_unlock_irqrestore(
2076 &container_of(hw, struct hw20k1, hw)->reg_20k1_lock, flags);
2077
2078}
2079
2080static u32 hw_read_pci(struct hw *hw, u32 reg)
2081{
2082 u32 value;
2083 unsigned long flags;
2084
2085 spin_lock_irqsave(
2086 &container_of(hw, struct hw20k1, hw)->reg_pci_lock, flags);
2087 outl(reg, hw->io_base + 0x10);
2088 value = inl(hw->io_base + 0x14);
2089 spin_unlock_irqrestore(
2090 &container_of(hw, struct hw20k1, hw)->reg_pci_lock, flags);
2091
2092 return value;
2093}
2094
2095static void hw_write_pci(struct hw *hw, u32 reg, u32 data)
2096{
2097 unsigned long flags;
2098
2099 spin_lock_irqsave(
2100 &container_of(hw, struct hw20k1, hw)->reg_pci_lock, flags);
2101 outl(reg, hw->io_base + 0x10);
2102 outl(data, hw->io_base + 0x14);
2103 spin_unlock_irqrestore(
2104 &container_of(hw, struct hw20k1, hw)->reg_pci_lock, flags);
2105}
2106
2107int create_20k1_hw_obj(struct hw **rhw)
2108{
2109 struct hw *hw;
2110 struct hw20k1 *hw20k1;
2111
2112 *rhw = NULL;
2113 hw20k1 = kzalloc(sizeof(*hw20k1), GFP_KERNEL);
2114 if (NULL == hw20k1)
2115 return -ENOMEM;
2116
2117 spin_lock_init(&hw20k1->reg_20k1_lock);
2118 spin_lock_init(&hw20k1->reg_pci_lock);
2119
2120 hw = &hw20k1->hw;
2121
2122 hw->io_base = 0;
2123 hw->mem_base = (unsigned long)NULL;
2124 hw->irq = -1;
2125
2126 hw->card_init = hw_card_init;
2127 hw->card_stop = hw_card_stop;
2128 hw->pll_init = hw_pll_init;
2129 hw->is_adc_source_selected = hw_is_adc_input_selected;
2130 hw->select_adc_source = hw_adc_input_select;
2131 hw->have_digit_io_switch = hw_have_digit_io_switch;
2132
2133 hw->src_rsc_get_ctrl_blk = src_get_rsc_ctrl_blk;
2134 hw->src_rsc_put_ctrl_blk = src_put_rsc_ctrl_blk;
2135 hw->src_mgr_get_ctrl_blk = src_mgr_get_ctrl_blk;
2136 hw->src_mgr_put_ctrl_blk = src_mgr_put_ctrl_blk;
2137 hw->src_set_state = src_set_state;
2138 hw->src_set_bm = src_set_bm;
2139 hw->src_set_rsr = src_set_rsr;
2140 hw->src_set_sf = src_set_sf;
2141 hw->src_set_wr = src_set_wr;
2142 hw->src_set_pm = src_set_pm;
2143 hw->src_set_rom = src_set_rom;
2144 hw->src_set_vo = src_set_vo;
2145 hw->src_set_st = src_set_st;
2146 hw->src_set_ie = src_set_ie;
2147 hw->src_set_ilsz = src_set_ilsz;
2148 hw->src_set_bp = src_set_bp;
2149 hw->src_set_cisz = src_set_cisz;
2150 hw->src_set_ca = src_set_ca;
2151 hw->src_set_sa = src_set_sa;
2152 hw->src_set_la = src_set_la;
2153 hw->src_set_pitch = src_set_pitch;
2154 hw->src_set_dirty = src_set_dirty;
2155 hw->src_set_clear_zbufs = src_set_clear_zbufs;
2156 hw->src_set_dirty_all = src_set_dirty_all;
2157 hw->src_commit_write = src_commit_write;
2158 hw->src_get_ca = src_get_ca;
2159 hw->src_get_dirty = src_get_dirty;
2160 hw->src_dirty_conj_mask = src_dirty_conj_mask;
2161 hw->src_mgr_enbs_src = src_mgr_enbs_src;
2162 hw->src_mgr_enb_src = src_mgr_enb_src;
2163 hw->src_mgr_dsb_src = src_mgr_dsb_src;
2164 hw->src_mgr_commit_write = src_mgr_commit_write;
2165
2166 hw->srcimp_mgr_get_ctrl_blk = srcimp_mgr_get_ctrl_blk;
2167 hw->srcimp_mgr_put_ctrl_blk = srcimp_mgr_put_ctrl_blk;
2168 hw->srcimp_mgr_set_imaparc = srcimp_mgr_set_imaparc;
2169 hw->srcimp_mgr_set_imapuser = srcimp_mgr_set_imapuser;
2170 hw->srcimp_mgr_set_imapnxt = srcimp_mgr_set_imapnxt;
2171 hw->srcimp_mgr_set_imapaddr = srcimp_mgr_set_imapaddr;
2172 hw->srcimp_mgr_commit_write = srcimp_mgr_commit_write;
2173
2174 hw->amixer_rsc_get_ctrl_blk = amixer_rsc_get_ctrl_blk;
2175 hw->amixer_rsc_put_ctrl_blk = amixer_rsc_put_ctrl_blk;
2176 hw->amixer_mgr_get_ctrl_blk = amixer_mgr_get_ctrl_blk;
2177 hw->amixer_mgr_put_ctrl_blk = amixer_mgr_put_ctrl_blk;
2178 hw->amixer_set_mode = amixer_set_mode;
2179 hw->amixer_set_iv = amixer_set_iv;
2180 hw->amixer_set_x = amixer_set_x;
2181 hw->amixer_set_y = amixer_set_y;
2182 hw->amixer_set_sadr = amixer_set_sadr;
2183 hw->amixer_set_se = amixer_set_se;
2184 hw->amixer_set_dirty = amixer_set_dirty;
2185 hw->amixer_set_dirty_all = amixer_set_dirty_all;
2186 hw->amixer_commit_write = amixer_commit_write;
2187 hw->amixer_get_y = amixer_get_y;
2188 hw->amixer_get_dirty = amixer_get_dirty;
2189
2190 hw->dai_get_ctrl_blk = dai_get_ctrl_blk;
2191 hw->dai_put_ctrl_blk = dai_put_ctrl_blk;
2192 hw->dai_srt_set_srco = dai_srt_set_srcr;
2193 hw->dai_srt_set_srcm = dai_srt_set_srcl;
2194 hw->dai_srt_set_rsr = dai_srt_set_rsr;
2195 hw->dai_srt_set_drat = dai_srt_set_drat;
2196 hw->dai_srt_set_ec = dai_srt_set_ec;
2197 hw->dai_srt_set_et = dai_srt_set_et;
2198 hw->dai_commit_write = dai_commit_write;
2199
2200 hw->dao_get_ctrl_blk = dao_get_ctrl_blk;
2201 hw->dao_put_ctrl_blk = dao_put_ctrl_blk;
2202 hw->dao_set_spos = dao_set_spos;
2203 hw->dao_commit_write = dao_commit_write;
2204 hw->dao_get_spos = dao_get_spos;
2205
2206 hw->daio_mgr_get_ctrl_blk = daio_mgr_get_ctrl_blk;
2207 hw->daio_mgr_put_ctrl_blk = daio_mgr_put_ctrl_blk;
2208 hw->daio_mgr_enb_dai = daio_mgr_enb_dai;
2209 hw->daio_mgr_dsb_dai = daio_mgr_dsb_dai;
2210 hw->daio_mgr_enb_dao = daio_mgr_enb_dao;
2211 hw->daio_mgr_dsb_dao = daio_mgr_dsb_dao;
2212 hw->daio_mgr_dao_init = daio_mgr_dao_init;
2213 hw->daio_mgr_set_imaparc = daio_mgr_set_imaparc;
2214 hw->daio_mgr_set_imapnxt = daio_mgr_set_imapnxt;
2215 hw->daio_mgr_set_imapaddr = daio_mgr_set_imapaddr;
2216 hw->daio_mgr_commit_write = daio_mgr_commit_write;
2217
2218 *rhw = hw;
2219
2220 return 0;
2221}
2222
2223int destroy_20k1_hw_obj(struct hw *hw)
2224{
2225 if (hw->io_base)
2226 hw_card_shutdown(hw);
2227
2228 kfree(container_of(hw, struct hw20k1, hw));
2229 return 0;
2230}
diff --git a/sound/pci/ctxfi/cthw20k1.h b/sound/pci/ctxfi/cthw20k1.h
new file mode 100644
index 000000000000..02f72fb448a6
--- /dev/null
+++ b/sound/pci/ctxfi/cthw20k1.h
@@ -0,0 +1,26 @@
1/**
2 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
3 *
4 * This source file is released under GPL v2 license (no other versions).
5 * See the COPYING file included in the main directory of this source
6 * distribution for the license terms and conditions.
7 *
8 * @File cthw20k1.h
9 *
10 * @Brief
11 * This file contains the definition of hardware access methord.
12 *
13 * @Author Liu Chun
14 * @Date May 13 2008
15 *
16 */
17
18#ifndef CTHW20K1_H
19#define CTHW20K1_H
20
21#include "cthardware.h"
22
23int create_20k1_hw_obj(struct hw **rhw);
24int destroy_20k1_hw_obj(struct hw *hw);
25
26#endif /* CTHW20K1_H */
diff --git a/sound/pci/ctxfi/cthw20k2.c b/sound/pci/ctxfi/cthw20k2.c
new file mode 100644
index 000000000000..cdcb75cc33b6
--- /dev/null
+++ b/sound/pci/ctxfi/cthw20k2.c
@@ -0,0 +1,2133 @@
1/**
2 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
3 *
4 * This source file is released under GPL v2 license (no other versions).
5 * See the COPYING file included in the main directory of this source
6 * distribution for the license terms and conditions.
7 *
8 * @File cthw20k2.c
9 *
10 * @Brief
11 * This file contains the implementation of hardware access methord for 20k2.
12 *
13 * @Author Liu Chun
14 * @Date May 14 2008
15 *
16 */
17
18#include "cthw20k2.h"
19#include "ct20k2reg.h"
20#include <linux/types.h>
21#include <linux/slab.h>
22#include <linux/pci.h>
23#include <linux/io.h>
24#include <linux/string.h>
25#include <linux/kernel.h>
26#include <linux/interrupt.h>
27
28#define CT_XFI_DMA_MASK DMA_BIT_MASK(32) /* 32 bits */
29
30static u32 hw_read_20kx(struct hw *hw, u32 reg);
31static void hw_write_20kx(struct hw *hw, u32 reg, u32 data);
32
33/*
34 * Type definition block.
35 * The layout of control structures can be directly applied on 20k2 chip.
36 */
37
38/*
39 * SRC control block definitions.
40 */
41
42/* SRC resource control block */
43#define SRCCTL_STATE 0x00000007
44#define SRCCTL_BM 0x00000008
45#define SRCCTL_RSR 0x00000030
46#define SRCCTL_SF 0x000001C0
47#define SRCCTL_WR 0x00000200
48#define SRCCTL_PM 0x00000400
49#define SRCCTL_ROM 0x00001800
50#define SRCCTL_VO 0x00002000
51#define SRCCTL_ST 0x00004000
52#define SRCCTL_IE 0x00008000
53#define SRCCTL_ILSZ 0x000F0000
54#define SRCCTL_BP 0x00100000
55
56#define SRCCCR_CISZ 0x000007FF
57#define SRCCCR_CWA 0x001FF800
58#define SRCCCR_D 0x00200000
59#define SRCCCR_RS 0x01C00000
60#define SRCCCR_NAL 0x3E000000
61#define SRCCCR_RA 0xC0000000
62
63#define SRCCA_CA 0x0FFFFFFF
64#define SRCCA_RS 0xE0000000
65
66#define SRCSA_SA 0x0FFFFFFF
67
68#define SRCLA_LA 0x0FFFFFFF
69
70/* Mixer Parameter Ring ram Low and Hight register.
71 * Fixed-point value in 8.24 format for parameter channel */
72#define MPRLH_PITCH 0xFFFFFFFF
73
74/* SRC resource register dirty flags */
75union src_dirty {
76 struct {
77 u16 ctl:1;
78 u16 ccr:1;
79 u16 sa:1;
80 u16 la:1;
81 u16 ca:1;
82 u16 mpr:1;
83 u16 czbfs:1; /* Clear Z-Buffers */
84 u16 rsv:9;
85 } bf;
86 u16 data;
87};
88
89struct src_rsc_ctrl_blk {
90 unsigned int ctl;
91 unsigned int ccr;
92 unsigned int ca;
93 unsigned int sa;
94 unsigned int la;
95 unsigned int mpr;
96 union src_dirty dirty;
97};
98
99/* SRC manager control block */
100union src_mgr_dirty {
101 struct {
102 u16 enb0:1;
103 u16 enb1:1;
104 u16 enb2:1;
105 u16 enb3:1;
106 u16 enb4:1;
107 u16 enb5:1;
108 u16 enb6:1;
109 u16 enb7:1;
110 u16 enbsa:1;
111 u16 rsv:7;
112 } bf;
113 u16 data;
114};
115
116struct src_mgr_ctrl_blk {
117 unsigned int enbsa;
118 unsigned int enb[8];
119 union src_mgr_dirty dirty;
120};
121
122/* SRCIMP manager control block */
123#define SRCAIM_ARC 0x00000FFF
124#define SRCAIM_NXT 0x00FF0000
125#define SRCAIM_SRC 0xFF000000
126
127struct srcimap {
128 unsigned int srcaim;
129 unsigned int idx;
130};
131
132/* SRCIMP manager register dirty flags */
133union srcimp_mgr_dirty {
134 struct {
135 u16 srcimap:1;
136 u16 rsv:15;
137 } bf;
138 u16 data;
139};
140
141struct srcimp_mgr_ctrl_blk {
142 struct srcimap srcimap;
143 union srcimp_mgr_dirty dirty;
144};
145
146/*
147 * Function implementation block.
148 */
149
150static int src_get_rsc_ctrl_blk(void **rblk)
151{
152 struct src_rsc_ctrl_blk *blk;
153
154 *rblk = NULL;
155 blk = kzalloc(sizeof(*blk), GFP_KERNEL);
156 if (NULL == blk)
157 return -ENOMEM;
158
159 *rblk = blk;
160
161 return 0;
162}
163
164static int src_put_rsc_ctrl_blk(void *blk)
165{
166 kfree((struct src_rsc_ctrl_blk *)blk);
167
168 return 0;
169}
170
171static int src_set_state(void *blk, unsigned int state)
172{
173 struct src_rsc_ctrl_blk *ctl = blk;
174
175 set_field(&ctl->ctl, SRCCTL_STATE, state);
176 ctl->dirty.bf.ctl = 1;
177 return 0;
178}
179
180static int src_set_bm(void *blk, unsigned int bm)
181{
182 struct src_rsc_ctrl_blk *ctl = blk;
183
184 set_field(&ctl->ctl, SRCCTL_BM, bm);
185 ctl->dirty.bf.ctl = 1;
186 return 0;
187}
188
189static int src_set_rsr(void *blk, unsigned int rsr)
190{
191 struct src_rsc_ctrl_blk *ctl = blk;
192
193 set_field(&ctl->ctl, SRCCTL_RSR, rsr);
194 ctl->dirty.bf.ctl = 1;
195 return 0;
196}
197
198static int src_set_sf(void *blk, unsigned int sf)
199{
200 struct src_rsc_ctrl_blk *ctl = blk;
201
202 set_field(&ctl->ctl, SRCCTL_SF, sf);
203 ctl->dirty.bf.ctl = 1;
204 return 0;
205}
206
207static int src_set_wr(void *blk, unsigned int wr)
208{
209 struct src_rsc_ctrl_blk *ctl = blk;
210
211 set_field(&ctl->ctl, SRCCTL_WR, wr);
212 ctl->dirty.bf.ctl = 1;
213 return 0;
214}
215
216static int src_set_pm(void *blk, unsigned int pm)
217{
218 struct src_rsc_ctrl_blk *ctl = blk;
219
220 set_field(&ctl->ctl, SRCCTL_PM, pm);
221 ctl->dirty.bf.ctl = 1;
222 return 0;
223}
224
225static int src_set_rom(void *blk, unsigned int rom)
226{
227 struct src_rsc_ctrl_blk *ctl = blk;
228
229 set_field(&ctl->ctl, SRCCTL_ROM, rom);
230 ctl->dirty.bf.ctl = 1;
231 return 0;
232}
233
234static int src_set_vo(void *blk, unsigned int vo)
235{
236 struct src_rsc_ctrl_blk *ctl = blk;
237
238 set_field(&ctl->ctl, SRCCTL_VO, vo);
239 ctl->dirty.bf.ctl = 1;
240 return 0;
241}
242
243static int src_set_st(void *blk, unsigned int st)
244{
245 struct src_rsc_ctrl_blk *ctl = blk;
246
247 set_field(&ctl->ctl, SRCCTL_ST, st);
248 ctl->dirty.bf.ctl = 1;
249 return 0;
250}
251
252static int src_set_ie(void *blk, unsigned int ie)
253{
254 struct src_rsc_ctrl_blk *ctl = blk;
255
256 set_field(&ctl->ctl, SRCCTL_IE, ie);
257 ctl->dirty.bf.ctl = 1;
258 return 0;
259}
260
261static int src_set_ilsz(void *blk, unsigned int ilsz)
262{
263 struct src_rsc_ctrl_blk *ctl = blk;
264
265 set_field(&ctl->ctl, SRCCTL_ILSZ, ilsz);
266 ctl->dirty.bf.ctl = 1;
267 return 0;
268}
269
270static int src_set_bp(void *blk, unsigned int bp)
271{
272 struct src_rsc_ctrl_blk *ctl = blk;
273
274 set_field(&ctl->ctl, SRCCTL_BP, bp);
275 ctl->dirty.bf.ctl = 1;
276 return 0;
277}
278
279static int src_set_cisz(void *blk, unsigned int cisz)
280{
281 struct src_rsc_ctrl_blk *ctl = blk;
282
283 set_field(&ctl->ccr, SRCCCR_CISZ, cisz);
284 ctl->dirty.bf.ccr = 1;
285 return 0;
286}
287
288static int src_set_ca(void *blk, unsigned int ca)
289{
290 struct src_rsc_ctrl_blk *ctl = blk;
291
292 set_field(&ctl->ca, SRCCA_CA, ca);
293 ctl->dirty.bf.ca = 1;
294 return 0;
295}
296
297static int src_set_sa(void *blk, unsigned int sa)
298{
299 struct src_rsc_ctrl_blk *ctl = blk;
300
301 set_field(&ctl->sa, SRCSA_SA, sa);
302 ctl->dirty.bf.sa = 1;
303 return 0;
304}
305
306static int src_set_la(void *blk, unsigned int la)
307{
308 struct src_rsc_ctrl_blk *ctl = blk;
309
310 set_field(&ctl->la, SRCLA_LA, la);
311 ctl->dirty.bf.la = 1;
312 return 0;
313}
314
315static int src_set_pitch(void *blk, unsigned int pitch)
316{
317 struct src_rsc_ctrl_blk *ctl = blk;
318
319 set_field(&ctl->mpr, MPRLH_PITCH, pitch);
320 ctl->dirty.bf.mpr = 1;
321 return 0;
322}
323
324static int src_set_clear_zbufs(void *blk, unsigned int clear)
325{
326 ((struct src_rsc_ctrl_blk *)blk)->dirty.bf.czbfs = (clear ? 1 : 0);
327 return 0;
328}
329
330static int src_set_dirty(void *blk, unsigned int flags)
331{
332 ((struct src_rsc_ctrl_blk *)blk)->dirty.data = (flags & 0xffff);
333 return 0;
334}
335
336static int src_set_dirty_all(void *blk)
337{
338 ((struct src_rsc_ctrl_blk *)blk)->dirty.data = ~(0x0);
339 return 0;
340}
341
342#define AR_SLOT_SIZE 4096
343#define AR_SLOT_BLOCK_SIZE 16
344#define AR_PTS_PITCH 6
345#define AR_PARAM_SRC_OFFSET 0x60
346
347static unsigned int src_param_pitch_mixer(unsigned int src_idx)
348{
349 return ((src_idx << 4) + AR_PTS_PITCH + AR_SLOT_SIZE
350 - AR_PARAM_SRC_OFFSET) % AR_SLOT_SIZE;
351
352}
353
354static int src_commit_write(struct hw *hw, unsigned int idx, void *blk)
355{
356 struct src_rsc_ctrl_blk *ctl = blk;
357 int i = 0;
358
359 if (ctl->dirty.bf.czbfs) {
360 /* Clear Z-Buffer registers */
361 for (i = 0; i < 8; i++)
362 hw_write_20kx(hw, SRC_UPZ+idx*0x100+i*0x4, 0);
363
364 for (i = 0; i < 4; i++)
365 hw_write_20kx(hw, SRC_DN0Z+idx*0x100+i*0x4, 0);
366
367 for (i = 0; i < 8; i++)
368 hw_write_20kx(hw, SRC_DN1Z+idx*0x100+i*0x4, 0);
369
370 ctl->dirty.bf.czbfs = 0;
371 }
372 if (ctl->dirty.bf.mpr) {
373 /* Take the parameter mixer resource in the same group as that
374 * the idx src is in for simplicity. Unlike src, all conjugate
375 * parameter mixer resources must be programmed for
376 * corresponding conjugate src resources. */
377 unsigned int pm_idx = src_param_pitch_mixer(idx);
378 hw_write_20kx(hw, MIXER_PRING_LO_HI+4*pm_idx, ctl->mpr);
379 hw_write_20kx(hw, MIXER_PMOPLO+8*pm_idx, 0x3);
380 hw_write_20kx(hw, MIXER_PMOPHI+8*pm_idx, 0x0);
381 ctl->dirty.bf.mpr = 0;
382 }
383 if (ctl->dirty.bf.sa) {
384 hw_write_20kx(hw, SRC_SA+idx*0x100, ctl->sa);
385 ctl->dirty.bf.sa = 0;
386 }
387 if (ctl->dirty.bf.la) {
388 hw_write_20kx(hw, SRC_LA+idx*0x100, ctl->la);
389 ctl->dirty.bf.la = 0;
390 }
391 if (ctl->dirty.bf.ca) {
392 hw_write_20kx(hw, SRC_CA+idx*0x100, ctl->ca);
393 ctl->dirty.bf.ca = 0;
394 }
395
396 /* Write srccf register */
397 hw_write_20kx(hw, SRC_CF+idx*0x100, 0x0);
398
399 if (ctl->dirty.bf.ccr) {
400 hw_write_20kx(hw, SRC_CCR+idx*0x100, ctl->ccr);
401 ctl->dirty.bf.ccr = 0;
402 }
403 if (ctl->dirty.bf.ctl) {
404 hw_write_20kx(hw, SRC_CTL+idx*0x100, ctl->ctl);
405 ctl->dirty.bf.ctl = 0;
406 }
407
408 return 0;
409}
410
411static int src_get_ca(struct hw *hw, unsigned int idx, void *blk)
412{
413 struct src_rsc_ctrl_blk *ctl = blk;
414
415 ctl->ca = hw_read_20kx(hw, SRC_CA+idx*0x100);
416 ctl->dirty.bf.ca = 0;
417
418 return get_field(ctl->ca, SRCCA_CA);
419}
420
421static unsigned int src_get_dirty(void *blk)
422{
423 return ((struct src_rsc_ctrl_blk *)blk)->dirty.data;
424}
425
426static unsigned int src_dirty_conj_mask(void)
427{
428 return 0x20;
429}
430
431static int src_mgr_enbs_src(void *blk, unsigned int idx)
432{
433 ((struct src_mgr_ctrl_blk *)blk)->enbsa |= (0x1 << ((idx%128)/4));
434 ((struct src_mgr_ctrl_blk *)blk)->dirty.bf.enbsa = 1;
435 ((struct src_mgr_ctrl_blk *)blk)->enb[idx/32] |= (0x1 << (idx%32));
436 return 0;
437}
438
439static int src_mgr_enb_src(void *blk, unsigned int idx)
440{
441 ((struct src_mgr_ctrl_blk *)blk)->enb[idx/32] |= (0x1 << (idx%32));
442 ((struct src_mgr_ctrl_blk *)blk)->dirty.data |= (0x1 << (idx/32));
443 return 0;
444}
445
446static int src_mgr_dsb_src(void *blk, unsigned int idx)
447{
448 ((struct src_mgr_ctrl_blk *)blk)->enb[idx/32] &= ~(0x1 << (idx%32));
449 ((struct src_mgr_ctrl_blk *)blk)->dirty.data |= (0x1 << (idx/32));
450 return 0;
451}
452
453static int src_mgr_commit_write(struct hw *hw, void *blk)
454{
455 struct src_mgr_ctrl_blk *ctl = blk;
456 int i = 0;
457 unsigned int ret = 0;
458
459 if (ctl->dirty.bf.enbsa) {
460 do {
461 ret = hw_read_20kx(hw, SRC_ENBSTAT);
462 } while (ret & 0x1);
463 hw_write_20kx(hw, SRC_ENBSA, ctl->enbsa);
464 ctl->dirty.bf.enbsa = 0;
465 }
466 for (i = 0; i < 8; i++) {
467 if ((ctl->dirty.data & (0x1 << i))) {
468 hw_write_20kx(hw, SRC_ENB+(i*0x100), ctl->enb[i]);
469 ctl->dirty.data &= ~(0x1 << i);
470 }
471 }
472
473 return 0;
474}
475
476static int src_mgr_get_ctrl_blk(void **rblk)
477{
478 struct src_mgr_ctrl_blk *blk;
479
480 *rblk = NULL;
481 blk = kzalloc(sizeof(*blk), GFP_KERNEL);
482 if (NULL == blk)
483 return -ENOMEM;
484
485 *rblk = blk;
486
487 return 0;
488}
489
490static int src_mgr_put_ctrl_blk(void *blk)
491{
492 kfree((struct src_mgr_ctrl_blk *)blk);
493
494 return 0;
495}
496
497static int srcimp_mgr_get_ctrl_blk(void **rblk)
498{
499 struct srcimp_mgr_ctrl_blk *blk;
500
501 *rblk = NULL;
502 blk = kzalloc(sizeof(*blk), GFP_KERNEL);
503 if (NULL == blk)
504 return -ENOMEM;
505
506 *rblk = blk;
507
508 return 0;
509}
510
511static int srcimp_mgr_put_ctrl_blk(void *blk)
512{
513 kfree((struct srcimp_mgr_ctrl_blk *)blk);
514
515 return 0;
516}
517
518static int srcimp_mgr_set_imaparc(void *blk, unsigned int slot)
519{
520 struct srcimp_mgr_ctrl_blk *ctl = blk;
521
522 set_field(&ctl->srcimap.srcaim, SRCAIM_ARC, slot);
523 ctl->dirty.bf.srcimap = 1;
524 return 0;
525}
526
527static int srcimp_mgr_set_imapuser(void *blk, unsigned int user)
528{
529 struct srcimp_mgr_ctrl_blk *ctl = blk;
530
531 set_field(&ctl->srcimap.srcaim, SRCAIM_SRC, user);
532 ctl->dirty.bf.srcimap = 1;
533 return 0;
534}
535
536static int srcimp_mgr_set_imapnxt(void *blk, unsigned int next)
537{
538 struct srcimp_mgr_ctrl_blk *ctl = blk;
539
540 set_field(&ctl->srcimap.srcaim, SRCAIM_NXT, next);
541 ctl->dirty.bf.srcimap = 1;
542 return 0;
543}
544
545static int srcimp_mgr_set_imapaddr(void *blk, unsigned int addr)
546{
547 ((struct srcimp_mgr_ctrl_blk *)blk)->srcimap.idx = addr;
548 ((struct srcimp_mgr_ctrl_blk *)blk)->dirty.bf.srcimap = 1;
549 return 0;
550}
551
552static int srcimp_mgr_commit_write(struct hw *hw, void *blk)
553{
554 struct srcimp_mgr_ctrl_blk *ctl = blk;
555
556 if (ctl->dirty.bf.srcimap) {
557 hw_write_20kx(hw, SRC_IMAP+ctl->srcimap.idx*0x100,
558 ctl->srcimap.srcaim);
559 ctl->dirty.bf.srcimap = 0;
560 }
561
562 return 0;
563}
564
565/*
566 * AMIXER control block definitions.
567 */
568
569#define AMOPLO_M 0x00000003
570#define AMOPLO_IV 0x00000004
571#define AMOPLO_X 0x0003FFF0
572#define AMOPLO_Y 0xFFFC0000
573
574#define AMOPHI_SADR 0x000000FF
575#define AMOPHI_SE 0x80000000
576
577/* AMIXER resource register dirty flags */
578union amixer_dirty {
579 struct {
580 u16 amoplo:1;
581 u16 amophi:1;
582 u16 rsv:14;
583 } bf;
584 u16 data;
585};
586
587/* AMIXER resource control block */
588struct amixer_rsc_ctrl_blk {
589 unsigned int amoplo;
590 unsigned int amophi;
591 union amixer_dirty dirty;
592};
593
594static int amixer_set_mode(void *blk, unsigned int mode)
595{
596 struct amixer_rsc_ctrl_blk *ctl = blk;
597
598 set_field(&ctl->amoplo, AMOPLO_M, mode);
599 ctl->dirty.bf.amoplo = 1;
600 return 0;
601}
602
603static int amixer_set_iv(void *blk, unsigned int iv)
604{
605 struct amixer_rsc_ctrl_blk *ctl = blk;
606
607 set_field(&ctl->amoplo, AMOPLO_IV, iv);
608 ctl->dirty.bf.amoplo = 1;
609 return 0;
610}
611
612static int amixer_set_x(void *blk, unsigned int x)
613{
614 struct amixer_rsc_ctrl_blk *ctl = blk;
615
616 set_field(&ctl->amoplo, AMOPLO_X, x);
617 ctl->dirty.bf.amoplo = 1;
618 return 0;
619}
620
621static int amixer_set_y(void *blk, unsigned int y)
622{
623 struct amixer_rsc_ctrl_blk *ctl = blk;
624
625 set_field(&ctl->amoplo, AMOPLO_Y, y);
626 ctl->dirty.bf.amoplo = 1;
627 return 0;
628}
629
630static int amixer_set_sadr(void *blk, unsigned int sadr)
631{
632 struct amixer_rsc_ctrl_blk *ctl = blk;
633
634 set_field(&ctl->amophi, AMOPHI_SADR, sadr);
635 ctl->dirty.bf.amophi = 1;
636 return 0;
637}
638
639static int amixer_set_se(void *blk, unsigned int se)
640{
641 struct amixer_rsc_ctrl_blk *ctl = blk;
642
643 set_field(&ctl->amophi, AMOPHI_SE, se);
644 ctl->dirty.bf.amophi = 1;
645 return 0;
646}
647
648static int amixer_set_dirty(void *blk, unsigned int flags)
649{
650 ((struct amixer_rsc_ctrl_blk *)blk)->dirty.data = (flags & 0xffff);
651 return 0;
652}
653
654static int amixer_set_dirty_all(void *blk)
655{
656 ((struct amixer_rsc_ctrl_blk *)blk)->dirty.data = ~(0x0);
657 return 0;
658}
659
660static int amixer_commit_write(struct hw *hw, unsigned int idx, void *blk)
661{
662 struct amixer_rsc_ctrl_blk *ctl = blk;
663
664 if (ctl->dirty.bf.amoplo || ctl->dirty.bf.amophi) {
665 hw_write_20kx(hw, MIXER_AMOPLO+idx*8, ctl->amoplo);
666 ctl->dirty.bf.amoplo = 0;
667 hw_write_20kx(hw, MIXER_AMOPHI+idx*8, ctl->amophi);
668 ctl->dirty.bf.amophi = 0;
669 }
670
671 return 0;
672}
673
674static int amixer_get_y(void *blk)
675{
676 struct amixer_rsc_ctrl_blk *ctl = blk;
677
678 return get_field(ctl->amoplo, AMOPLO_Y);
679}
680
681static unsigned int amixer_get_dirty(void *blk)
682{
683 return ((struct amixer_rsc_ctrl_blk *)blk)->dirty.data;
684}
685
686static int amixer_rsc_get_ctrl_blk(void **rblk)
687{
688 struct amixer_rsc_ctrl_blk *blk;
689
690 *rblk = NULL;
691 blk = kzalloc(sizeof(*blk), GFP_KERNEL);
692 if (NULL == blk)
693 return -ENOMEM;
694
695 *rblk = blk;
696
697 return 0;
698}
699
700static int amixer_rsc_put_ctrl_blk(void *blk)
701{
702 kfree((struct amixer_rsc_ctrl_blk *)blk);
703
704 return 0;
705}
706
707static int amixer_mgr_get_ctrl_blk(void **rblk)
708{
709 *rblk = NULL;
710
711 return 0;
712}
713
714static int amixer_mgr_put_ctrl_blk(void *blk)
715{
716 return 0;
717}
718
719/*
720 * DAIO control block definitions.
721 */
722
723/* Receiver Sample Rate Tracker Control register */
724#define SRTCTL_SRCO 0x000000FF
725#define SRTCTL_SRCM 0x0000FF00
726#define SRTCTL_RSR 0x00030000
727#define SRTCTL_DRAT 0x00300000
728#define SRTCTL_EC 0x01000000
729#define SRTCTL_ET 0x10000000
730
731/* DAIO Receiver register dirty flags */
732union dai_dirty {
733 struct {
734 u16 srt:1;
735 u16 rsv:15;
736 } bf;
737 u16 data;
738};
739
740/* DAIO Receiver control block */
741struct dai_ctrl_blk {
742 unsigned int srt;
743 union dai_dirty dirty;
744};
745
746/* Audio Input Mapper RAM */
747#define AIM_ARC 0x00000FFF
748#define AIM_NXT 0x007F0000
749
750struct daoimap {
751 unsigned int aim;
752 unsigned int idx;
753};
754
755/* Audio Transmitter Control and Status register */
756#define ATXCTL_EN 0x00000001
757#define ATXCTL_MODE 0x00000010
758#define ATXCTL_CD 0x00000020
759#define ATXCTL_RAW 0x00000100
760#define ATXCTL_MT 0x00000200
761#define ATXCTL_NUC 0x00003000
762#define ATXCTL_BEN 0x00010000
763#define ATXCTL_BMUX 0x00700000
764#define ATXCTL_B24 0x01000000
765#define ATXCTL_CPF 0x02000000
766#define ATXCTL_RIV 0x10000000
767#define ATXCTL_LIV 0x20000000
768#define ATXCTL_RSAT 0x40000000
769#define ATXCTL_LSAT 0x80000000
770
771/* XDIF Transmitter register dirty flags */
772union dao_dirty {
773 struct {
774 u16 atxcsl:1;
775 u16 rsv:15;
776 } bf;
777 u16 data;
778};
779
780/* XDIF Transmitter control block */
781struct dao_ctrl_blk {
782 /* XDIF Transmitter Channel Status Low Register */
783 unsigned int atxcsl;
784 union dao_dirty dirty;
785};
786
787/* Audio Receiver Control register */
788#define ARXCTL_EN 0x00000001
789
790/* DAIO manager register dirty flags */
791union daio_mgr_dirty {
792 struct {
793 u32 atxctl:8;
794 u32 arxctl:8;
795 u32 daoimap:1;
796 u32 rsv:15;
797 } bf;
798 u32 data;
799};
800
801/* DAIO manager control block */
802struct daio_mgr_ctrl_blk {
803 struct daoimap daoimap;
804 unsigned int txctl[8];
805 unsigned int rxctl[8];
806 union daio_mgr_dirty dirty;
807};
808
809static int dai_srt_set_srco(void *blk, unsigned int src)
810{
811 struct dai_ctrl_blk *ctl = blk;
812
813 set_field(&ctl->srt, SRTCTL_SRCO, src);
814 ctl->dirty.bf.srt = 1;
815 return 0;
816}
817
818static int dai_srt_set_srcm(void *blk, unsigned int src)
819{
820 struct dai_ctrl_blk *ctl = blk;
821
822 set_field(&ctl->srt, SRTCTL_SRCM, src);
823 ctl->dirty.bf.srt = 1;
824 return 0;
825}
826
827static int dai_srt_set_rsr(void *blk, unsigned int rsr)
828{
829 struct dai_ctrl_blk *ctl = blk;
830
831 set_field(&ctl->srt, SRTCTL_RSR, rsr);
832 ctl->dirty.bf.srt = 1;
833 return 0;
834}
835
836static int dai_srt_set_drat(void *blk, unsigned int drat)
837{
838 struct dai_ctrl_blk *ctl = blk;
839
840 set_field(&ctl->srt, SRTCTL_DRAT, drat);
841 ctl->dirty.bf.srt = 1;
842 return 0;
843}
844
845static int dai_srt_set_ec(void *blk, unsigned int ec)
846{
847 struct dai_ctrl_blk *ctl = blk;
848
849 set_field(&ctl->srt, SRTCTL_EC, ec ? 1 : 0);
850 ctl->dirty.bf.srt = 1;
851 return 0;
852}
853
854static int dai_srt_set_et(void *blk, unsigned int et)
855{
856 struct dai_ctrl_blk *ctl = blk;
857
858 set_field(&ctl->srt, SRTCTL_ET, et ? 1 : 0);
859 ctl->dirty.bf.srt = 1;
860 return 0;
861}
862
863static int dai_commit_write(struct hw *hw, unsigned int idx, void *blk)
864{
865 struct dai_ctrl_blk *ctl = blk;
866
867 if (ctl->dirty.bf.srt) {
868 hw_write_20kx(hw, AUDIO_IO_RX_SRT_CTL+0x40*idx, ctl->srt);
869 ctl->dirty.bf.srt = 0;
870 }
871
872 return 0;
873}
874
875static int dai_get_ctrl_blk(void **rblk)
876{
877 struct dai_ctrl_blk *blk;
878
879 *rblk = NULL;
880 blk = kzalloc(sizeof(*blk), GFP_KERNEL);
881 if (NULL == blk)
882 return -ENOMEM;
883
884 *rblk = blk;
885
886 return 0;
887}
888
889static int dai_put_ctrl_blk(void *blk)
890{
891 kfree((struct dai_ctrl_blk *)blk);
892
893 return 0;
894}
895
896static int dao_set_spos(void *blk, unsigned int spos)
897{
898 ((struct dao_ctrl_blk *)blk)->atxcsl = spos;
899 ((struct dao_ctrl_blk *)blk)->dirty.bf.atxcsl = 1;
900 return 0;
901}
902
903static int dao_commit_write(struct hw *hw, unsigned int idx, void *blk)
904{
905 struct dao_ctrl_blk *ctl = blk;
906
907 if (ctl->dirty.bf.atxcsl) {
908 if (idx < 4) {
909 /* S/PDIF SPOSx */
910 hw_write_20kx(hw, AUDIO_IO_TX_CSTAT_L+0x40*idx,
911 ctl->atxcsl);
912 }
913 ctl->dirty.bf.atxcsl = 0;
914 }
915
916 return 0;
917}
918
919static int dao_get_spos(void *blk, unsigned int *spos)
920{
921 *spos = ((struct dao_ctrl_blk *)blk)->atxcsl;
922 return 0;
923}
924
925static int dao_get_ctrl_blk(void **rblk)
926{
927 struct dao_ctrl_blk *blk;
928
929 *rblk = NULL;
930 blk = kzalloc(sizeof(*blk), GFP_KERNEL);
931 if (NULL == blk)
932 return -ENOMEM;
933
934 *rblk = blk;
935
936 return 0;
937}
938
939static int dao_put_ctrl_blk(void *blk)
940{
941 kfree((struct dao_ctrl_blk *)blk);
942
943 return 0;
944}
945
946static int daio_mgr_enb_dai(void *blk, unsigned int idx)
947{
948 struct daio_mgr_ctrl_blk *ctl = blk;
949
950 set_field(&ctl->rxctl[idx], ARXCTL_EN, 1);
951 ctl->dirty.bf.arxctl |= (0x1 << idx);
952 return 0;
953}
954
955static int daio_mgr_dsb_dai(void *blk, unsigned int idx)
956{
957 struct daio_mgr_ctrl_blk *ctl = blk;
958
959 set_field(&ctl->rxctl[idx], ARXCTL_EN, 0);
960
961 ctl->dirty.bf.arxctl |= (0x1 << idx);
962 return 0;
963}
964
965static int daio_mgr_enb_dao(void *blk, unsigned int idx)
966{
967 struct daio_mgr_ctrl_blk *ctl = blk;
968
969 set_field(&ctl->txctl[idx], ATXCTL_EN, 1);
970 ctl->dirty.bf.atxctl |= (0x1 << idx);
971 return 0;
972}
973
974static int daio_mgr_dsb_dao(void *blk, unsigned int idx)
975{
976 struct daio_mgr_ctrl_blk *ctl = blk;
977
978 set_field(&ctl->txctl[idx], ATXCTL_EN, 0);
979 ctl->dirty.bf.atxctl |= (0x1 << idx);
980 return 0;
981}
982
983static int daio_mgr_dao_init(void *blk, unsigned int idx, unsigned int conf)
984{
985 struct daio_mgr_ctrl_blk *ctl = blk;
986
987 if (idx < 4) {
988 /* S/PDIF output */
989 switch ((conf & 0x7)) {
990 case 1:
991 set_field(&ctl->txctl[idx], ATXCTL_NUC, 0);
992 break;
993 case 2:
994 set_field(&ctl->txctl[idx], ATXCTL_NUC, 1);
995 break;
996 case 4:
997 set_field(&ctl->txctl[idx], ATXCTL_NUC, 2);
998 break;
999 case 8:
1000 set_field(&ctl->txctl[idx], ATXCTL_NUC, 3);
1001 break;
1002 default:
1003 break;
1004 }
1005 /* CDIF */
1006 set_field(&ctl->txctl[idx], ATXCTL_CD, (!(conf & 0x7)));
1007 /* Non-audio */
1008 set_field(&ctl->txctl[idx], ATXCTL_LIV, (conf >> 4) & 0x1);
1009 /* Non-audio */
1010 set_field(&ctl->txctl[idx], ATXCTL_RIV, (conf >> 4) & 0x1);
1011 set_field(&ctl->txctl[idx], ATXCTL_RAW,
1012 ((conf >> 3) & 0x1) ? 0 : 0);
1013 ctl->dirty.bf.atxctl |= (0x1 << idx);
1014 } else {
1015 /* I2S output */
1016 /*idx %= 4; */
1017 }
1018 return 0;
1019}
1020
1021static int daio_mgr_set_imaparc(void *blk, unsigned int slot)
1022{
1023 struct daio_mgr_ctrl_blk *ctl = blk;
1024
1025 set_field(&ctl->daoimap.aim, AIM_ARC, slot);
1026 ctl->dirty.bf.daoimap = 1;
1027 return 0;
1028}
1029
1030static int daio_mgr_set_imapnxt(void *blk, unsigned int next)
1031{
1032 struct daio_mgr_ctrl_blk *ctl = blk;
1033
1034 set_field(&ctl->daoimap.aim, AIM_NXT, next);
1035 ctl->dirty.bf.daoimap = 1;
1036 return 0;
1037}
1038
1039static int daio_mgr_set_imapaddr(void *blk, unsigned int addr)
1040{
1041 ((struct daio_mgr_ctrl_blk *)blk)->daoimap.idx = addr;
1042 ((struct daio_mgr_ctrl_blk *)blk)->dirty.bf.daoimap = 1;
1043 return 0;
1044}
1045
1046static int daio_mgr_commit_write(struct hw *hw, void *blk)
1047{
1048 struct daio_mgr_ctrl_blk *ctl = blk;
1049 unsigned int data = 0;
1050 int i = 0;
1051
1052 for (i = 0; i < 8; i++) {
1053 if ((ctl->dirty.bf.atxctl & (0x1 << i))) {
1054 data = ctl->txctl[i];
1055 hw_write_20kx(hw, (AUDIO_IO_TX_CTL+(0x40*i)), data);
1056 ctl->dirty.bf.atxctl &= ~(0x1 << i);
1057 mdelay(1);
1058 }
1059 if ((ctl->dirty.bf.arxctl & (0x1 << i))) {
1060 data = ctl->rxctl[i];
1061 hw_write_20kx(hw, (AUDIO_IO_RX_CTL+(0x40*i)), data);
1062 ctl->dirty.bf.arxctl &= ~(0x1 << i);
1063 mdelay(1);
1064 }
1065 }
1066 if (ctl->dirty.bf.daoimap) {
1067 hw_write_20kx(hw, AUDIO_IO_AIM+ctl->daoimap.idx*4,
1068 ctl->daoimap.aim);
1069 ctl->dirty.bf.daoimap = 0;
1070 }
1071
1072 return 0;
1073}
1074
1075static int daio_mgr_get_ctrl_blk(struct hw *hw, void **rblk)
1076{
1077 struct daio_mgr_ctrl_blk *blk;
1078 int i = 0;
1079
1080 *rblk = NULL;
1081 blk = kzalloc(sizeof(*blk), GFP_KERNEL);
1082 if (NULL == blk)
1083 return -ENOMEM;
1084
1085 for (i = 0; i < 8; i++) {
1086 blk->txctl[i] = hw_read_20kx(hw, AUDIO_IO_TX_CTL+(0x40*i));
1087 blk->rxctl[i] = hw_read_20kx(hw, AUDIO_IO_RX_CTL+(0x40*i));
1088 }
1089
1090 *rblk = blk;
1091
1092 return 0;
1093}
1094
1095static int daio_mgr_put_ctrl_blk(void *blk)
1096{
1097 kfree((struct daio_mgr_ctrl_blk *)blk);
1098
1099 return 0;
1100}
1101
1102/* Card hardware initialization block */
1103struct dac_conf {
1104 unsigned int msr; /* master sample rate in rsrs */
1105};
1106
1107struct adc_conf {
1108 unsigned int msr; /* master sample rate in rsrs */
1109 unsigned char input; /* the input source of ADC */
1110 unsigned char mic20db; /* boost mic by 20db if input is microphone */
1111};
1112
1113struct daio_conf {
1114 unsigned int msr; /* master sample rate in rsrs */
1115};
1116
1117struct trn_conf {
1118 unsigned long vm_pgt_phys;
1119};
1120
1121static int hw_daio_init(struct hw *hw, const struct daio_conf *info)
1122{
1123 u32 dwData = 0;
1124 int i;
1125
1126 /* Program I2S with proper sample rate and enable the correct I2S
1127 * channel. ED(0/8/16/24): Enable all I2S/I2X master clock output */
1128 if (1 == info->msr) {
1129 hw_write_20kx(hw, AUDIO_IO_MCLK, 0x01010101);
1130 hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x01010101);
1131 hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0);
1132 } else if (2 == info->msr) {
1133 hw_write_20kx(hw, AUDIO_IO_MCLK, 0x11111111);
1134 /* Specify all playing 96khz
1135 * EA [0] - Enabled
1136 * RTA [4:5] - 96kHz
1137 * EB [8] - Enabled
1138 * RTB [12:13] - 96kHz
1139 * EC [16] - Enabled
1140 * RTC [20:21] - 96kHz
1141 * ED [24] - Enabled
1142 * RTD [28:29] - 96kHz */
1143 hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x11111111);
1144 hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0);
1145 } else {
1146 printk(KERN_ALERT "ERROR!!! Invalid sampling rate!!!\n");
1147 return -EINVAL;
1148 }
1149
1150 for (i = 0; i < 8; i++) {
1151 if (i <= 3) {
1152 /* 1st 3 channels are SPDIFs (SB0960) */
1153 if (i == 3)
1154 dwData = 0x1001001;
1155 else
1156 dwData = 0x1000001;
1157
1158 hw_write_20kx(hw, (AUDIO_IO_TX_CTL+(0x40*i)), dwData);
1159 hw_write_20kx(hw, (AUDIO_IO_RX_CTL+(0x40*i)), dwData);
1160
1161 /* Initialize the SPDIF Out Channel status registers.
1162 * The value specified here is based on the typical
1163 * values provided in the specification, namely: Clock
1164 * Accuracy of 1000ppm, Sample Rate of 48KHz,
1165 * unspecified source number, Generation status = 1,
1166 * Category code = 0x12 (Digital Signal Mixer),
1167 * Mode = 0, Emph = 0, Copy Permitted, AN = 0
1168 * (indicating that we're transmitting digital audio,
1169 * and the Professional Use bit is 0. */
1170
1171 hw_write_20kx(hw, AUDIO_IO_TX_CSTAT_L+(0x40*i),
1172 0x02109204); /* Default to 48kHz */
1173
1174 hw_write_20kx(hw, AUDIO_IO_TX_CSTAT_H+(0x40*i), 0x0B);
1175 } else {
1176 /* Next 5 channels are I2S (SB0960) */
1177 dwData = 0x11;
1178 hw_write_20kx(hw, AUDIO_IO_RX_CTL+(0x40*i), dwData);
1179 if (2 == info->msr) {
1180 /* Four channels per sample period */
1181 dwData |= 0x1000;
1182 }
1183 hw_write_20kx(hw, AUDIO_IO_TX_CTL+(0x40*i), dwData);
1184 }
1185 }
1186
1187 return 0;
1188}
1189
1190/* TRANSPORT operations */
1191static int hw_trn_init(struct hw *hw, const struct trn_conf *info)
1192{
1193 u32 vmctl = 0, data = 0;
1194 unsigned long ptp_phys_low = 0, ptp_phys_high = 0;
1195 int i = 0;
1196
1197 /* Set up device page table */
1198 if ((~0UL) == info->vm_pgt_phys) {
1199 printk(KERN_ALERT "Wrong device page table page address!!!\n");
1200 return -1;
1201 }
1202
1203 vmctl = 0x80000C0F; /* 32-bit, 4k-size page */
1204#if BITS_PER_LONG == 64
1205 ptp_phys_low = info->vm_pgt_phys & ((1UL<<32)-1);
1206 ptp_phys_high = (info->vm_pgt_phys>>32) & ((1UL<<32)-1);
1207 vmctl |= (3<<8);
1208#elif BITS_PER_LONG == 32
1209 ptp_phys_low = info->vm_pgt_phys & (~0UL);
1210 ptp_phys_high = 0;
1211#else
1212# error "Unknown BITS_PER_LONG!"
1213#endif
1214#if PAGE_SIZE == 8192
1215# error "Don't support 8k-page!"
1216#endif
1217 /* Write page table physical address to all PTPAL registers */
1218 for (i = 0; i < 64; i++) {
1219 hw_write_20kx(hw, VMEM_PTPAL+(16*i), ptp_phys_low);
1220 hw_write_20kx(hw, VMEM_PTPAH+(16*i), ptp_phys_high);
1221 }
1222 /* Enable virtual memory transfer */
1223 hw_write_20kx(hw, VMEM_CTL, vmctl);
1224 /* Enable transport bus master and queueing of request */
1225 hw_write_20kx(hw, TRANSPORT_CTL, 0x03);
1226 hw_write_20kx(hw, TRANSPORT_INT, 0x200c01);
1227 /* Enable transport ring */
1228 data = hw_read_20kx(hw, TRANSPORT_ENB);
1229 hw_write_20kx(hw, TRANSPORT_ENB, (data | 0x03));
1230
1231 return 0;
1232}
1233
1234/* Card initialization */
1235#define GCTL_AIE 0x00000001
1236#define GCTL_UAA 0x00000002
1237#define GCTL_DPC 0x00000004
1238#define GCTL_DBP 0x00000008
1239#define GCTL_ABP 0x00000010
1240#define GCTL_TBP 0x00000020
1241#define GCTL_SBP 0x00000040
1242#define GCTL_FBP 0x00000080
1243#define GCTL_ME 0x00000100
1244#define GCTL_AID 0x00001000
1245
1246#define PLLCTL_SRC 0x00000007
1247#define PLLCTL_SPE 0x00000008
1248#define PLLCTL_RD 0x000000F0
1249#define PLLCTL_FD 0x0001FF00
1250#define PLLCTL_OD 0x00060000
1251#define PLLCTL_B 0x00080000
1252#define PLLCTL_AS 0x00100000
1253#define PLLCTL_LF 0x03E00000
1254#define PLLCTL_SPS 0x1C000000
1255#define PLLCTL_AD 0x60000000
1256
1257#define PLLSTAT_CCS 0x00000007
1258#define PLLSTAT_SPL 0x00000008
1259#define PLLSTAT_CRD 0x000000F0
1260#define PLLSTAT_CFD 0x0001FF00
1261#define PLLSTAT_SL 0x00020000
1262#define PLLSTAT_FAS 0x00040000
1263#define PLLSTAT_B 0x00080000
1264#define PLLSTAT_PD 0x00100000
1265#define PLLSTAT_OCA 0x00200000
1266#define PLLSTAT_NCA 0x00400000
1267
1268static int hw_pll_init(struct hw *hw, unsigned int rsr)
1269{
1270 unsigned int pllenb;
1271 unsigned int pllctl;
1272 unsigned int pllstat;
1273 int i;
1274
1275 pllenb = 0xB;
1276 hw_write_20kx(hw, PLL_ENB, pllenb);
1277 pllctl = 0x20D00000;
1278 set_field(&pllctl, PLLCTL_FD, 16 - 4);
1279 hw_write_20kx(hw, PLL_CTL, pllctl);
1280 mdelay(40);
1281 pllctl = hw_read_20kx(hw, PLL_CTL);
1282 set_field(&pllctl, PLLCTL_B, 0);
1283 if (48000 == rsr) {
1284 set_field(&pllctl, PLLCTL_FD, 16 - 2);
1285 set_field(&pllctl, PLLCTL_RD, 1 - 1);
1286 } else { /* 44100 */
1287 set_field(&pllctl, PLLCTL_FD, 147 - 2);
1288 set_field(&pllctl, PLLCTL_RD, 10 - 1);
1289 }
1290 hw_write_20kx(hw, PLL_CTL, pllctl);
1291 mdelay(40);
1292 for (i = 0; i < 1000; i++) {
1293 pllstat = hw_read_20kx(hw, PLL_STAT);
1294 if (get_field(pllstat, PLLSTAT_PD))
1295 continue;
1296
1297 if (get_field(pllstat, PLLSTAT_B) !=
1298 get_field(pllctl, PLLCTL_B))
1299 continue;
1300
1301 if (get_field(pllstat, PLLSTAT_CCS) !=
1302 get_field(pllctl, PLLCTL_SRC))
1303 continue;
1304
1305 if (get_field(pllstat, PLLSTAT_CRD) !=
1306 get_field(pllctl, PLLCTL_RD))
1307 continue;
1308
1309 if (get_field(pllstat, PLLSTAT_CFD) !=
1310 get_field(pllctl, PLLCTL_FD))
1311 continue;
1312
1313 break;
1314 }
1315 if (i >= 1000) {
1316 printk(KERN_ALERT "PLL initialization failed!!!\n");
1317 return -EBUSY;
1318 }
1319
1320 return 0;
1321}
1322
1323static int hw_auto_init(struct hw *hw)
1324{
1325 unsigned int gctl;
1326 int i;
1327
1328 gctl = hw_read_20kx(hw, GLOBAL_CNTL_GCTL);
1329 set_field(&gctl, GCTL_AIE, 0);
1330 hw_write_20kx(hw, GLOBAL_CNTL_GCTL, gctl);
1331 set_field(&gctl, GCTL_AIE, 1);
1332 hw_write_20kx(hw, GLOBAL_CNTL_GCTL, gctl);
1333 mdelay(10);
1334 for (i = 0; i < 400000; i++) {
1335 gctl = hw_read_20kx(hw, GLOBAL_CNTL_GCTL);
1336 if (get_field(gctl, GCTL_AID))
1337 break;
1338 }
1339 if (!get_field(gctl, GCTL_AID)) {
1340 printk(KERN_ALERT "Card Auto-init failed!!!\n");
1341 return -EBUSY;
1342 }
1343
1344 return 0;
1345}
1346
1347/* DAC operations */
1348
1349#define CS4382_MC1 0x1
1350#define CS4382_MC2 0x2
1351#define CS4382_MC3 0x3
1352#define CS4382_FC 0x4
1353#define CS4382_IC 0x5
1354#define CS4382_XC1 0x6
1355#define CS4382_VCA1 0x7
1356#define CS4382_VCB1 0x8
1357#define CS4382_XC2 0x9
1358#define CS4382_VCA2 0xA
1359#define CS4382_VCB2 0xB
1360#define CS4382_XC3 0xC
1361#define CS4382_VCA3 0xD
1362#define CS4382_VCB3 0xE
1363#define CS4382_XC4 0xF
1364#define CS4382_VCA4 0x10
1365#define CS4382_VCB4 0x11
1366#define CS4382_CREV 0x12
1367
1368/* I2C status */
1369#define STATE_LOCKED 0x00
1370#define STATE_UNLOCKED 0xAA
1371#define DATA_READY 0x800000 /* Used with I2C_IF_STATUS */
1372#define DATA_ABORT 0x10000 /* Used with I2C_IF_STATUS */
1373
1374#define I2C_STATUS_DCM 0x00000001
1375#define I2C_STATUS_BC 0x00000006
1376#define I2C_STATUS_APD 0x00000008
1377#define I2C_STATUS_AB 0x00010000
1378#define I2C_STATUS_DR 0x00800000
1379
1380#define I2C_ADDRESS_PTAD 0x0000FFFF
1381#define I2C_ADDRESS_SLAD 0x007F0000
1382
1383struct REGS_CS4382 {
1384 u32 dwModeControl_1;
1385 u32 dwModeControl_2;
1386 u32 dwModeControl_3;
1387
1388 u32 dwFilterControl;
1389 u32 dwInvertControl;
1390
1391 u32 dwMixControl_P1;
1392 u32 dwVolControl_A1;
1393 u32 dwVolControl_B1;
1394
1395 u32 dwMixControl_P2;
1396 u32 dwVolControl_A2;
1397 u32 dwVolControl_B2;
1398
1399 u32 dwMixControl_P3;
1400 u32 dwVolControl_A3;
1401 u32 dwVolControl_B3;
1402
1403 u32 dwMixControl_P4;
1404 u32 dwVolControl_A4;
1405 u32 dwVolControl_B4;
1406};
1407
1408static u8 m_bAddressSize, m_bDataSize, m_bDeviceID;
1409
1410static int I2CUnlockFullAccess(struct hw *hw)
1411{
1412 u8 UnlockKeySequence_FLASH_FULLACCESS_MODE[2] = {0xB3, 0xD4};
1413
1414 /* Send keys for forced BIOS mode */
1415 hw_write_20kx(hw, I2C_IF_WLOCK,
1416 UnlockKeySequence_FLASH_FULLACCESS_MODE[0]);
1417 hw_write_20kx(hw, I2C_IF_WLOCK,
1418 UnlockKeySequence_FLASH_FULLACCESS_MODE[1]);
1419 /* Check whether the chip is unlocked */
1420 if (hw_read_20kx(hw, I2C_IF_WLOCK) == STATE_UNLOCKED)
1421 return 0;
1422
1423 return -1;
1424}
1425
1426static int I2CLockChip(struct hw *hw)
1427{
1428 /* Write twice */
1429 hw_write_20kx(hw, I2C_IF_WLOCK, STATE_LOCKED);
1430 hw_write_20kx(hw, I2C_IF_WLOCK, STATE_LOCKED);
1431 if (hw_read_20kx(hw, I2C_IF_WLOCK) == STATE_LOCKED)
1432 return 0;
1433
1434 return -1;
1435}
1436
1437static int I2CInit(struct hw *hw, u8 bDeviceID, u8 bAddressSize, u8 bDataSize)
1438{
1439 int err = 0;
1440 unsigned int RegI2CStatus;
1441 unsigned int RegI2CAddress;
1442
1443 err = I2CUnlockFullAccess(hw);
1444 if (err < 0)
1445 return err;
1446
1447 m_bAddressSize = bAddressSize;
1448 m_bDataSize = bDataSize;
1449 m_bDeviceID = bDeviceID;
1450
1451 RegI2CAddress = 0;
1452 set_field(&RegI2CAddress, I2C_ADDRESS_SLAD, bDeviceID);
1453
1454 hw_write_20kx(hw, I2C_IF_ADDRESS, RegI2CAddress);
1455
1456 RegI2CStatus = hw_read_20kx(hw, I2C_IF_STATUS);
1457
1458 set_field(&RegI2CStatus, I2C_STATUS_DCM, 1); /* Direct control mode */
1459
1460 hw_write_20kx(hw, I2C_IF_STATUS, RegI2CStatus);
1461
1462 return 0;
1463}
1464
1465static int I2CUninit(struct hw *hw)
1466{
1467 unsigned int RegI2CStatus;
1468 unsigned int RegI2CAddress;
1469
1470 RegI2CAddress = 0;
1471 set_field(&RegI2CAddress, I2C_ADDRESS_SLAD, 0x57); /* I2C id */
1472
1473 hw_write_20kx(hw, I2C_IF_ADDRESS, RegI2CAddress);
1474
1475 RegI2CStatus = hw_read_20kx(hw, I2C_IF_STATUS);
1476
1477 set_field(&RegI2CStatus, I2C_STATUS_DCM, 0); /* I2C mode */
1478
1479 hw_write_20kx(hw, I2C_IF_STATUS, RegI2CStatus);
1480
1481 return I2CLockChip(hw);
1482}
1483
1484static int I2CWaitDataReady(struct hw *hw)
1485{
1486 int i = 0x400000;
1487 unsigned int ret = 0;
1488
1489 do {
1490 ret = hw_read_20kx(hw, I2C_IF_STATUS);
1491 } while ((!(ret & DATA_READY)) && --i);
1492
1493 return i;
1494}
1495
1496static int I2CRead(struct hw *hw, u16 wAddress, u32 *pdwData)
1497{
1498 unsigned int RegI2CStatus;
1499
1500 RegI2CStatus = hw_read_20kx(hw, I2C_IF_STATUS);
1501 set_field(&RegI2CStatus, I2C_STATUS_BC,
1502 (4 == m_bAddressSize) ? 0 : m_bAddressSize);
1503 hw_write_20kx(hw, I2C_IF_STATUS, RegI2CStatus);
1504 if (!I2CWaitDataReady(hw))
1505 return -1;
1506
1507 hw_write_20kx(hw, I2C_IF_WDATA, (u32)wAddress);
1508 if (!I2CWaitDataReady(hw))
1509 return -1;
1510
1511 /* Force a read operation */
1512 hw_write_20kx(hw, I2C_IF_RDATA, 0);
1513 if (!I2CWaitDataReady(hw))
1514 return -1;
1515
1516 *pdwData = hw_read_20kx(hw, I2C_IF_RDATA);
1517
1518 return 0;
1519}
1520
1521static int I2CWrite(struct hw *hw, u16 wAddress, u32 dwData)
1522{
1523 unsigned int dwI2CData = (dwData << (m_bAddressSize * 8)) | wAddress;
1524 unsigned int RegI2CStatus;
1525
1526 RegI2CStatus = hw_read_20kx(hw, I2C_IF_STATUS);
1527
1528 set_field(&RegI2CStatus, I2C_STATUS_BC,
1529 (4 == (m_bAddressSize + m_bDataSize)) ?
1530 0 : (m_bAddressSize + m_bDataSize));
1531
1532 hw_write_20kx(hw, I2C_IF_STATUS, RegI2CStatus);
1533 I2CWaitDataReady(hw);
1534 /* Dummy write to trigger the write oprtation */
1535 hw_write_20kx(hw, I2C_IF_WDATA, 0);
1536 I2CWaitDataReady(hw);
1537
1538 /* This is the real data */
1539 hw_write_20kx(hw, I2C_IF_WDATA, dwI2CData);
1540 I2CWaitDataReady(hw);
1541
1542 return 0;
1543}
1544
1545static int hw_dac_init(struct hw *hw, const struct dac_conf *info)
1546{
1547 int err = 0;
1548 u32 dwData = 0;
1549 int i = 0;
1550 struct REGS_CS4382 cs4382_Read = {0};
1551 struct REGS_CS4382 cs4382_Def = {
1552 0x00000001, /* Mode Control 1 */
1553 0x00000000, /* Mode Control 2 */
1554 0x00000084, /* Mode Control 3 */
1555 0x00000000, /* Filter Control */
1556 0x00000000, /* Invert Control */
1557 0x00000024, /* Mixing Control Pair 1 */
1558 0x00000000, /* Vol Control A1 */
1559 0x00000000, /* Vol Control B1 */
1560 0x00000024, /* Mixing Control Pair 2 */
1561 0x00000000, /* Vol Control A2 */
1562 0x00000000, /* Vol Control B2 */
1563 0x00000024, /* Mixing Control Pair 3 */
1564 0x00000000, /* Vol Control A3 */
1565 0x00000000, /* Vol Control B3 */
1566 0x00000024, /* Mixing Control Pair 4 */
1567 0x00000000, /* Vol Control A4 */
1568 0x00000000 /* Vol Control B4 */
1569 };
1570
1571 /* Set DAC reset bit as output */
1572 dwData = hw_read_20kx(hw, GPIO_CTRL);
1573 dwData |= 0x02;
1574 hw_write_20kx(hw, GPIO_CTRL, dwData);
1575
1576 err = I2CInit(hw, 0x18, 1, 1);
1577 if (err < 0)
1578 goto End;
1579
1580 for (i = 0; i < 2; i++) {
1581 /* Reset DAC twice just in-case the chip
1582 * didn't initialized properly */
1583 dwData = hw_read_20kx(hw, GPIO_DATA);
1584 /* GPIO data bit 1 */
1585 dwData &= 0xFFFFFFFD;
1586 hw_write_20kx(hw, GPIO_DATA, dwData);
1587 mdelay(10);
1588 dwData |= 0x2;
1589 hw_write_20kx(hw, GPIO_DATA, dwData);
1590 mdelay(50);
1591
1592 /* Reset the 2nd time */
1593 dwData &= 0xFFFFFFFD;
1594 hw_write_20kx(hw, GPIO_DATA, dwData);
1595 mdelay(10);
1596 dwData |= 0x2;
1597 hw_write_20kx(hw, GPIO_DATA, dwData);
1598 mdelay(50);
1599
1600 if (I2CRead(hw, CS4382_MC1, &cs4382_Read.dwModeControl_1))
1601 continue;
1602
1603 if (I2CRead(hw, CS4382_MC2, &cs4382_Read.dwModeControl_2))
1604 continue;
1605
1606 if (I2CRead(hw, CS4382_MC3, &cs4382_Read.dwModeControl_3))
1607 continue;
1608
1609 if (I2CRead(hw, CS4382_FC, &cs4382_Read.dwFilterControl))
1610 continue;
1611
1612 if (I2CRead(hw, CS4382_IC, &cs4382_Read.dwInvertControl))
1613 continue;
1614
1615 if (I2CRead(hw, CS4382_XC1, &cs4382_Read.dwMixControl_P1))
1616 continue;
1617
1618 if (I2CRead(hw, CS4382_VCA1, &cs4382_Read.dwVolControl_A1))
1619 continue;
1620
1621 if (I2CRead(hw, CS4382_VCB1, &cs4382_Read.dwVolControl_B1))
1622 continue;
1623
1624 if (I2CRead(hw, CS4382_XC2, &cs4382_Read.dwMixControl_P2))
1625 continue;
1626
1627 if (I2CRead(hw, CS4382_VCA2, &cs4382_Read.dwVolControl_A2))
1628 continue;
1629
1630 if (I2CRead(hw, CS4382_VCB2, &cs4382_Read.dwVolControl_B2))
1631 continue;
1632
1633 if (I2CRead(hw, CS4382_XC3, &cs4382_Read.dwMixControl_P3))
1634 continue;
1635
1636 if (I2CRead(hw, CS4382_VCA3, &cs4382_Read.dwVolControl_A3))
1637 continue;
1638
1639 if (I2CRead(hw, CS4382_VCB3, &cs4382_Read.dwVolControl_B3))
1640 continue;
1641
1642 if (I2CRead(hw, CS4382_XC4, &cs4382_Read.dwMixControl_P4))
1643 continue;
1644
1645 if (I2CRead(hw, CS4382_VCA4, &cs4382_Read.dwVolControl_A4))
1646 continue;
1647
1648 if (I2CRead(hw, CS4382_VCB4, &cs4382_Read.dwVolControl_B4))
1649 continue;
1650
1651 if (memcmp(&cs4382_Read, &cs4382_Def,
1652 sizeof(struct REGS_CS4382)))
1653 continue;
1654 else
1655 break;
1656 }
1657
1658 if (i >= 2)
1659 goto End;
1660
1661 /* Note: Every I2C write must have some delay.
1662 * This is not a requirement but the delay works here... */
1663 I2CWrite(hw, CS4382_MC1, 0x80);
1664 I2CWrite(hw, CS4382_MC2, 0x10);
1665 if (1 == info->msr) {
1666 I2CWrite(hw, CS4382_XC1, 0x24);
1667 I2CWrite(hw, CS4382_XC2, 0x24);
1668 I2CWrite(hw, CS4382_XC3, 0x24);
1669 I2CWrite(hw, CS4382_XC4, 0x24);
1670 } else if (2 == info->msr) {
1671 I2CWrite(hw, CS4382_XC1, 0x25);
1672 I2CWrite(hw, CS4382_XC2, 0x25);
1673 I2CWrite(hw, CS4382_XC3, 0x25);
1674 I2CWrite(hw, CS4382_XC4, 0x25);
1675 } else {
1676 I2CWrite(hw, CS4382_XC1, 0x26);
1677 I2CWrite(hw, CS4382_XC2, 0x26);
1678 I2CWrite(hw, CS4382_XC3, 0x26);
1679 I2CWrite(hw, CS4382_XC4, 0x26);
1680 }
1681
1682 return 0;
1683End:
1684
1685 I2CUninit(hw);
1686 return -1;
1687}
1688
1689/* ADC operations */
1690#define MAKE_WM8775_ADDR(addr, data) (u32)(((addr<<1)&0xFE)|((data>>8)&0x1))
1691#define MAKE_WM8775_DATA(data) (u32)(data&0xFF)
1692
1693#define WM8775_IC 0x0B
1694#define WM8775_MMC 0x0C
1695#define WM8775_AADCL 0x0E
1696#define WM8775_AADCR 0x0F
1697#define WM8775_ADCMC 0x15
1698#define WM8775_RESET 0x17
1699
1700static int hw_is_adc_input_selected(struct hw *hw, enum ADCSRC type)
1701{
1702 u32 data = 0;
1703
1704 data = hw_read_20kx(hw, GPIO_DATA);
1705 switch (type) {
1706 case ADC_MICIN:
1707 data = (data & (0x1 << 14)) ? 1 : 0;
1708 break;
1709 case ADC_LINEIN:
1710 data = (data & (0x1 << 14)) ? 0 : 1;
1711 break;
1712 default:
1713 data = 0;
1714 }
1715 return data;
1716}
1717
1718static int hw_adc_input_select(struct hw *hw, enum ADCSRC type)
1719{
1720 u32 data = 0;
1721
1722 data = hw_read_20kx(hw, GPIO_DATA);
1723 switch (type) {
1724 case ADC_MICIN:
1725 data |= (0x1 << 14);
1726 hw_write_20kx(hw, GPIO_DATA, data);
1727 I2CWrite(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, 0x101),
1728 MAKE_WM8775_DATA(0x101)); /* Mic-in */
1729 I2CWrite(hw, MAKE_WM8775_ADDR(WM8775_AADCL, 0xE7),
1730 MAKE_WM8775_DATA(0xE7)); /* +12dB boost */
1731 I2CWrite(hw, MAKE_WM8775_ADDR(WM8775_AADCR, 0xE7),
1732 MAKE_WM8775_DATA(0xE7)); /* +12dB boost */
1733 break;
1734 case ADC_LINEIN:
1735 data &= ~(0x1 << 14);
1736 hw_write_20kx(hw, GPIO_DATA, data);
1737 I2CWrite(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, 0x102),
1738 MAKE_WM8775_DATA(0x102)); /* Line-in */
1739 I2CWrite(hw, MAKE_WM8775_ADDR(WM8775_AADCL, 0xCF),
1740 MAKE_WM8775_DATA(0xCF)); /* No boost */
1741 I2CWrite(hw, MAKE_WM8775_ADDR(WM8775_AADCR, 0xCF),
1742 MAKE_WM8775_DATA(0xCF)); /* No boost */
1743 break;
1744 default:
1745 break;
1746 }
1747
1748 return 0;
1749}
1750
1751static int hw_adc_init(struct hw *hw, const struct adc_conf *info)
1752{
1753 int err = 0;
1754 u32 dwMux = 2, dwData = 0, dwCtl = 0;
1755
1756 /* Set ADC reset bit as output */
1757 dwData = hw_read_20kx(hw, GPIO_CTRL);
1758 dwData |= (0x1 << 15);
1759 hw_write_20kx(hw, GPIO_CTRL, dwData);
1760
1761 /* Initialize I2C */
1762 err = I2CInit(hw, 0x1A, 1, 1);
1763 if (err < 0) {
1764 printk(KERN_ALERT "Failure to acquire I2C!!!\n");
1765 goto error;
1766 }
1767
1768 /* Make ADC in normal operation */
1769 dwData = hw_read_20kx(hw, GPIO_DATA);
1770 dwData &= ~(0x1 << 15);
1771 mdelay(10);
1772 dwData |= (0x1 << 15);
1773 hw_write_20kx(hw, GPIO_DATA, dwData);
1774 mdelay(50);
1775
1776 /* Set the master mode (256fs) */
1777 if (1 == info->msr) {
1778 I2CWrite(hw, MAKE_WM8775_ADDR(WM8775_MMC, 0x02),
1779 MAKE_WM8775_DATA(0x02));
1780 } else if (2 == info->msr) {
1781 I2CWrite(hw, MAKE_WM8775_ADDR(WM8775_MMC, 0x0A),
1782 MAKE_WM8775_DATA(0x0A));
1783 } else {
1784 printk(KERN_ALERT "Invalid master sampling "
1785 "rate (msr %d)!!!\n", info->msr);
1786 err = -EINVAL;
1787 goto error;
1788 }
1789
1790 /* Configure GPIO bit 14 change to line-in/mic-in */
1791 dwCtl = hw_read_20kx(hw, GPIO_CTRL);
1792 dwCtl |= 0x1<<14;
1793 hw_write_20kx(hw, GPIO_CTRL, dwCtl);
1794
1795 /* Check using Mic-in or Line-in */
1796 dwData = hw_read_20kx(hw, GPIO_DATA);
1797
1798 if (dwMux == 1) {
1799 /* Configures GPIO data to select Mic-in */
1800 dwData |= 0x1<<14;
1801 hw_write_20kx(hw, GPIO_DATA, dwData);
1802
1803 I2CWrite(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, 0x101),
1804 MAKE_WM8775_DATA(0x101)); /* Mic-in */
1805 I2CWrite(hw, MAKE_WM8775_ADDR(WM8775_AADCL, 0xE7),
1806 MAKE_WM8775_DATA(0xE7)); /* +12dB boost */
1807 I2CWrite(hw, MAKE_WM8775_ADDR(WM8775_AADCR, 0xE7),
1808 MAKE_WM8775_DATA(0xE7)); /* +12dB boost */
1809 } else if (dwMux == 2) {
1810 /* Configures GPIO data to select Line-in */
1811 dwData &= ~(0x1<<14);
1812 hw_write_20kx(hw, GPIO_DATA, dwData);
1813
1814 /* Setup ADC */
1815 I2CWrite(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, 0x102),
1816 MAKE_WM8775_DATA(0x102)); /* Line-in */
1817 I2CWrite(hw, MAKE_WM8775_ADDR(WM8775_AADCL, 0xCF),
1818 MAKE_WM8775_DATA(0xCF)); /* No boost */
1819 I2CWrite(hw, MAKE_WM8775_ADDR(WM8775_AADCR, 0xCF),
1820 MAKE_WM8775_DATA(0xCF)); /* No boost */
1821 } else {
1822 printk(KERN_ALERT "ERROR!!! Invalid input mux!!!\n");
1823 err = -EINVAL;
1824 goto error;
1825 }
1826
1827 return 0;
1828
1829error:
1830 I2CUninit(hw);
1831 return err;
1832}
1833
1834static int hw_have_digit_io_switch(struct hw *hw)
1835{
1836 return 0;
1837}
1838
1839static int hw_card_start(struct hw *hw)
1840{
1841 int err = 0;
1842 struct pci_dev *pci = hw->pci;
1843 unsigned int gctl;
1844 unsigned int dma_mask = 0;
1845
1846 err = pci_enable_device(pci);
1847 if (err < 0)
1848 return err;
1849
1850 /* Set DMA transfer mask */
1851 dma_mask = CT_XFI_DMA_MASK;
1852 if (pci_set_dma_mask(pci, dma_mask) < 0 ||
1853 pci_set_consistent_dma_mask(pci, dma_mask) < 0) {
1854 printk(KERN_ERR "architecture does not support PCI "
1855 "busmaster DMA with mask 0x%x\n", dma_mask);
1856 err = -ENXIO;
1857 goto error1;
1858 }
1859
1860 err = pci_request_regions(pci, "XFi");
1861 if (err < 0)
1862 goto error1;
1863
1864 hw->io_base = pci_resource_start(hw->pci, 2);
1865 hw->mem_base = (unsigned long)ioremap(hw->io_base,
1866 pci_resource_len(hw->pci, 2));
1867 if (NULL == (void *)hw->mem_base) {
1868 err = -ENOENT;
1869 goto error2;
1870 }
1871
1872 /* Switch to 20k2 mode from UAA mode. */
1873 gctl = hw_read_20kx(hw, GLOBAL_CNTL_GCTL);
1874 set_field(&gctl, GCTL_UAA, 0);
1875 hw_write_20kx(hw, GLOBAL_CNTL_GCTL, gctl);
1876
1877 /*if ((err = request_irq(pci->irq, ct_atc_interrupt, IRQF_SHARED,
1878 atc->chip_details->nm_card, hw))) {
1879 goto error3;
1880 }
1881 hw->irq = pci->irq;
1882 */
1883
1884 pci_set_master(pci);
1885
1886 return 0;
1887
1888/*error3:
1889 iounmap((void *)hw->mem_base);
1890 hw->mem_base = (unsigned long)NULL;*/
1891error2:
1892 pci_release_regions(pci);
1893 hw->io_base = 0;
1894error1:
1895 pci_disable_device(pci);
1896 return err;
1897}
1898
1899static int hw_card_stop(struct hw *hw)
1900{
1901 /* TODO: Disable interrupt and so on... */
1902 return 0;
1903}
1904
1905static int hw_card_shutdown(struct hw *hw)
1906{
1907 if (hw->irq >= 0)
1908 free_irq(hw->irq, hw);
1909
1910 hw->irq = -1;
1911
1912 if (NULL != ((void *)hw->mem_base))
1913 iounmap((void *)hw->mem_base);
1914
1915 hw->mem_base = (unsigned long)NULL;
1916
1917 if (hw->io_base)
1918 pci_release_regions(hw->pci);
1919
1920 hw->io_base = 0;
1921
1922 pci_disable_device(hw->pci);
1923
1924 return 0;
1925}
1926
1927static int hw_card_init(struct hw *hw, struct card_conf *info)
1928{
1929 int err;
1930 unsigned int gctl;
1931 u32 data = 0;
1932 struct dac_conf dac_info = {0};
1933 struct adc_conf adc_info = {0};
1934 struct daio_conf daio_info = {0};
1935 struct trn_conf trn_info = {0};
1936
1937 /* Get PCI io port/memory base address and
1938 * do 20kx core switch if needed. */
1939 if (!hw->io_base) {
1940 err = hw_card_start(hw);
1941 if (err)
1942 return err;
1943 }
1944
1945 /* PLL init */
1946 err = hw_pll_init(hw, info->rsr);
1947 if (err < 0)
1948 return err;
1949
1950 /* kick off auto-init */
1951 err = hw_auto_init(hw);
1952 if (err < 0)
1953 return err;
1954
1955 gctl = hw_read_20kx(hw, GLOBAL_CNTL_GCTL);
1956 set_field(&gctl, GCTL_DBP, 1);
1957 set_field(&gctl, GCTL_TBP, 1);
1958 set_field(&gctl, GCTL_FBP, 1);
1959 set_field(&gctl, GCTL_DPC, 0);
1960 hw_write_20kx(hw, GLOBAL_CNTL_GCTL, gctl);
1961
1962 /* Reset all global pending interrupts */
1963 hw_write_20kx(hw, INTERRUPT_GIE, 0);
1964 /* Reset all SRC pending interrupts */
1965 hw_write_20kx(hw, SRC_IP, 0);
1966
1967 /* TODO: detect the card ID and configure GPIO accordingly. */
1968 /* Configures GPIO (0xD802 0x98028) */
1969 /*hw_write_20kx(hw, GPIO_CTRL, 0x7F07);*/
1970 /* Configures GPIO (SB0880) */
1971 /*hw_write_20kx(hw, GPIO_CTRL, 0xFF07);*/
1972 hw_write_20kx(hw, GPIO_CTRL, 0xD802);
1973
1974 /* Enable audio ring */
1975 hw_write_20kx(hw, MIXER_AR_ENABLE, 0x01);
1976
1977 trn_info.vm_pgt_phys = info->vm_pgt_phys;
1978 err = hw_trn_init(hw, &trn_info);
1979 if (err < 0)
1980 return err;
1981
1982 daio_info.msr = info->msr;
1983 err = hw_daio_init(hw, &daio_info);
1984 if (err < 0)
1985 return err;
1986
1987 dac_info.msr = info->msr;
1988 err = hw_dac_init(hw, &dac_info);
1989 if (err < 0)
1990 return err;
1991
1992 adc_info.msr = info->msr;
1993 adc_info.input = ADC_LINEIN;
1994 adc_info.mic20db = 0;
1995 err = hw_adc_init(hw, &adc_info);
1996 if (err < 0)
1997 return err;
1998
1999 data = hw_read_20kx(hw, SRC_MCTL);
2000 data |= 0x1; /* Enables input from the audio ring */
2001 hw_write_20kx(hw, SRC_MCTL, data);
2002
2003 return 0;
2004}
2005
2006static u32 hw_read_20kx(struct hw *hw, u32 reg)
2007{
2008 return readl((void *)(hw->mem_base + reg));
2009}
2010
2011static void hw_write_20kx(struct hw *hw, u32 reg, u32 data)
2012{
2013 writel(data, (void *)(hw->mem_base + reg));
2014}
2015
2016int create_20k2_hw_obj(struct hw **rhw)
2017{
2018 struct hw *hw;
2019
2020 *rhw = NULL;
2021 hw = kzalloc(sizeof(*hw), GFP_KERNEL);
2022 if (NULL == hw)
2023 return -ENOMEM;
2024
2025 hw->io_base = 0;
2026 hw->mem_base = (unsigned long)NULL;
2027 hw->irq = -1;
2028
2029 hw->card_init = hw_card_init;
2030 hw->card_stop = hw_card_stop;
2031 hw->pll_init = hw_pll_init;
2032 hw->is_adc_source_selected = hw_is_adc_input_selected;
2033 hw->select_adc_source = hw_adc_input_select;
2034 hw->have_digit_io_switch = hw_have_digit_io_switch;
2035
2036 hw->src_rsc_get_ctrl_blk = src_get_rsc_ctrl_blk;
2037 hw->src_rsc_put_ctrl_blk = src_put_rsc_ctrl_blk;
2038 hw->src_mgr_get_ctrl_blk = src_mgr_get_ctrl_blk;
2039 hw->src_mgr_put_ctrl_blk = src_mgr_put_ctrl_blk;
2040 hw->src_set_state = src_set_state;
2041 hw->src_set_bm = src_set_bm;
2042 hw->src_set_rsr = src_set_rsr;
2043 hw->src_set_sf = src_set_sf;
2044 hw->src_set_wr = src_set_wr;
2045 hw->src_set_pm = src_set_pm;
2046 hw->src_set_rom = src_set_rom;
2047 hw->src_set_vo = src_set_vo;
2048 hw->src_set_st = src_set_st;
2049 hw->src_set_ie = src_set_ie;
2050 hw->src_set_ilsz = src_set_ilsz;
2051 hw->src_set_bp = src_set_bp;
2052 hw->src_set_cisz = src_set_cisz;
2053 hw->src_set_ca = src_set_ca;
2054 hw->src_set_sa = src_set_sa;
2055 hw->src_set_la = src_set_la;
2056 hw->src_set_pitch = src_set_pitch;
2057 hw->src_set_dirty = src_set_dirty;
2058 hw->src_set_clear_zbufs = src_set_clear_zbufs;
2059 hw->src_set_dirty_all = src_set_dirty_all;
2060 hw->src_commit_write = src_commit_write;
2061 hw->src_get_ca = src_get_ca;
2062 hw->src_get_dirty = src_get_dirty;
2063 hw->src_dirty_conj_mask = src_dirty_conj_mask;
2064 hw->src_mgr_enbs_src = src_mgr_enbs_src;
2065 hw->src_mgr_enb_src = src_mgr_enb_src;
2066 hw->src_mgr_dsb_src = src_mgr_dsb_src;
2067 hw->src_mgr_commit_write = src_mgr_commit_write;
2068
2069 hw->srcimp_mgr_get_ctrl_blk = srcimp_mgr_get_ctrl_blk;
2070 hw->srcimp_mgr_put_ctrl_blk = srcimp_mgr_put_ctrl_blk;
2071 hw->srcimp_mgr_set_imaparc = srcimp_mgr_set_imaparc;
2072 hw->srcimp_mgr_set_imapuser = srcimp_mgr_set_imapuser;
2073 hw->srcimp_mgr_set_imapnxt = srcimp_mgr_set_imapnxt;
2074 hw->srcimp_mgr_set_imapaddr = srcimp_mgr_set_imapaddr;
2075 hw->srcimp_mgr_commit_write = srcimp_mgr_commit_write;
2076
2077 hw->amixer_rsc_get_ctrl_blk = amixer_rsc_get_ctrl_blk;
2078 hw->amixer_rsc_put_ctrl_blk = amixer_rsc_put_ctrl_blk;
2079 hw->amixer_mgr_get_ctrl_blk = amixer_mgr_get_ctrl_blk;
2080 hw->amixer_mgr_put_ctrl_blk = amixer_mgr_put_ctrl_blk;
2081 hw->amixer_set_mode = amixer_set_mode;
2082 hw->amixer_set_iv = amixer_set_iv;
2083 hw->amixer_set_x = amixer_set_x;
2084 hw->amixer_set_y = amixer_set_y;
2085 hw->amixer_set_sadr = amixer_set_sadr;
2086 hw->amixer_set_se = amixer_set_se;
2087 hw->amixer_set_dirty = amixer_set_dirty;
2088 hw->amixer_set_dirty_all = amixer_set_dirty_all;
2089 hw->amixer_commit_write = amixer_commit_write;
2090 hw->amixer_get_y = amixer_get_y;
2091 hw->amixer_get_dirty = amixer_get_dirty;
2092
2093 hw->dai_get_ctrl_blk = dai_get_ctrl_blk;
2094 hw->dai_put_ctrl_blk = dai_put_ctrl_blk;
2095 hw->dai_srt_set_srco = dai_srt_set_srco;
2096 hw->dai_srt_set_srcm = dai_srt_set_srcm;
2097 hw->dai_srt_set_rsr = dai_srt_set_rsr;
2098 hw->dai_srt_set_drat = dai_srt_set_drat;
2099 hw->dai_srt_set_ec = dai_srt_set_ec;
2100 hw->dai_srt_set_et = dai_srt_set_et;
2101 hw->dai_commit_write = dai_commit_write;
2102
2103 hw->dao_get_ctrl_blk = dao_get_ctrl_blk;
2104 hw->dao_put_ctrl_blk = dao_put_ctrl_blk;
2105 hw->dao_set_spos = dao_set_spos;
2106 hw->dao_commit_write = dao_commit_write;
2107 hw->dao_get_spos = dao_get_spos;
2108
2109 hw->daio_mgr_get_ctrl_blk = daio_mgr_get_ctrl_blk;
2110 hw->daio_mgr_put_ctrl_blk = daio_mgr_put_ctrl_blk;
2111 hw->daio_mgr_enb_dai = daio_mgr_enb_dai;
2112 hw->daio_mgr_dsb_dai = daio_mgr_dsb_dai;
2113 hw->daio_mgr_enb_dao = daio_mgr_enb_dao;
2114 hw->daio_mgr_dsb_dao = daio_mgr_dsb_dao;
2115 hw->daio_mgr_dao_init = daio_mgr_dao_init;
2116 hw->daio_mgr_set_imaparc = daio_mgr_set_imaparc;
2117 hw->daio_mgr_set_imapnxt = daio_mgr_set_imapnxt;
2118 hw->daio_mgr_set_imapaddr = daio_mgr_set_imapaddr;
2119 hw->daio_mgr_commit_write = daio_mgr_commit_write;
2120
2121 *rhw = hw;
2122
2123 return 0;
2124}
2125
2126int destroy_20k2_hw_obj(struct hw *hw)
2127{
2128 if (hw->io_base)
2129 hw_card_shutdown(hw);
2130
2131 kfree(hw);
2132 return 0;
2133}
diff --git a/sound/pci/ctxfi/cthw20k2.h b/sound/pci/ctxfi/cthw20k2.h
new file mode 100644
index 000000000000..d2b7daab6815
--- /dev/null
+++ b/sound/pci/ctxfi/cthw20k2.h
@@ -0,0 +1,26 @@
1/**
2 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
3 *
4 * This source file is released under GPL v2 license (no other versions).
5 * See the COPYING file included in the main directory of this source
6 * distribution for the license terms and conditions.
7 *
8 * @File cthw20k2.h
9 *
10 * @Brief
11 * This file contains the definition of hardware access methord.
12 *
13 * @Author Liu Chun
14 * @Date May 13 2008
15 *
16 */
17
18#ifndef CTHW20K2_H
19#define CTHW20K2_H
20
21#include "cthardware.h"
22
23int create_20k2_hw_obj(struct hw **rhw);
24int destroy_20k2_hw_obj(struct hw *hw);
25
26#endif /* CTHW20K2_H */
diff --git a/sound/pci/ctxfi/ctimap.c b/sound/pci/ctxfi/ctimap.c
new file mode 100644
index 000000000000..d34eacd902ce
--- /dev/null
+++ b/sound/pci/ctxfi/ctimap.c
@@ -0,0 +1,112 @@
1/**
2 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
3 *
4 * This source file is released under GPL v2 license (no other versions).
5 * See the COPYING file included in the main directory of this source
6 * distribution for the license terms and conditions.
7 *
8 * @File ctimap.c
9 *
10 * @Brief
11 * This file contains the implementation of generic input mapper operations
12 * for input mapper management.
13 *
14 * @Author Liu Chun
15 * @Date May 23 2008
16 *
17 */
18
19#include "ctimap.h"
20#include <linux/slab.h>
21
22int input_mapper_add(struct list_head *mappers, struct imapper *entry,
23 int (*map_op)(void *, struct imapper *), void *data)
24{
25 struct list_head *pos, *pre, *head;
26 struct imapper *pre_ent, *pos_ent;
27
28 head = mappers;
29
30 if (list_empty(head)) {
31 entry->next = entry->addr;
32 map_op(data, entry);
33 list_add(&entry->list, head);
34 return 0;
35 }
36
37 list_for_each(pos, head) {
38 pos_ent = list_entry(pos, struct imapper, list);
39 if (pos_ent->slot > entry->slot) {
40 /* found a position in list */
41 break;
42 }
43 }
44
45 if (pos != head) {
46 pre = pos->prev;
47 if (pre == head)
48 pre = head->prev;
49
50 __list_add(&entry->list, pos->prev, pos);
51 } else {
52 pre = head->prev;
53 pos = head->next;
54 list_add_tail(&entry->list, head);
55 }
56
57 pre_ent = list_entry(pre, struct imapper, list);
58 pos_ent = list_entry(pos, struct imapper, list);
59
60 entry->next = pos_ent->addr;
61 map_op(data, entry);
62 pre_ent->next = entry->addr;
63 map_op(data, pre_ent);
64
65 return 0;
66}
67
68int input_mapper_delete(struct list_head *mappers, struct imapper *entry,
69 int (*map_op)(void *, struct imapper *), void *data)
70{
71 struct list_head *next, *pre, *head;
72 struct imapper *pre_ent, *next_ent;
73
74 head = mappers;
75
76 if (list_empty(head))
77 return 0;
78
79 pre = (entry->list.prev == head) ? head->prev : entry->list.prev;
80 next = (entry->list.next == head) ? head->next : entry->list.next;
81
82 if (pre == &entry->list) {
83 /* entry is the only one node in mappers list */
84 entry->next = entry->addr = entry->user = entry->slot = 0;
85 map_op(data, entry);
86 list_del(&entry->list);
87 return 0;
88 }
89
90 pre_ent = list_entry(pre, struct imapper, list);
91 next_ent = list_entry(next, struct imapper, list);
92
93 pre_ent->next = next_ent->addr;
94 map_op(data, pre_ent);
95 list_del(&entry->list);
96
97 return 0;
98}
99
100void free_input_mapper_list(struct list_head *head)
101{
102 struct imapper *entry = NULL;
103 struct list_head *pos = NULL;
104
105 while (!list_empty(head)) {
106 pos = head->next;
107 list_del(pos);
108 entry = list_entry(pos, struct imapper, list);
109 kfree(entry);
110 }
111}
112
diff --git a/sound/pci/ctxfi/ctimap.h b/sound/pci/ctxfi/ctimap.h
new file mode 100644
index 000000000000..53ccf9be8b68
--- /dev/null
+++ b/sound/pci/ctxfi/ctimap.h
@@ -0,0 +1,40 @@
1/**
2 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
3 *
4 * This source file is released under GPL v2 license (no other versions).
5 * See the COPYING file included in the main directory of this source
6 * distribution for the license terms and conditions.
7 *
8 * @File ctimap.h
9 *
10 * @Brief
11 * This file contains the definition of generic input mapper operations
12 * for input mapper management.
13 *
14 * @Author Liu Chun
15 * @Date May 23 2008
16 *
17 */
18
19#ifndef CTIMAP_H
20#define CTIMAP_H
21
22#include <linux/list.h>
23
24struct imapper {
25 unsigned short slot; /* the id of the slot containing input data */
26 unsigned short user; /* the id of the user resource consuming data */
27 unsigned short addr; /* the input mapper ram id */
28 unsigned short next; /* the next input mapper ram id */
29 struct list_head list;
30};
31
32int input_mapper_add(struct list_head *mappers, struct imapper *entry,
33 int (*map_op)(void *, struct imapper *), void *data);
34
35int input_mapper_delete(struct list_head *mappers, struct imapper *entry,
36 int (*map_op)(void *, struct imapper *), void *data);
37
38void free_input_mapper_list(struct list_head *mappers);
39
40#endif /* CTIMAP_H */
diff --git a/sound/pci/ctxfi/ctmixer.c b/sound/pci/ctxfi/ctmixer.c
new file mode 100644
index 000000000000..c80d692952f9
--- /dev/null
+++ b/sound/pci/ctxfi/ctmixer.c
@@ -0,0 +1,1108 @@
1/**
2 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
3 *
4 * This source file is released under GPL v2 license (no other versions).
5 * See the COPYING file included in the main directory of this source
6 * distribution for the license terms and conditions.
7 *
8 * @File ctmixer.c
9 *
10 * @Brief
11 * This file contains the implementation of alsa mixer device functions.
12 *
13 * @Author Liu Chun
14 * @Date May 28 2008
15 *
16 */
17
18
19#include "ctmixer.h"
20#include "ctamixer.h"
21#include <sound/core.h>
22#include <sound/control.h>
23#include <sound/asoundef.h>
24#include <sound/pcm.h>
25#include <linux/slab.h>
26
27enum CT_SUM_CTL {
28 SUM_IN_F,
29 SUM_IN_R,
30 SUM_IN_C,
31 SUM_IN_S,
32 SUM_IN_F_C,
33
34 NUM_CT_SUMS
35};
36
37enum CT_AMIXER_CTL {
38 /* volume control mixers */
39 AMIXER_MASTER_F,
40 AMIXER_MASTER_R,
41 AMIXER_MASTER_C,
42 AMIXER_MASTER_S,
43 AMIXER_PCM_F,
44 AMIXER_PCM_R,
45 AMIXER_PCM_C,
46 AMIXER_PCM_S,
47 AMIXER_SPDIFI,
48 AMIXER_LINEIN,
49 AMIXER_MIC,
50 AMIXER_SPDIFO,
51 AMIXER_WAVE_F,
52 AMIXER_WAVE_R,
53 AMIXER_WAVE_C,
54 AMIXER_WAVE_S,
55 AMIXER_MASTER_F_C,
56 AMIXER_PCM_F_C,
57 AMIXER_SPDIFI_C,
58 AMIXER_LINEIN_C,
59 AMIXER_MIC_C,
60
61 /* this should always be the last one */
62 NUM_CT_AMIXERS
63};
64
65enum CTALSA_MIXER_CTL {
66 /* volume control mixers */
67 MIXER_MASTER_P,
68 MIXER_PCM_P,
69 MIXER_LINEIN_P,
70 MIXER_MIC_P,
71 MIXER_SPDIFI_P,
72 MIXER_SPDIFO_P,
73 MIXER_WAVEF_P,
74 MIXER_WAVER_P,
75 MIXER_WAVEC_P,
76 MIXER_WAVES_P,
77 MIXER_MASTER_C,
78 MIXER_PCM_C,
79 MIXER_LINEIN_C,
80 MIXER_MIC_C,
81 MIXER_SPDIFI_C,
82
83 /* switch control mixers */
84 MIXER_PCM_C_S,
85 MIXER_LINEIN_C_S,
86 MIXER_MIC_C_S,
87 MIXER_SPDIFI_C_S,
88 MIXER_LINEIN_P_S,
89 MIXER_SPDIFO_P_S,
90 MIXER_SPDIFI_P_S,
91 MIXER_WAVEF_P_S,
92 MIXER_WAVER_P_S,
93 MIXER_WAVEC_P_S,
94 MIXER_WAVES_P_S,
95 MIXER_DIGITAL_IO_S,
96 MIXER_IEC958_MASK,
97 MIXER_IEC958_DEFAULT,
98 MIXER_IEC958_STREAM,
99
100 /* this should always be the last one */
101 NUM_CTALSA_MIXERS
102};
103
104#define VOL_MIXER_START MIXER_MASTER_P
105#define VOL_MIXER_END MIXER_SPDIFI_C
106#define VOL_MIXER_NUM (VOL_MIXER_END - VOL_MIXER_START + 1)
107#define SWH_MIXER_START MIXER_PCM_C_S
108#define SWH_MIXER_END MIXER_DIGITAL_IO_S
109#define SWH_CAPTURE_START MIXER_PCM_C_S
110#define SWH_CAPTURE_END MIXER_SPDIFI_C_S
111
112#define CHN_NUM 2
113
114struct ct_kcontrol_init {
115 unsigned char ctl;
116 char *name;
117};
118
119static struct ct_kcontrol_init
120ct_kcontrol_init_table[NUM_CTALSA_MIXERS] = {
121 [MIXER_MASTER_P] = {
122 .ctl = 1,
123 .name = "Master Playback Volume",
124 },
125 [MIXER_MASTER_C] = {
126 .ctl = 1,
127 .name = "Master Capture Volume",
128 },
129 [MIXER_PCM_P] = {
130 .ctl = 1,
131 .name = "PCM Playback Volume",
132 },
133 [MIXER_PCM_C] = {
134 .ctl = 1,
135 .name = "PCM Capture Volume",
136 },
137 [MIXER_LINEIN_P] = {
138 .ctl = 1,
139 .name = "Line-in Playback Volume",
140 },
141 [MIXER_LINEIN_C] = {
142 .ctl = 1,
143 .name = "Line-in Capture Volume",
144 },
145 [MIXER_MIC_P] = {
146 .ctl = 1,
147 .name = "Mic Playback Volume",
148 },
149 [MIXER_MIC_C] = {
150 .ctl = 1,
151 .name = "Mic Capture Volume",
152 },
153 [MIXER_SPDIFI_P] = {
154 .ctl = 1,
155 .name = "S/PDIF-in Playback Volume",
156 },
157 [MIXER_SPDIFI_C] = {
158 .ctl = 1,
159 .name = "S/PDIF-in Capture Volume",
160 },
161 [MIXER_SPDIFO_P] = {
162 .ctl = 1,
163 .name = "S/PDIF-out Playback Volume",
164 },
165 [MIXER_WAVEF_P] = {
166 .ctl = 1,
167 .name = "Front Playback Volume",
168 },
169 [MIXER_WAVES_P] = {
170 .ctl = 1,
171 .name = "Surround Playback Volume",
172 },
173 [MIXER_WAVEC_P] = {
174 .ctl = 1,
175 .name = "Center/LFE Playback Volume",
176 },
177 [MIXER_WAVER_P] = {
178 .ctl = 1,
179 .name = "Rear Playback Volume",
180 },
181
182 [MIXER_PCM_C_S] = {
183 .ctl = 1,
184 .name = "PCM Capture Switch",
185 },
186 [MIXER_LINEIN_C_S] = {
187 .ctl = 1,
188 .name = "Line-in Capture Switch",
189 },
190 [MIXER_MIC_C_S] = {
191 .ctl = 1,
192 .name = "Mic Capture Switch",
193 },
194 [MIXER_SPDIFI_C_S] = {
195 .ctl = 1,
196 .name = "S/PDIF-in Capture Switch",
197 },
198 [MIXER_LINEIN_P_S] = {
199 .ctl = 1,
200 .name = "Line-in Playback Switch",
201 },
202 [MIXER_SPDIFO_P_S] = {
203 .ctl = 1,
204 .name = "S/PDIF-out Playback Switch",
205 },
206 [MIXER_SPDIFI_P_S] = {
207 .ctl = 1,
208 .name = "S/PDIF-in Playback Switch",
209 },
210 [MIXER_WAVEF_P_S] = {
211 .ctl = 1,
212 .name = "Front Playback Switch",
213 },
214 [MIXER_WAVES_P_S] = {
215 .ctl = 1,
216 .name = "Surround Playback Switch",
217 },
218 [MIXER_WAVEC_P_S] = {
219 .ctl = 1,
220 .name = "Center/LFE Playback Switch",
221 },
222 [MIXER_WAVER_P_S] = {
223 .ctl = 1,
224 .name = "Rear Playback Switch",
225 },
226 [MIXER_DIGITAL_IO_S] = {
227 .ctl = 0,
228 .name = "Digit-IO Playback Switch",
229 },
230};
231
232static void
233ct_mixer_recording_select(struct ct_mixer *mixer, enum CT_AMIXER_CTL type);
234
235static void
236ct_mixer_recording_unselect(struct ct_mixer *mixer, enum CT_AMIXER_CTL type);
237
238static struct snd_kcontrol *kctls[2] = {NULL};
239
240static enum CT_AMIXER_CTL get_amixer_index(enum CTALSA_MIXER_CTL alsa_index)
241{
242 switch (alsa_index) {
243 case MIXER_MASTER_P: return AMIXER_MASTER_F;
244 case MIXER_MASTER_C: return AMIXER_MASTER_F_C;
245 case MIXER_PCM_P: return AMIXER_PCM_F;
246 case MIXER_PCM_C:
247 case MIXER_PCM_C_S: return AMIXER_PCM_F_C;
248 case MIXER_LINEIN_P: return AMIXER_LINEIN;
249 case MIXER_LINEIN_C:
250 case MIXER_LINEIN_C_S: return AMIXER_LINEIN_C;
251 case MIXER_MIC_P: return AMIXER_MIC;
252 case MIXER_MIC_C:
253 case MIXER_MIC_C_S: return AMIXER_MIC_C;
254 case MIXER_SPDIFI_P: return AMIXER_SPDIFI;
255 case MIXER_SPDIFI_C:
256 case MIXER_SPDIFI_C_S: return AMIXER_SPDIFI_C;
257 case MIXER_SPDIFO_P: return AMIXER_SPDIFO;
258 case MIXER_WAVEF_P: return AMIXER_WAVE_F;
259 case MIXER_WAVES_P: return AMIXER_WAVE_S;
260 case MIXER_WAVEC_P: return AMIXER_WAVE_C;
261 case MIXER_WAVER_P: return AMIXER_WAVE_R;
262 default: return NUM_CT_AMIXERS;
263 }
264}
265
266static enum CT_AMIXER_CTL get_recording_amixer(enum CT_AMIXER_CTL index)
267{
268 switch (index) {
269 case AMIXER_MASTER_F: return AMIXER_MASTER_F_C;
270 case AMIXER_PCM_F: return AMIXER_PCM_F_C;
271 case AMIXER_SPDIFI: return AMIXER_SPDIFI_C;
272 case AMIXER_LINEIN: return AMIXER_LINEIN_C;
273 case AMIXER_MIC: return AMIXER_MIC_C;
274 default: return NUM_CT_AMIXERS;
275 }
276}
277
278static unsigned char
279get_switch_state(struct ct_mixer *mixer, enum CTALSA_MIXER_CTL type)
280{
281 return (mixer->switch_state & (0x1 << (type - SWH_MIXER_START)))
282 ? 1 : 0;
283}
284
285static void
286set_switch_state(struct ct_mixer *mixer,
287 enum CTALSA_MIXER_CTL type, unsigned char state)
288{
289 if (state)
290 mixer->switch_state |= (0x1 << (type - SWH_MIXER_START));
291 else
292 mixer->switch_state &= ~(0x1 << (type - SWH_MIXER_START));
293}
294
295/* Map integer value ranging from 0 to 65535 to 14-bit float value ranging
296 * from 2^-6 to (1+1023/1024) */
297static unsigned int uint16_to_float14(unsigned int x)
298{
299 unsigned int i = 0;
300
301 if (x < 17)
302 return 0;
303
304 x *= 2031;
305 x /= 65535;
306 x += 16;
307
308 /* i <= 6 */
309 for (i = 0; !(x & 0x400); i++)
310 x <<= 1;
311
312 x = (((7 - i) & 0x7) << 10) | (x & 0x3ff);
313
314 return x;
315}
316
317static unsigned int float14_to_uint16(unsigned int x)
318{
319 unsigned int e = 0;
320
321 if (!x)
322 return x;
323
324 e = (x >> 10) & 0x7;
325 x &= 0x3ff;
326 x += 1024;
327 x >>= (7 - e);
328 x -= 16;
329 x *= 65535;
330 x /= 2031;
331
332 return x;
333}
334
335static int ct_alsa_mix_volume_info(struct snd_kcontrol *kcontrol,
336 struct snd_ctl_elem_info *uinfo)
337{
338 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
339 uinfo->count = 2;
340 uinfo->value.integer.min = 0;
341 uinfo->value.integer.max = 43690;
342 uinfo->value.integer.step = 128;
343
344 return 0;
345}
346
347static int ct_alsa_mix_volume_get(struct snd_kcontrol *kcontrol,
348 struct snd_ctl_elem_value *ucontrol)
349{
350 struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
351 enum CT_AMIXER_CTL type = get_amixer_index(kcontrol->private_value);
352 struct amixer *amixer = NULL;
353 int i = 0;
354
355 for (i = 0; i < 2; i++) {
356 amixer = ((struct ct_mixer *)atc->mixer)->
357 amixers[type*CHN_NUM+i];
358 /* Convert 14-bit float-point scale to 16-bit integer volume */
359 ucontrol->value.integer.value[i] =
360 (float14_to_uint16(amixer->ops->get_scale(amixer)) & 0xffff);
361 }
362
363 return 0;
364}
365
366static int ct_alsa_mix_volume_put(struct snd_kcontrol *kcontrol,
367 struct snd_ctl_elem_value *ucontrol)
368{
369 struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
370 struct ct_mixer *mixer = atc->mixer;
371 enum CT_AMIXER_CTL type = get_amixer_index(kcontrol->private_value);
372 struct amixer *amixer = NULL;
373 int i = 0, j = 0, change = 0, val = 0;
374
375 for (i = 0; i < 2; i++) {
376 /* Convert 16-bit integer volume to 14-bit float-point scale */
377 val = (ucontrol->value.integer.value[i] & 0xffff);
378 amixer = mixer->amixers[type*CHN_NUM+i];
379 if ((float14_to_uint16(amixer->ops->get_scale(amixer)) & 0xff80)
380 != (val & 0xff80)) {
381 val = uint16_to_float14(val);
382 amixer->ops->set_scale(amixer, val);
383 amixer->ops->commit_write(amixer);
384 change = 1;
385 /* Synchronize Master/PCM playback AMIXERs. */
386 if (AMIXER_MASTER_F == type || AMIXER_PCM_F == type) {
387 for (j = 1; j < 4; j++) {
388 amixer = mixer->
389 amixers[(type+j)*CHN_NUM+i];
390 amixer->ops->set_scale(amixer, val);
391 amixer->ops->commit_write(amixer);
392 }
393 }
394 }
395 }
396
397 return change;
398}
399
400static struct snd_kcontrol_new vol_ctl = {
401 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
402 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
403 .info = ct_alsa_mix_volume_info,
404 .get = ct_alsa_mix_volume_get,
405 .put = ct_alsa_mix_volume_put
406};
407
408static void
409do_line_mic_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type)
410{
411
412 if (MIXER_LINEIN_C_S == type) {
413 atc->select_line_in(atc);
414 set_switch_state(atc->mixer, MIXER_MIC_C_S, 0);
415 snd_ctl_notify(atc->card, SNDRV_CTL_EVENT_MASK_VALUE,
416 &kctls[1]->id);
417 } else if (MIXER_MIC_C_S == type) {
418 atc->select_mic_in(atc);
419 set_switch_state(atc->mixer, MIXER_LINEIN_C_S, 0);
420 snd_ctl_notify(atc->card, SNDRV_CTL_EVENT_MASK_VALUE,
421 &kctls[0]->id);
422 }
423}
424
425static void
426do_digit_io_switch(struct ct_atc *atc, int state)
427{
428 struct ct_mixer *mixer = atc->mixer;
429
430 if (state) {
431 atc->select_digit_io(atc);
432 atc->spdif_out_unmute(atc,
433 get_switch_state(mixer, MIXER_SPDIFO_P_S));
434 atc->spdif_in_unmute(atc, 1);
435 atc->line_in_unmute(atc, 0);
436 return;
437 }
438
439 if (get_switch_state(mixer, MIXER_LINEIN_C_S))
440 atc->select_line_in(atc);
441 else if (get_switch_state(mixer, MIXER_MIC_C_S))
442 atc->select_mic_in(atc);
443
444 atc->spdif_out_unmute(atc, 0);
445 atc->spdif_in_unmute(atc, 0);
446 atc->line_in_unmute(atc, 1);
447 return;
448}
449
450static int ct_alsa_mix_switch_info(struct snd_kcontrol *kcontrol,
451 struct snd_ctl_elem_info *uinfo)
452{
453 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
454 uinfo->count = 1;
455 uinfo->value.integer.min = 0;
456 uinfo->value.integer.max = 1;
457 uinfo->value.integer.step = 1;
458
459 return 0;
460}
461
462static int ct_alsa_mix_switch_get(struct snd_kcontrol *kcontrol,
463 struct snd_ctl_elem_value *ucontrol)
464{
465 struct ct_mixer *mixer =
466 ((struct ct_atc *)snd_kcontrol_chip(kcontrol))->mixer;
467 enum CTALSA_MIXER_CTL type = kcontrol->private_value;
468
469 ucontrol->value.integer.value[0] = get_switch_state(mixer, type);
470 return 0;
471}
472
473static int ct_alsa_mix_switch_put(struct snd_kcontrol *kcontrol,
474 struct snd_ctl_elem_value *ucontrol)
475{
476 struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
477 struct ct_mixer *mixer = atc->mixer;
478 enum CTALSA_MIXER_CTL type = kcontrol->private_value;
479 int state = 0;
480
481 state = ucontrol->value.integer.value[0];
482 if (get_switch_state(mixer, type) == state)
483 return 0;
484
485 set_switch_state(mixer, type, state);
486 /* Do changes in mixer. */
487 if ((SWH_CAPTURE_START <= type) && (SWH_CAPTURE_END >= type)) {
488 if (state) {
489 ct_mixer_recording_select(mixer,
490 get_amixer_index(type));
491 } else {
492 ct_mixer_recording_unselect(mixer,
493 get_amixer_index(type));
494 }
495 }
496 /* Do changes out of mixer. */
497 if (state && (MIXER_LINEIN_C_S == type || MIXER_MIC_C_S == type))
498 do_line_mic_switch(atc, type);
499 else if (MIXER_WAVEF_P_S == type)
500 atc->line_front_unmute(atc, state);
501 else if (MIXER_WAVES_P_S == type)
502 atc->line_surround_unmute(atc, state);
503 else if (MIXER_WAVEC_P_S == type)
504 atc->line_clfe_unmute(atc, state);
505 else if (MIXER_WAVER_P_S == type)
506 atc->line_rear_unmute(atc, state);
507 else if (MIXER_LINEIN_P_S == type)
508 atc->line_in_unmute(atc, state);
509 else if (MIXER_SPDIFO_P_S == type)
510 atc->spdif_out_unmute(atc, state);
511 else if (MIXER_SPDIFI_P_S == type)
512 atc->spdif_in_unmute(atc, state);
513 else if (MIXER_DIGITAL_IO_S == type)
514 do_digit_io_switch(atc, state);
515
516 return 1;
517}
518
519static struct snd_kcontrol_new swh_ctl = {
520 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
521 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
522 .info = ct_alsa_mix_switch_info,
523 .get = ct_alsa_mix_switch_get,
524 .put = ct_alsa_mix_switch_put
525};
526
527static int ct_spdif_info(struct snd_kcontrol *kcontrol,
528 struct snd_ctl_elem_info *uinfo)
529{
530 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
531 uinfo->count = 1;
532 return 0;
533}
534
535static int ct_spdif_get_mask(struct snd_kcontrol *kcontrol,
536 struct snd_ctl_elem_value *ucontrol)
537{
538 ucontrol->value.iec958.status[0] = 0xff;
539 ucontrol->value.iec958.status[1] = 0xff;
540 ucontrol->value.iec958.status[2] = 0xff;
541 ucontrol->value.iec958.status[3] = 0xff;
542 return 0;
543}
544
545static int ct_spdif_default_get(struct snd_kcontrol *kcontrol,
546 struct snd_ctl_elem_value *ucontrol)
547{
548 unsigned int status = SNDRV_PCM_DEFAULT_CON_SPDIF;
549
550 ucontrol->value.iec958.status[0] = (status >> 0) & 0xff;
551 ucontrol->value.iec958.status[1] = (status >> 8) & 0xff;
552 ucontrol->value.iec958.status[2] = (status >> 16) & 0xff;
553 ucontrol->value.iec958.status[3] = (status >> 24) & 0xff;
554
555 return 0;
556}
557
558static int ct_spdif_get(struct snd_kcontrol *kcontrol,
559 struct snd_ctl_elem_value *ucontrol)
560{
561 struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
562 unsigned int status = 0;
563
564 atc->spdif_out_get_status(atc, &status);
565 ucontrol->value.iec958.status[0] = (status >> 0) & 0xff;
566 ucontrol->value.iec958.status[1] = (status >> 8) & 0xff;
567 ucontrol->value.iec958.status[2] = (status >> 16) & 0xff;
568 ucontrol->value.iec958.status[3] = (status >> 24) & 0xff;
569
570 return 0;
571}
572
573static int ct_spdif_put(struct snd_kcontrol *kcontrol,
574 struct snd_ctl_elem_value *ucontrol)
575{
576 struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
577 int change = 1;
578 unsigned int status = 0, old_status = 0;
579
580 status = (ucontrol->value.iec958.status[0] << 0) |
581 (ucontrol->value.iec958.status[1] << 8) |
582 (ucontrol->value.iec958.status[2] << 16) |
583 (ucontrol->value.iec958.status[3] << 24);
584
585 atc->spdif_out_get_status(atc, &old_status);
586 change = (old_status != status);
587 if (change)
588 atc->spdif_out_set_status(atc, status);
589
590 return change;
591}
592
593static struct snd_kcontrol_new iec958_mask_ctl = {
594 .access = SNDRV_CTL_ELEM_ACCESS_READ,
595 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
596 .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, MASK),
597 .count = 1,
598 .info = ct_spdif_info,
599 .get = ct_spdif_get_mask,
600 .private_value = MIXER_IEC958_MASK
601};
602
603static struct snd_kcontrol_new iec958_default_ctl = {
604 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
605 .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
606 .count = 1,
607 .info = ct_spdif_info,
608 .get = ct_spdif_default_get,
609 .put = ct_spdif_put,
610 .private_value = MIXER_IEC958_DEFAULT
611};
612
613static struct snd_kcontrol_new iec958_ctl = {
614 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
615 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
616 .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PCM_STREAM),
617 .count = 1,
618 .info = ct_spdif_info,
619 .get = ct_spdif_get,
620 .put = ct_spdif_put,
621 .private_value = MIXER_IEC958_STREAM
622};
623
624#define NUM_IEC958_CTL 3
625
626static int
627ct_mixer_kcontrol_new(struct ct_mixer *mixer, struct snd_kcontrol_new *new)
628{
629 struct snd_kcontrol *kctl = NULL;
630 int err = 0;
631
632 kctl = snd_ctl_new1(new, mixer->atc);
633 if (NULL == kctl)
634 return -ENOMEM;
635
636 if (SNDRV_CTL_ELEM_IFACE_PCM == kctl->id.iface)
637 kctl->id.device = IEC958;
638
639 err = snd_ctl_add(mixer->atc->card, kctl);
640 if (err)
641 return err;
642
643 switch (new->private_value) {
644 case MIXER_LINEIN_C_S:
645 kctls[0] = kctl; break;
646 case MIXER_MIC_C_S:
647 kctls[1] = kctl; break;
648 default:
649 break;
650 }
651
652 return 0;
653}
654
655static int ct_mixer_kcontrols_create(struct ct_mixer *mixer)
656{
657 enum CTALSA_MIXER_CTL type = 0;
658 struct ct_atc *atc = mixer->atc;
659 int err = 0;
660
661 /* Create snd kcontrol instances on demand */
662 for (type = VOL_MIXER_START; type <= VOL_MIXER_END; type++) {
663 if (ct_kcontrol_init_table[type].ctl) {
664 vol_ctl.name = ct_kcontrol_init_table[type].name;
665 vol_ctl.private_value = (unsigned long)type;
666 err = ct_mixer_kcontrol_new(mixer, &vol_ctl);
667 if (err)
668 return err;
669 }
670 }
671
672 ct_kcontrol_init_table[MIXER_DIGITAL_IO_S].ctl =
673 atc->have_digit_io_switch(atc);
674 for (type = SWH_MIXER_START; type <= SWH_MIXER_END; type++) {
675 if (ct_kcontrol_init_table[type].ctl) {
676 swh_ctl.name = ct_kcontrol_init_table[type].name;
677 swh_ctl.private_value = (unsigned long)type;
678 err = ct_mixer_kcontrol_new(mixer, &swh_ctl);
679 if (err)
680 return err;
681 }
682 }
683
684 err = ct_mixer_kcontrol_new(mixer, &iec958_mask_ctl);
685 if (err)
686 return err;
687
688 err = ct_mixer_kcontrol_new(mixer, &iec958_default_ctl);
689 if (err)
690 return err;
691
692 err = ct_mixer_kcontrol_new(mixer, &iec958_ctl);
693 if (err)
694 return err;
695
696 atc->line_front_unmute(atc, 1);
697 set_switch_state(mixer, MIXER_WAVEF_P_S, 1);
698 atc->line_surround_unmute(atc, 0);
699 set_switch_state(mixer, MIXER_WAVES_P_S, 0);
700 atc->line_clfe_unmute(atc, 0);
701 set_switch_state(mixer, MIXER_WAVEC_P_S, 0);
702 atc->line_rear_unmute(atc, 0);
703 set_switch_state(mixer, MIXER_WAVER_P_S, 0);
704 atc->spdif_out_unmute(atc, 0);
705 set_switch_state(mixer, MIXER_SPDIFO_P_S, 0);
706 atc->line_in_unmute(atc, 0);
707 set_switch_state(mixer, MIXER_LINEIN_P_S, 0);
708 atc->spdif_in_unmute(atc, 0);
709 set_switch_state(mixer, MIXER_SPDIFI_P_S, 0);
710
711 set_switch_state(mixer, MIXER_PCM_C_S, 1);
712 set_switch_state(mixer, MIXER_LINEIN_C_S, 1);
713 set_switch_state(mixer, MIXER_SPDIFI_C_S, 1);
714
715 return 0;
716}
717
718static void
719ct_mixer_recording_select(struct ct_mixer *mixer, enum CT_AMIXER_CTL type)
720{
721 struct amixer *amix_d = NULL;
722 struct sum *sum_c = NULL;
723 int i = 0;
724
725 for (i = 0; i < 2; i++) {
726 amix_d = mixer->amixers[type*CHN_NUM+i];
727 sum_c = mixer->sums[SUM_IN_F_C*CHN_NUM+i];
728 amix_d->ops->set_sum(amix_d, sum_c);
729 amix_d->ops->commit_write(amix_d);
730 }
731}
732
733static void
734ct_mixer_recording_unselect(struct ct_mixer *mixer, enum CT_AMIXER_CTL type)
735{
736 struct amixer *amix_d = NULL;
737 int i = 0;
738
739 for (i = 0; i < 2; i++) {
740 amix_d = mixer->amixers[type*CHN_NUM+i];
741 amix_d->ops->set_sum(amix_d, NULL);
742 amix_d->ops->commit_write(amix_d);
743 }
744}
745
746static int ct_mixer_get_resources(struct ct_mixer *mixer)
747{
748 struct sum_mgr *sum_mgr = NULL;
749 struct sum *sum = NULL;
750 struct sum_desc sum_desc = {0};
751 struct amixer_mgr *amixer_mgr = NULL;
752 struct amixer *amixer = NULL;
753 struct amixer_desc am_desc = {0};
754 int err = 0;
755 int i = 0;
756
757 /* Allocate sum resources for mixer obj */
758 sum_mgr = (struct sum_mgr *)mixer->atc->rsc_mgrs[SUM];
759 sum_desc.msr = mixer->atc->msr;
760 for (i = 0; i < (NUM_CT_SUMS * CHN_NUM); i++) {
761 err = sum_mgr->get_sum(sum_mgr, &sum_desc, &sum);
762 if (err) {
763 printk(KERN_ERR "Failed to get sum resources for "
764 "front output!\n");
765 break;
766 }
767 mixer->sums[i] = sum;
768 }
769 if (err)
770 goto error1;
771
772 /* Allocate amixer resources for mixer obj */
773 amixer_mgr = (struct amixer_mgr *)mixer->atc->rsc_mgrs[AMIXER];
774 am_desc.msr = mixer->atc->msr;
775 for (i = 0; i < (NUM_CT_AMIXERS * CHN_NUM); i++) {
776 err = amixer_mgr->get_amixer(amixer_mgr, &am_desc, &amixer);
777 if (err) {
778 printk(KERN_ERR "Failed to get amixer resources for "
779 "mixer obj!\n");
780 break;
781 }
782 mixer->amixers[i] = amixer;
783 }
784 if (err)
785 goto error2;
786
787 return 0;
788
789error2:
790 for (i = 0; i < (NUM_CT_AMIXERS * CHN_NUM); i++) {
791 if (NULL != mixer->amixers[i]) {
792 amixer = mixer->amixers[i];
793 amixer_mgr->put_amixer(amixer_mgr, amixer);
794 mixer->amixers[i] = NULL;
795 }
796 }
797error1:
798 for (i = 0; i < (NUM_CT_SUMS * CHN_NUM); i++) {
799 if (NULL != mixer->sums[i]) {
800 sum_mgr->put_sum(sum_mgr, (struct sum *)mixer->sums[i]);
801 mixer->sums[i] = NULL;
802 }
803 }
804
805 return err;
806}
807
808static int ct_mixer_get_mem(struct ct_mixer **rmixer)
809{
810 struct ct_mixer *mixer = NULL;
811 int err = 0;
812
813 *rmixer = NULL;
814 /* Allocate mem for mixer obj */
815 mixer = kzalloc(sizeof(*mixer), GFP_KERNEL);
816 if (NULL == mixer)
817 return -ENOMEM;
818
819 mixer->amixers = kzalloc(sizeof(void *)*(NUM_CT_AMIXERS*CHN_NUM),
820 GFP_KERNEL);
821 if (NULL == mixer->amixers) {
822 err = -ENOMEM;
823 goto error1;
824 }
825 mixer->sums = kzalloc(sizeof(void *)*(NUM_CT_SUMS*CHN_NUM), GFP_KERNEL);
826 if (NULL == mixer->sums) {
827 err = -ENOMEM;
828 goto error2;
829 }
830
831 *rmixer = mixer;
832 return 0;
833
834error2:
835 kfree(mixer->amixers);
836error1:
837 kfree(mixer);
838 return err;
839}
840
841static int ct_mixer_topology_build(struct ct_mixer *mixer)
842{
843 struct sum *sum = NULL;
844 struct amixer *amix_d = NULL, *amix_s = NULL;
845 enum CT_AMIXER_CTL i = 0, j = 0;
846
847 /* Build topology from destination to source */
848
849 /* Set up Master mixer */
850 for (i = AMIXER_MASTER_F, j = SUM_IN_F;
851 i <= AMIXER_MASTER_S; i++, j++) {
852 amix_d = mixer->amixers[i*CHN_NUM];
853 sum = mixer->sums[j*CHN_NUM];
854 amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL);
855 amix_d = mixer->amixers[i*CHN_NUM+1];
856 sum = mixer->sums[j*CHN_NUM+1];
857 amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL);
858 }
859
860 /* Set up Wave-out mixer */
861 for (i = AMIXER_WAVE_F, j = AMIXER_MASTER_F;
862 i <= AMIXER_WAVE_S; i++, j++) {
863 amix_d = mixer->amixers[i*CHN_NUM];
864 amix_s = mixer->amixers[j*CHN_NUM];
865 amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL);
866 amix_d = mixer->amixers[i*CHN_NUM+1];
867 amix_s = mixer->amixers[j*CHN_NUM+1];
868 amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL);
869 }
870
871 /* Set up S/PDIF-out mixer */
872 amix_d = mixer->amixers[AMIXER_SPDIFO*CHN_NUM];
873 amix_s = mixer->amixers[AMIXER_MASTER_F*CHN_NUM];
874 amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL);
875 amix_d = mixer->amixers[AMIXER_SPDIFO*CHN_NUM+1];
876 amix_s = mixer->amixers[AMIXER_MASTER_F*CHN_NUM+1];
877 amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL);
878
879 /* Set up PCM-in mixer */
880 for (i = AMIXER_PCM_F, j = SUM_IN_F; i <= AMIXER_PCM_S; i++, j++) {
881 amix_d = mixer->amixers[i*CHN_NUM];
882 sum = mixer->sums[j*CHN_NUM];
883 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
884 amix_d = mixer->amixers[i*CHN_NUM+1];
885 sum = mixer->sums[j*CHN_NUM+1];
886 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
887 }
888
889 /* Set up Line-in mixer */
890 amix_d = mixer->amixers[AMIXER_LINEIN*CHN_NUM];
891 sum = mixer->sums[SUM_IN_F*CHN_NUM];
892 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
893 amix_d = mixer->amixers[AMIXER_LINEIN*CHN_NUM+1];
894 sum = mixer->sums[SUM_IN_F*CHN_NUM+1];
895 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
896
897 /* Set up Mic-in mixer */
898 amix_d = mixer->amixers[AMIXER_MIC*CHN_NUM];
899 sum = mixer->sums[SUM_IN_F*CHN_NUM];
900 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
901 amix_d = mixer->amixers[AMIXER_MIC*CHN_NUM+1];
902 sum = mixer->sums[SUM_IN_F*CHN_NUM+1];
903 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
904
905 /* Set up S/PDIF-in mixer */
906 amix_d = mixer->amixers[AMIXER_SPDIFI*CHN_NUM];
907 sum = mixer->sums[SUM_IN_F*CHN_NUM];
908 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
909 amix_d = mixer->amixers[AMIXER_SPDIFI*CHN_NUM+1];
910 sum = mixer->sums[SUM_IN_F*CHN_NUM+1];
911 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
912
913 /* Set up Master recording mixer */
914 amix_d = mixer->amixers[AMIXER_MASTER_F_C*CHN_NUM];
915 sum = mixer->sums[SUM_IN_F_C*CHN_NUM];
916 amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL);
917 amix_d = mixer->amixers[AMIXER_MASTER_F_C*CHN_NUM+1];
918 sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1];
919 amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL);
920
921 /* Set up PCM-in recording mixer */
922 amix_d = mixer->amixers[AMIXER_PCM_F_C*CHN_NUM];
923 sum = mixer->sums[SUM_IN_F_C*CHN_NUM];
924 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
925 amix_d = mixer->amixers[AMIXER_PCM_F_C*CHN_NUM+1];
926 sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1];
927 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
928
929 /* Set up Line-in recording mixer */
930 amix_d = mixer->amixers[AMIXER_LINEIN_C*CHN_NUM];
931 sum = mixer->sums[SUM_IN_F_C*CHN_NUM];
932 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
933 amix_d = mixer->amixers[AMIXER_LINEIN_C*CHN_NUM+1];
934 sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1];
935 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
936
937 /* Set up Mic-in recording mixer */
938 amix_d = mixer->amixers[AMIXER_MIC_C*CHN_NUM];
939 sum = mixer->sums[SUM_IN_F_C*CHN_NUM];
940 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
941 amix_d = mixer->amixers[AMIXER_MIC_C*CHN_NUM+1];
942 sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1];
943 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
944
945 /* Set up S/PDIF-in recording mixer */
946 amix_d = mixer->amixers[AMIXER_SPDIFI_C*CHN_NUM];
947 sum = mixer->sums[SUM_IN_F_C*CHN_NUM];
948 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
949 amix_d = mixer->amixers[AMIXER_SPDIFI_C*CHN_NUM+1];
950 sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1];
951 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
952
953 return 0;
954}
955
956static int mixer_set_input_port(struct amixer *amixer, struct rsc *rsc)
957{
958 amixer->ops->set_input(amixer, rsc);
959 amixer->ops->commit_write(amixer);
960
961 return 0;
962}
963
964static enum CT_AMIXER_CTL port_to_amixer(enum MIXER_PORT_T type)
965{
966 switch (type) {
967 case MIX_WAVE_FRONT: return AMIXER_WAVE_F;
968 case MIX_WAVE_SURROUND: return AMIXER_WAVE_S;
969 case MIX_WAVE_CENTLFE: return AMIXER_WAVE_C;
970 case MIX_WAVE_REAR: return AMIXER_WAVE_R;
971 case MIX_PCMO_FRONT: return AMIXER_MASTER_F_C;
972 case MIX_SPDIF_OUT: return AMIXER_SPDIFO;
973 case MIX_LINE_IN: return AMIXER_LINEIN;
974 case MIX_MIC_IN: return AMIXER_MIC;
975 case MIX_SPDIF_IN: return AMIXER_SPDIFI;
976 case MIX_PCMI_FRONT: return AMIXER_PCM_F;
977 case MIX_PCMI_SURROUND: return AMIXER_PCM_S;
978 case MIX_PCMI_CENTLFE: return AMIXER_PCM_C;
979 case MIX_PCMI_REAR: return AMIXER_PCM_R;
980 default: return 0;
981 }
982}
983
984static int mixer_get_output_ports(struct ct_mixer *mixer,
985 enum MIXER_PORT_T type,
986 struct rsc **rleft, struct rsc **rright)
987{
988 enum CT_AMIXER_CTL amix = port_to_amixer(type);
989
990 if (NULL != rleft)
991 *rleft = &((struct amixer *)mixer->amixers[amix*CHN_NUM])->rsc;
992
993 if (NULL != rright)
994 *rright =
995 &((struct amixer *)mixer->amixers[amix*CHN_NUM+1])->rsc;
996
997 return 0;
998}
999
1000static int mixer_set_input_left(struct ct_mixer *mixer,
1001 enum MIXER_PORT_T type, struct rsc *rsc)
1002{
1003 enum CT_AMIXER_CTL amix = port_to_amixer(type);
1004
1005 mixer_set_input_port(mixer->amixers[amix*CHN_NUM], rsc);
1006 amix = get_recording_amixer(amix);
1007 if (amix < NUM_CT_AMIXERS)
1008 mixer_set_input_port(mixer->amixers[amix*CHN_NUM], rsc);
1009
1010 return 0;
1011}
1012
1013static int
1014mixer_set_input_right(struct ct_mixer *mixer,
1015 enum MIXER_PORT_T type, struct rsc *rsc)
1016{
1017 enum CT_AMIXER_CTL amix = port_to_amixer(type);
1018
1019 mixer_set_input_port(mixer->amixers[amix*CHN_NUM+1], rsc);
1020 amix = get_recording_amixer(amix);
1021 if (amix < NUM_CT_AMIXERS)
1022 mixer_set_input_port(mixer->amixers[amix*CHN_NUM+1], rsc);
1023
1024 return 0;
1025}
1026
1027int ct_mixer_destroy(struct ct_mixer *mixer)
1028{
1029 struct sum_mgr *sum_mgr = (struct sum_mgr *)mixer->atc->rsc_mgrs[SUM];
1030 struct amixer_mgr *amixer_mgr =
1031 (struct amixer_mgr *)mixer->atc->rsc_mgrs[AMIXER];
1032 struct amixer *amixer = NULL;
1033 int i = 0;
1034
1035 /* Release amixer resources */
1036 for (i = 0; i < (NUM_CT_AMIXERS * CHN_NUM); i++) {
1037 if (NULL != mixer->amixers[i]) {
1038 amixer = mixer->amixers[i];
1039 amixer_mgr->put_amixer(amixer_mgr, amixer);
1040 }
1041 }
1042
1043 /* Release sum resources */
1044 for (i = 0; i < (NUM_CT_SUMS * CHN_NUM); i++) {
1045 if (NULL != mixer->sums[i])
1046 sum_mgr->put_sum(sum_mgr, (struct sum *)mixer->sums[i]);
1047 }
1048
1049 /* Release mem assigned to mixer object */
1050 kfree(mixer->sums);
1051 kfree(mixer->amixers);
1052 kfree(mixer);
1053
1054 return 0;
1055}
1056
1057int ct_mixer_create(struct ct_atc *atc, struct ct_mixer **rmixer)
1058{
1059 struct ct_mixer *mixer = NULL;
1060 int err = 0;
1061
1062 *rmixer = NULL;
1063
1064 /* Allocate mem for mixer obj */
1065 err = ct_mixer_get_mem(&mixer);
1066 if (err)
1067 return err;
1068
1069 mixer->switch_state = 0;
1070 mixer->atc = atc;
1071 /* Set operations */
1072 mixer->get_output_ports = mixer_get_output_ports;
1073 mixer->set_input_left = mixer_set_input_left;
1074 mixer->set_input_right = mixer_set_input_right;
1075
1076 /* Allocate chip resources for mixer obj */
1077 err = ct_mixer_get_resources(mixer);
1078 if (err)
1079 goto error;
1080
1081 /* Build internal mixer topology */
1082 ct_mixer_topology_build(mixer);
1083
1084 *rmixer = mixer;
1085
1086 return 0;
1087
1088error:
1089 ct_mixer_destroy(mixer);
1090 return err;
1091}
1092
1093int ct_alsa_mix_create(struct ct_atc *atc,
1094 enum CTALSADEVS device,
1095 const char *device_name)
1096{
1097 int err = 0;
1098
1099 /* Create snd kcontrol instances on demand */
1100 vol_ctl.device = swh_ctl.device = device;
1101 err = ct_mixer_kcontrols_create((struct ct_mixer *)atc->mixer);
1102 if (err)
1103 return err;
1104
1105 strcpy(atc->card->mixername, device_name);
1106
1107 return 0;
1108}
diff --git a/sound/pci/ctxfi/ctmixer.h b/sound/pci/ctxfi/ctmixer.h
new file mode 100644
index 000000000000..e2d96ebde746
--- /dev/null
+++ b/sound/pci/ctxfi/ctmixer.h
@@ -0,0 +1,67 @@
1/**
2 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
3 *
4 * This source file is released under GPL v2 license (no other versions).
5 * See the COPYING file included in the main directory of this source
6 * distribution for the license terms and conditions.
7 *
8 * @File ctmixer.h
9 *
10 * @Brief
11 * This file contains the definition of the mixer device functions.
12 *
13 * @Author Liu Chun
14 * @Date Mar 28 2008
15 *
16 */
17
18#ifndef CTMIXER_H
19#define CTMIXER_H
20
21#include "ctatc.h"
22#include "ctresource.h"
23
24#define INIT_VOL 0x1c00
25
26enum MIXER_PORT_T {
27 MIX_WAVE_FRONT,
28 MIX_WAVE_REAR,
29 MIX_WAVE_CENTLFE,
30 MIX_WAVE_SURROUND,
31 MIX_SPDIF_OUT,
32 MIX_PCMO_FRONT,
33 MIX_MIC_IN,
34 MIX_LINE_IN,
35 MIX_SPDIF_IN,
36 MIX_PCMI_FRONT,
37 MIX_PCMI_REAR,
38 MIX_PCMI_CENTLFE,
39 MIX_PCMI_SURROUND,
40
41 NUM_MIX_PORTS
42};
43
44/* alsa mixer descriptor */
45struct ct_mixer {
46 struct ct_atc *atc;
47
48 void **amixers; /* amixer resources for volume control */
49 void **sums; /* sum resources for signal collection */
50 unsigned int switch_state; /* A bit-map to indicate state of switches */
51
52 int (*get_output_ports)(struct ct_mixer *mixer, enum MIXER_PORT_T type,
53 struct rsc **rleft, struct rsc **rright);
54
55 int (*set_input_left)(struct ct_mixer *mixer,
56 enum MIXER_PORT_T type, struct rsc *rsc);
57 int (*set_input_right)(struct ct_mixer *mixer,
58 enum MIXER_PORT_T type, struct rsc *rsc);
59};
60
61int ct_alsa_mix_create(struct ct_atc *atc,
62 enum CTALSADEVS device,
63 const char *device_name);
64int ct_mixer_create(struct ct_atc *atc, struct ct_mixer **rmixer);
65int ct_mixer_destroy(struct ct_mixer *mixer);
66
67#endif /* CTMIXER_H */
diff --git a/sound/pci/ctxfi/ctpcm.c b/sound/pci/ctxfi/ctpcm.c
new file mode 100644
index 000000000000..73d4fdbbb9f4
--- /dev/null
+++ b/sound/pci/ctxfi/ctpcm.c
@@ -0,0 +1,499 @@
1/**
2 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
3 *
4 * This source file is released under GPL v2 license (no other versions).
5 * See the COPYING file included in the main directory of this source
6 * distribution for the license terms and conditions.
7 *
8 * @File ctpcm.c
9 *
10 * @Brief
11 * This file contains the definition of the pcm device functions.
12 *
13 * @Author Liu Chun
14 * @Date Apr 2 2008
15 *
16 */
17
18#include "ctpcm.h"
19#include <sound/pcm.h>
20
21/* Hardware descriptions for playback */
22static struct snd_pcm_hardware ct_pcm_playback_hw = {
23 .info = (SNDRV_PCM_INFO_MMAP |
24 SNDRV_PCM_INFO_INTERLEAVED |
25 SNDRV_PCM_INFO_BLOCK_TRANSFER |
26 SNDRV_PCM_INFO_MMAP_VALID |
27 SNDRV_PCM_INFO_PAUSE),
28 .formats = (SNDRV_PCM_FMTBIT_U8 |
29 SNDRV_PCM_FMTBIT_S8 |
30 SNDRV_PCM_FMTBIT_S16_LE |
31 SNDRV_PCM_FMTBIT_U16_LE |
32 SNDRV_PCM_FMTBIT_S24_3LE |
33 SNDRV_PCM_FMTBIT_S24_LE |
34 SNDRV_PCM_FMTBIT_S32_LE),
35 .rates = (SNDRV_PCM_RATE_CONTINUOUS |
36 SNDRV_PCM_RATE_8000_192000),
37 .rate_min = 8000,
38 .rate_max = 192000,
39 .channels_min = 1,
40 .channels_max = 2,
41 .buffer_bytes_max = (128*1024),
42 .period_bytes_min = (64),
43 .period_bytes_max = (128*1024),
44 .periods_min = 1,
45 .periods_max = 1024,
46 .fifo_size = 0,
47};
48
49static struct snd_pcm_hardware ct_spdif_passthru_playback_hw = {
50 .info = (SNDRV_PCM_INFO_MMAP |
51 SNDRV_PCM_INFO_INTERLEAVED |
52 SNDRV_PCM_INFO_BLOCK_TRANSFER |
53 SNDRV_PCM_INFO_MMAP_VALID |
54 SNDRV_PCM_INFO_PAUSE),
55 .formats = (SNDRV_PCM_FMTBIT_S16_LE |
56 SNDRV_PCM_FMTBIT_U16_LE),
57 .rates = (SNDRV_PCM_RATE_48000 |
58 SNDRV_PCM_RATE_44100 |
59 SNDRV_PCM_RATE_32000),
60 .rate_min = 32000,
61 .rate_max = 48000,
62 .channels_min = 2,
63 .channels_max = 2,
64 .buffer_bytes_max = (128*1024),
65 .period_bytes_min = (64),
66 .period_bytes_max = (128*1024),
67 .periods_min = 1,
68 .periods_max = 1024,
69 .fifo_size = 0,
70};
71
72/* Hardware descriptions for capture */
73static struct snd_pcm_hardware ct_pcm_capture_hw = {
74 .info = (SNDRV_PCM_INFO_MMAP |
75 SNDRV_PCM_INFO_INTERLEAVED |
76 SNDRV_PCM_INFO_BLOCK_TRANSFER |
77 SNDRV_PCM_INFO_PAUSE |
78 SNDRV_PCM_INFO_MMAP_VALID),
79 .formats = (SNDRV_PCM_FMTBIT_U8 |
80 SNDRV_PCM_FMTBIT_S8 |
81 SNDRV_PCM_FMTBIT_S16_LE |
82 SNDRV_PCM_FMTBIT_U16_LE |
83 SNDRV_PCM_FMTBIT_S24_3LE |
84 SNDRV_PCM_FMTBIT_S24_LE |
85 SNDRV_PCM_FMTBIT_S32_LE),
86 .rates = (SNDRV_PCM_RATE_CONTINUOUS |
87 SNDRV_PCM_RATE_8000_96000),
88 .rate_min = 8000,
89 .rate_max = 96000,
90 .channels_min = 1,
91 .channels_max = 2,
92 .buffer_bytes_max = (128*1024),
93 .period_bytes_min = (384),
94 .period_bytes_max = (64*1024),
95 .periods_min = 2,
96 .periods_max = 1024,
97 .fifo_size = 0,
98};
99
100static void ct_atc_pcm_interrupt(struct ct_atc_pcm *atc_pcm)
101{
102 struct ct_atc_pcm *apcm = atc_pcm;
103
104 if (NULL == apcm->substream)
105 return;
106
107 snd_pcm_period_elapsed(apcm->substream);
108}
109
110static void ct_atc_pcm_free_substream(struct snd_pcm_runtime *runtime)
111{
112 struct ct_atc_pcm *apcm = runtime->private_data;
113 struct ct_atc *atc = snd_pcm_substream_chip(apcm->substream);
114
115 atc->pcm_release_resources(atc, apcm);
116 kfree(apcm);
117 runtime->private_data = NULL;
118}
119
120/* pcm playback operations */
121static int ct_pcm_playback_open(struct snd_pcm_substream *substream)
122{
123 struct ct_atc *atc = snd_pcm_substream_chip(substream);
124 struct snd_pcm_runtime *runtime = substream->runtime;
125 struct ct_atc_pcm *apcm;
126 int err;
127
128 apcm = kzalloc(sizeof(*apcm), GFP_KERNEL);
129 if (NULL == apcm)
130 return -ENOMEM;
131
132 spin_lock_init(&apcm->timer_lock);
133 apcm->stop_timer = 0;
134 apcm->substream = substream;
135 apcm->interrupt = ct_atc_pcm_interrupt;
136 runtime->private_data = apcm;
137 runtime->private_free = ct_atc_pcm_free_substream;
138 if (IEC958 == substream->pcm->device) {
139 runtime->hw = ct_spdif_passthru_playback_hw;
140 atc->spdif_out_passthru(atc, 1);
141 } else {
142 runtime->hw = ct_pcm_playback_hw;
143 if (FRONT == substream->pcm->device)
144 runtime->hw.channels_max = 8;
145 }
146
147 err = snd_pcm_hw_constraint_integer(runtime,
148 SNDRV_PCM_HW_PARAM_PERIODS);
149 if (err < 0) {
150 kfree(apcm);
151 return err;
152 }
153 err = snd_pcm_hw_constraint_minmax(runtime,
154 SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
155 1024, UINT_MAX);
156 if (err < 0) {
157 kfree(apcm);
158 return err;
159 }
160
161 return 0;
162}
163
164static int ct_pcm_playback_close(struct snd_pcm_substream *substream)
165{
166 struct ct_atc *atc = snd_pcm_substream_chip(substream);
167
168 /* TODO: Notify mixer inactive. */
169 if (IEC958 == substream->pcm->device)
170 atc->spdif_out_passthru(atc, 0);
171
172 /* The ct_atc_pcm object will be freed by runtime->private_free */
173
174 return 0;
175}
176
177static int ct_pcm_hw_params(struct snd_pcm_substream *substream,
178 struct snd_pcm_hw_params *hw_params)
179{
180 return snd_pcm_lib_malloc_pages(substream,
181 params_buffer_bytes(hw_params));
182}
183
184static int ct_pcm_hw_free(struct snd_pcm_substream *substream)
185{
186 /* Free snd-allocated pages */
187 return snd_pcm_lib_free_pages(substream);
188}
189
190static void ct_pcm_timer_callback(unsigned long data)
191{
192 struct ct_atc_pcm *apcm = (struct ct_atc_pcm *)data;
193 struct snd_pcm_substream *substream = apcm->substream;
194 struct snd_pcm_runtime *runtime = substream->runtime;
195 unsigned int period_size = runtime->period_size;
196 unsigned int buffer_size = runtime->buffer_size;
197 unsigned long flags;
198 unsigned int position = 0, dist = 0, interval = 0;
199
200 position = substream->ops->pointer(substream);
201 dist = (position + buffer_size - apcm->position) % buffer_size;
202 if ((dist >= period_size) ||
203 (position/period_size != apcm->position/period_size)) {
204 apcm->interrupt(apcm);
205 apcm->position = position;
206 }
207 /* Add extra HZ*5/1000 to avoid overrun issue when recording
208 * at 8kHz in 8-bit format or at 88kHz in 24-bit format. */
209 interval = ((period_size - (position % period_size))
210 * HZ + (runtime->rate - 1)) / runtime->rate + HZ * 5 / 1000;
211 spin_lock_irqsave(&apcm->timer_lock, flags);
212 apcm->timer.expires = jiffies + interval;
213 if (!apcm->stop_timer)
214 add_timer(&apcm->timer);
215
216 spin_unlock_irqrestore(&apcm->timer_lock, flags);
217}
218
219static int ct_pcm_timer_prepare(struct ct_atc_pcm *apcm)
220{
221 unsigned long flags;
222
223 spin_lock_irqsave(&apcm->timer_lock, flags);
224 if (timer_pending(&apcm->timer)) {
225 /* The timer has already been started. */
226 spin_unlock_irqrestore(&apcm->timer_lock, flags);
227 return 0;
228 }
229
230 init_timer(&apcm->timer);
231 apcm->timer.data = (unsigned long)apcm;
232 apcm->timer.function = ct_pcm_timer_callback;
233 spin_unlock_irqrestore(&apcm->timer_lock, flags);
234 apcm->position = 0;
235
236 return 0;
237}
238
239static int ct_pcm_timer_start(struct ct_atc_pcm *apcm)
240{
241 struct snd_pcm_runtime *runtime = apcm->substream->runtime;
242 unsigned long flags;
243
244 spin_lock_irqsave(&apcm->timer_lock, flags);
245 if (timer_pending(&apcm->timer)) {
246 /* The timer has already been started. */
247 spin_unlock_irqrestore(&apcm->timer_lock, flags);
248 return 0;
249 }
250
251 apcm->timer.expires = jiffies + (runtime->period_size * HZ +
252 (runtime->rate - 1)) / runtime->rate;
253 apcm->stop_timer = 0;
254 add_timer(&apcm->timer);
255 spin_unlock_irqrestore(&apcm->timer_lock, flags);
256
257 return 0;
258}
259
260static int ct_pcm_timer_stop(struct ct_atc_pcm *apcm)
261{
262 unsigned long flags;
263
264 spin_lock_irqsave(&apcm->timer_lock, flags);
265 apcm->stop_timer = 1;
266 del_timer(&apcm->timer);
267 spin_unlock_irqrestore(&apcm->timer_lock, flags);
268
269 try_to_del_timer_sync(&apcm->timer);
270
271 return 0;
272}
273
274static int ct_pcm_playback_prepare(struct snd_pcm_substream *substream)
275{
276 int err;
277 struct ct_atc *atc = snd_pcm_substream_chip(substream);
278 struct snd_pcm_runtime *runtime = substream->runtime;
279 struct ct_atc_pcm *apcm = runtime->private_data;
280
281 if (IEC958 == substream->pcm->device)
282 err = atc->spdif_passthru_playback_prepare(atc, apcm);
283 else
284 err = atc->pcm_playback_prepare(atc, apcm);
285
286 if (err < 0) {
287 printk(KERN_ERR "Preparing pcm playback failed!!!\n");
288 return err;
289 }
290
291 ct_pcm_timer_prepare(apcm);
292
293 return 0;
294}
295
296static int
297ct_pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd)
298{
299 struct ct_atc *atc = snd_pcm_substream_chip(substream);
300 struct snd_pcm_runtime *runtime = substream->runtime;
301 struct ct_atc_pcm *apcm = runtime->private_data;
302
303 switch (cmd) {
304 case SNDRV_PCM_TRIGGER_START:
305 case SNDRV_PCM_TRIGGER_RESUME:
306 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
307 atc->pcm_playback_start(atc, apcm);
308 ct_pcm_timer_start(apcm);
309 break;
310 case SNDRV_PCM_TRIGGER_STOP:
311 case SNDRV_PCM_TRIGGER_SUSPEND:
312 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
313 ct_pcm_timer_stop(apcm);
314 atc->pcm_playback_stop(atc, apcm);
315 break;
316 default:
317 break;
318 }
319
320 return 0;
321}
322
323static snd_pcm_uframes_t
324ct_pcm_playback_pointer(struct snd_pcm_substream *substream)
325{
326 unsigned long position;
327 struct ct_atc *atc = snd_pcm_substream_chip(substream);
328 struct snd_pcm_runtime *runtime = substream->runtime;
329 struct ct_atc_pcm *apcm = runtime->private_data;
330
331 /* Read out playback position */
332 position = atc->pcm_playback_position(atc, apcm);
333 position = bytes_to_frames(runtime, position);
334 return position;
335}
336
337/* pcm capture operations */
338static int ct_pcm_capture_open(struct snd_pcm_substream *substream)
339{
340 struct ct_atc *atc = snd_pcm_substream_chip(substream);
341 struct snd_pcm_runtime *runtime = substream->runtime;
342 struct ct_atc_pcm *apcm;
343 int err;
344
345 apcm = kzalloc(sizeof(*apcm), GFP_KERNEL);
346 if (NULL == apcm)
347 return -ENOMEM;
348
349 spin_lock_init(&apcm->timer_lock);
350 apcm->started = 0;
351 apcm->stop_timer = 0;
352 apcm->substream = substream;
353 apcm->interrupt = ct_atc_pcm_interrupt;
354 runtime->private_data = apcm;
355 runtime->private_free = ct_atc_pcm_free_substream;
356 runtime->hw = ct_pcm_capture_hw;
357 runtime->hw.rate_max = atc->rsr * atc->msr;
358
359 err = snd_pcm_hw_constraint_integer(runtime,
360 SNDRV_PCM_HW_PARAM_PERIODS);
361 if (err < 0) {
362 kfree(apcm);
363 return err;
364 }
365 err = snd_pcm_hw_constraint_minmax(runtime,
366 SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
367 1024, UINT_MAX);
368 if (err < 0) {
369 kfree(apcm);
370 return err;
371 }
372
373 return 0;
374}
375
376static int ct_pcm_capture_close(struct snd_pcm_substream *substream)
377{
378 /* The ct_atc_pcm object will be freed by runtime->private_free */
379 /* TODO: Notify mixer inactive. */
380 return 0;
381}
382
383static int ct_pcm_capture_prepare(struct snd_pcm_substream *substream)
384{
385 int err;
386 struct ct_atc *atc = snd_pcm_substream_chip(substream);
387 struct snd_pcm_runtime *runtime = substream->runtime;
388 struct ct_atc_pcm *apcm = runtime->private_data;
389
390 err = atc->pcm_capture_prepare(atc, apcm);
391 if (err < 0) {
392 printk(KERN_ERR "Preparing pcm capture failed!!!\n");
393 return err;
394 }
395
396 ct_pcm_timer_prepare(apcm);
397
398 return 0;
399}
400
401static int
402ct_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd)
403{
404 struct ct_atc *atc = snd_pcm_substream_chip(substream);
405 struct snd_pcm_runtime *runtime = substream->runtime;
406 struct ct_atc_pcm *apcm = runtime->private_data;
407
408 switch (cmd) {
409 case SNDRV_PCM_TRIGGER_START:
410 atc->pcm_capture_start(atc, apcm);
411 ct_pcm_timer_start(apcm);
412 break;
413 case SNDRV_PCM_TRIGGER_STOP:
414 ct_pcm_timer_stop(apcm);
415 atc->pcm_capture_stop(atc, apcm);
416 break;
417 default:
418 ct_pcm_timer_stop(apcm);
419 atc->pcm_capture_stop(atc, apcm);
420 break;
421 }
422
423 return 0;
424}
425
426static snd_pcm_uframes_t
427ct_pcm_capture_pointer(struct snd_pcm_substream *substream)
428{
429 unsigned long position;
430 struct ct_atc *atc = snd_pcm_substream_chip(substream);
431 struct snd_pcm_runtime *runtime = substream->runtime;
432 struct ct_atc_pcm *apcm = runtime->private_data;
433
434 /* Read out playback position */
435 position = atc->pcm_capture_position(atc, apcm);
436 position = bytes_to_frames(runtime, position);
437 return position;
438}
439
440/* PCM operators for playback */
441static struct snd_pcm_ops ct_pcm_playback_ops = {
442 .open = ct_pcm_playback_open,
443 .close = ct_pcm_playback_close,
444 .ioctl = snd_pcm_lib_ioctl,
445 .hw_params = ct_pcm_hw_params,
446 .hw_free = ct_pcm_hw_free,
447 .prepare = ct_pcm_playback_prepare,
448 .trigger = ct_pcm_playback_trigger,
449 .pointer = ct_pcm_playback_pointer,
450};
451
452/* PCM operators for capture */
453static struct snd_pcm_ops ct_pcm_capture_ops = {
454 .open = ct_pcm_capture_open,
455 .close = ct_pcm_capture_close,
456 .ioctl = snd_pcm_lib_ioctl,
457 .hw_params = ct_pcm_hw_params,
458 .hw_free = ct_pcm_hw_free,
459 .prepare = ct_pcm_capture_prepare,
460 .trigger = ct_pcm_capture_trigger,
461 .pointer = ct_pcm_capture_pointer,
462};
463
464/* Create ALSA pcm device */
465int ct_alsa_pcm_create(struct ct_atc *atc,
466 enum CTALSADEVS device,
467 const char *device_name)
468{
469 struct snd_pcm *pcm;
470 int err;
471 int playback_count, capture_count;
472 char name[128];
473
474 strncpy(name, device_name, sizeof(name));
475 playback_count = (IEC958 == device) ? 1 : 8;
476 capture_count = (FRONT == device) ? 1 : 0;
477 err = snd_pcm_new(atc->card, name, device,
478 playback_count, capture_count, &pcm);
479 if (err < 0) {
480 printk(KERN_ERR "snd_pcm_new failed!! Err=%d\n", err);
481 return err;
482 }
483
484 pcm->private_data = atc;
485 pcm->info_flags = 0;
486 pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
487 strcpy(pcm->name, device_name);
488
489 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &ct_pcm_playback_ops);
490
491 if (FRONT == device)
492 snd_pcm_set_ops(pcm,
493 SNDRV_PCM_STREAM_CAPTURE, &ct_pcm_capture_ops);
494
495 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
496 snd_dma_pci_data(atc->pci), 128*1024, 128*1024);
497
498 return 0;
499}
diff --git a/sound/pci/ctxfi/ctpcm.h b/sound/pci/ctxfi/ctpcm.h
new file mode 100644
index 000000000000..178da0dca647
--- /dev/null
+++ b/sound/pci/ctxfi/ctpcm.h
@@ -0,0 +1,27 @@
1/**
2 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
3 *
4 * This source file is released under GPL v2 license (no other versions).
5 * See the COPYING file included in the main directory of this source
6 * distribution for the license terms and conditions.
7 *
8 * @File ctpcm.h
9 *
10 * @Brief
11 * This file contains the definition of the pcm device functions.
12 *
13 * @Author Liu Chun
14 * @Date Mar 28 2008
15 *
16 */
17
18#ifndef CTPCM_H
19#define CTPCM_H
20
21#include "ctatc.h"
22
23int ct_alsa_pcm_create(struct ct_atc *atc,
24 enum CTALSADEVS device,
25 const char *device_name);
26
27#endif /* CTPCM_H */
diff --git a/sound/pci/ctxfi/ctresource.c b/sound/pci/ctxfi/ctresource.c
new file mode 100644
index 000000000000..414fc23267cd
--- /dev/null
+++ b/sound/pci/ctxfi/ctresource.c
@@ -0,0 +1,297 @@
1/**
2 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
3 *
4 * This source file is released under GPL v2 license (no other versions).
5 * See the COPYING file included in the main directory of this source
6 * distribution for the license terms and conditions.
7 *
8 * @File ctresource.c
9 *
10 * @Brief
11 * This file contains the implementation of some generic helper functions.
12 *
13 * @Author Liu Chun
14 * @Date May 15 2008
15 *
16 */
17
18#include "ctresource.h"
19#include "cthardware.h"
20#include <linux/err.h>
21#include <linux/slab.h>
22
23#define AUDIO_SLOT_BLOCK_NUM 256
24
25/* Resource allocation based on bit-map management mechanism */
26static int
27get_resource(u8 *rscs, unsigned int amount,
28 unsigned int multi, unsigned int *ridx)
29{
30 int i = 0, j = 0, k = 0, n = 0;
31
32 /* Check whether there are sufficient resources to meet request. */
33 for (i = 0, n = multi; i < amount; i++) {
34 j = i / 8;
35 k = i % 8;
36 if (rscs[j] & ((u8)1 << k)) {
37 n = multi;
38 continue;
39 }
40 if (!(--n))
41 break; /* found sufficient contiguous resources */
42 }
43
44 if (i >= amount) {
45 /* Can not find sufficient contiguous resources */
46 return -ENOENT;
47 }
48
49 /* Mark the contiguous bits in resource bit-map as used */
50 for (n = multi; n > 0; n--) {
51 j = i / 8;
52 k = i % 8;
53 rscs[j] |= ((u8)1 << k);
54 i--;
55 }
56
57 *ridx = i + 1;
58
59 return 0;
60}
61
62static int put_resource(u8 *rscs, unsigned int multi, unsigned int idx)
63{
64 unsigned int i = 0, j = 0, k = 0, n = 0;
65
66 /* Mark the contiguous bits in resource bit-map as used */
67 for (n = multi, i = idx; n > 0; n--) {
68 j = i / 8;
69 k = i % 8;
70 rscs[j] &= ~((u8)1 << k);
71 i++;
72 }
73
74 return 0;
75}
76
77int mgr_get_resource(struct rsc_mgr *mgr, unsigned int n, unsigned int *ridx)
78{
79 int err = 0;
80
81 if (n > mgr->avail)
82 return -ENOENT;
83
84 err = get_resource(mgr->rscs, mgr->amount, n, ridx);
85 if (!err)
86 mgr->avail -= n;
87
88 return err;
89}
90
91int mgr_put_resource(struct rsc_mgr *mgr, unsigned int n, unsigned int idx)
92{
93 put_resource(mgr->rscs, n, idx);
94 mgr->avail += n;
95
96 return 0;
97}
98
99static unsigned char offset_in_audio_slot_block[NUM_RSCTYP] = {
100 /* SRC channel is at Audio Ring slot 1 every 16 slots. */
101 [SRC] = 0x1,
102 [AMIXER] = 0x4,
103 [SUM] = 0xc,
104};
105
106static int rsc_index(const struct rsc *rsc)
107{
108 return rsc->conj;
109}
110
111static int audio_ring_slot(const struct rsc *rsc)
112{
113 return (rsc->conj << 4) + offset_in_audio_slot_block[rsc->type];
114}
115
116static int rsc_next_conj(struct rsc *rsc)
117{
118 unsigned int i;
119 for (i = 0; (i < 8) && (!(rsc->msr & (0x1 << i))); )
120 i++;
121 rsc->conj += (AUDIO_SLOT_BLOCK_NUM >> i);
122 return rsc->conj;
123}
124
125static int rsc_master(struct rsc *rsc)
126{
127 return rsc->conj = rsc->idx;
128}
129
130static struct rsc_ops rsc_generic_ops = {
131 .index = rsc_index,
132 .output_slot = audio_ring_slot,
133 .master = rsc_master,
134 .next_conj = rsc_next_conj,
135};
136
137int rsc_init(struct rsc *rsc, u32 idx, enum RSCTYP type, u32 msr, void *hw)
138{
139 int err = 0;
140
141 rsc->idx = idx;
142 rsc->conj = idx;
143 rsc->type = type;
144 rsc->msr = msr;
145 rsc->hw = hw;
146 rsc->ops = &rsc_generic_ops;
147 if (NULL == hw) {
148 rsc->ctrl_blk = NULL;
149 return 0;
150 }
151
152 switch (type) {
153 case SRC:
154 err = ((struct hw *)hw)->src_rsc_get_ctrl_blk(&rsc->ctrl_blk);
155 break;
156 case AMIXER:
157 err = ((struct hw *)hw)->
158 amixer_rsc_get_ctrl_blk(&rsc->ctrl_blk);
159 break;
160 case SRCIMP:
161 case SUM:
162 case DAIO:
163 break;
164 default:
165 printk(KERN_ERR "Invalid resource type value %d!\n", type);
166 return -EINVAL;
167 }
168
169 if (err) {
170 printk(KERN_ERR "Failed to get resource control block!\n");
171 return err;
172 }
173
174 return 0;
175}
176
177int rsc_uninit(struct rsc *rsc)
178{
179 if ((NULL != rsc->hw) && (NULL != rsc->ctrl_blk)) {
180 switch (rsc->type) {
181 case SRC:
182 ((struct hw *)rsc->hw)->
183 src_rsc_put_ctrl_blk(rsc->ctrl_blk);
184 break;
185 case AMIXER:
186 ((struct hw *)rsc->hw)->
187 amixer_rsc_put_ctrl_blk(rsc->ctrl_blk);
188 break;
189 case SUM:
190 case DAIO:
191 break;
192 default:
193 printk(KERN_ERR "Invalid resource type value %d!\n",
194 rsc->type);
195 break;
196 }
197
198 rsc->hw = rsc->ctrl_blk = NULL;
199 }
200
201 rsc->idx = rsc->conj = 0;
202 rsc->type = NUM_RSCTYP;
203 rsc->msr = 0;
204
205 return 0;
206}
207
208int rsc_mgr_init(struct rsc_mgr *mgr, enum RSCTYP type,
209 unsigned int amount, void *hw_obj)
210{
211 int err = 0;
212 struct hw *hw = hw_obj;
213
214 mgr->type = NUM_RSCTYP;
215
216 mgr->rscs = kzalloc(((amount + 8 - 1) / 8), GFP_KERNEL);
217 if (NULL == mgr->rscs)
218 return -ENOMEM;
219
220 switch (type) {
221 case SRC:
222 err = hw->src_mgr_get_ctrl_blk(&mgr->ctrl_blk);
223 break;
224 case SRCIMP:
225 err = hw->srcimp_mgr_get_ctrl_blk(&mgr->ctrl_blk);
226 break;
227 case AMIXER:
228 err = hw->amixer_mgr_get_ctrl_blk(&mgr->ctrl_blk);
229 break;
230 case DAIO:
231 err = hw->daio_mgr_get_ctrl_blk(hw, &mgr->ctrl_blk);
232 break;
233 case SUM:
234 break;
235 default:
236 printk(KERN_ERR "Invalid resource type value %d!\n", type);
237 err = -EINVAL;
238 goto error;
239 }
240
241 if (err) {
242 printk(KERN_ERR "Failed to get manager control block!\n");
243 goto error;
244 }
245
246 mgr->type = type;
247 mgr->avail = mgr->amount = amount;
248 mgr->hw = hw;
249
250 return 0;
251
252error:
253 kfree(mgr->rscs);
254 return err;
255}
256
257int rsc_mgr_uninit(struct rsc_mgr *mgr)
258{
259 if (NULL != mgr->rscs) {
260 kfree(mgr->rscs);
261 mgr->rscs = NULL;
262 }
263
264 if ((NULL != mgr->hw) && (NULL != mgr->ctrl_blk)) {
265 switch (mgr->type) {
266 case SRC:
267 ((struct hw *)mgr->hw)->
268 src_mgr_put_ctrl_blk(mgr->ctrl_blk);
269 break;
270 case SRCIMP:
271 ((struct hw *)mgr->hw)->
272 srcimp_mgr_put_ctrl_blk(mgr->ctrl_blk);
273 break;
274 case AMIXER:
275 ((struct hw *)mgr->hw)->
276 amixer_mgr_put_ctrl_blk(mgr->ctrl_blk);
277 break;
278 case DAIO:
279 ((struct hw *)mgr->hw)->
280 daio_mgr_put_ctrl_blk(mgr->ctrl_blk);
281 break;
282 case SUM:
283 break;
284 default:
285 printk(KERN_ERR "Invalid resource type value %d!\n",
286 mgr->type);
287 break;
288 }
289
290 mgr->hw = mgr->ctrl_blk = NULL;
291 }
292
293 mgr->type = NUM_RSCTYP;
294 mgr->avail = mgr->amount = 0;
295
296 return 0;
297}
diff --git a/sound/pci/ctxfi/ctresource.h b/sound/pci/ctxfi/ctresource.h
new file mode 100644
index 000000000000..0838c2e84f8b
--- /dev/null
+++ b/sound/pci/ctxfi/ctresource.h
@@ -0,0 +1,72 @@
1/**
2 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
3 *
4 * This source file is released under GPL v2 license (no other versions).
5 * See the COPYING file included in the main directory of this source
6 * distribution for the license terms and conditions.
7 *
8 * @File ctresource.h
9 *
10 * @Brief
11 * This file contains the definition of generic hardware resources for
12 * resource management.
13 *
14 * @Author Liu Chun
15 * @Date May 13 2008
16 *
17 */
18
19#ifndef CTRESOURCE_H
20#define CTRESOURCE_H
21
22#include <linux/types.h>
23
24enum RSCTYP {
25 SRC,
26 SRCIMP,
27 AMIXER,
28 SUM,
29 DAIO,
30 NUM_RSCTYP /* This must be the last one and less than 16 */
31};
32
33struct rsc_ops;
34
35struct rsc {
36 u32 idx:12; /* The index of a resource */
37 u32 type:4; /* The type (RSCTYP) of a resource */
38 u32 conj:12; /* Current conjugate index */
39 u32 msr:4; /* The Master Sample Rate a resource working on */
40 void *ctrl_blk; /* Chip specific control info block for a resource */
41 void *hw; /* Chip specific object for hardware access means */
42 struct rsc_ops *ops; /* Generic resource operations */
43};
44
45struct rsc_ops {
46 int (*master)(struct rsc *rsc); /* Move to master resource */
47 int (*next_conj)(struct rsc *rsc); /* Move to next conjugate resource */
48 int (*index)(const struct rsc *rsc); /* Return the index of resource */
49 /* Return the output slot number */
50 int (*output_slot)(const struct rsc *rsc);
51};
52
53int rsc_init(struct rsc *rsc, u32 idx, enum RSCTYP type, u32 msr, void *hw);
54int rsc_uninit(struct rsc *rsc);
55
56struct rsc_mgr {
57 enum RSCTYP type; /* The type (RSCTYP) of resource to manage */
58 unsigned int amount; /* The total amount of a kind of resource */
59 unsigned int avail; /* The amount of currently available resources */
60 unsigned char *rscs; /* The bit-map for resource allocation */
61 void *ctrl_blk; /* Chip specific control info block */
62 void *hw; /* Chip specific object for hardware access */
63};
64
65/* Resource management is based on bit-map mechanism */
66int rsc_mgr_init(struct rsc_mgr *mgr, enum RSCTYP type,
67 unsigned int amount, void *hw);
68int rsc_mgr_uninit(struct rsc_mgr *mgr);
69int mgr_get_resource(struct rsc_mgr *mgr, unsigned int n, unsigned int *ridx);
70int mgr_put_resource(struct rsc_mgr *mgr, unsigned int n, unsigned int idx);
71
72#endif /* CTRESOURCE_H */
diff --git a/sound/pci/ctxfi/ctsrc.c b/sound/pci/ctxfi/ctsrc.c
new file mode 100644
index 000000000000..d3e0ad5ed9fb
--- /dev/null
+++ b/sound/pci/ctxfi/ctsrc.c
@@ -0,0 +1,886 @@
1/**
2 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
3 *
4 * This source file is released under GPL v2 license (no other versions).
5 * See the COPYING file included in the main directory of this source
6 * distribution for the license terms and conditions.
7 *
8 * @File ctsrc.c
9 *
10 * @Brief
11 * This file contains the implementation of the Sample Rate Convertor
12 * resource management object.
13 *
14 * @Author Liu Chun
15 * @Date May 13 2008
16 *
17 */
18
19#include "ctsrc.h"
20#include "cthardware.h"
21#include <linux/slab.h>
22
23#define SRC_RESOURCE_NUM 64
24#define SRCIMP_RESOURCE_NUM 256
25
26static unsigned int conj_mask;
27
28static int src_default_config_memrd(struct src *src);
29static int src_default_config_memwr(struct src *src);
30static int src_default_config_arcrw(struct src *src);
31
32static int (*src_default_config[3])(struct src *) = {
33 [MEMRD] = src_default_config_memrd,
34 [MEMWR] = src_default_config_memwr,
35 [ARCRW] = src_default_config_arcrw
36};
37
38static int src_set_state(struct src *src, unsigned int state)
39{
40 struct hw *hw = NULL;
41
42 hw = (struct hw *)src->rsc.hw;
43 hw->src_set_state(src->rsc.ctrl_blk, state);
44
45 return 0;
46}
47
48static int src_set_bm(struct src *src, unsigned int bm)
49{
50 struct hw *hw = NULL;
51
52 hw = (struct hw *)src->rsc.hw;
53 hw->src_set_bm(src->rsc.ctrl_blk, bm);
54
55 return 0;
56}
57
58static int src_set_sf(struct src *src, unsigned int sf)
59{
60 struct hw *hw = NULL;
61
62 hw = (struct hw *)src->rsc.hw;
63 hw->src_set_sf(src->rsc.ctrl_blk, sf);
64
65 return 0;
66}
67
68static int src_set_pm(struct src *src, unsigned int pm)
69{
70 struct hw *hw = NULL;
71
72 hw = (struct hw *)src->rsc.hw;
73 hw->src_set_pm(src->rsc.ctrl_blk, pm);
74
75 return 0;
76}
77
78static int src_set_rom(struct src *src, unsigned int rom)
79{
80 struct hw *hw = NULL;
81
82 hw = (struct hw *)src->rsc.hw;
83 hw->src_set_rom(src->rsc.ctrl_blk, rom);
84
85 return 0;
86}
87
88static int src_set_vo(struct src *src, unsigned int vo)
89{
90 struct hw *hw = NULL;
91
92 hw = (struct hw *)src->rsc.hw;
93 hw->src_set_vo(src->rsc.ctrl_blk, vo);
94
95 return 0;
96}
97
98static int src_set_st(struct src *src, unsigned int st)
99{
100 struct hw *hw = NULL;
101
102 hw = (struct hw *)src->rsc.hw;
103 hw->src_set_st(src->rsc.ctrl_blk, st);
104
105 return 0;
106}
107
108static int src_set_bp(struct src *src, unsigned int bp)
109{
110 struct hw *hw = NULL;
111
112 hw = (struct hw *)src->rsc.hw;
113 hw->src_set_bp(src->rsc.ctrl_blk, bp);
114
115 return 0;
116}
117
118static int src_set_cisz(struct src *src, unsigned int cisz)
119{
120 struct hw *hw = NULL;
121
122 hw = (struct hw *)src->rsc.hw;
123 hw->src_set_cisz(src->rsc.ctrl_blk, cisz);
124
125 return 0;
126}
127
128static int src_set_ca(struct src *src, unsigned int ca)
129{
130 struct hw *hw = NULL;
131
132 hw = (struct hw *)src->rsc.hw;
133 hw->src_set_ca(src->rsc.ctrl_blk, ca);
134
135 return 0;
136}
137
138static int src_set_sa(struct src *src, unsigned int sa)
139{
140 struct hw *hw = NULL;
141
142 hw = (struct hw *)src->rsc.hw;
143 hw->src_set_sa(src->rsc.ctrl_blk, sa);
144
145 return 0;
146}
147
148static int src_set_la(struct src *src, unsigned int la)
149{
150 struct hw *hw = NULL;
151
152 hw = (struct hw *)src->rsc.hw;
153 hw->src_set_la(src->rsc.ctrl_blk, la);
154
155 return 0;
156}
157
158static int src_set_pitch(struct src *src, unsigned int pitch)
159{
160 struct hw *hw = NULL;
161
162 hw = (struct hw *)src->rsc.hw;
163 hw->src_set_pitch(src->rsc.ctrl_blk, pitch);
164
165 return 0;
166}
167
168static int src_set_clear_zbufs(struct src *src)
169{
170 struct hw *hw = NULL;
171
172 hw = (struct hw *)src->rsc.hw;
173 hw->src_set_clear_zbufs(src->rsc.ctrl_blk, 1);
174
175 return 0;
176}
177
178static int src_commit_write(struct src *src)
179{
180 struct hw *hw = NULL;
181 int i = 0;
182 unsigned int dirty = 0;
183
184 hw = (struct hw *)src->rsc.hw;
185 src->rsc.ops->master(&src->rsc);
186 if (src->rsc.msr > 1) {
187 /* Save dirty flags for conjugate resource programming */
188 dirty = hw->src_get_dirty(src->rsc.ctrl_blk) & conj_mask;
189 }
190 hw->src_commit_write(hw, src->rsc.ops->index(&src->rsc),
191 src->rsc.ctrl_blk);
192
193 /* Program conjugate parameter mixer resources */
194 if (MEMWR == src->mode)
195 return 0;
196
197 for (i = 1; i < src->rsc.msr; i++) {
198 src->rsc.ops->next_conj(&src->rsc);
199 hw->src_set_dirty(src->rsc.ctrl_blk, dirty);
200 hw->src_commit_write(hw, src->rsc.ops->index(&src->rsc),
201 src->rsc.ctrl_blk);
202 }
203 src->rsc.ops->master(&src->rsc);
204
205 return 0;
206}
207
208static int src_get_ca(struct src *src)
209{
210 struct hw *hw = NULL;
211
212 hw = (struct hw *)src->rsc.hw;
213 return hw->src_get_ca(hw, src->rsc.ops->index(&src->rsc),
214 src->rsc.ctrl_blk);
215}
216
217static int src_init(struct src *src)
218{
219 src_default_config[src->mode](src);
220
221 return 0;
222}
223
224static struct src *src_next_interleave(struct src *src)
225{
226 return src->intlv;
227}
228
229static int src_default_config_memrd(struct src *src)
230{
231 struct hw *hw = src->rsc.hw;
232 unsigned int rsr = 0, msr = 0;
233
234 hw->src_set_state(src->rsc.ctrl_blk, SRC_STATE_OFF);
235 hw->src_set_bm(src->rsc.ctrl_blk, 1);
236 for (rsr = 0, msr = src->rsc.msr; msr > 1; msr >>= 1)
237 rsr++;
238
239 hw->src_set_rsr(src->rsc.ctrl_blk, rsr);
240 hw->src_set_sf(src->rsc.ctrl_blk, SRC_SF_S16);
241 hw->src_set_wr(src->rsc.ctrl_blk, 0);
242 hw->src_set_pm(src->rsc.ctrl_blk, 0);
243 hw->src_set_rom(src->rsc.ctrl_blk, 0);
244 hw->src_set_vo(src->rsc.ctrl_blk, 0);
245 hw->src_set_st(src->rsc.ctrl_blk, 0);
246 hw->src_set_ilsz(src->rsc.ctrl_blk, src->multi - 1);
247 hw->src_set_cisz(src->rsc.ctrl_blk, 0x80);
248 hw->src_set_sa(src->rsc.ctrl_blk, 0x0);
249 hw->src_set_la(src->rsc.ctrl_blk, 0x1000);
250 hw->src_set_ca(src->rsc.ctrl_blk, 0x80);
251 hw->src_set_pitch(src->rsc.ctrl_blk, 0x1000000);
252 hw->src_set_clear_zbufs(src->rsc.ctrl_blk, 1);
253
254 src->rsc.ops->master(&src->rsc);
255 hw->src_commit_write(hw, src->rsc.ops->index(&src->rsc),
256 src->rsc.ctrl_blk);
257
258 for (msr = 1; msr < src->rsc.msr; msr++) {
259 src->rsc.ops->next_conj(&src->rsc);
260 hw->src_set_pitch(src->rsc.ctrl_blk, 0x1000000);
261 hw->src_commit_write(hw, src->rsc.ops->index(&src->rsc),
262 src->rsc.ctrl_blk);
263 }
264 src->rsc.ops->master(&src->rsc);
265
266 return 0;
267}
268
269static int src_default_config_memwr(struct src *src)
270{
271 struct hw *hw = src->rsc.hw;
272
273 hw->src_set_state(src->rsc.ctrl_blk, SRC_STATE_OFF);
274 hw->src_set_bm(src->rsc.ctrl_blk, 1);
275 hw->src_set_rsr(src->rsc.ctrl_blk, 0);
276 hw->src_set_sf(src->rsc.ctrl_blk, SRC_SF_S16);
277 hw->src_set_wr(src->rsc.ctrl_blk, 1);
278 hw->src_set_pm(src->rsc.ctrl_blk, 0);
279 hw->src_set_rom(src->rsc.ctrl_blk, 0);
280 hw->src_set_vo(src->rsc.ctrl_blk, 0);
281 hw->src_set_st(src->rsc.ctrl_blk, 0);
282 hw->src_set_ilsz(src->rsc.ctrl_blk, 0);
283 hw->src_set_cisz(src->rsc.ctrl_blk, 0x80);
284 hw->src_set_sa(src->rsc.ctrl_blk, 0x0);
285 hw->src_set_la(src->rsc.ctrl_blk, 0x1000);
286 hw->src_set_ca(src->rsc.ctrl_blk, 0x80);
287 hw->src_set_pitch(src->rsc.ctrl_blk, 0x1000000);
288 hw->src_set_clear_zbufs(src->rsc.ctrl_blk, 1);
289
290 src->rsc.ops->master(&src->rsc);
291 hw->src_commit_write(hw, src->rsc.ops->index(&src->rsc),
292 src->rsc.ctrl_blk);
293
294 return 0;
295}
296
297static int src_default_config_arcrw(struct src *src)
298{
299 struct hw *hw = src->rsc.hw;
300 unsigned int rsr = 0, msr = 0;
301 unsigned int dirty;
302
303 hw->src_set_state(src->rsc.ctrl_blk, SRC_STATE_OFF);
304 hw->src_set_bm(src->rsc.ctrl_blk, 0);
305 for (rsr = 0, msr = src->rsc.msr; msr > 1; msr >>= 1)
306 rsr++;
307
308 hw->src_set_rsr(src->rsc.ctrl_blk, rsr);
309 hw->src_set_sf(src->rsc.ctrl_blk, SRC_SF_F32);
310 hw->src_set_wr(src->rsc.ctrl_blk, 0);
311 hw->src_set_pm(src->rsc.ctrl_blk, 0);
312 hw->src_set_rom(src->rsc.ctrl_blk, 0);
313 hw->src_set_vo(src->rsc.ctrl_blk, 0);
314 hw->src_set_st(src->rsc.ctrl_blk, 0);
315 hw->src_set_ilsz(src->rsc.ctrl_blk, 0);
316 hw->src_set_cisz(src->rsc.ctrl_blk, 0x80);
317 hw->src_set_sa(src->rsc.ctrl_blk, 0x0);
318 /*hw->src_set_sa(src->rsc.ctrl_blk, 0x100);*/
319 hw->src_set_la(src->rsc.ctrl_blk, 0x1000);
320 /*hw->src_set_la(src->rsc.ctrl_blk, 0x03ffffe0);*/
321 hw->src_set_ca(src->rsc.ctrl_blk, 0x80);
322 hw->src_set_pitch(src->rsc.ctrl_blk, 0x1000000);
323 hw->src_set_clear_zbufs(src->rsc.ctrl_blk, 1);
324
325 dirty = hw->src_get_dirty(src->rsc.ctrl_blk);
326 src->rsc.ops->master(&src->rsc);
327 for (msr = 0; msr < src->rsc.msr; msr++) {
328 hw->src_set_dirty(src->rsc.ctrl_blk, dirty);
329 hw->src_commit_write(hw, src->rsc.ops->index(&src->rsc),
330 src->rsc.ctrl_blk);
331 src->rsc.ops->next_conj(&src->rsc);
332 }
333 src->rsc.ops->master(&src->rsc);
334
335 return 0;
336}
337
338static struct src_rsc_ops src_rsc_ops = {
339 .set_state = src_set_state,
340 .set_bm = src_set_bm,
341 .set_sf = src_set_sf,
342 .set_pm = src_set_pm,
343 .set_rom = src_set_rom,
344 .set_vo = src_set_vo,
345 .set_st = src_set_st,
346 .set_bp = src_set_bp,
347 .set_cisz = src_set_cisz,
348 .set_ca = src_set_ca,
349 .set_sa = src_set_sa,
350 .set_la = src_set_la,
351 .set_pitch = src_set_pitch,
352 .set_clr_zbufs = src_set_clear_zbufs,
353 .commit_write = src_commit_write,
354 .get_ca = src_get_ca,
355 .init = src_init,
356 .next_interleave = src_next_interleave,
357};
358
359static int
360src_rsc_init(struct src *src, u32 idx,
361 const struct src_desc *desc, struct src_mgr *mgr)
362{
363 int err = 0;
364 int i = 0, n = 0;
365 struct src *p;
366
367 n = (MEMRD == desc->mode) ? desc->multi : 1;
368 for (i = 0, p = src; i < n; i++, p++) {
369 err = rsc_init(&p->rsc, idx + i, SRC, desc->msr, mgr->mgr.hw);
370 if (err)
371 goto error1;
372
373 /* Initialize src specific rsc operations */
374 p->ops = &src_rsc_ops;
375 p->multi = (0 == i) ? desc->multi : 1;
376 p->mode = desc->mode;
377 src_default_config[desc->mode](p);
378 mgr->src_enable(mgr, p);
379 p->intlv = p + 1;
380 }
381 (--p)->intlv = NULL; /* Set @intlv of the last SRC to NULL */
382
383 mgr->commit_write(mgr);
384
385 return 0;
386
387error1:
388 for (i--, p--; i >= 0; i--, p--) {
389 mgr->src_disable(mgr, p);
390 rsc_uninit(&p->rsc);
391 }
392 mgr->commit_write(mgr);
393 return err;
394}
395
396static int src_rsc_uninit(struct src *src, struct src_mgr *mgr)
397{
398 int i = 0, n = 0;
399 struct src *p;
400
401 n = (MEMRD == src->mode) ? src->multi : 1;
402 for (i = 0, p = src; i < n; i++, p++) {
403 mgr->src_disable(mgr, p);
404 rsc_uninit(&p->rsc);
405 p->multi = 0;
406 p->ops = NULL;
407 p->mode = NUM_SRCMODES;
408 p->intlv = NULL;
409 }
410 mgr->commit_write(mgr);
411
412 return 0;
413}
414
415static int
416get_src_rsc(struct src_mgr *mgr, const struct src_desc *desc, struct src **rsrc)
417{
418 unsigned int idx = SRC_RESOURCE_NUM;
419 int err = 0;
420 struct src *src = NULL;
421 unsigned long flags;
422
423 *rsrc = NULL;
424
425 /* Check whether there are sufficient src resources to meet request. */
426 spin_lock_irqsave(&mgr->mgr_lock, flags);
427 if (MEMRD == desc->mode)
428 err = mgr_get_resource(&mgr->mgr, desc->multi, &idx);
429 else
430 err = mgr_get_resource(&mgr->mgr, 1, &idx);
431
432 spin_unlock_irqrestore(&mgr->mgr_lock, flags);
433 if (err) {
434 printk(KERN_ERR "Can't meet SRC resource request!\n");
435 return err;
436 }
437
438 /* Allocate mem for master src resource */
439 if (MEMRD == desc->mode)
440 src = kzalloc(sizeof(*src)*desc->multi, GFP_KERNEL);
441 else
442 src = kzalloc(sizeof(*src), GFP_KERNEL);
443
444 if (NULL == src) {
445 err = -ENOMEM;
446 goto error1;
447 }
448
449 err = src_rsc_init(src, idx, desc, mgr);
450 if (err)
451 goto error2;
452
453 *rsrc = src;
454
455 return 0;
456
457error2:
458 kfree(src);
459error1:
460 spin_lock_irqsave(&mgr->mgr_lock, flags);
461 if (MEMRD == desc->mode)
462 mgr_put_resource(&mgr->mgr, desc->multi, idx);
463 else
464 mgr_put_resource(&mgr->mgr, 1, idx);
465
466 spin_unlock_irqrestore(&mgr->mgr_lock, flags);
467 return err;
468}
469
470static int put_src_rsc(struct src_mgr *mgr, struct src *src)
471{
472 unsigned long flags;
473
474 spin_lock_irqsave(&mgr->mgr_lock, flags);
475 src->rsc.ops->master(&src->rsc);
476 if (MEMRD == src->mode)
477 mgr_put_resource(&mgr->mgr, src->multi,
478 src->rsc.ops->index(&src->rsc));
479 else
480 mgr_put_resource(&mgr->mgr, 1, src->rsc.ops->index(&src->rsc));
481
482 spin_unlock_irqrestore(&mgr->mgr_lock, flags);
483 src_rsc_uninit(src, mgr);
484 kfree(src);
485
486 return 0;
487}
488
489static int src_enable_s(struct src_mgr *mgr, struct src *src)
490{
491 struct hw *hw = mgr->mgr.hw;
492 int i = 0;
493
494 src->rsc.ops->master(&src->rsc);
495 for (i = 0; i < src->rsc.msr; i++) {
496 hw->src_mgr_enbs_src(mgr->mgr.ctrl_blk,
497 src->rsc.ops->index(&src->rsc));
498 src->rsc.ops->next_conj(&src->rsc);
499 }
500 src->rsc.ops->master(&src->rsc);
501
502 return 0;
503}
504
505static int src_enable(struct src_mgr *mgr, struct src *src)
506{
507 struct hw *hw = mgr->mgr.hw;
508 int i = 0;
509
510 src->rsc.ops->master(&src->rsc);
511 for (i = 0; i < src->rsc.msr; i++) {
512 hw->src_mgr_enb_src(mgr->mgr.ctrl_blk,
513 src->rsc.ops->index(&src->rsc));
514 src->rsc.ops->next_conj(&src->rsc);
515 }
516 src->rsc.ops->master(&src->rsc);
517
518 return 0;
519}
520
521static int src_disable(struct src_mgr *mgr, struct src *src)
522{
523 struct hw *hw = mgr->mgr.hw;
524 int i = 0;
525
526 src->rsc.ops->master(&src->rsc);
527 for (i = 0; i < src->rsc.msr; i++) {
528 hw->src_mgr_dsb_src(mgr->mgr.ctrl_blk,
529 src->rsc.ops->index(&src->rsc));
530 src->rsc.ops->next_conj(&src->rsc);
531 }
532 src->rsc.ops->master(&src->rsc);
533
534 return 0;
535}
536
537static int src_mgr_commit_write(struct src_mgr *mgr)
538{
539 struct hw *hw = mgr->mgr.hw;
540
541 hw->src_mgr_commit_write(hw, mgr->mgr.ctrl_blk);
542
543 return 0;
544}
545
546int src_mgr_create(void *hw, struct src_mgr **rsrc_mgr)
547{
548 int err = 0, i = 0;
549 struct src_mgr *src_mgr;
550
551 *rsrc_mgr = NULL;
552 src_mgr = kzalloc(sizeof(*src_mgr), GFP_KERNEL);
553 if (NULL == src_mgr)
554 return -ENOMEM;
555
556 err = rsc_mgr_init(&src_mgr->mgr, SRC, SRC_RESOURCE_NUM, hw);
557 if (err)
558 goto error1;
559
560 spin_lock_init(&src_mgr->mgr_lock);
561 conj_mask = ((struct hw *)hw)->src_dirty_conj_mask();
562
563 src_mgr->get_src = get_src_rsc;
564 src_mgr->put_src = put_src_rsc;
565 src_mgr->src_enable_s = src_enable_s;
566 src_mgr->src_enable = src_enable;
567 src_mgr->src_disable = src_disable;
568 src_mgr->commit_write = src_mgr_commit_write;
569
570 /* Disable all SRC resources. */
571 for (i = 0; i < 256; i++)
572 ((struct hw *)hw)->src_mgr_dsb_src(src_mgr->mgr.ctrl_blk, i);
573
574 ((struct hw *)hw)->src_mgr_commit_write(hw, src_mgr->mgr.ctrl_blk);
575
576 *rsrc_mgr = src_mgr;
577
578 return 0;
579
580error1:
581 kfree(src_mgr);
582 return err;
583}
584
585int src_mgr_destroy(struct src_mgr *src_mgr)
586{
587 rsc_mgr_uninit(&src_mgr->mgr);
588 kfree(src_mgr);
589
590 return 0;
591}
592
593/* SRCIMP resource manager operations */
594
595static int srcimp_master(struct rsc *rsc)
596{
597 rsc->conj = 0;
598 return rsc->idx = container_of(rsc, struct srcimp, rsc)->idx[0];
599}
600
601static int srcimp_next_conj(struct rsc *rsc)
602{
603 rsc->conj++;
604 return container_of(rsc, struct srcimp, rsc)->idx[rsc->conj];
605}
606
607static int srcimp_index(const struct rsc *rsc)
608{
609 return container_of(rsc, struct srcimp, rsc)->idx[rsc->conj];
610}
611
612static struct rsc_ops srcimp_basic_rsc_ops = {
613 .master = srcimp_master,
614 .next_conj = srcimp_next_conj,
615 .index = srcimp_index,
616 .output_slot = NULL,
617};
618
619static int srcimp_map(struct srcimp *srcimp, struct src *src, struct rsc *input)
620{
621 struct imapper *entry = NULL;
622 int i = 0;
623
624 srcimp->rsc.ops->master(&srcimp->rsc);
625 src->rsc.ops->master(&src->rsc);
626 input->ops->master(input);
627
628 /* Program master and conjugate resources */
629 for (i = 0; i < srcimp->rsc.msr; i++) {
630 entry = &srcimp->imappers[i];
631 entry->slot = input->ops->output_slot(input);
632 entry->user = src->rsc.ops->index(&src->rsc);
633 entry->addr = srcimp->rsc.ops->index(&srcimp->rsc);
634 srcimp->mgr->imap_add(srcimp->mgr, entry);
635 srcimp->mapped |= (0x1 << i);
636
637 srcimp->rsc.ops->next_conj(&srcimp->rsc);
638 input->ops->next_conj(input);
639 }
640
641 srcimp->rsc.ops->master(&srcimp->rsc);
642 input->ops->master(input);
643
644 return 0;
645}
646
647static int srcimp_unmap(struct srcimp *srcimp)
648{
649 int i = 0;
650
651 /* Program master and conjugate resources */
652 for (i = 0; i < srcimp->rsc.msr; i++) {
653 if (srcimp->mapped & (0x1 << i)) {
654 srcimp->mgr->imap_delete(srcimp->mgr,
655 &srcimp->imappers[i]);
656 srcimp->mapped &= ~(0x1 << i);
657 }
658 }
659
660 return 0;
661}
662
663static struct srcimp_rsc_ops srcimp_ops = {
664 .map = srcimp_map,
665 .unmap = srcimp_unmap
666};
667
668static int srcimp_rsc_init(struct srcimp *srcimp,
669 const struct srcimp_desc *desc,
670 struct srcimp_mgr *mgr)
671{
672 int err = 0;
673
674 err = rsc_init(&srcimp->rsc, srcimp->idx[0],
675 SRCIMP, desc->msr, mgr->mgr.hw);
676 if (err)
677 return err;
678
679 /* Reserve memory for imapper nodes */
680 srcimp->imappers = kzalloc(sizeof(struct imapper)*desc->msr,
681 GFP_KERNEL);
682 if (NULL == srcimp->imappers) {
683 err = -ENOMEM;
684 goto error1;
685 }
686
687 /* Set srcimp specific operations */
688 srcimp->rsc.ops = &srcimp_basic_rsc_ops;
689 srcimp->ops = &srcimp_ops;
690 srcimp->mgr = mgr;
691
692 srcimp->rsc.ops->master(&srcimp->rsc);
693
694 return 0;
695
696error1:
697 rsc_uninit(&srcimp->rsc);
698 return err;
699}
700
701static int srcimp_rsc_uninit(struct srcimp *srcimp)
702{
703 if (NULL != srcimp->imappers) {
704 kfree(srcimp->imappers);
705 srcimp->imappers = NULL;
706 }
707 srcimp->ops = NULL;
708 srcimp->mgr = NULL;
709 rsc_uninit(&srcimp->rsc);
710
711 return 0;
712}
713
714static int get_srcimp_rsc(struct srcimp_mgr *mgr,
715 const struct srcimp_desc *desc,
716 struct srcimp **rsrcimp)
717{
718 int err = 0, i = 0;
719 unsigned int idx = 0;
720 struct srcimp *srcimp = NULL;
721 unsigned long flags;
722
723 *rsrcimp = NULL;
724
725 /* Allocate mem for SRCIMP resource */
726 srcimp = kzalloc(sizeof(*srcimp), GFP_KERNEL);
727 if (NULL == srcimp) {
728 err = -ENOMEM;
729 return err;
730 }
731
732 /* Check whether there are sufficient SRCIMP resources. */
733 spin_lock_irqsave(&mgr->mgr_lock, flags);
734 for (i = 0; i < desc->msr; i++) {
735 err = mgr_get_resource(&mgr->mgr, 1, &idx);
736 if (err)
737 break;
738
739 srcimp->idx[i] = idx;
740 }
741 spin_unlock_irqrestore(&mgr->mgr_lock, flags);
742 if (err) {
743 printk(KERN_ERR "Can't meet SRCIMP resource request!\n");
744 goto error1;
745 }
746
747 err = srcimp_rsc_init(srcimp, desc, mgr);
748 if (err)
749 goto error1;
750
751 *rsrcimp = srcimp;
752
753 return 0;
754
755error1:
756 spin_lock_irqsave(&mgr->mgr_lock, flags);
757 for (i--; i >= 0; i--)
758 mgr_put_resource(&mgr->mgr, 1, srcimp->idx[i]);
759
760 spin_unlock_irqrestore(&mgr->mgr_lock, flags);
761 kfree(srcimp);
762 return err;
763}
764
765static int put_srcimp_rsc(struct srcimp_mgr *mgr, struct srcimp *srcimp)
766{
767 unsigned long flags;
768 int i = 0;
769
770 spin_lock_irqsave(&mgr->mgr_lock, flags);
771 for (i = 0; i < srcimp->rsc.msr; i++)
772 mgr_put_resource(&mgr->mgr, 1, srcimp->idx[i]);
773
774 spin_unlock_irqrestore(&mgr->mgr_lock, flags);
775 srcimp_rsc_uninit(srcimp);
776 kfree(srcimp);
777
778 return 0;
779}
780
781static int srcimp_map_op(void *data, struct imapper *entry)
782{
783 struct rsc_mgr *mgr = &((struct srcimp_mgr *)data)->mgr;
784 struct hw *hw = mgr->hw;
785
786 hw->srcimp_mgr_set_imaparc(mgr->ctrl_blk, entry->slot);
787 hw->srcimp_mgr_set_imapuser(mgr->ctrl_blk, entry->user);
788 hw->srcimp_mgr_set_imapnxt(mgr->ctrl_blk, entry->next);
789 hw->srcimp_mgr_set_imapaddr(mgr->ctrl_blk, entry->addr);
790 hw->srcimp_mgr_commit_write(mgr->hw, mgr->ctrl_blk);
791
792 return 0;
793}
794
795static int srcimp_imap_add(struct srcimp_mgr *mgr, struct imapper *entry)
796{
797 unsigned long flags;
798 int err = 0;
799
800 spin_lock_irqsave(&mgr->imap_lock, flags);
801 if ((0 == entry->addr) && (mgr->init_imap_added)) {
802 input_mapper_delete(&mgr->imappers,
803 mgr->init_imap, srcimp_map_op, mgr);
804 mgr->init_imap_added = 0;
805 }
806 err = input_mapper_add(&mgr->imappers, entry, srcimp_map_op, mgr);
807 spin_unlock_irqrestore(&mgr->imap_lock, flags);
808
809 return err;
810}
811
812static int srcimp_imap_delete(struct srcimp_mgr *mgr, struct imapper *entry)
813{
814 unsigned long flags;
815 int err = 0;
816
817 spin_lock_irqsave(&mgr->imap_lock, flags);
818 err = input_mapper_delete(&mgr->imappers, entry, srcimp_map_op, mgr);
819 if (list_empty(&mgr->imappers)) {
820 input_mapper_add(&mgr->imappers, mgr->init_imap,
821 srcimp_map_op, mgr);
822 mgr->init_imap_added = 1;
823 }
824 spin_unlock_irqrestore(&mgr->imap_lock, flags);
825
826 return err;
827}
828
829int srcimp_mgr_create(void *hw, struct srcimp_mgr **rsrcimp_mgr)
830{
831 int err = 0;
832 struct srcimp_mgr *srcimp_mgr;
833 struct imapper *entry;
834
835 *rsrcimp_mgr = NULL;
836 srcimp_mgr = kzalloc(sizeof(*srcimp_mgr), GFP_KERNEL);
837 if (NULL == srcimp_mgr)
838 return -ENOMEM;
839
840 err = rsc_mgr_init(&srcimp_mgr->mgr, SRCIMP, SRCIMP_RESOURCE_NUM, hw);
841 if (err)
842 goto error1;
843
844 spin_lock_init(&srcimp_mgr->mgr_lock);
845 spin_lock_init(&srcimp_mgr->imap_lock);
846 INIT_LIST_HEAD(&srcimp_mgr->imappers);
847 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
848 if (NULL == entry) {
849 err = -ENOMEM;
850 goto error2;
851 }
852 entry->slot = entry->addr = entry->next = entry->user = 0;
853 list_add(&entry->list, &srcimp_mgr->imappers);
854 srcimp_mgr->init_imap = entry;
855 srcimp_mgr->init_imap_added = 1;
856
857 srcimp_mgr->get_srcimp = get_srcimp_rsc;
858 srcimp_mgr->put_srcimp = put_srcimp_rsc;
859 srcimp_mgr->imap_add = srcimp_imap_add;
860 srcimp_mgr->imap_delete = srcimp_imap_delete;
861
862 *rsrcimp_mgr = srcimp_mgr;
863
864 return 0;
865
866error2:
867 rsc_mgr_uninit(&srcimp_mgr->mgr);
868error1:
869 kfree(srcimp_mgr);
870 return err;
871}
872
873int srcimp_mgr_destroy(struct srcimp_mgr *srcimp_mgr)
874{
875 unsigned long flags;
876
877 /* free src input mapper list */
878 spin_lock_irqsave(&srcimp_mgr->imap_lock, flags);
879 free_input_mapper_list(&srcimp_mgr->imappers);
880 spin_unlock_irqrestore(&srcimp_mgr->imap_lock, flags);
881
882 rsc_mgr_uninit(&srcimp_mgr->mgr);
883 kfree(srcimp_mgr);
884
885 return 0;
886}
diff --git a/sound/pci/ctxfi/ctsrc.h b/sound/pci/ctxfi/ctsrc.h
new file mode 100644
index 000000000000..259366aabcac
--- /dev/null
+++ b/sound/pci/ctxfi/ctsrc.h
@@ -0,0 +1,149 @@
1/**
2 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
3 *
4 * This source file is released under GPL v2 license (no other versions).
5 * See the COPYING file included in the main directory of this source
6 * distribution for the license terms and conditions.
7 *
8 * @File ctsrc.h
9 *
10 * @Brief
11 * This file contains the definition of the Sample Rate Convertor
12 * resource management object.
13 *
14 * @Author Liu Chun
15 * @Date May 13 2008
16 *
17 */
18
19#ifndef CTSRC_H
20#define CTSRC_H
21
22#include "ctresource.h"
23#include "ctimap.h"
24#include <linux/spinlock.h>
25#include <linux/list.h>
26
27#define SRC_STATE_OFF 0x0
28#define SRC_STATE_INIT 0x4
29#define SRC_STATE_RUN 0x5
30
31#define SRC_SF_U8 0x0
32#define SRC_SF_S16 0x1
33#define SRC_SF_S24 0x2
34#define SRC_SF_S32 0x3
35#define SRC_SF_F32 0x4
36
37/* Define the descriptor of a src resource */
38enum SRCMODE {
39 MEMRD, /* Read data from host memory */
40 MEMWR, /* Write data to host memory */
41 ARCRW, /* Read from and write to audio ring channel */
42 NUM_SRCMODES
43};
44
45struct src_rsc_ops;
46
47struct src {
48 struct rsc rsc; /* Basic resource info */
49 struct src *intlv; /* Pointer to next interleaved SRC in a series */
50 struct src_rsc_ops *ops; /* SRC specific operations */
51 /* Number of contiguous srcs for interleaved usage */
52 unsigned char multi;
53 unsigned char mode; /* Working mode of this SRC resource */
54};
55
56struct src_rsc_ops {
57 int (*set_state)(struct src *src, unsigned int state);
58 int (*set_bm)(struct src *src, unsigned int bm);
59 int (*set_sf)(struct src *src, unsigned int sf);
60 int (*set_pm)(struct src *src, unsigned int pm);
61 int (*set_rom)(struct src *src, unsigned int rom);
62 int (*set_vo)(struct src *src, unsigned int vo);
63 int (*set_st)(struct src *src, unsigned int st);
64 int (*set_bp)(struct src *src, unsigned int bp);
65 int (*set_cisz)(struct src *src, unsigned int cisz);
66 int (*set_ca)(struct src *src, unsigned int ca);
67 int (*set_sa)(struct src *src, unsigned int sa);
68 int (*set_la)(struct src *src, unsigned int la);
69 int (*set_pitch)(struct src *src, unsigned int pitch);
70 int (*set_clr_zbufs)(struct src *src);
71 int (*commit_write)(struct src *src);
72 int (*get_ca)(struct src *src);
73 int (*init)(struct src *src);
74 struct src* (*next_interleave)(struct src *src);
75};
76
77/* Define src resource request description info */
78struct src_desc {
79 /* Number of contiguous master srcs for interleaved usage */
80 unsigned char multi;
81 unsigned char msr;
82 unsigned char mode; /* Working mode of the requested srcs */
83};
84
85/* Define src manager object */
86struct src_mgr {
87 struct rsc_mgr mgr; /* Basic resource manager info */
88 spinlock_t mgr_lock;
89
90 /* request src resource */
91 int (*get_src)(struct src_mgr *mgr,
92 const struct src_desc *desc, struct src **rsrc);
93 /* return src resource */
94 int (*put_src)(struct src_mgr *mgr, struct src *src);
95 int (*src_enable_s)(struct src_mgr *mgr, struct src *src);
96 int (*src_enable)(struct src_mgr *mgr, struct src *src);
97 int (*src_disable)(struct src_mgr *mgr, struct src *src);
98 int (*commit_write)(struct src_mgr *mgr);
99};
100
101/* Define the descriptor of a SRC Input Mapper resource */
102struct srcimp_mgr;
103struct srcimp_rsc_ops;
104
105struct srcimp {
106 struct rsc rsc;
107 unsigned char idx[8];
108 struct imapper *imappers;
109 unsigned int mapped; /* A bit-map indicating which conj rsc is mapped */
110 struct srcimp_mgr *mgr;
111 struct srcimp_rsc_ops *ops;
112};
113
114struct srcimp_rsc_ops {
115 int (*map)(struct srcimp *srcimp, struct src *user, struct rsc *input);
116 int (*unmap)(struct srcimp *srcimp);
117};
118
119/* Define SRCIMP resource request description info */
120struct srcimp_desc {
121 unsigned int msr;
122};
123
124struct srcimp_mgr {
125 struct rsc_mgr mgr; /* Basic resource manager info */
126 spinlock_t mgr_lock;
127 spinlock_t imap_lock;
128 struct list_head imappers;
129 struct imapper *init_imap;
130 unsigned int init_imap_added;
131
132 /* request srcimp resource */
133 int (*get_srcimp)(struct srcimp_mgr *mgr,
134 const struct srcimp_desc *desc,
135 struct srcimp **rsrcimp);
136 /* return srcimp resource */
137 int (*put_srcimp)(struct srcimp_mgr *mgr, struct srcimp *srcimp);
138 int (*imap_add)(struct srcimp_mgr *mgr, struct imapper *entry);
139 int (*imap_delete)(struct srcimp_mgr *mgr, struct imapper *entry);
140};
141
142/* Constructor and destructor of SRC resource manager */
143int src_mgr_create(void *hw, struct src_mgr **rsrc_mgr);
144int src_mgr_destroy(struct src_mgr *src_mgr);
145/* Constructor and destructor of SRCIMP resource manager */
146int srcimp_mgr_create(void *hw, struct srcimp_mgr **rsrc_mgr);
147int srcimp_mgr_destroy(struct srcimp_mgr *srcimp_mgr);
148
149#endif /* CTSRC_H */
diff --git a/sound/pci/ctxfi/ctvmem.c b/sound/pci/ctxfi/ctvmem.c
new file mode 100644
index 000000000000..46ca04ce9210
--- /dev/null
+++ b/sound/pci/ctxfi/ctvmem.c
@@ -0,0 +1,254 @@
1/**
2 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
3 *
4 * This source file is released under GPL v2 license (no other versions).
5 * See the COPYING file included in the main directory of this source
6 * distribution for the license terms and conditions.
7 *
8 * @File ctvmem.c
9 *
10 * @Brief
11 * This file contains the implementation of virtual memory management object
12 * for card device.
13 *
14 * @Author Liu Chun
15 * @Date Apr 1 2008
16 */
17
18#include "ctvmem.h"
19#include <linux/slab.h>
20#include <linux/mm.h>
21#include <asm/page.h> /* for PAGE_SIZE macro definition */
22#include <linux/io.h>
23#include <asm/pgtable.h>
24
25#define CT_PTES_PER_PAGE (PAGE_SIZE / sizeof(void *))
26#define CT_ADDRS_PER_PAGE (CT_PTES_PER_PAGE * PAGE_SIZE)
27
28/* *
29 * Find or create vm block based on requested @size.
30 * @size must be page aligned.
31 * */
32static struct ct_vm_block *
33get_vm_block(struct ct_vm *vm, unsigned int size)
34{
35 struct ct_vm_block *block = NULL, *entry = NULL;
36 struct list_head *pos = NULL;
37
38 list_for_each(pos, &vm->unused) {
39 entry = list_entry(pos, struct ct_vm_block, list);
40 if (entry->size >= size)
41 break; /* found a block that is big enough */
42 }
43 if (pos == &vm->unused)
44 return NULL;
45
46 if (entry->size == size) {
47 /* Move the vm node from unused list to used list directly */
48 list_del(&entry->list);
49 list_add(&entry->list, &vm->used);
50 vm->size -= size;
51 return entry;
52 }
53
54 block = kzalloc(sizeof(*block), GFP_KERNEL);
55 if (NULL == block)
56 return NULL;
57
58 block->addr = entry->addr;
59 block->size = size;
60 list_add(&block->list, &vm->used);
61 entry->addr += size;
62 entry->size -= size;
63 vm->size -= size;
64
65 return block;
66}
67
68static void put_vm_block(struct ct_vm *vm, struct ct_vm_block *block)
69{
70 struct ct_vm_block *entry = NULL, *pre_ent = NULL;
71 struct list_head *pos = NULL, *pre = NULL;
72
73 list_del(&block->list);
74 vm->size += block->size;
75
76 list_for_each(pos, &vm->unused) {
77 entry = list_entry(pos, struct ct_vm_block, list);
78 if (entry->addr >= (block->addr + block->size))
79 break; /* found a position */
80 }
81 if (pos == &vm->unused) {
82 list_add_tail(&block->list, &vm->unused);
83 entry = block;
84 } else {
85 if ((block->addr + block->size) == entry->addr) {
86 entry->addr = block->addr;
87 entry->size += block->size;
88 kfree(block);
89 } else {
90 __list_add(&block->list, pos->prev, pos);
91 entry = block;
92 }
93 }
94
95 pos = &entry->list;
96 pre = pos->prev;
97 while (pre != &vm->unused) {
98 entry = list_entry(pos, struct ct_vm_block, list);
99 pre_ent = list_entry(pre, struct ct_vm_block, list);
100 if ((pre_ent->addr + pre_ent->size) > entry->addr)
101 break;
102
103 pre_ent->size += entry->size;
104 list_del(pos);
105 kfree(entry);
106 pos = pre;
107 pre = pos->prev;
108 }
109}
110
111/* Map host addr (kmalloced/vmalloced) to device logical addr. */
112static struct ct_vm_block *
113ct_vm_map(struct ct_vm *vm, void *host_addr, int size)
114{
115 struct ct_vm_block *block = NULL;
116 unsigned long pte_start;
117 unsigned long i;
118 unsigned long pages;
119 unsigned long start_phys;
120 unsigned long *ptp;
121
122 /* do mapping */
123 if ((unsigned long)host_addr >= VMALLOC_START) {
124 printk(KERN_ERR "Fail! Not support vmalloced addr now!\n");
125 return NULL;
126 }
127
128 if (size > vm->size) {
129 printk(KERN_ERR "Fail! No sufficient device virtural "
130 "memory space available!\n");
131 return NULL;
132 }
133
134 start_phys = (virt_to_phys(host_addr) & PAGE_MASK);
135 pages = (PAGE_ALIGN(virt_to_phys(host_addr) + size)
136 - start_phys) >> PAGE_SHIFT;
137
138 ptp = vm->ptp[0];
139
140 block = get_vm_block(vm, (pages << PAGE_SHIFT));
141 if (block == NULL) {
142 printk(KERN_ERR "No virtual memory block that is big "
143 "enough to allocate!\n");
144 return NULL;
145 }
146
147 pte_start = (block->addr >> PAGE_SHIFT);
148 for (i = 0; i < pages; i++)
149 ptp[pte_start+i] = start_phys + (i << PAGE_SHIFT);
150
151 block->addr += (virt_to_phys(host_addr) & (~PAGE_MASK));
152 block->size = size;
153
154 return block;
155}
156
157static void ct_vm_unmap(struct ct_vm *vm, struct ct_vm_block *block)
158{
159 /* do unmapping */
160 block->size = ((block->addr + block->size + PAGE_SIZE - 1)
161 & PAGE_MASK) - (block->addr & PAGE_MASK);
162 block->addr &= PAGE_MASK;
163 put_vm_block(vm, block);
164}
165
166/* *
167 * return the host (kmalloced) addr of the @index-th device
168 * page talbe page on success, or NULL on failure.
169 * The first returned NULL indicates the termination.
170 * */
171static void *
172ct_get_ptp_virt(struct ct_vm *vm, int index)
173{
174 void *addr;
175
176 addr = (index >= CT_PTP_NUM) ? NULL : vm->ptp[index];
177
178 return addr;
179}
180
181int ct_vm_create(struct ct_vm **rvm)
182{
183 struct ct_vm *vm;
184 struct ct_vm_block *block;
185 int i;
186
187 *rvm = NULL;
188
189 vm = kzalloc(sizeof(*vm), GFP_KERNEL);
190 if (NULL == vm)
191 return -ENOMEM;
192
193 /* Allocate page table pages */
194 for (i = 0; i < CT_PTP_NUM; i++) {
195 vm->ptp[i] = kmalloc(PAGE_SIZE, GFP_KERNEL);
196 if (NULL == vm->ptp[i])
197 break;
198 }
199 if (!i) {
200 /* no page table pages are allocated */
201 kfree(vm);
202 return -ENOMEM;
203 }
204 vm->size = CT_ADDRS_PER_PAGE * i;
205 /* Initialise remaining ptps */
206 for (; i < CT_PTP_NUM; i++)
207 vm->ptp[i] = NULL;
208
209 vm->map = ct_vm_map;
210 vm->unmap = ct_vm_unmap;
211 vm->get_ptp_virt = ct_get_ptp_virt;
212 INIT_LIST_HEAD(&vm->unused);
213 INIT_LIST_HEAD(&vm->used);
214 block = kzalloc(sizeof(*block), GFP_KERNEL);
215 if (NULL != block) {
216 block->addr = 0;
217 block->size = vm->size;
218 list_add(&block->list, &vm->unused);
219 }
220
221 *rvm = vm;
222 return 0;
223}
224
225/* The caller must ensure no mapping pages are being used
226 * by hardware before calling this function */
227void ct_vm_destroy(struct ct_vm *vm)
228{
229 int i;
230 struct list_head *pos = NULL;
231 struct ct_vm_block *entry = NULL;
232
233 /* free used and unused list nodes */
234 while (!list_empty(&vm->used)) {
235 pos = vm->used.next;
236 list_del(pos);
237 entry = list_entry(pos, struct ct_vm_block, list);
238 kfree(entry);
239 }
240 while (!list_empty(&vm->unused)) {
241 pos = vm->unused.next;
242 list_del(pos);
243 entry = list_entry(pos, struct ct_vm_block, list);
244 kfree(entry);
245 }
246
247 /* free allocated page table pages */
248 for (i = 0; i < CT_PTP_NUM; i++)
249 kfree(vm->ptp[i]);
250
251 vm->size = 0;
252
253 kfree(vm);
254}
diff --git a/sound/pci/ctxfi/ctvmem.h b/sound/pci/ctxfi/ctvmem.h
new file mode 100644
index 000000000000..4eb5bdd5cad4
--- /dev/null
+++ b/sound/pci/ctxfi/ctvmem.h
@@ -0,0 +1,49 @@
1/**
2 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
3 *
4 * This source file is released under GPL v2 license (no other versions).
5 * See the COPYING file included in the main directory of this source
6 * distribution for the license terms and conditions.
7 *
8 * @File ctvmem.h
9 *
10 * @Brief
11 * This file contains the definition of virtual memory management object
12 * for card device.
13 *
14 * @Author Liu Chun
15 * @Date Mar 28 2008
16 */
17
18#ifndef CTVMEM_H
19#define CTVMEM_H
20
21#define CT_PTP_NUM 1 /* num of device page table pages */
22
23#include <linux/spinlock.h>
24#include <linux/list.h>
25
26struct ct_vm_block {
27 unsigned int addr; /* starting logical addr of this block */
28 unsigned int size; /* size of this device virtual mem block */
29 struct list_head list;
30};
31
32/* Virtual memory management object for card device */
33struct ct_vm {
34 void *ptp[CT_PTP_NUM]; /* Device page table pages */
35 unsigned int size; /* Available addr space in bytes */
36 struct list_head unused; /* List of unused blocks */
37 struct list_head used; /* List of used blocks */
38
39 /* Map host addr (kmalloced/vmalloced) to device logical addr. */
40 struct ct_vm_block *(*map)(struct ct_vm *, void *host_addr, int size);
41 /* Unmap device logical addr area. */
42 void (*unmap)(struct ct_vm *, struct ct_vm_block *block);
43 void *(*get_ptp_virt)(struct ct_vm *vm, int index);
44};
45
46int ct_vm_create(struct ct_vm **rvm);
47void ct_vm_destroy(struct ct_vm *vm);
48
49#endif /* CTVMEM_H */
diff --git a/sound/pci/ctxfi/xfi.c b/sound/pci/ctxfi/xfi.c
new file mode 100644
index 000000000000..f91144036512
--- /dev/null
+++ b/sound/pci/ctxfi/xfi.c
@@ -0,0 +1,125 @@
1/*
2 * xfi linux driver.
3 *
4 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
5 *
6 * This source file is released under GPL v2 license (no other versions).
7 * See the COPYING file included in the main directory of this source
8 * distribution for the license terms and conditions.
9 */
10
11#include <linux/init.h>
12#include <linux/pci.h>
13#include <linux/moduleparam.h>
14#include <sound/core.h>
15#include <sound/initval.h>
16#include "ctatc.h"
17#include "ctdrv.h"
18
19MODULE_AUTHOR("Creative Technology Ltd");
20MODULE_DESCRIPTION("X-Fi driver version 1.03");
21MODULE_LICENSE("GPLv2");
22MODULE_SUPPORTED_DEVICE("{{Creative Labs, Sound Blaster X-Fi}");
23
24static unsigned int reference_rate = 48000;
25static unsigned int multiple = 2;
26module_param(reference_rate, uint, S_IRUGO);
27module_param(multiple, uint, S_IRUGO);
28
29static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
30static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
31static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
32
33static struct pci_device_id ct_pci_dev_ids[] = {
34 /* only X-Fi is supported, so... */
35 { PCI_DEVICE(PCI_VENDOR_CREATIVE, PCI_DEVICE_CREATIVE_20K1) },
36 { PCI_DEVICE(PCI_VENDOR_CREATIVE, PCI_DEVICE_CREATIVE_20K2) },
37 { 0, }
38};
39MODULE_DEVICE_TABLE(pci, ct_pci_dev_ids);
40
41static int __devinit
42ct_card_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
43{
44 static int dev;
45 struct snd_card *card;
46 struct ct_atc *atc;
47 int err;
48
49 if (dev >= SNDRV_CARDS)
50 return -ENODEV;
51
52 if (!enable[dev]) {
53 dev++;
54 return -ENOENT;
55 }
56 err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
57 if (err)
58 return err;
59 if ((reference_rate != 48000) && (reference_rate != 44100)) {
60 printk(KERN_ERR "Invalid reference_rate value %u!!!\n"
61 "The valid values for reference_rate "
62 "are 48000 and 44100.\nValue 48000 is "
63 "assumed.\n", reference_rate);
64 reference_rate = 48000;
65 }
66 if ((multiple != 1) && (multiple != 2)) {
67 printk(KERN_ERR "Invalid multiple value %u!!!\nThe valid "
68 "values for multiple are 1 and 2.\nValue 2 "
69 "is assumed.\n", multiple);
70 multiple = 2;
71 }
72 err = ct_atc_create(card, pci, reference_rate, multiple, &atc);
73 if (err < 0)
74 goto error;
75
76 card->private_data = atc;
77
78 /* Create alsa devices supported by this card */
79 err = atc->create_alsa_devs(atc);
80 if (err < 0)
81 goto error;
82
83 strcpy(card->driver, "SB-XFi");
84 strcpy(card->shortname, "Creative X-Fi");
85 strcpy(card->longname, "Creative ALSA Driver X-Fi");
86
87 err = snd_card_register(card);
88 if (err < 0)
89 goto error;
90
91 pci_set_drvdata(pci, card);
92 dev++;
93
94 return 0;
95
96error:
97 snd_card_free(card);
98 return err;
99}
100
101static void __devexit ct_card_remove(struct pci_dev *pci)
102{
103 snd_card_free(pci_get_drvdata(pci));
104 pci_set_drvdata(pci, NULL);
105}
106
107static struct pci_driver ct_driver = {
108 .name = "SB-XFi",
109 .id_table = ct_pci_dev_ids,
110 .probe = ct_card_probe,
111 .remove = __devexit_p(ct_card_remove),
112};
113
114static int __init ct_card_init(void)
115{
116 return pci_register_driver(&ct_driver);
117}
118
119static void __exit ct_card_exit(void)
120{
121 pci_unregister_driver(&ct_driver);
122}
123
124module_init(ct_card_init)
125module_exit(ct_card_exit)