OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [sound/] [sb_mixer.c] - Blame information for rev 1777

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1626 jcastillo
 
2
/*
3
 * sound/sb_mixer.c
4
 *
5
 * The low level mixer driver for the Sound Blaster compatible cards.
6
 */
7
/*
8
 * Copyright (C) by Hannu Savolainen 1993-1996
9
 *
10
 * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
11
 * Version 2 (June 1991). See the "COPYING" file distributed with this software
12
 * for more info.
13
 */
14
#include <linux/config.h>
15
 
16
 
17
#include "sound_config.h"
18
 
19
#if defined(CONFIG_SBDSP)
20
#define __SB_MIXER_C__
21
 
22
#include "sb.h"
23
#include "sb_mixer.h"
24
 
25
void            sb_mixer_reset (sb_devc * devc);
26
 
27
void
28
sb_mixer_set_stereo (sb_devc * devc, int mode)
29
{
30
  sb_setmixer (devc, OUT_FILTER, ((sb_getmixer (devc, OUT_FILTER) & ~STEREO_DAC)
31
                                  | (mode ? STEREO_DAC : MONO_DAC)));
32
}
33
 
34
static int
35
detect_mixer (sb_devc * devc)
36
{
37
  /*
38
   * Detect the mixer by changing parameters of two volume channels. If the
39
   * values read back match with the values written, the mixer is there (is
40
   * it?)
41
   */
42
  sb_setmixer (devc, FM_VOL, 0xff);
43
  sb_setmixer (devc, VOC_VOL, 0x33);
44
 
45
  if (sb_getmixer (devc, FM_VOL) != 0xff)
46
    return 0;
47
  if (sb_getmixer (devc, VOC_VOL) != 0x33)
48
    return 0;
49
 
50
  return 1;
51
}
52
 
53
static void
54
change_bits (sb_devc * devc, unsigned char *regval, int dev, int chn, int newval)
55
{
56
  unsigned char   mask;
57
  int             shift;
58
 
59
  mask = (1 << (*devc->iomap)[dev][chn].nbits) - 1;
60
  newval = (int) ((newval * mask) + 50) / 100;  /* Scale */
61
 
62
  shift = (*devc->iomap)[dev][chn].bitoffs - (*devc->iomap)[dev][LEFT_CHN].nbits + 1;
63
 
64
  *regval &= ~(mask << shift);  /* Mask out previous value */
65
  *regval |= (newval & mask) << shift;  /* Set the new value */
66
}
67
 
68
static int
69
sb_mixer_get (sb_devc * devc, int dev)
70
{
71
  if (!((1 << dev) & devc->supported_devices))
72
    return -(EINVAL);
73
 
74
  return devc->levels[dev];
75
}
76
 
77
void
78
smw_mixer_init (sb_devc * devc)
79
{
80
  int             i;
81
 
82
  sb_setmixer (devc, 0x00, 0x18);       /* Mute unused (Telephone) line */
83
  sb_setmixer (devc, 0x10, 0x38);       /* Config register 2 */
84
 
85
  devc->supported_devices = 0;
86
  for (i = 0; i < sizeof (smw_mix_regs); i++)
87
    if (smw_mix_regs[i] != 0)
88
      devc->supported_devices |= (1 << i);
89
 
90
  devc->supported_rec_devices = devc->supported_devices &
91
    ~(SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_PCM |
92
      SOUND_MASK_VOLUME);
93
 
94
  sb_mixer_reset (devc);
95
}
96
 
97
static int
98
smw_mixer_set (sb_devc * devc, int dev, int value)
99
{
100
  int             left = value & 0x000000ff;
101
  int             right = (value & 0x0000ff00) >> 8;
102
  int             reg, val;
103
 
104
  if (left > 100)
105
    left = 100;
106
  if (right > 100)
107
    right = 100;
108
 
109
  if (dev > 31)
110
    return -(EINVAL);
111
 
112
  if (!(devc->supported_devices & (1 << dev)))  /* Not supported */
113
    return -(EINVAL);
114
 
115
  switch (dev)
116
    {
117
    case SOUND_MIXER_VOLUME:
118
      sb_setmixer (devc, 0x0b, 96 - (96 * left / 100));         /* 96=mute, 0=max */
119
      sb_setmixer (devc, 0x0c, 96 - (96 * right / 100));
120
      break;
121
 
122
    case SOUND_MIXER_BASS:
123
    case SOUND_MIXER_TREBLE:
124
      devc->levels[dev] = left | (right << 8);
125
 
126
      /* Set left bass and treble values */
127
      val = ((devc->levels[SOUND_MIXER_TREBLE] & 0xff) * 16 / (unsigned) 100) << 4;
128
      val |= ((devc->levels[SOUND_MIXER_BASS] & 0xff) * 16 / (unsigned) 100) & 0x0f;
129
      sb_setmixer (devc, 0x0d, val);
130
 
131
      /* Set right bass and treble values */
132
      val = (((devc->levels[SOUND_MIXER_TREBLE] >> 8) & 0xff) * 16 / (unsigned) 100) << 4;
133
      val |= (((devc->levels[SOUND_MIXER_BASS] >> 8) & 0xff) * 16 / (unsigned) 100) & 0x0f;
134
      sb_setmixer (devc, 0x0e, val);
135
      break;
136
 
137
    default:
138
      reg = smw_mix_regs[dev];
139
      if (reg == 0)
140
        return -(EINVAL);
141
      sb_setmixer (devc, reg, (24 - (24 * left / 100)) | 0x20);         /* 24=mute, 0=max */
142
      sb_setmixer (devc, reg + 1, (24 - (24 * right / 100)) | 0x40);
143
    }
144
 
145
  devc->levels[dev] = left | (right << 8);
146
  return left | (right << 8);
147
}
148
 
149
static int
150
sb_mixer_set (sb_devc * devc, int dev, int value)
151
{
152
  int             left = value & 0x000000ff;
153
  int             right = (value & 0x0000ff00) >> 8;
154
 
155
  int             regoffs;
156
  unsigned char   val;
157
 
158
  if (devc->model == MDL_SMW)
159
    return smw_mixer_set (devc, dev, value);
160
 
161
  if (left > 100)
162
    left = 100;
163
  if (right > 100)
164
    right = 100;
165
 
166
  if (dev > 31)
167
    return -(EINVAL);
168
 
169
  if (!(devc->supported_devices & (1 << dev)))  /*
170
                                                 * Not supported
171
                                                 */
172
    return -(EINVAL);
173
 
174
  regoffs = (*devc->iomap)[dev][LEFT_CHN].regno;
175
 
176
  if (regoffs == 0)
177
    return -(EINVAL);
178
 
179
  val = sb_getmixer (devc, regoffs);
180
  change_bits (devc, &val, dev, LEFT_CHN, left);
181
 
182
  devc->levels[dev] = left | (left << 8);
183
 
184
  if ((*devc->iomap)[dev][RIGHT_CHN].regno != regoffs)  /*
185
                                                         * Change register
186
                                                         */
187
    {
188
      sb_setmixer (devc, regoffs, val);         /*
189
                                                 * Save the old one
190
                                                 */
191
      regoffs = (*devc->iomap)[dev][RIGHT_CHN].regno;
192
 
193
      if (regoffs == 0)
194
        return left | (left << 8);      /*
195
                                         * Just left channel present
196
                                         */
197
 
198
      val = sb_getmixer (devc, regoffs);        /*
199
                                                   * Read the new one
200
                                                 */
201
    }
202
 
203
  change_bits (devc, &val, dev, RIGHT_CHN, right);
204
 
205
  sb_setmixer (devc, regoffs, val);
206
 
207
  devc->levels[dev] = left | (right << 8);
208
  return left | (right << 8);
209
}
210
 
211
static void
212
set_recsrc (sb_devc * devc, int src)
213
{
214
  sb_setmixer (devc, RECORD_SRC, (sb_getmixer (devc, RECORD_SRC) & ~7) | (src & 0x7));
215
}
216
 
217
static int
218
set_recmask (sb_devc * devc, int mask)
219
{
220
  int             devmask, i;
221
  unsigned char   regimageL, regimageR;
222
 
223
  devmask = mask & devc->supported_rec_devices;
224
 
225
  switch (devc->model)
226
    {
227
    case MDL_SBPRO:
228
    case MDL_ESS:
229
    case MDL_JAZZ:
230
    case MDL_SMW:
231
 
232
      if (devmask != SOUND_MASK_MIC &&
233
          devmask != SOUND_MASK_LINE &&
234
          devmask != SOUND_MASK_CD)
235
        {                       /*
236
                                 * More than one devices selected. Drop the *
237
                                 * previous selection
238
                                 */
239
          devmask &= ~devc->recmask;
240
        }
241
 
242
      if (devmask != SOUND_MASK_MIC &&
243
          devmask != SOUND_MASK_LINE &&
244
          devmask != SOUND_MASK_CD)
245
        {                       /*
246
                                 * More than one devices selected. Default to
247
                                 * * mic
248
                                 */
249
          devmask = SOUND_MASK_MIC;
250
        }
251
 
252
 
253
      if (devmask ^ devc->recmask)      /*
254
                                           * Input source changed
255
                                         */
256
        {
257
          switch (devmask)
258
            {
259
 
260
            case SOUND_MASK_MIC:
261
              set_recsrc (devc, SRC__MIC);
262
              break;
263
 
264
            case SOUND_MASK_LINE:
265
              set_recsrc (devc, SRC__LINE);
266
              break;
267
 
268
            case SOUND_MASK_CD:
269
              set_recsrc (devc, SRC__CD);
270
              break;
271
 
272
            default:
273
              set_recsrc (devc, SRC__MIC);
274
            }
275
        }
276
 
277
      break;
278
 
279
    case MDL_SB16:
280
      if (!devmask)
281
        devmask = SOUND_MASK_MIC;
282
 
283
      regimageL = regimageR = 0;
284
      for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
285
        if ((1 << i) & devmask)
286
          {
287
            regimageL |= sb16_recmasks_L[i];
288
            regimageR |= sb16_recmasks_R[i];
289
          }
290
      sb_setmixer (devc, SB16_IMASK_L, regimageL);
291
      sb_setmixer (devc, SB16_IMASK_R, regimageR);
292
      break;
293
    }
294
 
295
  devc->recmask = devmask;
296
  return devc->recmask;
297
}
298
 
299
static int
300
sb_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
301
{
302
  sb_devc        *devc = mixer_devs[dev]->devc;
303
 
304
  if (((cmd >> 8) & 0xff) == 'M')
305
    {
306
      if (_IOC_DIR (cmd) & _IOC_WRITE)
307
        switch (cmd & 0xff)
308
          {
309
          case SOUND_MIXER_RECSRC:
310
            return snd_ioctl_return ((int *) arg, set_recmask (devc, get_user ((int *) arg)));
311
            break;
312
 
313
          default:
314
 
315
            return snd_ioctl_return ((int *) arg, sb_mixer_set (devc, cmd & 0xff, get_user ((int *) arg)));
316
          }
317
      else
318
        switch (cmd & 0xff)
319
          {
320
 
321
          case SOUND_MIXER_RECSRC:
322
            return snd_ioctl_return ((int *) arg, devc->recmask);
323
            break;
324
 
325
          case SOUND_MIXER_DEVMASK:
326
            return snd_ioctl_return ((int *) arg, devc->supported_devices);
327
            break;
328
 
329
          case SOUND_MIXER_STEREODEVS:
330
            if (devc->model == MDL_JAZZ || devc->model == MDL_SMW)
331
              return snd_ioctl_return ((int *) arg, devc->supported_devices);
332
            else
333
              return snd_ioctl_return ((int *) arg, devc->supported_devices & ~(SOUND_MASK_MIC | SOUND_MASK_SPEAKER));
334
            break;
335
 
336
          case SOUND_MIXER_RECMASK:
337
            return snd_ioctl_return ((int *) arg, devc->supported_rec_devices);
338
            break;
339
 
340
          case SOUND_MIXER_CAPS:
341
            return snd_ioctl_return ((int *) arg, devc->mixer_caps);
342
            break;
343
 
344
          default:
345
            return snd_ioctl_return ((int *) arg, sb_mixer_get (devc, cmd & 0xff));
346
          }
347
    }
348
  else
349
    return -(EINVAL);
350
}
351
 
352
static struct mixer_operations sb_mixer_operations =
353
{
354
  "SB",
355
  "Sound Blaster",
356
  sb_mixer_ioctl
357
};
358
 
359
void
360
sb_mixer_reset (sb_devc * devc)
361
{
362
  int             i;
363
 
364
  for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
365
    sb_mixer_set (devc, i, devc->levels[i]);
366
  set_recmask (devc, SOUND_MASK_MIC);
367
}
368
 
369
int
370
sb_mixer_init (sb_devc * devc)
371
{
372
  int             mixer_type = 0;
373
 
374
  sb_setmixer (devc, 0x00, 0);   /* Reset mixer */
375
 
376
  if (!(mixer_type = detect_mixer (devc)))
377
    return 0;                    /* No mixer. Why? */
378
 
379
  switch (devc->model)
380
    {
381
    case MDL_SBPRO:
382
    case MDL_JAZZ:
383
      devc->mixer_caps = SOUND_CAP_EXCL_INPUT;
384
      devc->supported_devices = SBPRO_MIXER_DEVICES;
385
      devc->supported_rec_devices = SBPRO_RECORDING_DEVICES;
386
      devc->iomap = &sbpro_mix;
387
      break;
388
 
389
    case MDL_ESS:
390
      devc->mixer_caps = SOUND_CAP_EXCL_INPUT;
391
      devc->supported_devices = ES688_MIXER_DEVICES;
392
      devc->supported_rec_devices = ES688_RECORDING_DEVICES;
393
      devc->iomap = &es688_mix;
394
      break;
395
 
396
    case MDL_SMW:
397
      devc->mixer_caps = SOUND_CAP_EXCL_INPUT;
398
      devc->supported_devices = 0;
399
      devc->supported_rec_devices = 0;
400
      devc->iomap = &sbpro_mix;
401
      smw_mixer_init (devc);
402
      break;
403
 
404
    case MDL_SB16:
405
      devc->mixer_caps = 0;
406
      devc->supported_devices = SB16_MIXER_DEVICES;
407
      devc->supported_rec_devices = SB16_RECORDING_DEVICES;
408
      devc->iomap = &sb16_mix;
409
      break;
410
 
411
    default:
412
      printk ("SB Warning: Unsupported mixer type %d\n", devc->model);
413
      return 0;
414
    }
415
 
416
  if (num_mixers >= MAX_MIXER_DEV)
417
    return 0;
418
 
419
 
420
  mixer_devs[num_mixers] = (struct mixer_operations *) (sound_mem_blocks[sound_nblocks] = vmalloc (sizeof (struct mixer_operations)));
421
 
422
  if (sound_nblocks < 1024)
423
    sound_nblocks++;;
424
  if (mixer_devs[num_mixers] == NULL)
425
    {
426
      printk ("sb_mixer: Can't allocate memory\n");
427
      return 0;
428
    }
429
 
430
  memcpy ((char *) mixer_devs[num_mixers], (char *) &sb_mixer_operations,
431
          sizeof (struct mixer_operations));
432
 
433
  mixer_devs[num_mixers]->devc = devc;
434
  memcpy ((char *) devc->levels, (char *) &default_levels, sizeof (default_levels));
435
 
436
  sb_mixer_reset (devc);
437
  devc->my_mixerdev = num_mixers++;
438
  return 1;
439
}
440
 
441
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.