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

Subversion Repositories or1k

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

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

Line No. Rev Author Line
1 1626 jcastillo
/*
2
 * sound/cs4232.c
3
 *
4
 * The low level driver for Crystal CS4232 based cards. The CS4232 is
5
 * a PnP compatible chip which contains a CS4231A codec, SB emulation,
6
 * a MPU401 compatible MIDI port, joystick and synthesizer and IDE CD-ROM
7
 * interfaces. This is just a temporary driver until full PnP support
8
 * gets implemented. Just the WSS codec, FM synth and the MIDI ports are
9
 * supported. Other interfaces are left uninitialized.
10
 */
11
/*
12
 * Copyright (C) by Hannu Savolainen 1993-1996
13
 *
14
 * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
15
 * Version 2 (June 1991). See the "COPYING" file distributed with this software
16
 * for more info.
17
 */
18
#include <linux/config.h>
19
 
20
 
21
#include "sound_config.h"
22
 
23
#if defined(CONFIG_CS4232)
24
 
25
#define KEY_PORT        0x279   /* Same as LPT1 status port */
26
#define CSN_NUM         0x99    /* Just a random number */
27
 
28
static int     *osp;
29
 
30
static void
31
CS_OUT (unsigned char a)
32
{
33
  outb (a, KEY_PORT);
34
}
35
#define CS_OUT2(a, b)           {CS_OUT(a);CS_OUT(b);}
36
#define CS_OUT3(a, b, c)        {CS_OUT(a);CS_OUT(b);CS_OUT(c);}
37
 
38
static int      mpu_base = 0, mpu_irq = 0;
39
static int      mpu_detected = 0;
40
 
41
int
42
probe_cs4232_mpu (struct address_info *hw_config)
43
{
44
/*
45
 * Just write down the config values.
46
 */
47
 
48
  mpu_base = hw_config->io_base;
49
  mpu_irq = hw_config->irq;
50
 
51
  return 0;
52
}
53
 
54
void
55
attach_cs4232_mpu (struct address_info *hw_config)
56
{
57
}
58
 
59
static unsigned char crystal_key[] =    /* A 32 byte magic key sequence */
60
{
61
  0x96, 0x35, 0x9a, 0xcd, 0xe6, 0xf3, 0x79, 0xbc,
62
  0x5e, 0xaf, 0x57, 0x2b, 0x15, 0x8a, 0xc5, 0xe2,
63
  0xf1, 0xf8, 0x7c, 0x3e, 0x9f, 0x4f, 0x27, 0x13,
64
  0x09, 0x84, 0x42, 0xa1, 0xd0, 0x68, 0x34, 0x1a
65
};
66
 
67
int
68
probe_cs4232 (struct address_info *hw_config)
69
{
70
  int             i, n;
71
  int             base = hw_config->io_base, irq = hw_config->irq;
72
  int             dma1 = hw_config->dma, dma2 = hw_config->dma2;
73
 
74
  static wait_handle *cs_sleeper = NULL;
75
  static volatile struct snd_wait cs_sleep_flag =
76
  {0};
77
 
78
  osp = hw_config->osp;
79
 
80
/*
81
 * Verify that the I/O port range is free.
82
 */
83
 
84
  if (check_region (base, 4))
85
    {
86
      printk ("cs4232.c: I/O port 0x%03x not free\n", base);
87
      return 0;
88
    }
89
 
90
  if (ad1848_detect (hw_config->io_base, NULL, hw_config->osp))
91
    return 1;                   /* The card is already active */
92
 
93
/*
94
 * This version of the driver doesn't use the PnP method when configuring
95
 * the card but a simplified method defined by Crystal. This means that
96
 * just one CS4232 compatible device can exist on the system. Also this
97
 * method conflicts with possible PnP support in the OS. For this reason
98
 * driver is just a temporary kludge.
99
 */
100
 
101
/*
102
 * Repeat initialization few times since it doesn't always succeed in
103
 * first time.
104
 */
105
 
106
  for (n = 0; n < 4; n++)
107
    {
108
      cs_sleep_flag.flags = WK_NONE;
109
/*
110
 * Wake up the card by sending a 32 byte Crystal key to the key port.
111
 */
112
      for (i = 0; i < 32; i++)
113
        CS_OUT (crystal_key[i]);
114
 
115
 
116
      {
117
        unsigned long   tlimit;
118
 
119
        if (HZ / 10)
120
          current_set_timeout (tlimit = jiffies + (HZ / 10));
121
        else
122
          tlimit = (unsigned long) -1;
123
        cs_sleep_flag.flags = WK_SLEEP;
124
        module_interruptible_sleep_on (&cs_sleeper);
125
        if (!(cs_sleep_flag.flags & WK_WAKEUP))
126
          {
127
            if (jiffies >= tlimit)
128
              cs_sleep_flag.flags |= WK_TIMEOUT;
129
          }
130
        cs_sleep_flag.flags &= ~WK_SLEEP;
131
      };                        /* Delay */
132
 
133
/*
134
 * Now set the CSN (Card Select Number).
135
 */
136
 
137
      CS_OUT2 (0x06, CSN_NUM);
138
 
139
 
140
/*
141
 * Then set some config bytes. First logical device 0
142
 */
143
 
144
      CS_OUT2 (0x15, 0x00);     /* Select logical device 0 (WSS/SB/FM) */
145
      CS_OUT3 (0x47, (base >> 8) & 0xff, base & 0xff);  /* WSS base */
146
 
147
      if (check_region (0x388, 4))      /* Not free */
148
        CS_OUT3 (0x48, 0x00, 0x00)      /* FM base off */
149
          else
150
        CS_OUT3 (0x48, 0x03, 0x88);     /* FM base 0x388 */
151
 
152
      CS_OUT3 (0x42, 0x00, 0x00);       /* SB base off */
153
      CS_OUT2 (0x22, irq);      /* SB+WSS IRQ */
154
      CS_OUT2 (0x2a, dma1);     /* SB+WSS DMA */
155
 
156
      if (dma2 != -1)
157
        CS_OUT2 (0x25, dma2)    /* WSS DMA2 */
158
          else
159
        CS_OUT2 (0x25, 4);      /* No WSS DMA2 */
160
 
161
      CS_OUT2 (0x33, 0x01);     /* Activate logical dev 0 */
162
 
163
 
164
      {
165
        unsigned long   tlimit;
166
 
167
        if (HZ / 10)
168
          current_set_timeout (tlimit = jiffies + (HZ / 10));
169
        else
170
          tlimit = (unsigned long) -1;
171
        cs_sleep_flag.flags = WK_SLEEP;
172
        module_interruptible_sleep_on (&cs_sleeper);
173
        if (!(cs_sleep_flag.flags & WK_WAKEUP))
174
          {
175
            if (jiffies >= tlimit)
176
              cs_sleep_flag.flags |= WK_TIMEOUT;
177
          }
178
        cs_sleep_flag.flags &= ~WK_SLEEP;
179
      };                        /* Delay */
180
 
181
/*
182
 * Initialize logical device 3 (MPU)
183
 */
184
 
185
#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
186
      if (mpu_base != 0 && mpu_irq != 0)
187
        {
188
          CS_OUT2 (0x15, 0x03); /* Select logical device 3 (MPU) */
189
          CS_OUT3 (0x47, (mpu_base >> 8) & 0xff, mpu_base & 0xff);      /* MPU base */
190
          CS_OUT2 (0x22, mpu_irq);      /* MPU IRQ */
191
          CS_OUT2 (0x33, 0x01); /* Activate logical dev 3 */
192
        }
193
#endif
194
 
195
/*
196
 * Finally activate the chip
197
 */
198
      CS_OUT (0x79);
199
 
200
 
201
      {
202
        unsigned long   tlimit;
203
 
204
        if (HZ / 5)
205
          current_set_timeout (tlimit = jiffies + (HZ / 5));
206
        else
207
          tlimit = (unsigned long) -1;
208
        cs_sleep_flag.flags = WK_SLEEP;
209
        module_interruptible_sleep_on (&cs_sleeper);
210
        if (!(cs_sleep_flag.flags & WK_WAKEUP))
211
          {
212
            if (jiffies >= tlimit)
213
              cs_sleep_flag.flags |= WK_TIMEOUT;
214
          }
215
        cs_sleep_flag.flags &= ~WK_SLEEP;
216
      };                        /* Delay */
217
 
218
/*
219
 * Then try to detect the codec part of the chip
220
 */
221
 
222
      if (ad1848_detect (hw_config->io_base, NULL, hw_config->osp))
223
        return 1;
224
 
225
 
226
      {
227
        unsigned long   tlimit;
228
 
229
        if (HZ)
230
          current_set_timeout (tlimit = jiffies + (HZ));
231
        else
232
          tlimit = (unsigned long) -1;
233
        cs_sleep_flag.flags = WK_SLEEP;
234
        module_interruptible_sleep_on (&cs_sleeper);
235
        if (!(cs_sleep_flag.flags & WK_WAKEUP))
236
          {
237
            if (jiffies >= tlimit)
238
              cs_sleep_flag.flags |= WK_TIMEOUT;
239
          }
240
        cs_sleep_flag.flags &= ~WK_SLEEP;
241
      };                        /* Longer delay */
242
    }
243
 
244
  return 0;
245
}
246
 
247
void
248
attach_cs4232 (struct address_info *hw_config)
249
{
250
  int             base = hw_config->io_base, irq = hw_config->irq;
251
  int             dma1 = hw_config->dma, dma2 = hw_config->dma2;
252
 
253
  if (dma2 == -1)
254
    dma2 = dma1;
255
 
256
  ad1848_init ("CS4232", base,
257
               irq,
258
               dma1,            /* Playback DMA */
259
               dma2,            /* Capture DMA */
260
               0,
261
               hw_config->osp);
262
 
263
#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
264
  if (mpu_base != 0 && mpu_irq != 0)
265
    {
266
      static struct address_info hw_config2 =
267
      {0};                       /* Ensure it's initialized */
268
 
269
      hw_config2.io_base = mpu_base;
270
      hw_config2.irq = mpu_irq;
271
      hw_config2.dma = -1;
272
      hw_config2.dma2 = -1;
273
      hw_config2.always_detect = 0;
274
      hw_config2.name = NULL;
275
      hw_config2.driver_use_1 = 0;
276
      hw_config2.driver_use_2 = 0;
277
      hw_config2.card_subtype = 0;
278
      hw_config2.osp = hw_config->osp;
279
 
280
      if (probe_mpu401 (&hw_config2))
281
        {
282
          mpu_detected = 1;
283
          attach_mpu401 (&hw_config2);
284
        }
285
      else
286
        {
287
          mpu_base = mpu_irq = 0;
288
        }
289
    }
290
#endif
291
}
292
 
293
void
294
unload_cs4232 (struct address_info *hw_config)
295
{
296
  int             base = hw_config->io_base, irq = hw_config->irq;
297
  int             dma1 = hw_config->dma, dma2 = hw_config->dma2;
298
 
299
  if (dma2 == -1)
300
    dma2 = dma1;
301
 
302
  ad1848_unload (base,
303
                 irq,
304
                 dma1,          /* Playback DMA */
305
                 dma2,          /* Capture DMA */
306
                 0);
307
 
308
#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
309
  if (mpu_base != 0 && mpu_irq != 0 && mpu_detected)
310
    {
311
      static struct address_info hw_config2 =
312
      {0};                       /* Ensure it's initialized */
313
 
314
      hw_config2.io_base = mpu_base;
315
      hw_config2.irq = mpu_irq;
316
      hw_config2.dma = -1;
317
      hw_config2.dma2 = -1;
318
      hw_config2.always_detect = 0;
319
      hw_config2.name = NULL;
320
      hw_config2.driver_use_1 = 0;
321
      hw_config2.driver_use_2 = 0;
322
      hw_config2.card_subtype = 0;
323
      hw_config2.osp = hw_config->osp;
324
 
325
      unload_mpu401 (&hw_config2);
326
    }
327
#endif
328
}
329
 
330
void
331
unload_cs4232_mpu (struct address_info *hw_config)
332
{
333
  /* Not required. Handled by cs4232_unload */
334
}
335
 
336
 
337
#endif

powered by: WebSVN 2.1.0

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