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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1626 jcastillo
#define _PAS2_CARD_C_
2
/*
3
 * sound/pas2_card.c
4
 *
5
 * Detection routine for the Pro Audio Spectrum cards.
6
 */
7
 
8
#include <linux/config.h>
9
 
10
#include "sound_config.h"
11
 
12
#if defined(CONFIG_PAS)
13
 
14
static unsigned char dma_bits[] =
15
{4, 1, 2, 3, 0, 5, 6, 7};
16
static unsigned char irq_bits[] =
17
{0, 0, 1, 2, 3, 4, 5, 6, 0, 1, 7, 8, 9, 0, 10, 11};
18
static unsigned char sb_irq_bits[] =
19
{0x00, 0x00, 0x08, 0x10, 0x00, 0x18, 0x00, 0x20, 0x00, 0x08, 0x28, 0x30, 0x38, 0, 0};
20
static unsigned char sb_dma_bits[] =
21
{0x00, 0x40, 0x80, 0xC0, 0, 0, 0, 0};
22
 
23
/*
24
 * The Address Translation code is used to convert I/O register addresses to
25
 * be relative to the given base -register
26
 */
27
 
28
int             translate_code;
29
static int      pas_intr_mask = 0;
30
static int      pas_irq = 0;
31
static int      pas_sb_base = 0;
32
 
33
int            *pas_osp;
34
 
35
char            pas_model;
36
static char    *pas_model_names[] =
37
{"", "Pro AudioSpectrum+", "CDPC", "Pro AudioSpectrum 16", "Pro AudioSpectrum 16D"};
38
 
39
/*
40
 * pas_read() and pas_write() are equivalents of inb and outb
41
 * These routines perform the I/O address translation required
42
 * to support other than the default base address
43
 */
44
extern void     mix_write (unsigned char data, int ioaddr);
45
 
46
unsigned char
47
pas_read (int ioaddr)
48
{
49
  return inb (ioaddr ^ translate_code);
50
}
51
 
52
void
53
pas_write (unsigned char data, int ioaddr)
54
{
55
  outb (data, ioaddr ^ translate_code);
56
}
57
 
58
/******************* Begin of the Interrupt Handler ********************/
59
 
60
void
61
pasintr (int irq, void *dev_id, struct pt_regs *dummy)
62
{
63
  int             status;
64
 
65
  status = pas_read (0x0B89);
66
  pas_write (status, 0x0B89);   /* Clear interrupt */
67
 
68
  if (status & 0x08)
69
    {
70
#ifdef CONFIG_AUDIO
71
      pas_pcm_interrupt (status, 1);
72
#endif
73
      status &= ~0x08;
74
    }
75
  if (status & 0x10)
76
    {
77
#ifdef CONFIG_MIDI
78
      pas_midi_interrupt ();
79
#endif
80
      status &= ~0x10;
81
    }
82
}
83
 
84
int
85
pas_set_intr (int mask)
86
{
87
  if (!mask)
88
    return 0;
89
 
90
  pas_intr_mask |= mask;
91
 
92
  pas_write (pas_intr_mask, 0x0B8B);
93
  return 0;
94
}
95
 
96
int
97
pas_remove_intr (int mask)
98
{
99
  if (!mask)
100
    return 0;
101
 
102
  pas_intr_mask &= ~mask;
103
  pas_write (pas_intr_mask, 0x0B8B);
104
 
105
  return 0;
106
}
107
 
108
/******************* End of the Interrupt handler **********************/
109
 
110
/******************* Begin of the Initialization Code ******************/
111
 
112
int
113
config_pas_hw (struct address_info *hw_config)
114
{
115
  char            ok = 1;
116
  unsigned        int_ptrs;     /* scsi/sound interrupt pointers */
117
 
118
  pas_irq = hw_config->irq;
119
 
120
  pas_write (0x00, 0x0B8B);
121
 
122
  pas_write (0x36, 0x138B);     /*
123
                                   * Local timer control *
124
                                   * register
125
                                 */
126
 
127
  pas_write (0x36, 0x1388);     /*
128
                                   * Sample rate timer (16 bit)
129
                                 */
130
  pas_write (0, 0x1388);
131
 
132
  pas_write (0x74, 0x138B);     /*
133
                                   * Local timer control *
134
                                   * register
135
                                 */
136
 
137
  pas_write (0x74, 0x1389);     /*
138
                                   * Sample count register (16
139
                                   * * bit)
140
                                 */
141
  pas_write (0, 0x1389);
142
 
143
  pas_write (0x80 | 0x40 | 0x20 | 1, 0x0B8A);
144
  pas_write (0x80 | 0x20 | 0x10 | 0x08 | 0x01, 0xF8A);
145
  pas_write (0x01 | 0x02 | 0x04 | 0x10  /*
146
                                           * |
147
                                           * 0x80
148
                                         */ , 0xB88);
149
 
150
  pas_write (0x80
151
#ifdef PAS_JOYSTICK_ENABLE
152
             | 0x40
153
#endif
154
             ,0xF388);
155
 
156
  if (pas_irq < 0 || pas_irq > 15)
157
    {
158
      printk ("PAS2: Invalid IRQ %d", pas_irq);
159
      ok = 0;
160
    }
161
  else
162
    {
163
      int_ptrs = pas_read (0xF38A);
164
      int_ptrs |= irq_bits[pas_irq] & 0xf;
165
      pas_write (int_ptrs, 0xF38A);
166
      if (!irq_bits[pas_irq])
167
        {
168
          printk ("PAS2: Invalid IRQ %d", pas_irq);
169
          ok = 0;
170
        }
171
      else
172
        {
173
          if (snd_set_irq_handler (pas_irq, pasintr, "PAS16", hw_config->osp) < 0)
174
            ok = 0;
175
        }
176
    }
177
 
178
  if (hw_config->dma < 0 || hw_config->dma > 7)
179
    {
180
      printk ("PAS2: Invalid DMA selection %d", hw_config->dma);
181
      ok = 0;
182
    }
183
  else
184
    {
185
      pas_write (dma_bits[hw_config->dma], 0xF389);
186
      if (!dma_bits[hw_config->dma])
187
        {
188
          printk ("PAS2: Invalid DMA selection %d", hw_config->dma);
189
          ok = 0;
190
        }
191
      else
192
        {
193
          if (sound_alloc_dma (hw_config->dma, "PAS16"))
194
            {
195
              printk ("pas2_card.c: Can't allocate DMA channel\n");
196
              ok = 0;
197
            }
198
        }
199
    }
200
 
201
  /*
202
     * This fixes the timing problems of the PAS due to the Symphony chipset
203
     * as per Media Vision.  Only define this if your PAS doesn't work correctly.
204
   */
205
#ifdef SYMPHONY_PAS
206
  outb (0x05, 0xa8);
207
  outb (0x60, 0xa9);
208
#endif
209
 
210
#ifdef BROKEN_BUS_CLOCK
211
  pas_write (0x01 | 0x10 | 0x20 | 0x04, 0x8388);
212
#else
213
  /*
214
   * pas_write(0x01, 0x8388);
215
   */
216
  pas_write (0x01 | 0x10 | 0x20, 0x8388);
217
#endif
218
  pas_write (0x18, 0x838A);     /* ??? */
219
  pas_write (0x20 | 0x01, 0x0B8A);      /* Mute off, filter = 17.897 kHz */
220
  pas_write (8, 0xBF8A);
221
 
222
  mix_write (0x80 | 5, 0x078B);
223
  mix_write (5, 0x078B);
224
 
225
#if !defined(DISABLE_SB_EMULATION) && defined(CONFIG_SB)
226
 
227
  {
228
    struct address_info *sb_config;
229
 
230
    if ((sb_config = sound_getconf (SNDCARD_SB)))
231
      {
232
        unsigned char   irq_dma;
233
 
234
        /*
235
         * Turn on Sound Blaster compatibility
236
         * bit 1 = SB emulation
237
         * bit 0 = MPU401 emulation (CDPC only :-( )
238
         */
239
        pas_write (0x02, 0xF788);
240
 
241
        /*
242
         * "Emulation address"
243
         */
244
        pas_write ((sb_config->io_base >> 4) & 0x0f, 0xF789);
245
        pas_sb_base = sb_config->io_base;
246
 
247
        if (!sb_dma_bits[sb_config->dma])
248
          printk ("\n\nPAS16 Warning: Invalid SB DMA %d\n\n",
249
                  sb_config->dma);
250
 
251
        if (!sb_irq_bits[sb_config->irq])
252
          printk ("\n\nPAS16 Warning: Invalid SB IRQ %d\n\n",
253
                  sb_config->irq);
254
 
255
        irq_dma = sb_dma_bits[sb_config->dma] |
256
          sb_irq_bits[sb_config->irq];
257
 
258
        pas_write (irq_dma, 0xFB8A);
259
      }
260
    else
261
      pas_write (0x00, 0xF788);
262
  }
263
#else
264
  pas_write (0x00, 0xF788);
265
#endif
266
 
267
  if (!ok)
268
    printk ("PAS16: Driver not enabled\n");
269
 
270
  return ok;
271
}
272
 
273
int
274
detect_pas_hw (struct address_info *hw_config)
275
{
276
  unsigned char   board_id, foo;
277
 
278
  /*
279
   * WARNING: Setting an option like W:1 or so that disables warm boot reset
280
   * of the card will screw up this detect code something fierce. Adding code
281
   * to handle this means possibly interfering with other cards on the bus if
282
   * you have something on base port 0x388. SO be forewarned.
283
   */
284
 
285
  outb (0xBC, 0x9A01);          /* Activate first board */
286
  outb (hw_config->io_base >> 2, 0x9A01);       /* Set base address */
287
  translate_code = 0x388 ^ hw_config->io_base;
288
  pas_write (1, 0xBF88);        /* Select one wait states */
289
 
290
  board_id = pas_read (0x0B8B);
291
 
292
  if (board_id == 0xff)
293
    return 0;
294
 
295
  /*
296
   * We probably have a PAS-series board, now check for a PAS2-series board
297
   * by trying to change the board revision bits. PAS2-series hardware won't
298
   * let you do this - the bits are read-only.
299
   */
300
 
301
  foo = board_id ^ 0xe0;
302
 
303
  pas_write (foo, 0x0B8B);
304
  foo = inb (0x0B8B);
305
  pas_write (board_id, 0x0B8B);
306
 
307
  if (board_id != foo)          /*
308
                                 * Not a PAS2
309
                                 */
310
    return 0;
311
 
312
  pas_model = pas_read (0xFF88);
313
 
314
  return pas_model;
315
}
316
 
317
void
318
attach_pas_card (struct address_info *hw_config)
319
{
320
  pas_irq = hw_config->irq;
321
  pas_osp = hw_config->osp;
322
 
323
  if (detect_pas_hw (hw_config))
324
    {
325
 
326
      if ((pas_model = pas_read (0xFF88)))
327
        {
328
          char            temp[100];
329
 
330
          sprintf (temp,
331
                   "%s rev %d", pas_model_names[(int) pas_model],
332
                   pas_read (0x2789));
333
          conf_printf (temp, hw_config);
334
        }
335
 
336
      if (config_pas_hw (hw_config))
337
        {
338
 
339
#ifdef CONFIG_AUDIO
340
          pas_pcm_init (hw_config);
341
#endif
342
 
343
#if !defined(DISABLE_SB_EMULATION) && defined(CONFIG_SB)
344
 
345
          sb_dsp_disable_midi (pas_sb_base);    /* No MIDI capability */
346
#endif
347
 
348
 
349
#ifdef CONFIG_MIDI
350
          pas_midi_init ();
351
#endif
352
 
353
          pas_init_mixer ();
354
        }
355
    }
356
 
357
}
358
 
359
int
360
probe_pas (struct address_info *hw_config)
361
{
362
  pas_osp = hw_config->osp;
363
  return detect_pas_hw (hw_config);
364
}
365
 
366
void
367
unload_pas (struct address_info *hw_config)
368
{
369
  sound_free_dma (hw_config->dma);
370
  snd_release_irq (hw_config->irq);
371
}
372
 
373
#endif

powered by: WebSVN 2.1.0

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