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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1626 jcastillo
/*
2
 * sound/ics2101.c
3
 *
4
 * Driver for the ICS2101 mixer of GUS v3.7.
5
 */
6
/*
7
 * Copyright (C) by Hannu Savolainen 1993-1996
8
 *
9
 * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
10
 * Version 2 (June 1991). See the "COPYING" file distributed with this software
11
 * for more info.
12
 */
13
#include <linux/config.h>
14
 
15
 
16
#include "sound_config.h"
17
#if defined(CONFIG_GUS)
18
 
19
#include <linux/ultrasound.h>
20
#include "gus_hw.h"
21
 
22
#define MIX_DEVS        (SOUND_MASK_MIC|SOUND_MASK_LINE| \
23
                         SOUND_MASK_SYNTH| \
24
                         SOUND_MASK_CD | SOUND_MASK_VOLUME)
25
 
26
extern int     *gus_osp;
27
extern int      gus_base;
28
static int      volumes[ICS_MIXDEVS];
29
static int      left_fix[ICS_MIXDEVS] =
30
{1, 1, 1, 2, 1, 2};
31
static int      right_fix[ICS_MIXDEVS] =
32
{2, 2, 2, 1, 2, 1};
33
 
34
static int
35
scale_vol (int vol)
36
{
37
  /*
38
     *  Experimental volume scaling by Risto Kankkunen.
39
     *  This should give smoother volume response than just
40
     *  a plain multiplication.
41
   */
42
  int             e;
43
 
44
  if (vol < 0)
45
    vol = 0;
46
  if (vol > 100)
47
    vol = 100;
48
  vol = (31 * vol + 50) / 100;
49
  e = 0;
50
  if (vol)
51
    {
52
      while (vol < 16)
53
        {
54
          vol <<= 1;
55
          e--;
56
        }
57
      vol -= 16;
58
      e += 7;
59
    }
60
  return ((e << 4) + vol);
61
}
62
 
63
static void
64
write_mix (int dev, int chn, int vol)
65
{
66
  int            *selector;
67
  unsigned long   flags;
68
  int             ctrl_addr = dev << 3;
69
  int             attn_addr = dev << 3;
70
 
71
  vol = scale_vol (vol);
72
 
73
  if (chn == CHN_LEFT)
74
    {
75
      selector = left_fix;
76
      ctrl_addr |= 0x00;
77
      attn_addr |= 0x02;
78
    }
79
  else
80
    {
81
      selector = right_fix;
82
      ctrl_addr |= 0x01;
83
      attn_addr |= 0x03;
84
    }
85
 
86
  save_flags (flags);
87
  cli ();
88
  outb (ctrl_addr, u_MixSelect);
89
  outb (selector[dev], u_MixData);
90
  outb (attn_addr, u_MixSelect);
91
  outb ((unsigned char) vol, u_MixData);
92
  restore_flags (flags);
93
}
94
 
95
static int
96
set_volumes (int dev, int vol)
97
{
98
  int             left = vol & 0x00ff;
99
  int             right = (vol >> 8) & 0x00ff;
100
 
101
  if (left < 0)
102
    left = 0;
103
  if (left > 100)
104
    left = 100;
105
  if (right < 0)
106
    right = 0;
107
  if (right > 100)
108
    right = 100;
109
 
110
  write_mix (dev, CHN_LEFT, left);
111
  write_mix (dev, CHN_RIGHT, right);
112
 
113
  vol = left + (right << 8);
114
  volumes[dev] = vol;
115
  return vol;
116
}
117
 
118
static int
119
ics2101_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
120
{
121
  if (((cmd >> 8) & 0xff) == 'M')
122
    {
123
      if (_IOC_DIR (cmd) & _IOC_WRITE)
124
        switch (cmd & 0xff)
125
          {
126
          case SOUND_MIXER_RECSRC:
127
            return gus_default_mixer_ioctl (dev, cmd, arg);
128
            break;
129
 
130
          case SOUND_MIXER_MIC:
131
            return snd_ioctl_return ((int *) arg, set_volumes (DEV_MIC, get_user ((int *) arg)));
132
            break;
133
 
134
          case SOUND_MIXER_CD:
135
            return snd_ioctl_return ((int *) arg, set_volumes (DEV_CD, get_user ((int *) arg)));
136
            break;
137
 
138
          case SOUND_MIXER_LINE:
139
            return snd_ioctl_return ((int *) arg, set_volumes (DEV_LINE, get_user ((int *) arg)));
140
            break;
141
 
142
          case SOUND_MIXER_SYNTH:
143
            return snd_ioctl_return ((int *) arg, set_volumes (DEV_GF1, get_user ((int *) arg)));
144
            break;
145
 
146
          case SOUND_MIXER_VOLUME:
147
            return snd_ioctl_return ((int *) arg, set_volumes (DEV_VOL, get_user ((int *) arg)));
148
            break;
149
 
150
          default:
151
            return -(EINVAL);
152
          }
153
      else
154
        switch (cmd & 0xff)     /*
155
                                 * Return parameters
156
                                 */
157
          {
158
 
159
          case SOUND_MIXER_RECSRC:
160
            return gus_default_mixer_ioctl (dev, cmd, arg);
161
            break;
162
 
163
          case SOUND_MIXER_DEVMASK:
164
            return snd_ioctl_return ((int *) arg, MIX_DEVS);
165
            break;
166
 
167
          case SOUND_MIXER_STEREODEVS:
168
            return snd_ioctl_return ((int *) arg, SOUND_MASK_LINE | SOUND_MASK_CD | SOUND_MASK_SYNTH | SOUND_MASK_VOLUME | SOUND_MASK_MIC);
169
            break;
170
 
171
          case SOUND_MIXER_RECMASK:
172
            return snd_ioctl_return ((int *) arg, SOUND_MASK_MIC | SOUND_MASK_LINE);
173
            break;
174
 
175
          case SOUND_MIXER_CAPS:
176
            return snd_ioctl_return ((int *) arg, 0);
177
            break;
178
 
179
          case SOUND_MIXER_MIC:
180
            return snd_ioctl_return ((int *) arg, volumes[DEV_MIC]);
181
            break;
182
 
183
          case SOUND_MIXER_LINE:
184
            return snd_ioctl_return ((int *) arg, volumes[DEV_LINE]);
185
            break;
186
 
187
          case SOUND_MIXER_CD:
188
            return snd_ioctl_return ((int *) arg, volumes[DEV_CD]);
189
            break;
190
 
191
          case SOUND_MIXER_VOLUME:
192
            return snd_ioctl_return ((int *) arg, volumes[DEV_VOL]);
193
            break;
194
 
195
          case SOUND_MIXER_SYNTH:
196
            return snd_ioctl_return ((int *) arg, volumes[DEV_GF1]);
197
            break;
198
 
199
          default:
200
            return -(EINVAL);
201
          }
202
    }
203
 
204
  return -(EINVAL);
205
}
206
 
207
static struct mixer_operations ics2101_mixer_operations =
208
{
209
  "ICS2101",
210
  "ICS2101 Multimedia Mixer",
211
  ics2101_mixer_ioctl
212
};
213
 
214
void
215
ics2101_mixer_init (void)
216
{
217
  int             i;
218
 
219
  if (num_mixers < MAX_MIXER_DEV)
220
    {
221
      mixer_devs[num_mixers++] = &ics2101_mixer_operations;
222
 
223
      /*
224
         * Some GUS v3.7 cards had some channels flipped. Disable
225
         * the flipping feature if the model id is other than 5.
226
       */
227
 
228
      if (inb (u_MixSelect) != 5)
229
        {
230
          for (i = 0; i < ICS_MIXDEVS; i++)
231
            left_fix[i] = 1;
232
          for (i = 0; i < ICS_MIXDEVS; i++)
233
            right_fix[i] = 2;
234
        }
235
 
236
      set_volumes (DEV_GF1, 0x5a5a);
237
      set_volumes (DEV_CD, 0x5a5a);
238
      set_volumes (DEV_MIC, 0x0000);
239
      set_volumes (DEV_LINE, 0x5a5a);
240
      set_volumes (DEV_VOL, 0x5a5a);
241
      set_volumes (DEV_UNUSED, 0x0000);
242
    }
243
 
244
}
245
 
246
#endif

powered by: WebSVN 2.1.0

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