[142] | 1 | /* $Id: mixer.c 198 2001-10-08 11:26:46Z sandervl $ */
|
---|
| 2 |
|
---|
| 3 |
|
---|
| 4 | /*
|
---|
| 5 | **********************************************************************
|
---|
| 6 | * mixer.c - /dev/mixer interface for emu10k1 driver
|
---|
| 7 | * Copyright 1999, 2000 Creative Labs, Inc.
|
---|
| 8 | *
|
---|
| 9 | * This program uses some code from es1371.c, Copyright 1998-1999
|
---|
| 10 | * Thomas Sailer
|
---|
| 11 | *
|
---|
| 12 | **********************************************************************
|
---|
| 13 | *
|
---|
| 14 | * Date Author Summary of changes
|
---|
| 15 | * ---- ------ ------------------
|
---|
| 16 | * October 20, 1999 Bertrand Lee base code release
|
---|
| 17 | * November 2, 1999 Alan Cox cleaned up stuff
|
---|
| 18 | *
|
---|
| 19 | **********************************************************************
|
---|
| 20 | *
|
---|
| 21 | * This program is free software; you can redistribute it and/or
|
---|
| 22 | * modify it under the terms of the GNU General Public License as
|
---|
| 23 | * published by the Free Software Foundation; either version 2 of
|
---|
| 24 | * the License, or (at your option) any later version.
|
---|
| 25 | *
|
---|
| 26 | * This program is distributed in the hope that it will be useful,
|
---|
| 27 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
| 28 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
| 29 | * GNU General Public License for more details.
|
---|
| 30 | *
|
---|
| 31 | * You should have received a copy of the GNU General Public
|
---|
| 32 | * License along with this program; if not, write to the Free
|
---|
| 33 | * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
|
---|
| 34 | * USA.
|
---|
| 35 | *
|
---|
| 36 | **********************************************************************
|
---|
| 37 | */
|
---|
| 38 |
|
---|
| 39 | #define __NO_VERSION__ /* Kernel version only defined once */
|
---|
| 40 | #include <linux/module.h>
|
---|
| 41 | #include <asm/uaccess.h>
|
---|
| 42 |
|
---|
| 43 | #include "hwaccess.h"
|
---|
| 44 |
|
---|
| 45 | #define AC97_PESSIMISTIC
|
---|
| 46 | #undef OSS_DOCUMENTED_MIXER_SEMANTICS
|
---|
| 47 |
|
---|
| 48 | #define vol_to_hw_5(swvol) (31 - (((swvol) * 31) / 100))
|
---|
| 49 | #define vol_to_hw_4(swvol) (15 - (((swvol) * 15) / 100))
|
---|
| 50 |
|
---|
| 51 | #define vol_to_sw_5(hwvol) (((31 - (hwvol)) * 100) / 31)
|
---|
| 52 | #define vol_to_sw_4(hwvol) (((15 - (hwvol)) * 100) / 15)
|
---|
| 53 |
|
---|
| 54 | #ifdef PRIVATE_PCM_VOLUME
|
---|
| 55 | struct sblive_pcm_volume_rec sblive_pcm_volume[MAX_PCM_CHANNELS];
|
---|
| 56 | #endif
|
---|
| 57 |
|
---|
| 58 | /* --------------------------------------------------------------------- */
|
---|
| 59 |
|
---|
| 60 | /*
|
---|
| 61 | * hweightN: returns the hamming weight (i.e. the number
|
---|
| 62 | * of bits set) of a N-bit word
|
---|
| 63 | */
|
---|
| 64 |
|
---|
| 65 | #ifdef hweight32
|
---|
| 66 | #undef hweight32
|
---|
| 67 | #endif
|
---|
| 68 |
|
---|
| 69 | extern __inline__ unsigned int hweight32(unsigned int w)
|
---|
| 70 | {
|
---|
| 71 | unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555);
|
---|
| 72 |
|
---|
| 73 | res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
|
---|
| 74 | res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F);
|
---|
| 75 | res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF);
|
---|
| 76 | return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
|
---|
| 77 | }
|
---|
| 78 |
|
---|
| 79 | /* Mapping arrays */
|
---|
| 80 | static const unsigned int recsrc[] = {
|
---|
| 81 | SOUND_MASK_MIC,
|
---|
| 82 | SOUND_MASK_CD,
|
---|
| 83 | SOUND_MASK_VIDEO,
|
---|
| 84 | SOUND_MASK_LINE1,
|
---|
| 85 | SOUND_MASK_LINE,
|
---|
| 86 | SOUND_MASK_VOLUME,
|
---|
| 87 | SOUND_MASK_OGAIN, /* Used to be PHONEOUT */
|
---|
| 88 | SOUND_MASK_PHONEIN,
|
---|
| 89 | SOUND_MASK_TREBLE,
|
---|
| 90 | SOUND_MASK_BASS,
|
---|
| 91 | SOUND_MASK_MONITOR,
|
---|
| 92 | SOUND_MASK_PCM,
|
---|
| 93 | };
|
---|
| 94 |
|
---|
| 95 | #ifdef TARGET_OS2
|
---|
| 96 | static const unsigned char volreg[SOUND_MIXER_NRDEVICES] =
|
---|
| 97 | {
|
---|
| 98 | AC97_MASTERVOLUME, //SOUND_MIXER_VOLUME
|
---|
| 99 | AC97_GENERALPUPOSE, //SOUND_MIXER_BASS
|
---|
| 100 | AC97_MASTERTONE, //SOUND_MIXER_TREBLE
|
---|
| 101 | 0, //SOUND_MIXER_SYNTH
|
---|
| 102 | AC97_PCMOUTVOLUME, //SOUND_MIXER_PCM
|
---|
| 103 | AC97_PCBEEPVOLUME, //SOUND_MIXER_SPEAKER
|
---|
| 104 | AC97_LINEINVOLUME, //SOUND_MIXER_LINE
|
---|
| 105 | AC97_MICVOLUME, //SOUND_MIXER_MIC
|
---|
| 106 | AC97_CDVOLUME, //SOUND_MIXER_CD
|
---|
| 107 | 0, //SOUND_MIXER_IMIX
|
---|
| 108 | 0, //SOUND_MIXER_ALTPCM
|
---|
| 109 | AC97_RECORDGAIN, //SOUND_MIXER_RECLEV
|
---|
| 110 | AC97_RECORDGAIN, //SOUND_MIXER_IGAIN
|
---|
| 111 | AC97_MASTERVOLUMEMONO, //SOUND_MIXER_OGAIN
|
---|
| 112 | AC97_AUXVOLUME, //SOUND_MIXER_LINE1
|
---|
| 113 | AC97_PCMOUTVOLUME, //SOUND_MIXER_LINE2
|
---|
| 114 | 0, //SOUND_MIXER_LINE3
|
---|
| 115 | 0, //SOUND_MIXER_DIGITAL1
|
---|
| 116 | AC97_MASTERVOLUME, //SOUND_MIXER_DIGITAL2
|
---|
| 117 | 0, //SOUND_MIXER_DIGITAL3
|
---|
| 118 | AC97_PHONEVOLUME, //SOUND_MIXER_PHONEIN
|
---|
| 119 | AC97_HEADPHONEVOLUME, //SOUND_MIXER_PHONEOUT
|
---|
| 120 | AC97_VIDEOVOLUME, //SOUND_MIXER_VIDEO
|
---|
| 121 | 0, //SOUND_MIXER_RADIO
|
---|
| 122 | 0, //SOUND_MIXER_MONITOR
|
---|
| 123 | };
|
---|
| 124 | #else
|
---|
| 125 | static const unsigned char volreg[SOUND_MIXER_NRDEVICES] = {
|
---|
| 126 | /* 5 bit stereo */
|
---|
| 127 | [SOUND_MIXER_LINE] = AC97_LINEINVOLUME,
|
---|
| 128 | [SOUND_MIXER_CD] = AC97_CDVOLUME,
|
---|
| 129 | [SOUND_MIXER_VIDEO] = AC97_VIDEOVOLUME,
|
---|
| 130 | [SOUND_MIXER_LINE1] = AC97_AUXVOLUME,
|
---|
| 131 |
|
---|
| 132 | /* [SOUND_MIXER_PCM] = AC97_PCMOUTVOLUME, */
|
---|
| 133 | /* 5 bit stereo, setting 6th bit equal to maximum attenuation */
|
---|
| 134 |
|
---|
| 135 | /* [SOUND_MIXER_VOLUME] = AC97_MASTERVOLUME, */
|
---|
| 136 | [SOUND_MIXER_PHONEOUT] = AC97_HEADPHONEVOLUME,
|
---|
| 137 | /* 5 bit mono, setting 6th bit equal to maximum attenuation */
|
---|
| 138 | [SOUND_MIXER_OGAIN] = AC97_MASTERVOLUMEMONO,
|
---|
| 139 | /* 5 bit mono */
|
---|
| 140 | [SOUND_MIXER_PHONEIN] = AC97_PHONEVOLUME,
|
---|
| 141 | /* 4 bit mono but shifted by 1 */
|
---|
| 142 | [SOUND_MIXER_SPEAKER] = AC97_PCBEEPVOLUME,
|
---|
| 143 | /* 5 bit mono, 7th bit = preamp */
|
---|
| 144 | [SOUND_MIXER_MIC] = AC97_MICVOLUME,
|
---|
| 145 | /* 4 bit stereo */
|
---|
| 146 | [SOUND_MIXER_RECLEV] = AC97_RECORDGAIN,
|
---|
| 147 | /* 4 bit mono */
|
---|
| 148 | [SOUND_MIXER_IGAIN] = AC97_RECORDGAINMIC,
|
---|
| 149 | /* test code */
|
---|
| 150 | [SOUND_MIXER_BASS] = AC97_GENERALPUPOSE,
|
---|
| 151 | [SOUND_MIXER_TREBLE] = AC97_MASTERTONE,
|
---|
| 152 | [SOUND_MIXER_LINE2] = AC97_PCMOUTVOLUME,
|
---|
| 153 | [SOUND_MIXER_DIGITAL2] = AC97_MASTERVOLUME
|
---|
| 154 | };
|
---|
| 155 | #endif //TARGET_OS2
|
---|
| 156 |
|
---|
| 157 | #ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
|
---|
| 158 |
|
---|
| 159 | #define swab(x) ((((x) >> 8) & 0xff) | (((x) << 8) & 0xff00))
|
---|
| 160 |
|
---|
| 161 | /* FIXME: mixer_rdch() is broken. */
|
---|
| 162 |
|
---|
| 163 | static int mixer_rdch(struct emu10k1_card *card, unsigned int ch, int *arg)
|
---|
| 164 | {
|
---|
| 165 | u16 reg;
|
---|
| 166 | int j;
|
---|
| 167 | int nL, nR;
|
---|
| 168 |
|
---|
| 169 | switch (ch) {
|
---|
| 170 | case SOUND_MIXER_LINE:
|
---|
| 171 | case SOUND_MIXER_CD:
|
---|
| 172 | case SOUND_MIXER_VIDEO:
|
---|
| 173 | case SOUND_MIXER_LINE1:
|
---|
| 174 | case SOUND_MIXER_PCM:
|
---|
| 175 | case SOUND_MIXER_VOLUME:
|
---|
| 176 | sblive_readac97(card, volreg[ch], ®);
|
---|
| 177 | nL = ((~(reg >> 8) & 0x1f) * 100) / 32;
|
---|
| 178 | nR = (~(reg & 0x1f) * 100) / 32;
|
---|
| 179 | DPD(2, "mixer_rdch: l=%d, r=%d\n", nL, nR);
|
---|
| 180 | return put_user(reg & 0x8000 ? 0 : (nL << 8) | nR, (int *) arg);
|
---|
| 181 |
|
---|
| 182 | case SOUND_MIXER_OGAIN:
|
---|
| 183 | case SOUND_MIXER_PHONEIN:
|
---|
| 184 | sblive_readac97(card, volreg[ch], ®);
|
---|
| 185 | return put_user(reg & 0x8000 ? 0 : ~(reg & 0x1f) * 0x64 / 0x20 * 0x101, (int *) arg);
|
---|
| 186 |
|
---|
| 187 | case SOUND_MIXER_SPEAKER:
|
---|
| 188 | sblive_readac97(card, volreg[ch], ®);
|
---|
| 189 | return put_user(reg & 0x8000 ? 0 : ~((reg >> 1) & 0xf) * 0x64 / 0x10 * 0x101, (int *) arg);
|
---|
| 190 |
|
---|
| 191 | case SOUND_MIXER_MIC:
|
---|
| 192 | sblive_readac97(card, volreg[ch], ®);
|
---|
| 193 | return put_user(reg & 0x8000 ? 0 : ~(reg & 0x1f) * 0x64 / 0x20 * 0x101 + ((reg & 0x40) ? 0x1e1e : 0), (int *) arg);
|
---|
| 194 |
|
---|
| 195 | case SOUND_MIXER_RECLEV:
|
---|
| 196 | sblive_readac97(card, volreg[ch], ®);
|
---|
| 197 | nL = ((~(reg >> 8) & 0x1f) * 100) / 16;
|
---|
| 198 | nR = (~(reg & 0x1f) * 100) / 16;
|
---|
| 199 | return put_user(reg & 0x8000 ? 0 : (nL << 8) | nR, (int *) arg);
|
---|
| 200 |
|
---|
| 201 | case SOUND_MIXER_TREBLE:
|
---|
| 202 | case SOUND_MIXER_BASS:
|
---|
| 203 | return put_user(0x0000, (int *) arg);
|
---|
| 204 | default:
|
---|
| 205 | return -EINVAL;
|
---|
| 206 | }
|
---|
| 207 | }
|
---|
| 208 |
|
---|
| 209 | #endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */
|
---|
| 210 |
|
---|
| 211 | #ifdef TARGET_OS2
|
---|
| 212 | static const unsigned char volidx[SOUND_MIXER_NRDEVICES] =
|
---|
| 213 | {
|
---|
| 214 | 6, //SOUND_MIXER_VOLUME
|
---|
| 215 | 15, //SOUND_MIXER_BASS
|
---|
| 216 | 14, //SOUND_MIXER_TREBLE
|
---|
| 217 | 0, //SOUND_MIXER_SYNTH
|
---|
| 218 | 5, //SOUND_MIXER_PCM
|
---|
| 219 | 10, //SOUND_MIXER_SPEAKER
|
---|
| 220 | 1, //SOUND_MIXER_LINE
|
---|
| 221 | 11, //SOUND_MIXER_MIC
|
---|
| 222 | 2, //SOUND_MIXER_CD
|
---|
| 223 | 0, //SOUND_MIXER_IMIX
|
---|
| 224 | 16, //SOUND_MIXER_ALTPCM
|
---|
| 225 | 12, //SOUND_MIXER_RECLEV
|
---|
| 226 | 13, //SOUND_MIXER_IGAIN
|
---|
| 227 | 8, //SOUND_MIXER_OGAIN
|
---|
| 228 | 4, //SOUND_MIXER_LINE1
|
---|
| 229 | 16, //SOUND_MIXER_LINE2
|
---|
| 230 | 17, //SOUND_MIXER_LINE3
|
---|
| 231 | 18, //SOUND_MIXER_DIGITAL1
|
---|
| 232 | 19, //SOUND_MIXER_DIGITAL2
|
---|
| 233 | 0, //SOUND_MIXER_DIGITAL3
|
---|
| 234 | 9, //SOUND_MIXER_PHONEIN
|
---|
| 235 | 7, //SOUND_MIXER_PHONEOUT
|
---|
| 236 | 3, //SOUND_MIXER_VIDEO
|
---|
| 237 | 0, //SOUND_MIXER_RADIO
|
---|
| 238 | 0, //SOUND_MIXER_MONITOR
|
---|
| 239 | };
|
---|
| 240 | #else
|
---|
| 241 | static const unsigned char volidx[SOUND_MIXER_NRDEVICES] = {
|
---|
| 242 | /* 5 bit stereo */
|
---|
| 243 | [SOUND_MIXER_LINE] = 1,
|
---|
| 244 | [SOUND_MIXER_CD] = 2,
|
---|
| 245 | [SOUND_MIXER_VIDEO] = 3,
|
---|
| 246 | [SOUND_MIXER_LINE1] = 4,
|
---|
| 247 | [SOUND_MIXER_PCM] = 5,
|
---|
| 248 | /* 6 bit stereo */
|
---|
| 249 | [SOUND_MIXER_VOLUME] = 6,
|
---|
| 250 | [SOUND_MIXER_PHONEOUT] = 7,
|
---|
| 251 | /* 6 bit mono */
|
---|
| 252 | [SOUND_MIXER_OGAIN] = 8,
|
---|
| 253 | [SOUND_MIXER_PHONEIN] = 9,
|
---|
| 254 | /* 4 bit mono but shifted by 1 */
|
---|
| 255 | [SOUND_MIXER_SPEAKER] = 10,
|
---|
| 256 | /* 6 bit mono + preamp */
|
---|
| 257 | [SOUND_MIXER_MIC] = 11,
|
---|
| 258 | /* 4 bit stereo */
|
---|
| 259 | [SOUND_MIXER_RECLEV] = 12,
|
---|
| 260 | /* 4 bit mono */
|
---|
| 261 | [SOUND_MIXER_IGAIN] = 13,
|
---|
| 262 | [SOUND_MIXER_TREBLE] = 14,
|
---|
| 263 | [SOUND_MIXER_BASS] = 15,
|
---|
| 264 | [SOUND_MIXER_LINE2] = 16,
|
---|
| 265 | [SOUND_MIXER_LINE3] = 17,
|
---|
| 266 | [SOUND_MIXER_DIGITAL1] = 18,
|
---|
| 267 | [SOUND_MIXER_DIGITAL2] = 19
|
---|
| 268 | };
|
---|
| 269 | #endif //TARGET_OS2
|
---|
| 270 |
|
---|
[153] | 271 | static const u32 bass_table[41][5] = {
|
---|
[142] | 272 | { 0x3e4f844f, 0x84ed4cc3, 0x3cc69927, 0x7b03553a, 0xc4da8486 },
|
---|
| 273 | { 0x3e69a17a, 0x84c280fb, 0x3cd77cd4, 0x7b2f2a6f, 0xc4b08d1d },
|
---|
| 274 | { 0x3e82ff42, 0x849991d5, 0x3ce7466b, 0x7b5917c6, 0xc48863ee },
|
---|
| 275 | { 0x3e9bab3c, 0x847267f0, 0x3cf5ffe8, 0x7b813560, 0xc461f22c },
|
---|
| 276 | { 0x3eb3b275, 0x844ced29, 0x3d03b295, 0x7ba79a1c, 0xc43d223b },
|
---|
| 277 | { 0x3ecb2174, 0x84290c8b, 0x3d106714, 0x7bcc5ba3, 0xc419dfa5 },
|
---|
| 278 | { 0x3ee2044b, 0x8406b244, 0x3d1c2561, 0x7bef8e77, 0xc3f8170f },
|
---|
| 279 | { 0x3ef86698, 0x83e5cb96, 0x3d26f4d8, 0x7c114600, 0xc3d7b625 },
|
---|
| 280 | { 0x3f0e5390, 0x83c646c9, 0x3d30dc39, 0x7c319498, 0xc3b8ab97 },
|
---|
| 281 | { 0x3f23d60b, 0x83a81321, 0x3d39e1af, 0x7c508b9c, 0xc39ae704 },
|
---|
| 282 | { 0x3f38f884, 0x838b20d2, 0x3d420ad2, 0x7c6e3b75, 0xc37e58f1 },
|
---|
| 283 | { 0x3f4dc52c, 0x836f60ef, 0x3d495cab, 0x7c8ab3a6, 0xc362f2be },
|
---|
| 284 | { 0x3f6245e8, 0x8354c565, 0x3d4fdbb8, 0x7ca602d6, 0xc348a69b },
|
---|
| 285 | { 0x3f76845f, 0x833b40ec, 0x3d558bf0, 0x7cc036df, 0xc32f677c },
|
---|
| 286 | { 0x3f8a8a03, 0x8322c6fb, 0x3d5a70c4, 0x7cd95cd7, 0xc317290b },
|
---|
| 287 | { 0x3f9e6014, 0x830b4bc3, 0x3d5e8d25, 0x7cf1811a, 0xc2ffdfa5 },
|
---|
| 288 | { 0x3fb20fae, 0x82f4c420, 0x3d61e37f, 0x7d08af56, 0xc2e9804a },
|
---|
| 289 | { 0x3fc5a1cc, 0x82df2592, 0x3d6475c3, 0x7d1ef294, 0xc2d40096 },
|
---|
| 290 | { 0x3fd91f55, 0x82ca6632, 0x3d664564, 0x7d345541, 0xc2bf56b9 },
|
---|
| 291 | { 0x3fec9120, 0x82b67cac, 0x3d675356, 0x7d48e138, 0xc2ab796e },
|
---|
| 292 | { 0x40000000, 0x82a36037, 0x3d67a012, 0x7d5c9fc9, 0xc2985fee },
|
---|
| 293 | { 0x401374c7, 0x8291088a, 0x3d672b93, 0x7d6f99c3, 0xc28601f2 },
|
---|
| 294 | { 0x4026f857, 0x827f6dd7, 0x3d65f559, 0x7d81d77c, 0xc27457a3 },
|
---|
| 295 | { 0x403a939f, 0x826e88c5, 0x3d63fc63, 0x7d9360d4, 0xc2635996 },
|
---|
| 296 | { 0x404e4faf, 0x825e5266, 0x3d613f32, 0x7da43d42, 0xc25300c6 },
|
---|
| 297 | { 0x406235ba, 0x824ec434, 0x3d5dbbc3, 0x7db473d7, 0xc243468e },
|
---|
| 298 | { 0x40764f1f, 0x823fd80c, 0x3d596f8f, 0x7dc40b44, 0xc23424a2 },
|
---|
| 299 | { 0x408aa576, 0x82318824, 0x3d545787, 0x7dd309e2, 0xc2259509 },
|
---|
| 300 | { 0x409f4296, 0x8223cf0b, 0x3d4e7012, 0x7de175b5, 0xc2179218 },
|
---|
| 301 | { 0x40b430a0, 0x8216a7a1, 0x3d47b505, 0x7def5475, 0xc20a1670 },
|
---|
| 302 | { 0x40c97a0a, 0x820a0d12, 0x3d4021a1, 0x7dfcab8d, 0xc1fd1cf5 },
|
---|
| 303 | { 0x40df29a6, 0x81fdfad6, 0x3d37b08d, 0x7e098028, 0xc1f0a0ca },
|
---|
| 304 | { 0x40f54ab1, 0x81f26ca9, 0x3d2e5bd1, 0x7e15d72b, 0xc1e49d52 },
|
---|
| 305 | { 0x410be8da, 0x81e75e89, 0x3d241cce, 0x7e21b544, 0xc1d90e24 },
|
---|
| 306 | { 0x41231051, 0x81dcccb3, 0x3d18ec37, 0x7e2d1ee6, 0xc1cdef10 },
|
---|
| 307 | { 0x413acdd0, 0x81d2b39e, 0x3d0cc20a, 0x7e38184e, 0xc1c33c13 },
|
---|
| 308 | { 0x41532ea7, 0x81c90ffb, 0x3cff9585, 0x7e42a58b, 0xc1b8f15a },
|
---|
| 309 | { 0x416c40cd, 0x81bfdeb2, 0x3cf15d21, 0x7e4cca7c, 0xc1af0b3f },
|
---|
| 310 | { 0x418612ea, 0x81b71cdc, 0x3ce20e85, 0x7e568ad3, 0xc1a58640 },
|
---|
| 311 | { 0x41a0b465, 0x81aec7c5, 0x3cd19e7c, 0x7e5fea1e, 0xc19c5f03 },
|
---|
| 312 | { 0x41bc3573, 0x81a6dcea, 0x3cc000e9, 0x7e68ebc2, 0xc1939250 }
|
---|
| 313 | };
|
---|
| 314 |
|
---|
[153] | 315 | static const u32 treble_table[41][5] = {
|
---|
[142] | 316 | { 0x0125cba9, 0xfed5debd, 0x00599b6c, 0x0d2506da, 0xfa85b354 },
|
---|
| 317 | { 0x0142f67e, 0xfeb03163, 0x0066cd0f, 0x0d14c69d, 0xfa914473 },
|
---|
| 318 | { 0x016328bd, 0xfe860158, 0x0075b7f2, 0x0d03eb27, 0xfa9d32d2 },
|
---|
| 319 | { 0x0186b438, 0xfe56c982, 0x00869234, 0x0cf27048, 0xfaa97fca },
|
---|
| 320 | { 0x01adf358, 0xfe21f5fe, 0x00999842, 0x0ce051c2, 0xfab62ca5 },
|
---|
| 321 | { 0x01d949fa, 0xfde6e287, 0x00af0d8d, 0x0ccd8b4a, 0xfac33aa7 },
|
---|
| 322 | { 0x02092669, 0xfda4d8bf, 0x00c73d4c, 0x0cba1884, 0xfad0ab07 },
|
---|
| 323 | { 0x023e0268, 0xfd5b0e4a, 0x00e27b54, 0x0ca5f509, 0xfade7ef2 },
|
---|
| 324 | { 0x0278645c, 0xfd08a2b0, 0x01012509, 0x0c911c63, 0xfaecb788 },
|
---|
| 325 | { 0x02b8e091, 0xfcac9d1a, 0x0123a262, 0x0c7b8a14, 0xfafb55df },
|
---|
| 326 | { 0x03001a9a, 0xfc45e9ce, 0x014a6709, 0x0c65398f, 0xfb0a5aff },
|
---|
| 327 | { 0x034ec6d7, 0xfbd3576b, 0x0175f397, 0x0c4e2643, 0xfb19c7e4 },
|
---|
| 328 | { 0x03a5ac15, 0xfb5393ee, 0x01a6d6ed, 0x0c364b94, 0xfb299d7c },
|
---|
| 329 | { 0x0405a562, 0xfac52968, 0x01ddafae, 0x0c1da4e2, 0xfb39dca5 },
|
---|
| 330 | { 0x046fa3fe, 0xfa267a66, 0x021b2ddd, 0x0c042d8d, 0xfb4a8631 },
|
---|
| 331 | { 0x04e4b17f, 0xf975be0f, 0x0260149f, 0x0be9e0f2, 0xfb5b9ae0 },
|
---|
| 332 | { 0x0565f220, 0xf8b0fbe5, 0x02ad3c29, 0x0bceba73, 0xfb6d1b60 },
|
---|
| 333 | { 0x05f4a745, 0xf7d60722, 0x030393d4, 0x0bb2b578, 0xfb7f084d },
|
---|
| 334 | { 0x06923236, 0xf6e279bd, 0x03642465, 0x0b95cd75, 0xfb916233 },
|
---|
| 335 | { 0x07401713, 0xf5d3aef9, 0x03d01283, 0x0b77fded, 0xfba42984 },
|
---|
| 336 | { 0x08000000, 0xf4a6bd88, 0x0448a161, 0x0b594278, 0xfbb75e9f },
|
---|
| 337 | { 0x08d3c097, 0xf3587131, 0x04cf35a4, 0x0b3996c9, 0xfbcb01cb },
|
---|
| 338 | { 0x09bd59a2, 0xf1e543f9, 0x05655880, 0x0b18f6b2, 0xfbdf1333 },
|
---|
| 339 | { 0x0abefd0f, 0xf04956ca, 0x060cbb12, 0x0af75e2c, 0xfbf392e8 },
|
---|
| 340 | { 0x0bdb123e, 0xee806984, 0x06c739fe, 0x0ad4c962, 0xfc0880dd },
|
---|
| 341 | { 0x0d143a94, 0xec85d287, 0x0796e150, 0x0ab134b0, 0xfc1ddce5 },
|
---|
| 342 | { 0x0e6d5664, 0xea547598, 0x087df0a0, 0x0a8c9cb6, 0xfc33a6ad },
|
---|
| 343 | { 0x0fe98a2a, 0xe7e6ba35, 0x097edf83, 0x0a66fe5b, 0xfc49ddc2 },
|
---|
| 344 | { 0x118c4421, 0xe536813a, 0x0a9c6248, 0x0a4056d7, 0xfc608185 },
|
---|
| 345 | { 0x1359422e, 0xe23d19eb, 0x0bd96efb, 0x0a18a3bf, 0xfc77912c },
|
---|
| 346 | { 0x1554982b, 0xdef33645, 0x0d3942bd, 0x09efe312, 0xfc8f0bc1 },
|
---|
| 347 | { 0x1782b68a, 0xdb50deb1, 0x0ebf676d, 0x09c6133f, 0xfca6f019 },
|
---|
| 348 | { 0x19e8715d, 0xd74d64fd, 0x106fb999, 0x099b3337, 0xfcbf3cd6 },
|
---|
| 349 | { 0x1c8b07b8, 0xd2df56ab, 0x124e6ec8, 0x096f4274, 0xfcd7f060 },
|
---|
| 350 | { 0x1f702b6d, 0xcdfc6e92, 0x14601c10, 0x0942410b, 0xfcf108e5 },
|
---|
| 351 | { 0x229e0933, 0xc89985cd, 0x16a9bcfa, 0x09142fb5, 0xfd0a8451 },
|
---|
| 352 | { 0x261b5118, 0xc2aa8409, 0x1930bab6, 0x08e50fdc, 0xfd24604d },
|
---|
| 353 | { 0x29ef3f5d, 0xbc224f28, 0x1bfaf396, 0x08b4e3aa, 0xfd3e9a3b },
|
---|
| 354 | { 0x2e21a59b, 0xb4f2ba46, 0x1f0ec2d6, 0x0883ae15, 0xfd592f33 },
|
---|
| 355 | { 0x32baf44b, 0xad0c7429, 0x227308a3, 0x085172eb, 0xfd741bfd },
|
---|
| 356 | { 0x37c4448b, 0xa45ef51d, 0x262f3267, 0x081e36dc, 0xfd8f5d14 }
|
---|
| 357 | };
|
---|
| 358 |
|
---|
| 359 | static void set_bass(struct emu10k1_card *card, int l, int r)
|
---|
| 360 | {
|
---|
| 361 | int i;
|
---|
| 362 |
|
---|
| 363 | l = (l * 40 + 50) / 100;
|
---|
| 364 | r = (r * 40 + 50) / 100;
|
---|
| 365 | for (i = 0; i < 5; i++) {
|
---|
| 366 | sblive_writeptr(card, FXGPREGBASE + 0x80 + (i * 2), 0, bass_table[l][i]);
|
---|
| 367 | sblive_writeptr(card, FXGPREGBASE + 0x80 + (i * 2) + 1, 0, bass_table[r][i]);
|
---|
| 368 | }
|
---|
| 369 | }
|
---|
| 370 |
|
---|
| 371 | static void set_treble(struct emu10k1_card *card, int l, int r)
|
---|
| 372 | {
|
---|
| 373 | int i;
|
---|
| 374 |
|
---|
| 375 | l = (l * 40 + 50) / 100;
|
---|
| 376 | r = (r * 40 + 50) / 100;
|
---|
| 377 | for (i = 0; i < 5; i++) {
|
---|
| 378 | sblive_writeptr(card, FXGPREGBASE + 0x90 + (i * 2), 0, treble_table[l][i]);
|
---|
| 379 | sblive_writeptr(card, FXGPREGBASE + 0x90 + (i * 2) + 1, 0, treble_table[r][i]);
|
---|
| 380 | }
|
---|
| 381 | }
|
---|
| 382 |
|
---|
[153] | 383 | static const u32 db_table[101] = {
|
---|
[142] | 384 | 0x00000000, 0x01571f82, 0x01674b41, 0x01783a1b, 0x0189f540,
|
---|
| 385 | 0x019c8651, 0x01aff763, 0x01c45306, 0x01d9a446, 0x01eff6b8,
|
---|
| 386 | 0x0207567a, 0x021fd03d, 0x0239714c, 0x02544792, 0x027061a1,
|
---|
| 387 | 0x028dcebb, 0x02ac9edc, 0x02cce2bf, 0x02eeabe8, 0x03120cb0,
|
---|
| 388 | 0x0337184e, 0x035de2df, 0x03868173, 0x03b10a18, 0x03dd93e9,
|
---|
| 389 | 0x040c3713, 0x043d0cea, 0x04702ff3, 0x04a5bbf2, 0x04ddcdfb,
|
---|
| 390 | 0x0518847f, 0x0555ff62, 0x05966005, 0x05d9c95d, 0x06206005,
|
---|
| 391 | 0x066a4a52, 0x06b7b067, 0x0708bc4c, 0x075d9a01, 0x07b6779d,
|
---|
| 392 | 0x08138561, 0x0874f5d5, 0x08dafde1, 0x0945d4ed, 0x09b5b4fd,
|
---|
| 393 | 0x0a2adad1, 0x0aa58605, 0x0b25f936, 0x0bac7a24, 0x0c3951d8,
|
---|
| 394 | 0x0ccccccc, 0x0d673b17, 0x0e08f093, 0x0eb24510, 0x0f639481,
|
---|
| 395 | 0x101d3f2d, 0x10dfa9e6, 0x11ab3e3f, 0x12806ac3, 0x135fa333,
|
---|
| 396 | 0x144960c5, 0x153e2266, 0x163e6cfe, 0x174acbb7, 0x1863d04d,
|
---|
| 397 | 0x198a1357, 0x1abe349f, 0x1c00db77, 0x1d52b712, 0x1eb47ee6,
|
---|
| 398 | 0x2026f30f, 0x21aadcb6, 0x23410e7e, 0x24ea64f9, 0x26a7c71d,
|
---|
| 399 | 0x287a26c4, 0x2a62812c, 0x2c61df84, 0x2e795779, 0x30aa0bcf,
|
---|
| 400 | 0x32f52cfe, 0x355bf9d8, 0x37dfc033, 0x3a81dda4, 0x3d43c038,
|
---|
| 401 | 0x4026e73c, 0x432ce40f, 0x46575af8, 0x49a8040f, 0x4d20ac2a,
|
---|
| 402 | 0x50c335d3, 0x54919a57, 0x588dead1, 0x5cba514a, 0x611911ea,
|
---|
| 403 | 0x65ac8c2f, 0x6a773c39, 0x6f7bbc23, 0x74bcc56c, 0x7a3d3272,
|
---|
| 404 | 0x7fffffff,
|
---|
| 405 | };
|
---|
| 406 |
|
---|
| 407 | static void update_digital(struct emu10k1_card *card)
|
---|
| 408 | {
|
---|
| 409 | int i, k, l1, r1, l2, r2, l3, r3, l4, r4;
|
---|
| 410 | u64 j;
|
---|
| 411 |
|
---|
| 412 | i = card->arrwVol[volidx[SOUND_MIXER_VOLUME]];
|
---|
| 413 | l1 = (i & 0xff);
|
---|
| 414 | r1 = ((i >> 8) & 0xff);
|
---|
| 415 | i = card->arrwVol[volidx[SOUND_MIXER_LINE3]];
|
---|
| 416 | l2 = i & 0xff;
|
---|
| 417 | r2 = (i >> 8) & 0xff;
|
---|
| 418 |
|
---|
| 419 | i = card->arrwVol[volidx[SOUND_MIXER_PCM]];
|
---|
| 420 | l3 = i & 0xff;
|
---|
| 421 | r3 = (i >> 8) & 0xff;
|
---|
| 422 |
|
---|
| 423 | i = card->arrwVol[volidx[SOUND_MIXER_DIGITAL1]];
|
---|
| 424 | l4 = i & 0xff;
|
---|
| 425 | r4 = (i >> 8) & 0xff;
|
---|
| 426 |
|
---|
| 427 | i = (r1 * r2) / 50;
|
---|
| 428 | if (r2 > 50)
|
---|
| 429 | r2 = 2 * r1 - i;
|
---|
| 430 | else {
|
---|
| 431 | r2 = r1;
|
---|
| 432 | r1 = i;
|
---|
| 433 | }
|
---|
| 434 |
|
---|
| 435 | i = (l1 * l2) / 50;
|
---|
| 436 | if (l2 > 50)
|
---|
| 437 | l2 = 2 * l1 - i;
|
---|
| 438 | else {
|
---|
| 439 | l2 = l1;
|
---|
| 440 | l1 = i;
|
---|
| 441 | }
|
---|
| 442 |
|
---|
[153] | 443 | for (i = 0; i < 36; i++) {
|
---|
[142] | 444 | if (card->digmix[i] != 0x80000000) {
|
---|
[153] | 445 | if (((i >= 0) && (i < 4)) || ((i >= 18) && (i < 22)))
|
---|
[142] | 446 | j = (i & 1) ? ((u64) db_table[r1] * (u64) db_table[r3]) : ((u64) db_table[l1] * (u64) db_table[l3]);
|
---|
[153] | 447 | else if ((i == 6) || (i == 7) || (i == 24) || (i == 25))
|
---|
[142] | 448 | j = (i & 1) ? ((u64) db_table[r1] * (u64) db_table[r4]) : ((u64) db_table[l1] * (u64) db_table[l4]);
|
---|
| 449 | else
|
---|
| 450 | j = ((i & 1) ? db_table[r1] : db_table[l1]) << 31;
|
---|
| 451 | card->digmix[i] = j >> 31;
|
---|
| 452 | sblive_writeptr(card, FXGPREGBASE + 0x10 + i, 0, card->digmix[i]);
|
---|
| 453 | }
|
---|
| 454 | }
|
---|
| 455 |
|
---|
| 456 | for (i = 72; i < 90; i++) {
|
---|
| 457 | if (card->digmix[i] != 0x80000000) {
|
---|
| 458 | if ((i >= 72) && (i < 76))
|
---|
| 459 | j = (i & 1) ? ((u64) db_table[r2] * (u64) db_table[r3]) : ((u64) db_table[l2] * (u64) db_table[l3]);
|
---|
| 460 | else if ((i == 78) || (i == 79))
|
---|
| 461 | j = (i & 1) ? ((u64) db_table[r2] * (u64) db_table[r4]) : ((u64) db_table[l2] * (u64) db_table[l4]);
|
---|
| 462 | else
|
---|
| 463 | j = ((i & 1) ? db_table[r2] : db_table[l2]) << 31;
|
---|
| 464 | card->digmix[i] = j >> 31;
|
---|
| 465 | sblive_writeptr(card, FXGPREGBASE + 0x10 + i, 0, card->digmix[i]);
|
---|
| 466 | }
|
---|
| 467 | }
|
---|
| 468 |
|
---|
[153] | 469 | for (i = 36; i <= 90; i += 18) {
|
---|
[142] | 470 | if (i != 72) {
|
---|
| 471 | for (k = 0; k < 4; k++)
|
---|
| 472 | if (card->digmix[i + k] != 0x80000000) {
|
---|
| 473 | card->digmix[i + k] = db_table[l3];
|
---|
| 474 | sblive_writeptr(card, FXGPREGBASE + 0x10 + i + k, 0, card->digmix[i + k]);
|
---|
| 475 | }
|
---|
| 476 | if (card->digmix[i + 6] != 0x80000000) {
|
---|
| 477 | card->digmix[i + 6] = db_table[l4];
|
---|
| 478 | sblive_writeptr(card, FXGPREGBASE + 0x10 + i + 6, 0, card->digmix[i + 6]);
|
---|
| 479 | }
|
---|
| 480 | if (card->digmix[i + 7] != 0x80000000) {
|
---|
| 481 | card->digmix[i + 7] = db_table[r4];
|
---|
| 482 | sblive_writeptr(card, FXGPREGBASE + 0x10 + i + 7, 0, card->digmix[i + 7]);
|
---|
| 483 | }
|
---|
| 484 | }
|
---|
| 485 | }
|
---|
| 486 |
|
---|
| 487 | }
|
---|
| 488 |
|
---|
| 489 | #ifdef PRIVATE_PCM_VOLUME
|
---|
| 490 |
|
---|
[154] | 491 | #if 1
|
---|
| 492 | static unsigned char LinToLog[100] = {
|
---|
| 493 | 0, 0, 0, 0, 1, 2, 2, 5, 5, 10,
|
---|
| 494 | 10, 10, 16, 19, 20, 22, 24, 25, 27, 27,
|
---|
| 495 | 28, 28, 29, 30, 30, 35, 35, 35, 39, 39,
|
---|
| 496 | 43, 44, 45, 47, 48, 49, 50, 51, 52, 53,
|
---|
| 497 | 55, 56, 57, 59, 60, 62, 63, 64, 65, 66,
|
---|
| 498 | 67, 68, 69, 70, 71, 72, 73, 74, 74, 75,
|
---|
| 499 | 76, 77, 78, 79, 79, 80, 81, 82, 83, 84,
|
---|
| 500 | 85, 86, 87, 88, 89, 90, 91, 92, 92, 93,
|
---|
| 501 | 93, 94, 94, 95, 95, 96, 96, 97, 97, 98,
|
---|
| 502 | 98, 99, 99, 99, 99, 100, 100, 100, 100, 100
|
---|
| 503 | };
|
---|
| 504 | #else
|
---|
| 505 | static unsigned char LinToLog[100] = {
|
---|
| 506 | 0, 0, 0, 0, 1, 2, 2, 5, 5, 10,
|
---|
| 507 | 10, 10, 16, 19, 20, 22, 24, 25, 27, 27,
|
---|
| 508 | 28, 28, 29, 30, 30, 35, 35, 35, 39, 39,
|
---|
| 509 | 43, 45, 47, 49, 50, 50, 60, 60, 70, 72,
|
---|
| 510 | 72, 74, 74, 74, 75, 75, 76, 77, 78, 80,
|
---|
| 511 | 82, 83, 85, 85, 85, 88, 88, 88, 88, 90,
|
---|
| 512 | 90, 93, 93, 93, 95, 95, 95, 95, 95, 95,
|
---|
| 513 | 95, 96, 96, 97, 97, 98, 98, 98, 98, 99,
|
---|
| 514 | 99, 99, 99, 99, 99, 99, 99, 99, 100, 100,
|
---|
| 515 | 100, 100, 100, 100, 100, 100, 100, 100, 100, 100
|
---|
| 516 | };
|
---|
| 517 | #endif
|
---|
[153] | 518 |
|
---|
[142] | 519 | /* calc & set attenuation factor for given channel */
|
---|
| 520 | static int set_pcm_attn(struct emu10k1_card *card, int ch, int l)
|
---|
| 521 | {
|
---|
| 522 | #ifndef PCMLEVEL
|
---|
[153] | 523 | #define PCMLEVEL 110 /* almost silence */
|
---|
[142] | 524 | #endif
|
---|
[153] | 525 | int vol = IFATN_ATTENUATION_MASK; /* silence */
|
---|
[142] | 526 |
|
---|
[153] | 527 | if (l > 0) {
|
---|
| 528 | if(l < 100) {
|
---|
| 529 | l = LinToLog[l];
|
---|
| 530 | }
|
---|
[142] | 531 | vol = (PCMLEVEL - (l * PCMLEVEL + 50) / 100);
|
---|
[153] | 532 | }
|
---|
[142] | 533 | sblive_writeptr(card, IFATN, ch, IFATN_FILTERCUTOFF_MASK | vol);
|
---|
| 534 | DPD(2, "SOUND_MIXER_PCM: channel:%d level:%d attn:%d\n", ch, l, vol);
|
---|
| 535 |
|
---|
| 536 | return vol;
|
---|
| 537 | #undef PCMLEVEL
|
---|
| 538 | }
|
---|
| 539 |
|
---|
| 540 | /* update value of local PCM volume level (using channel attenuation)
|
---|
| 541 | *
|
---|
| 542 | * return 1: in case its local change
|
---|
| 543 | * 0: if the current process doesn't have entry in table
|
---|
| 544 | * (it means this process have not opened audio (mixer usually)
|
---|
| 545 | */
|
---|
| 546 |
|
---|
| 547 | static int update_pcm_attn(struct emu10k1_card *card, unsigned l1, unsigned r1)
|
---|
| 548 | {
|
---|
| 549 | int i;
|
---|
| 550 | int mixer = (r1 << 8) | l1;
|
---|
| 551 |
|
---|
| 552 | //SvL; First call (during mixer init) must return 0 and fill in the
|
---|
| 553 | // arrwVol array. Only then will update_digital be called.
|
---|
| 554 | // If this doesn't happen, sound is disabled.
|
---|
| 555 | // Check here that current->files != 0
|
---|
| 556 | for (i = 0; i < MAX_PCM_CHANNELS; i++) {
|
---|
[147] | 557 | #ifdef TARGET_OS2
|
---|
[142] | 558 | if (current->files && sblive_pcm_volume[i].files == current->files) {
|
---|
[147] | 559 | #else
|
---|
| 560 | if (sblive_pcm_volume[i].files == current->files) {
|
---|
| 561 | #endif
|
---|
[142] | 562 | sblive_pcm_volume[i].mixer = mixer;
|
---|
| 563 | if (sblive_pcm_volume[i].opened) {
|
---|
| 564 | if (sblive_pcm_volume[i].channel_r < NUM_G) {
|
---|
| 565 | if (sblive_pcm_volume[i].channel_l < NUM_G)
|
---|
| 566 | sblive_pcm_volume[i].attn_l = set_pcm_attn(card, sblive_pcm_volume[i].channel_l, l1);
|
---|
| 567 | sblive_pcm_volume[i].attn_r = set_pcm_attn(card, sblive_pcm_volume[i].channel_r, r1);
|
---|
| 568 | } else {
|
---|
| 569 | // mono voice
|
---|
| 570 | if (sblive_pcm_volume[i].channel_l < NUM_G)
|
---|
| 571 | sblive_pcm_volume[i].attn_l =
|
---|
| 572 | set_pcm_attn(card, sblive_pcm_volume[i].channel_l, (l1 >= r1) ? l1 : r1);
|
---|
| 573 | // to correctly handle mono voice here we would need
|
---|
| 574 | // to go into stereo mode and move the voice to the right & left
|
---|
| 575 | // looks a bit overcomlicated...
|
---|
| 576 | }
|
---|
| 577 |
|
---|
| 578 | }
|
---|
| 579 | return 1;
|
---|
| 580 | }
|
---|
| 581 | }
|
---|
[153] | 582 | card->arrwVol[volidx[SOUND_MIXER_PCM]] = mixer;
|
---|
[142] | 583 |
|
---|
| 584 | return 0;
|
---|
| 585 | }
|
---|
| 586 | #endif
|
---|
| 587 |
|
---|
| 588 | int emu10k1_mixer_wrch(struct emu10k1_card *card, unsigned int ch, int val)
|
---|
| 589 | {
|
---|
| 590 | int i;
|
---|
| 591 | unsigned l1, r1;
|
---|
| 592 | u16 wval;
|
---|
| 593 |
|
---|
| 594 | l1 = val & 0xff;
|
---|
| 595 | r1 = (val >> 8) & 0xff;
|
---|
| 596 | if (l1 > 100)
|
---|
| 597 | l1 = 100;
|
---|
| 598 | if (r1 > 100)
|
---|
| 599 | r1 = 100;
|
---|
| 600 |
|
---|
| 601 | DPD(4, "emu10k1_mixer_wrch() called: ch=%u, l1=%u, r1=%u\n", ch, l1, r1);
|
---|
| 602 |
|
---|
| 603 | if (!volidx[ch])
|
---|
| 604 | return -EINVAL;
|
---|
| 605 | #ifdef PRIVATE_PCM_VOLUME
|
---|
| 606 | if (ch != SOUND_MIXER_PCM)
|
---|
| 607 | #endif
|
---|
| 608 | card->arrwVol[volidx[ch]] = (r1 << 8) | l1;
|
---|
| 609 |
|
---|
| 610 | switch (ch) {
|
---|
[198] | 611 | #ifndef TARGET_OS2
|
---|
[142] | 612 | case SOUND_MIXER_VOLUME:
|
---|
[198] | 613 | #endif
|
---|
[142] | 614 | case SOUND_MIXER_DIGITAL1:
|
---|
| 615 | case SOUND_MIXER_LINE3:
|
---|
| 616 | DPD(4, "SOUND_MIXER_%s:\n", (ch == SOUND_MIXER_VOLUME) ? "VOLUME" : (ch == SOUND_MIXER_DIGITAL1) ? "DIGITAL1" : "LINE3");
|
---|
| 617 | update_digital(card);
|
---|
| 618 | return 0;
|
---|
| 619 | case SOUND_MIXER_PCM:
|
---|
| 620 | DPF(4, "SOUND_MIXER_PCM\n");
|
---|
| 621 | #ifdef PRIVATE_PCM_VOLUME
|
---|
| 622 | if (update_pcm_attn(card, l1, r1))
|
---|
| 623 | return 0;
|
---|
| 624 | #endif
|
---|
| 625 | update_digital(card);
|
---|
| 626 | return 0;
|
---|
[198] | 627 | #ifdef TARGET_OS2
|
---|
| 628 | case SOUND_MIXER_VOLUME:
|
---|
| 629 | #endif
|
---|
[142] | 630 | case SOUND_MIXER_DIGITAL2:
|
---|
| 631 | case SOUND_MIXER_LINE2:
|
---|
| 632 | case SOUND_MIXER_LINE1:
|
---|
| 633 | case SOUND_MIXER_LINE:
|
---|
| 634 | case SOUND_MIXER_CD:
|
---|
| 635 | DPD(4, "SOUND_MIXER_%s:\n",
|
---|
| 636 | (ch == SOUND_MIXER_LINE1) ? "LINE1" :
|
---|
| 637 | (ch == SOUND_MIXER_LINE2) ? "LINE2" : (ch == SOUND_MIXER_LINE) ? "LINE" : (ch == SOUND_MIXER_DIGITAL2) ? "DIGITAL2" : "CD");
|
---|
| 638 | wval = ((((100 - l1) * 32 + 50) / 100) << 8) | (((100 - r1) * 32 + 50) / 100);
|
---|
| 639 | if (wval == 0x2020)
|
---|
| 640 | wval = 0x8000;
|
---|
| 641 | else
|
---|
| 642 | wval -= ((wval & 0x2020) / 0x20);
|
---|
| 643 | sblive_writeac97(card, volreg[ch], wval);
|
---|
| 644 | return 0;
|
---|
| 645 |
|
---|
| 646 | case SOUND_MIXER_OGAIN:
|
---|
| 647 | case SOUND_MIXER_PHONEIN:
|
---|
| 648 | DPD(4, "SOUND_MIXER_%s:\n", (ch == SOUND_MIXER_PHONEIN) ? "PHONEIN" : "OGAIN");
|
---|
| 649 | sblive_writeac97(card, volreg[ch], (l1 < 2) ? 0x8000 : ((100 - l1) * 32 + 50) / 100);
|
---|
| 650 | return 0;
|
---|
| 651 |
|
---|
| 652 | case SOUND_MIXER_SPEAKER:
|
---|
| 653 | DPF(4, "SOUND_MIXER_SPEAKER:\n");
|
---|
| 654 | sblive_writeac97(card, volreg[ch], (l1 < 4) ? 0x8000 : (((100 - l1) * 16 + 50) / 100) << 1);
|
---|
| 655 | return 0;
|
---|
| 656 |
|
---|
| 657 | case SOUND_MIXER_MIC:
|
---|
| 658 | DPF(4, "SOUND_MIXER_MIC:\n");
|
---|
| 659 | i = 0;
|
---|
| 660 | if (l1 >= 30)
|
---|
| 661 | // 20dB / (34.5dB + 12dB + 20dB) * 100 = 30
|
---|
| 662 | {
|
---|
| 663 | l1 -= 30;
|
---|
| 664 | i = 0x40;
|
---|
| 665 | }
|
---|
| 666 | sblive_writeac97(card, volreg[ch], (l1 < 2) ? 0x8000 : ((((70 - l1) * 0x20 + 35) / 70) | i));
|
---|
| 667 | return 0;
|
---|
| 668 |
|
---|
| 669 | case SOUND_MIXER_RECLEV:
|
---|
| 670 | DPF(4, "SOUND_MIXER_RECLEV:\n");
|
---|
| 671 |
|
---|
| 672 | wval = (((l1 * 16 + 50) / 100) << 8) | ((r1 * 16 + 50) / 100);
|
---|
| 673 | if (wval == 0)
|
---|
| 674 | wval = 0x8000;
|
---|
| 675 | else {
|
---|
| 676 | if (wval & 0xff)
|
---|
| 677 | wval--;
|
---|
| 678 | if (wval & 0xff00)
|
---|
| 679 | wval -= 0x0100;
|
---|
| 680 | }
|
---|
| 681 | sblive_writeac97(card, volreg[ch], wval);
|
---|
| 682 | return 0;
|
---|
| 683 |
|
---|
| 684 | case SOUND_MIXER_TREBLE:
|
---|
| 685 | DPF(4, "SOUND_MIXER_TREBLE:\n");
|
---|
| 686 | set_treble(card, l1, r1);
|
---|
| 687 | return 0;
|
---|
| 688 |
|
---|
| 689 | case SOUND_MIXER_BASS:
|
---|
| 690 | DPF(4, "SOUND_MIXER_BASS:\n");
|
---|
| 691 | set_bass(card, l1, r1);
|
---|
| 692 | return 0;
|
---|
| 693 |
|
---|
| 694 | default:
|
---|
| 695 | DPF(2, "Got unknown SOUND_MIXER ioctl\n");
|
---|
| 696 | return -EINVAL;
|
---|
| 697 | }
|
---|
| 698 | }
|
---|
| 699 |
|
---|
| 700 | static loff_t emu10k1_mixer_llseek(struct file *file, loff_t offset, int origin)
|
---|
| 701 | {
|
---|
| 702 | DPF(2, "sblive_mixer_llseek() called\n");
|
---|
| 703 | return -ESPIPE;
|
---|
| 704 | }
|
---|
| 705 |
|
---|
| 706 | /* Mixer file operations */
|
---|
| 707 |
|
---|
| 708 | /* FIXME: Do we need spinlocks in here? */
|
---|
| 709 | static int emu10k1_mixer_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
|
---|
| 710 | {
|
---|
| 711 | static const char id[] = "SBLive";
|
---|
| 712 | static const char name[] = "Creative SBLive";
|
---|
| 713 | int i, val;
|
---|
| 714 | struct emu10k1_card *card = (struct emu10k1_card *) file->private_data;
|
---|
| 715 | u16 reg;
|
---|
| 716 |
|
---|
| 717 | switch (cmd) {
|
---|
| 718 |
|
---|
| 719 | case SOUND_MIXER_INFO:{
|
---|
| 720 | mixer_info info;
|
---|
| 721 |
|
---|
| 722 | DPF(4, "SOUND_MIXER_INFO\n");
|
---|
| 723 |
|
---|
| 724 | strncpy(info.id, id, sizeof(info.id));
|
---|
| 725 | strncpy(info.name, name, sizeof(info.name));
|
---|
| 726 |
|
---|
| 727 | info.modify_counter = card->modcnt;
|
---|
| 728 | if (copy_to_user((void *) arg, &info, sizeof(info)))
|
---|
| 729 | return -EFAULT;
|
---|
| 730 |
|
---|
| 731 | return 0;
|
---|
| 732 | }
|
---|
| 733 | break;
|
---|
| 734 | case SOUND_OLD_MIXER_INFO:{
|
---|
| 735 | _old_mixer_info info;
|
---|
| 736 |
|
---|
| 737 | DPF(4, "SOUND_OLD_MIXER_INFO\n");
|
---|
| 738 |
|
---|
| 739 | strncpy(info.id, id, sizeof(info.id));
|
---|
| 740 | strncpy(info.name, name, sizeof(info.name));
|
---|
| 741 |
|
---|
| 742 | if (copy_to_user((void *) arg, &info, sizeof(info)))
|
---|
| 743 | return -EFAULT;
|
---|
| 744 |
|
---|
| 745 | return 0;
|
---|
| 746 | }
|
---|
| 747 | break;
|
---|
| 748 |
|
---|
| 749 | case OSS_GETVERSION:
|
---|
| 750 | DPF(4, "OSS_GETVERSION\n");
|
---|
| 751 | return put_user(SOUND_VERSION, (int *) arg);
|
---|
| 752 | break;
|
---|
| 753 |
|
---|
| 754 | case SOUND_MIXER_PRIVATE1:
|
---|
| 755 | DPF(4, "SOUND_MIXER_PRIVATE1");
|
---|
| 756 |
|
---|
| 757 | if (copy_to_user((void *) arg, card->digmix, sizeof(card->digmix)))
|
---|
| 758 | return -EFAULT;
|
---|
| 759 |
|
---|
| 760 | return 0;
|
---|
| 761 |
|
---|
| 762 | break;
|
---|
| 763 | case SOUND_MIXER_PRIVATE2:
|
---|
| 764 | DPF(4, "SOUND_MIXER_PRIVATE2");
|
---|
| 765 |
|
---|
| 766 | if (copy_from_user(card->digmix, (void *) arg, sizeof(card->digmix)))
|
---|
| 767 | return -EFAULT;
|
---|
| 768 |
|
---|
| 769 | for (i = 0; i < sizeof(card->digmix) / sizeof(card->digmix[0]); i++)
|
---|
| 770 | sblive_writeptr(card, FXGPREGBASE + 0x10 + i, 0, (card->digmix[i] & 0x80000000) ? 0 : card->digmix[i]);
|
---|
| 771 | return 0;
|
---|
| 772 |
|
---|
| 773 | break;
|
---|
| 774 |
|
---|
| 775 | default:
|
---|
| 776 | break;
|
---|
| 777 | }
|
---|
| 778 |
|
---|
| 779 | if (_IOC_TYPE(cmd) != 'M' || _IOC_SIZE(cmd) != sizeof(int))
|
---|
| 780 | return -EINVAL;
|
---|
| 781 |
|
---|
| 782 | if (_IOC_DIR(cmd) == _IOC_READ) {
|
---|
| 783 | switch (_IOC_NR(cmd)) {
|
---|
| 784 | case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */
|
---|
| 785 | DPF(2, "SOUND_MIXER_READ_RECSRC\n");
|
---|
| 786 | sblive_readac97(card, AC97_RECORDSELECT, ®);
|
---|
| 787 | return put_user(recsrc[reg & 7], (int *) arg);
|
---|
| 788 |
|
---|
| 789 | case SOUND_MIXER_DEVMASK: /* Arg contains a bit for each supported device */
|
---|
| 790 | DPF(4, "SOUND_MIXER_READ_DEVMASK\n");
|
---|
| 791 | return put_user(SOUND_MASK_LINE | SOUND_MASK_CD |
|
---|
| 792 | SOUND_MASK_OGAIN | SOUND_MASK_LINE1 |
|
---|
| 793 | SOUND_MASK_PCM | SOUND_MASK_VOLUME |
|
---|
| 794 | SOUND_MASK_PHONEIN | SOUND_MASK_MIC |
|
---|
| 795 | SOUND_MASK_BASS | SOUND_MASK_TREBLE |
|
---|
| 796 | SOUND_MASK_RECLEV | SOUND_MASK_SPEAKER |
|
---|
| 797 | SOUND_MASK_LINE3 | SOUND_MASK_DIGITAL1 |
|
---|
| 798 | SOUND_MASK_DIGITAL2 | SOUND_MASK_LINE2, (int *) arg);
|
---|
| 799 | case SOUND_MIXER_RECMASK: /* Arg contains a bit for each supported recording source */
|
---|
| 800 | DPF(2, "SOUND_MIXER_READ_RECMASK\n");
|
---|
| 801 | return put_user(SOUND_MASK_MIC | SOUND_MASK_CD |
|
---|
| 802 | SOUND_MASK_LINE1 | SOUND_MASK_LINE |
|
---|
| 803 | SOUND_MASK_VOLUME | SOUND_MASK_OGAIN |
|
---|
| 804 | SOUND_MASK_PHONEIN | SOUND_MASK_MONITOR |
|
---|
| 805 | SOUND_MASK_PCM, (int *) arg);
|
---|
| 806 |
|
---|
| 807 | case SOUND_MIXER_STEREODEVS: /* Mixer channels supporting stereo */
|
---|
| 808 | DPF(2, "SOUND_MIXER_READ_STEREODEVS\n");
|
---|
| 809 | return put_user(SOUND_MASK_LINE | SOUND_MASK_CD |
|
---|
| 810 | SOUND_MASK_OGAIN | SOUND_MASK_LINE1 |
|
---|
| 811 | SOUND_MASK_PCM | SOUND_MASK_VOLUME |
|
---|
| 812 | SOUND_MASK_BASS | SOUND_MASK_TREBLE |
|
---|
| 813 | SOUND_MASK_RECLEV | SOUND_MASK_LINE3 |
|
---|
| 814 | SOUND_MASK_DIGITAL1 | SOUND_MASK_DIGITAL2 |
|
---|
| 815 | SOUND_MASK_LINE2, (int *) arg);
|
---|
| 816 |
|
---|
| 817 | case SOUND_MIXER_CAPS:
|
---|
| 818 | DPF(2, "SOUND_MIXER_READ_CAPS\n");
|
---|
| 819 | return put_user(SOUND_CAP_EXCL_INPUT, (int *) arg);
|
---|
| 820 |
|
---|
| 821 | #ifdef PRIVATE_PCM_VOLUME
|
---|
| 822 | case SOUND_MIXER_PCM:
|
---|
| 823 | // needs to be before default: !!
|
---|
| 824 | {
|
---|
| 825 | int i;
|
---|
| 826 |
|
---|
| 827 | for (i = 0; i < MAX_PCM_CHANNELS; i++) {
|
---|
| 828 | if (sblive_pcm_volume[i].files == current->files) {
|
---|
| 829 | return put_user((int) sblive_pcm_volume[i].mixer, (int *) arg);
|
---|
| 830 | }
|
---|
| 831 | }
|
---|
| 832 | }
|
---|
| 833 | #endif
|
---|
| 834 | default:
|
---|
| 835 | i = _IOC_NR(cmd);
|
---|
| 836 | DPD(4, "SOUND_MIXER_READ(%d)\n", i);
|
---|
| 837 | if (i >= SOUND_MIXER_NRDEVICES)
|
---|
| 838 | return -EINVAL;
|
---|
| 839 | #ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
|
---|
| 840 | return mixer_rdch(card, i, (int *) arg);
|
---|
| 841 | #else /* OSS_DOCUMENTED_MIXER_SEMANTICS */
|
---|
| 842 | if (!volidx[i])
|
---|
| 843 | return -EINVAL;
|
---|
| 844 | return put_user(card->arrwVol[volidx[i]], (int *) arg);
|
---|
| 845 |
|
---|
| 846 | #endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */
|
---|
| 847 | }
|
---|
| 848 | }
|
---|
| 849 | /* End of _IOC_READ */
|
---|
| 850 | if (_IOC_DIR(cmd) != (_IOC_READ | _IOC_WRITE))
|
---|
| 851 | return -EINVAL;
|
---|
| 852 |
|
---|
| 853 | /* _IOC_WRITE */
|
---|
| 854 | card->modcnt++;
|
---|
| 855 |
|
---|
| 856 | switch (_IOC_NR(cmd)) {
|
---|
| 857 | case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */
|
---|
| 858 | DPF(2, "SOUND_MIXER_WRITE_RECSRC\n");
|
---|
| 859 |
|
---|
| 860 | get_user_ret(val, (int *) arg, -EFAULT);
|
---|
| 861 | i = hweight32(val);
|
---|
| 862 | if (i == 0)
|
---|
| 863 | return 0; /*val = mixer_recmask(s); */
|
---|
| 864 | else if (i > 1) {
|
---|
| 865 | sblive_readac97(card, AC97_RECORDSELECT, ®);
|
---|
| 866 | val &= ~recsrc[reg & 7];
|
---|
| 867 | }
|
---|
| 868 |
|
---|
| 869 | for (i = 0; i < 8; i++) {
|
---|
| 870 | if (val & recsrc[i]) {
|
---|
| 871 | DPD(2, "Selecting record source to be 0x%04x\n", 0x0101 * i);
|
---|
| 872 | sblive_writeac97(card, AC97_RECORDSELECT, 0x0101 * i);
|
---|
| 873 | return 0;
|
---|
| 874 | }
|
---|
| 875 | }
|
---|
| 876 | return 0;
|
---|
| 877 |
|
---|
| 878 | default:
|
---|
| 879 | i = _IOC_NR(cmd);
|
---|
| 880 | DPD(4, "SOUND_MIXER_WRITE(%d)\n", i);
|
---|
| 881 |
|
---|
| 882 | if (i >= SOUND_MIXER_NRDEVICES)
|
---|
| 883 | return -EINVAL;
|
---|
| 884 | get_user_ret(val, (int *) arg, -EFAULT);
|
---|
| 885 | if (emu10k1_mixer_wrch(card, i, val))
|
---|
| 886 | return -EINVAL;
|
---|
| 887 |
|
---|
| 888 | #ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
|
---|
| 889 | return mixer_rdch(card, i, (int *) arg);
|
---|
| 890 | #else /* OSS_DOCUMENTED_MIXER_SEMANTICS */
|
---|
| 891 | return put_user(card->arrwVol[volidx[i]], (int *) arg);
|
---|
| 892 | #endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */
|
---|
| 893 |
|
---|
| 894 | }
|
---|
| 895 | }
|
---|
| 896 |
|
---|
| 897 | static int emu10k1_mixer_open(struct inode *inode, struct file *file)
|
---|
| 898 | {
|
---|
| 899 | int minor = MINOR(inode->i_rdev);
|
---|
| 900 | struct emu10k1_card *card;
|
---|
| 901 | struct list_head *entry;
|
---|
| 902 |
|
---|
| 903 | DPF(4, "emu10k1_mixer_open()\n");
|
---|
| 904 |
|
---|
| 905 | list_for_each(entry, &emu10k1_devs) {
|
---|
| 906 | card = list_entry(entry, struct emu10k1_card, list);
|
---|
| 907 |
|
---|
| 908 | if (card->mixer_num == minor)
|
---|
| 909 | break;
|
---|
| 910 | }
|
---|
| 911 |
|
---|
| 912 | if (entry == &emu10k1_devs)
|
---|
| 913 | return -ENODEV;
|
---|
| 914 |
|
---|
| 915 | MOD_INC_USE_COUNT;
|
---|
| 916 |
|
---|
| 917 | file->private_data = card;
|
---|
| 918 | return 0;
|
---|
| 919 | }
|
---|
| 920 |
|
---|
| 921 | static int emu10k1_mixer_release(struct inode *inode, struct file *file)
|
---|
| 922 | {
|
---|
| 923 | DPF(3, "emu10k1_mixer_release()\n");
|
---|
| 924 | MOD_DEC_USE_COUNT;
|
---|
| 925 | return 0;
|
---|
| 926 | }
|
---|
| 927 |
|
---|
| 928 | #ifdef TARGET_OS2
|
---|
| 929 | //Hello!?! Use standard C!
|
---|
| 930 | struct file_operations emu10k1_mixer_fops =
|
---|
| 931 | {
|
---|
| 932 | &emu10k1_mixer_llseek,
|
---|
| 933 | NULL, /* read */
|
---|
| 934 | NULL, /* write */
|
---|
| 935 | NULL, /* readdir */
|
---|
| 936 | NULL, /* select/poll */
|
---|
| 937 | &emu10k1_mixer_ioctl,
|
---|
| 938 | NULL, /* mmap */
|
---|
| 939 | &emu10k1_mixer_open,
|
---|
| 940 | #if LINUX_VERSION_CODE >= 0x020100
|
---|
| 941 | NULL, /* flush */
|
---|
| 942 | #endif
|
---|
| 943 | &emu10k1_mixer_release,
|
---|
| 944 | NULL, /* fsync */
|
---|
| 945 | NULL, /* fasync */
|
---|
| 946 | NULL /* check_media_change */
|
---|
| 947 | };
|
---|
| 948 | #else
|
---|
| 949 | struct file_operations emu10k1_mixer_fops = {
|
---|
| 950 | llseek:emu10k1_mixer_llseek,
|
---|
| 951 | ioctl:emu10k1_mixer_ioctl,
|
---|
| 952 | open:emu10k1_mixer_open,
|
---|
| 953 | release:emu10k1_mixer_release,
|
---|
| 954 | };
|
---|
| 955 | #endif
|
---|