2 **********************************************************************
3 * mixer.c - /dev/mixer interface for emu10k1 driver
4 * Copyright 1999, 2000 Creative Labs, Inc.
6 **********************************************************************
8 * Date Author Summary of changes
9 * ---- ------ ------------------
10 * October 20, 1999 Bertrand Lee base code release
11 * November 2, 1999 Alan Cox cleaned up stuff
13 **********************************************************************
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License as
17 * published by the Free Software Foundation; either version 2 of
18 * the License, or (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public
26 * License along with this program; if not, write to the Free
27 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
30 **********************************************************************
33 #include <linux/module.h>
34 #include <asm/uaccess.h>
42 static const u32 bass_table
[41][5] = {
43 { 0x3e4f844f, 0x84ed4cc3, 0x3cc69927, 0x7b03553a, 0xc4da8486 },
44 { 0x3e69a17a, 0x84c280fb, 0x3cd77cd4, 0x7b2f2a6f, 0xc4b08d1d },
45 { 0x3e82ff42, 0x849991d5, 0x3ce7466b, 0x7b5917c6, 0xc48863ee },
46 { 0x3e9bab3c, 0x847267f0, 0x3cf5ffe8, 0x7b813560, 0xc461f22c },
47 { 0x3eb3b275, 0x844ced29, 0x3d03b295, 0x7ba79a1c, 0xc43d223b },
48 { 0x3ecb2174, 0x84290c8b, 0x3d106714, 0x7bcc5ba3, 0xc419dfa5 },
49 { 0x3ee2044b, 0x8406b244, 0x3d1c2561, 0x7bef8e77, 0xc3f8170f },
50 { 0x3ef86698, 0x83e5cb96, 0x3d26f4d8, 0x7c114600, 0xc3d7b625 },
51 { 0x3f0e5390, 0x83c646c9, 0x3d30dc39, 0x7c319498, 0xc3b8ab97 },
52 { 0x3f23d60b, 0x83a81321, 0x3d39e1af, 0x7c508b9c, 0xc39ae704 },
53 { 0x3f38f884, 0x838b20d2, 0x3d420ad2, 0x7c6e3b75, 0xc37e58f1 },
54 { 0x3f4dc52c, 0x836f60ef, 0x3d495cab, 0x7c8ab3a6, 0xc362f2be },
55 { 0x3f6245e8, 0x8354c565, 0x3d4fdbb8, 0x7ca602d6, 0xc348a69b },
56 { 0x3f76845f, 0x833b40ec, 0x3d558bf0, 0x7cc036df, 0xc32f677c },
57 { 0x3f8a8a03, 0x8322c6fb, 0x3d5a70c4, 0x7cd95cd7, 0xc317290b },
58 { 0x3f9e6014, 0x830b4bc3, 0x3d5e8d25, 0x7cf1811a, 0xc2ffdfa5 },
59 { 0x3fb20fae, 0x82f4c420, 0x3d61e37f, 0x7d08af56, 0xc2e9804a },
60 { 0x3fc5a1cc, 0x82df2592, 0x3d6475c3, 0x7d1ef294, 0xc2d40096 },
61 { 0x3fd91f55, 0x82ca6632, 0x3d664564, 0x7d345541, 0xc2bf56b9 },
62 { 0x3fec9120, 0x82b67cac, 0x3d675356, 0x7d48e138, 0xc2ab796e },
63 { 0x40000000, 0x82a36037, 0x3d67a012, 0x7d5c9fc9, 0xc2985fee },
64 { 0x401374c7, 0x8291088a, 0x3d672b93, 0x7d6f99c3, 0xc28601f2 },
65 { 0x4026f857, 0x827f6dd7, 0x3d65f559, 0x7d81d77c, 0xc27457a3 },
66 { 0x403a939f, 0x826e88c5, 0x3d63fc63, 0x7d9360d4, 0xc2635996 },
67 { 0x404e4faf, 0x825e5266, 0x3d613f32, 0x7da43d42, 0xc25300c6 },
68 { 0x406235ba, 0x824ec434, 0x3d5dbbc3, 0x7db473d7, 0xc243468e },
69 { 0x40764f1f, 0x823fd80c, 0x3d596f8f, 0x7dc40b44, 0xc23424a2 },
70 { 0x408aa576, 0x82318824, 0x3d545787, 0x7dd309e2, 0xc2259509 },
71 { 0x409f4296, 0x8223cf0b, 0x3d4e7012, 0x7de175b5, 0xc2179218 },
72 { 0x40b430a0, 0x8216a7a1, 0x3d47b505, 0x7def5475, 0xc20a1670 },
73 { 0x40c97a0a, 0x820a0d12, 0x3d4021a1, 0x7dfcab8d, 0xc1fd1cf5 },
74 { 0x40df29a6, 0x81fdfad6, 0x3d37b08d, 0x7e098028, 0xc1f0a0ca },
75 { 0x40f54ab1, 0x81f26ca9, 0x3d2e5bd1, 0x7e15d72b, 0xc1e49d52 },
76 { 0x410be8da, 0x81e75e89, 0x3d241cce, 0x7e21b544, 0xc1d90e24 },
77 { 0x41231051, 0x81dcccb3, 0x3d18ec37, 0x7e2d1ee6, 0xc1cdef10 },
78 { 0x413acdd0, 0x81d2b39e, 0x3d0cc20a, 0x7e38184e, 0xc1c33c13 },
79 { 0x41532ea7, 0x81c90ffb, 0x3cff9585, 0x7e42a58b, 0xc1b8f15a },
80 { 0x416c40cd, 0x81bfdeb2, 0x3cf15d21, 0x7e4cca7c, 0xc1af0b3f },
81 { 0x418612ea, 0x81b71cdc, 0x3ce20e85, 0x7e568ad3, 0xc1a58640 },
82 { 0x41a0b465, 0x81aec7c5, 0x3cd19e7c, 0x7e5fea1e, 0xc19c5f03 },
83 { 0x41bc3573, 0x81a6dcea, 0x3cc000e9, 0x7e68ebc2, 0xc1939250 }
86 static const u32 treble_table
[41][5] = {
87 { 0x0125cba9, 0xfed5debd, 0x00599b6c, 0x0d2506da, 0xfa85b354 },
88 { 0x0142f67e, 0xfeb03163, 0x0066cd0f, 0x0d14c69d, 0xfa914473 },
89 { 0x016328bd, 0xfe860158, 0x0075b7f2, 0x0d03eb27, 0xfa9d32d2 },
90 { 0x0186b438, 0xfe56c982, 0x00869234, 0x0cf27048, 0xfaa97fca },
91 { 0x01adf358, 0xfe21f5fe, 0x00999842, 0x0ce051c2, 0xfab62ca5 },
92 { 0x01d949fa, 0xfde6e287, 0x00af0d8d, 0x0ccd8b4a, 0xfac33aa7 },
93 { 0x02092669, 0xfda4d8bf, 0x00c73d4c, 0x0cba1884, 0xfad0ab07 },
94 { 0x023e0268, 0xfd5b0e4a, 0x00e27b54, 0x0ca5f509, 0xfade7ef2 },
95 { 0x0278645c, 0xfd08a2b0, 0x01012509, 0x0c911c63, 0xfaecb788 },
96 { 0x02b8e091, 0xfcac9d1a, 0x0123a262, 0x0c7b8a14, 0xfafb55df },
97 { 0x03001a9a, 0xfc45e9ce, 0x014a6709, 0x0c65398f, 0xfb0a5aff },
98 { 0x034ec6d7, 0xfbd3576b, 0x0175f397, 0x0c4e2643, 0xfb19c7e4 },
99 { 0x03a5ac15, 0xfb5393ee, 0x01a6d6ed, 0x0c364b94, 0xfb299d7c },
100 { 0x0405a562, 0xfac52968, 0x01ddafae, 0x0c1da4e2, 0xfb39dca5 },
101 { 0x046fa3fe, 0xfa267a66, 0x021b2ddd, 0x0c042d8d, 0xfb4a8631 },
102 { 0x04e4b17f, 0xf975be0f, 0x0260149f, 0x0be9e0f2, 0xfb5b9ae0 },
103 { 0x0565f220, 0xf8b0fbe5, 0x02ad3c29, 0x0bceba73, 0xfb6d1b60 },
104 { 0x05f4a745, 0xf7d60722, 0x030393d4, 0x0bb2b578, 0xfb7f084d },
105 { 0x06923236, 0xf6e279bd, 0x03642465, 0x0b95cd75, 0xfb916233 },
106 { 0x07401713, 0xf5d3aef9, 0x03d01283, 0x0b77fded, 0xfba42984 },
107 { 0x08000000, 0xf4a6bd88, 0x0448a161, 0x0b594278, 0xfbb75e9f },
108 { 0x08d3c097, 0xf3587131, 0x04cf35a4, 0x0b3996c9, 0xfbcb01cb },
109 { 0x09bd59a2, 0xf1e543f9, 0x05655880, 0x0b18f6b2, 0xfbdf1333 },
110 { 0x0abefd0f, 0xf04956ca, 0x060cbb12, 0x0af75e2c, 0xfbf392e8 },
111 { 0x0bdb123e, 0xee806984, 0x06c739fe, 0x0ad4c962, 0xfc0880dd },
112 { 0x0d143a94, 0xec85d287, 0x0796e150, 0x0ab134b0, 0xfc1ddce5 },
113 { 0x0e6d5664, 0xea547598, 0x087df0a0, 0x0a8c9cb6, 0xfc33a6ad },
114 { 0x0fe98a2a, 0xe7e6ba35, 0x097edf83, 0x0a66fe5b, 0xfc49ddc2 },
115 { 0x118c4421, 0xe536813a, 0x0a9c6248, 0x0a4056d7, 0xfc608185 },
116 { 0x1359422e, 0xe23d19eb, 0x0bd96efb, 0x0a18a3bf, 0xfc77912c },
117 { 0x1554982b, 0xdef33645, 0x0d3942bd, 0x09efe312, 0xfc8f0bc1 },
118 { 0x1782b68a, 0xdb50deb1, 0x0ebf676d, 0x09c6133f, 0xfca6f019 },
119 { 0x19e8715d, 0xd74d64fd, 0x106fb999, 0x099b3337, 0xfcbf3cd6 },
120 { 0x1c8b07b8, 0xd2df56ab, 0x124e6ec8, 0x096f4274, 0xfcd7f060 },
121 { 0x1f702b6d, 0xcdfc6e92, 0x14601c10, 0x0942410b, 0xfcf108e5 },
122 { 0x229e0933, 0xc89985cd, 0x16a9bcfa, 0x09142fb5, 0xfd0a8451 },
123 { 0x261b5118, 0xc2aa8409, 0x1930bab6, 0x08e50fdc, 0xfd24604d },
124 { 0x29ef3f5d, 0xbc224f28, 0x1bfaf396, 0x08b4e3aa, 0xfd3e9a3b },
125 { 0x2e21a59b, 0xb4f2ba46, 0x1f0ec2d6, 0x0883ae15, 0xfd592f33 },
126 { 0x32baf44b, 0xad0c7429, 0x227308a3, 0x085172eb, 0xfd741bfd },
127 { 0x37c4448b, 0xa45ef51d, 0x262f3267, 0x081e36dc, 0xfd8f5d14 }
131 static void set_bass(struct emu10k1_card
*card
, int l
, int r
)
135 l
= (l
* 40 + 50) / 100;
136 r
= (r
* 40 + 50) / 100;
138 for (i
= 0; i
< 5; i
++)
139 sblive_writeptr(card
, (card
->is_audigy
? A_GPR_BASE
: GPR_BASE
) + card
->mgr
.ctrl_gpr
[SOUND_MIXER_BASS
][0] + i
, 0, bass_table
[l
][i
]);
142 static void set_treble(struct emu10k1_card
*card
, int l
, int r
)
146 l
= (l
* 40 + 50) / 100;
147 r
= (r
* 40 + 50) / 100;
149 for (i
= 0; i
< 5; i
++)
150 sblive_writeptr(card
, (card
->is_audigy
? A_GPR_BASE
: GPR_BASE
) + card
->mgr
.ctrl_gpr
[SOUND_MIXER_TREBLE
][0] + i
, 0, treble_table
[l
][i
]);
153 const char volume_params
[SOUND_MIXER_NRDEVICES
]= {
154 /* Used by the ac97 driver */
155 [SOUND_MIXER_VOLUME
] = VOL_6BIT
,
156 [SOUND_MIXER_BASS
] = VOL_4BIT
,
157 [SOUND_MIXER_TREBLE
] = VOL_4BIT
,
158 [SOUND_MIXER_PCM
] = VOL_5BIT
,
159 [SOUND_MIXER_SPEAKER
] = VOL_4BIT
,
160 [SOUND_MIXER_LINE
] = VOL_5BIT
,
161 [SOUND_MIXER_MIC
] = VOL_5BIT
,
162 [SOUND_MIXER_CD
] = VOL_5BIT
,
163 [SOUND_MIXER_ALTPCM
] = VOL_6BIT
,
164 [SOUND_MIXER_IGAIN
] = VOL_4BIT
,
165 [SOUND_MIXER_LINE1
] = VOL_5BIT
,
166 [SOUND_MIXER_PHONEIN
] = VOL_5BIT
,
167 [SOUND_MIXER_PHONEOUT
] = VOL_6BIT
,
168 [SOUND_MIXER_VIDEO
] = VOL_5BIT
,
169 /* Not used by the ac97 driver */
170 [SOUND_MIXER_SYNTH
] = VOL_5BIT
,
171 [SOUND_MIXER_IMIX
] = VOL_5BIT
,
172 [SOUND_MIXER_RECLEV
] = VOL_5BIT
,
173 [SOUND_MIXER_OGAIN
] = VOL_5BIT
,
174 [SOUND_MIXER_LINE2
] = VOL_5BIT
,
175 [SOUND_MIXER_LINE3
] = VOL_5BIT
,
176 [SOUND_MIXER_DIGITAL1
] = VOL_5BIT
,
177 [SOUND_MIXER_DIGITAL2
] = VOL_5BIT
,
178 [SOUND_MIXER_DIGITAL3
] = VOL_5BIT
,
179 [SOUND_MIXER_RADIO
] = VOL_5BIT
,
180 [SOUND_MIXER_MONITOR
] = VOL_5BIT
183 /* Mixer file operations */
184 static int emu10k1_private_mixer(struct emu10k1_card
*card
, unsigned int cmd
, unsigned long arg
)
186 struct mixer_private_ioctl
*ctl
;
187 struct dsp_patch
*patch
;
189 int addr
, size_reg
, i
, ret
;
191 void __user
*argp
= (void __user
*)arg
;
195 case SOUND_MIXER_PRIVATE3
:
197 ctl
= (struct mixer_private_ioctl
*) kmalloc(sizeof(struct mixer_private_ioctl
), GFP_KERNEL
);
201 if (copy_from_user(ctl
, argp
, sizeof(struct mixer_private_ioctl
))) {
210 emu10k1_writefn0_2(card
, ctl
->val
[0], ctl
->val
[1], ctl
->val
[2]);
215 if (ctl
->val
[1] >= 0x40 || ctl
->val
[0] >= 0x1000) {
217 if (ctl
->val
[1] >= 0x40 || ctl
->val
[0] >= 0x1000 || ((ctl
->val
[0] < 0x100 ) &&
218 //Any register allowed raw access goes here:
219 (ctl
->val
[0] != A_SPDIF_SAMPLERATE
) && (ctl
->val
[0] != A_DBG
)
226 sblive_writeptr(card
, ctl
->val
[0], ctl
->val
[1], ctl
->val
[2]);
230 ctl
->val
[2] = emu10k1_readfn0(card
, ctl
->val
[0]);
232 if (copy_to_user(argp
, ctl
, sizeof(struct mixer_private_ioctl
)))
238 if (ctl
->val
[1] >= 0x40 || (ctl
->val
[0] & 0x7ff) > 0xff) {
243 if ((ctl
->val
[0] & 0x7ff) > 0x3f)
246 ctl
->val
[2] = sblive_readptr(card
, ctl
->val
[0], ctl
->val
[1]);
248 if (copy_to_user(argp
, ctl
, sizeof(struct mixer_private_ioctl
)))
254 switch (ctl
->val
[0]) {
255 case WAVERECORD_AC97
:
261 card
->wavein
.recsrc
= WAVERECORD_AC97
;
265 card
->wavein
.recsrc
= WAVERECORD_MIC
;
269 card
->wavein
.recsrc
= WAVERECORD_FX
;
270 card
->wavein
.fxwc
= ctl
->val
[1] & 0xffff;
272 if (!card
->wavein
.fxwc
)
284 ctl
->val
[0] = card
->wavein
.recsrc
;
285 ctl
->val
[1] = card
->wavein
.fxwc
;
286 if (copy_to_user(argp
, ctl
, sizeof(struct mixer_private_ioctl
)))
291 case CMD_GETVOICEPARAM
:
292 ctl
->val
[0] = card
->waveout
.send_routing
[0];
293 ctl
->val
[1] = card
->waveout
.send_dcba
[0];
295 ctl
->val
[2] = card
->waveout
.send_routing
[1];
296 ctl
->val
[3] = card
->waveout
.send_dcba
[1];
298 ctl
->val
[4] = card
->waveout
.send_routing
[2];
299 ctl
->val
[5] = card
->waveout
.send_dcba
[2];
301 if (copy_to_user(argp
, ctl
, sizeof(struct mixer_private_ioctl
)))
306 case CMD_SETVOICEPARAM
:
307 card
->waveout
.send_routing
[0] = ctl
->val
[0];
308 card
->waveout
.send_dcba
[0] = ctl
->val
[1];
310 card
->waveout
.send_routing
[1] = ctl
->val
[2];
311 card
->waveout
.send_dcba
[1] = ctl
->val
[3];
313 card
->waveout
.send_routing
[2] = ctl
->val
[4];
314 card
->waveout
.send_dcba
[2] = ctl
->val
[5];
319 card
->mchannel_fx
= ctl
->val
[0] & 0x000f;
323 if (ctl
->val
[0] == 0) {
324 if (copy_to_user(argp
, &card
->mgr
.rpatch
, sizeof(struct dsp_rpatch
)))
327 if ((ctl
->val
[0] - 1) / PATCHES_PER_PAGE
>= card
->mgr
.current_pages
) {
332 if (copy_to_user(argp
, PATCH(&card
->mgr
, ctl
->val
[0] - 1), sizeof(struct dsp_patch
)))
346 if (copy_to_user(argp
, &card
->mgr
.gpr
[id
], sizeof(struct dsp_gpr
)))
352 addr
= emu10k1_find_control_gpr(&card
->mgr
, (char *) ctl
->val
, &((char *) ctl
->val
)[PATCH_NAME_SIZE
]);
353 ctl
->val
[0] = sblive_readptr(card
, addr
, 0);
355 if (copy_to_user(argp
, ctl
, sizeof(struct mixer_private_ioctl
)))
361 if (ctl
->val
[0] == 0)
362 memcpy(&card
->mgr
.rpatch
, &ctl
->val
[1], sizeof(struct dsp_rpatch
));
364 page
= (ctl
->val
[0] - 1) / PATCHES_PER_PAGE
;
365 if (page
> MAX_PATCHES_PAGES
) {
370 if (page
>= card
->mgr
.current_pages
) {
371 for (i
= card
->mgr
.current_pages
; i
< page
+ 1; i
++) {
372 card
->mgr
.patch
[i
] = (void *)__get_free_page(GFP_KERNEL
);
373 if(card
->mgr
.patch
[i
] == NULL
) {
374 card
->mgr
.current_pages
= i
;
378 memset(card
->mgr
.patch
[i
], 0, PAGE_SIZE
);
380 card
->mgr
.current_pages
= page
+ 1;
383 patch
= PATCH(&card
->mgr
, ctl
->val
[0] - 1);
385 memcpy(patch
, &ctl
->val
[1], sizeof(struct dsp_patch
));
387 if (patch
->code_size
== 0) {
388 for(i
= page
+ 1; i
< card
->mgr
.current_pages
; i
++)
389 free_page((unsigned long) card
->mgr
.patch
[i
]);
391 card
->mgr
.current_pages
= page
+ 1;
397 if (ctl
->val
[0] > NUM_GPRS
) {
402 memcpy(&card
->mgr
.gpr
[ctl
->val
[0]], &ctl
->val
[1], sizeof(struct dsp_gpr
));
406 addr
= emu10k1_find_control_gpr(&card
->mgr
, (char *) ctl
->val
, (char *) ctl
->val
+ PATCH_NAME_SIZE
);
407 emu10k1_set_control_gpr(card
, addr
, *((s32
*)((char *) ctl
->val
+ 2 * PATCH_NAME_SIZE
)), 0);
411 if ( ((ctl
->val
[0] > 2) && (!card
->is_audigy
))
412 || (ctl
->val
[0] > 15) || ctl
->val
[1] > 1) {
418 emu10k1_writefn0(card
, (1 << 24) | ((ctl
->val
[0]) << 16) | A_IOCFG
, ctl
->val
[1]);
420 emu10k1_writefn0(card
, (1 << 24) | (((ctl
->val
[0]) + 10) << 16) | HCFG
, ctl
->val
[1]);
427 if (id
>= SOUND_MIXER_NRDEVICES
|| ch
>= 2) {
432 ctl
->val
[2] = card
->mgr
.ctrl_gpr
[id
][ch
];
434 if (copy_to_user(argp
, ctl
, sizeof(struct mixer_private_ioctl
)))
441 /* 0 == left, 1 == right */
445 if (id
>= SOUND_MIXER_NRDEVICES
|| ch
>= 2) {
450 card
->mgr
.ctrl_gpr
[id
][ch
] = addr
;
456 unsigned int state
= card
->ac97
->mixer_state
[id
];
460 card
->ac97
->stereo_mixers
|= (1 << id
);
463 card
->ac97
->supported_mixers
|= (1 << id
);
465 if (id
== SOUND_MIXER_TREBLE
) {
466 set_treble(card
, card
->ac97
->mixer_state
[id
] & 0xff, (card
->ac97
->mixer_state
[id
] >> 8) & 0xff);
467 } else if (id
== SOUND_MIXER_BASS
) {
468 set_bass(card
, card
->ac97
->mixer_state
[id
] & 0xff, (card
->ac97
->mixer_state
[id
] >> 8) & 0xff);
470 emu10k1_set_volume_gpr(card
, addr
, state
& 0xff,
473 card
->ac97
->stereo_mixers
&= ~(1 << id
);
474 card
->ac97
->stereo_mixers
|= card
->ac97_stereo_mixers
;
477 card
->ac97
->supported_mixers
&= ~(1 << id
);
478 card
->ac97
->supported_mixers
|= card
->ac97_supported_mixers
;
483 case CMD_SETPASSTHROUGH
:
484 card
->pt
.selected
= ctl
->val
[0] ? 1 : 0;
485 if (card
->pt
.state
!= PT_STATE_INACTIVE
)
488 card
->pt
.spcs_to_use
= ctl
->val
[0] & 0x07;
491 case CMD_PRIVATE3_VERSION
:
492 ctl
->val
[0] = PRIVATE3_VERSION
; //private3 version
493 ctl
->val
[1] = MAJOR_VER
; //major driver version
494 ctl
->val
[2] = MINOR_VER
; //minor driver version
495 ctl
->val
[3] = card
->is_audigy
; //1=card is audigy
498 ctl
->val
[4]=emu10k1_readfn0(card
, 0x18);
500 if (copy_to_user(argp
, ctl
, sizeof(struct mixer_private_ioctl
)))
506 emu10k1_ac97_write(card
->ac97
, 0x18, 0x0);
508 emu10k1_ac97_write(card
->ac97
, 0x18, 0x0808);
519 case SOUND_MIXER_PRIVATE4
:
521 if (copy_from_user(&size
, argp
, sizeof(size
)))
524 DPD(2, "External tram size %#x\n", size
);
532 size
= (size
- 1) >> 14;
539 size
= 0x4000 << size_reg
;
542 DPD(2, "External tram size %#x %#x\n", size
, size_reg
);
544 if (size
!= card
->tankmem
.size
) {
545 if (card
->tankmem
.size
> 0) {
546 emu10k1_writefn0(card
, HCFG_LOCKTANKCACHE
, 1);
548 sblive_writeptr_tag(card
, 0, TCB
, 0, TCBS
, 0, TAGLIST_END
);
550 pci_free_consistent(card
->pci_dev
, card
->tankmem
.size
, card
->tankmem
.addr
, card
->tankmem
.dma_handle
);
552 card
->tankmem
.size
= 0;
556 card
->tankmem
.addr
= pci_alloc_consistent(card
->pci_dev
, size
, &card
->tankmem
.dma_handle
);
557 if (card
->tankmem
.addr
== NULL
)
560 card
->tankmem
.size
= size
;
562 sblive_writeptr_tag(card
, 0, TCB
, (u32
) card
->tankmem
.dma_handle
, TCBS
,(u32
) size_reg
, TAGLIST_END
);
564 emu10k1_writefn0(card
, HCFG_LOCKTANKCACHE
, 0);
577 static int emu10k1_dsp_mixer(struct emu10k1_card
*card
, unsigned int oss_mixer
, unsigned long arg
)
579 unsigned int left
, right
;
583 card
->ac97
->modcnt
++;
585 if (get_user(val
, (int __user
*)arg
))
588 /* cleanse input a little */
589 right
= ((val
>> 8) & 0xff);
592 if (right
> 100) right
= 100;
593 if (left
> 100) left
= 100;
595 card
->ac97
->mixer_state
[oss_mixer
] = (right
<< 8) | left
;
596 if (oss_mixer
== SOUND_MIXER_TREBLE
) {
597 set_treble(card
, left
, right
);
599 } if (oss_mixer
== SOUND_MIXER_BASS
) {
600 set_bass(card
, left
, right
);
604 if (oss_mixer
== SOUND_MIXER_VOLUME
)
605 scale
= 1 << card
->ac97
->bit_resolution
;
607 scale
= volume_params
[oss_mixer
];
609 emu10k1_set_volume_gpr(card
, card
->mgr
.ctrl_gpr
[oss_mixer
][0], left
, scale
);
610 emu10k1_set_volume_gpr(card
, card
->mgr
.ctrl_gpr
[oss_mixer
][1], right
, scale
);
612 if (card
->ac97_supported_mixers
& (1 << oss_mixer
))
613 card
->ac97
->write_mixer(card
->ac97
, oss_mixer
, left
, right
);
618 static int emu10k1_mixer_ioctl(struct inode
*inode
, struct file
*file
, unsigned int cmd
, unsigned long arg
)
621 struct emu10k1_card
*card
= file
->private_data
;
622 unsigned int oss_mixer
= _IOC_NR(cmd
);
626 if (cmd
== SOUND_MIXER_INFO
) {
629 strlcpy(info
.id
, card
->ac97
->name
, sizeof(info
.id
));
632 strlcpy(info
.name
, "Audigy - Emu10k1", sizeof(info
.name
));
634 strlcpy(info
.name
, "Creative SBLive - Emu10k1", sizeof(info
.name
));
636 info
.modify_counter
= card
->ac97
->modcnt
;
638 if (copy_to_user((void __user
*)arg
, &info
, sizeof(info
)))
644 if ((_SIOC_DIR(cmd
) == (_SIOC_WRITE
|_SIOC_READ
)) && oss_mixer
<= SOUND_MIXER_NRDEVICES
)
645 ret
= emu10k1_dsp_mixer(card
, oss_mixer
, arg
);
647 ret
= card
->ac97
->mixer_ioctl(card
->ac97
, cmd
, arg
);
651 ret
= emu10k1_private_mixer(card
, cmd
, arg
);
656 static int emu10k1_mixer_open(struct inode
*inode
, struct file
*file
)
658 int minor
= iminor(inode
);
659 struct emu10k1_card
*card
= NULL
;
660 struct list_head
*entry
;
662 DPF(4, "emu10k1_mixer_open()\n");
664 list_for_each(entry
, &emu10k1_devs
) {
665 card
= list_entry(entry
, struct emu10k1_card
, list
);
667 if (card
->ac97
->dev_mixer
== minor
)
674 file
->private_data
= card
;
678 static int emu10k1_mixer_release(struct inode
*inode
, struct file
*file
)
680 DPF(4, "emu10k1_mixer_release()\n");
684 struct file_operations emu10k1_mixer_fops
= {
685 .owner
= THIS_MODULE
,
687 .ioctl
= emu10k1_mixer_ioctl
,
688 .open
= emu10k1_mixer_open
,
689 .release
= emu10k1_mixer_release
,