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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [sound/] [sscape.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/sscape.c
3
 *
4
 * Low level driver for Ensoniq SoundScape
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
 
18
#if defined(CONFIG_SSCAPE)
19
 
20
#include "coproc.h"
21
 
22
/*
23
 *    I/O ports
24
 */
25
#define MIDI_DATA        0
26
#define MIDI_CTRL        1
27
#define HOST_CTRL        2
28
#define TX_READY                0x02
29
#define RX_READY                0x01
30
#define HOST_DATA        3
31
#define ODIE_ADDR        4
32
#define ODIE_DATA        5
33
 
34
/*
35
 *    Indirect registers
36
 */
37
#define GA_INTSTAT_REG   0
38
#define GA_INTENA_REG    1
39
#define GA_DMAA_REG      2
40
#define GA_DMAB_REG      3
41
#define GA_INTCFG_REG    4
42
#define GA_DMACFG_REG    5
43
#define GA_CDCFG_REG     6
44
#define GA_SMCFGA_REG    7
45
#define GA_SMCFGB_REG    8
46
#define GA_HMCTL_REG     9
47
 
48
/*
49
 * DMA channel identifiers (A and B)
50
 */
51
#define SSCAPE_DMA_A            0
52
#define SSCAPE_DMA_B            1
53
 
54
#define PORT(name)      (devc->base+name)
55
 
56
/*
57
 * Host commands recognized by the OBP microcode
58
 */
59
#define CMD_GEN_HOST_ACK        0x80
60
#define CMD_GEN_MPU_ACK         0x81
61
#define CMD_GET_BOARD_TYPE      0x82
62
#define CMD_SET_CONTROL         0x88
63
#define CMD_GET_CONTROL         0x89
64
#define         CTL_MASTER_VOL          0
65
#define         CTL_MIC_MODE            2
66
#define         CTL_SYNTH_VOL           4
67
#define         CTL_WAVE_VOL            7
68
#define CMD_SET_MT32            0x96
69
#define CMD_GET_MT32            0x97
70
#define CMD_SET_EXTMIDI         0x9b
71
#define CMD_GET_EXTMIDI         0x9c
72
 
73
#define CMD_ACK                 0x80
74
 
75
typedef struct sscape_info
76
  {
77
    int             base, irq, dma;
78
    int             ok;         /* Properly detected */
79
    int             failed;
80
    int             dma_allocated;
81
    int             my_audiodev;
82
    int             opened;
83
    int            *osp;
84
  }
85
 
86
sscape_info;
87
static struct sscape_info dev_info =
88
{0};
89
static struct sscape_info *devc = &dev_info;
90
 
91
static wait_handle *sscape_sleeper = NULL;
92
static volatile struct snd_wait sscape_sleep_flag =
93
{0};
94
 
95
/* Some older cards have assigned interrupt bits differently than new ones */
96
static char     valid_interrupts_old[] =
97
{9, 7, 5, 15};
98
 
99
static char     valid_interrupts_new[] =
100
{9, 5, 7, 10};
101
 
102
static char    *valid_interrupts = valid_interrupts_new;
103
 
104
#ifdef REVEAL_SPEA
105
static char     old_hardware = 1;
106
 
107
#else
108
static char     old_hardware = 0;
109
 
110
#endif
111
 
112
static unsigned char
113
sscape_read (struct sscape_info *devc, int reg)
114
{
115
  unsigned long   flags;
116
  unsigned char   val;
117
 
118
  save_flags (flags);
119
  cli ();
120
  outb (reg, PORT (ODIE_ADDR));
121
  val = inb (PORT (ODIE_DATA));
122
  restore_flags (flags);
123
  return val;
124
}
125
 
126
static void
127
sscape_write (struct sscape_info *devc, int reg, int data)
128
{
129
  unsigned long   flags;
130
 
131
  save_flags (flags);
132
  cli ();
133
  outb (reg, PORT (ODIE_ADDR));
134
  outb (data, PORT (ODIE_DATA));
135
  restore_flags (flags);
136
}
137
 
138
static void
139
host_open (struct sscape_info *devc)
140
{
141
  outb (0x00, PORT (HOST_CTRL));        /* Put the board to the host mode */
142
}
143
 
144
static void
145
host_close (struct sscape_info *devc)
146
{
147
  outb (0x03, PORT (HOST_CTRL));        /* Put the board to the MIDI mode */
148
}
149
 
150
static int
151
host_write (struct sscape_info *devc, unsigned char *data, int count)
152
{
153
  unsigned long   flags;
154
  int             i, timeout_val;
155
 
156
  save_flags (flags);
157
  cli ();
158
 
159
  /*
160
     * Send the command and data bytes
161
   */
162
 
163
  for (i = 0; i < count; i++)
164
    {
165
      for (timeout_val = 10000; timeout_val > 0; timeout_val--)
166
        if (inb (PORT (HOST_CTRL)) & TX_READY)
167
          break;
168
 
169
      if (timeout_val <= 0)
170
        {
171
          restore_flags (flags);
172
          return 0;
173
        }
174
 
175
      outb (data[i], PORT (HOST_DATA));
176
    }
177
 
178
 
179
  restore_flags (flags);
180
 
181
  return 1;
182
}
183
 
184
static int
185
host_read (struct sscape_info *devc)
186
{
187
  unsigned long   flags;
188
  int             timeout_val;
189
  unsigned char   data;
190
 
191
  save_flags (flags);
192
  cli ();
193
 
194
  /*
195
     * Read a byte
196
   */
197
 
198
  for (timeout_val = 10000; timeout_val > 0; timeout_val--)
199
    if (inb (PORT (HOST_CTRL)) & RX_READY)
200
      break;
201
 
202
  if (timeout_val <= 0)
203
    {
204
      restore_flags (flags);
205
      return -1;
206
    }
207
 
208
  data = inb (PORT (HOST_DATA));
209
 
210
  restore_flags (flags);
211
 
212
  return data;
213
}
214
 
215
static int
216
host_command1 (struct sscape_info *devc, int cmd)
217
{
218
  unsigned char   buf[10];
219
 
220
  buf[0] = (unsigned char) (cmd & 0xff);
221
 
222
  return host_write (devc, buf, 1);
223
}
224
 
225
static int
226
host_command2 (struct sscape_info *devc, int cmd, int parm1)
227
{
228
  unsigned char   buf[10];
229
 
230
  buf[0] = (unsigned char) (cmd & 0xff);
231
  buf[1] = (unsigned char) (parm1 & 0xff);
232
 
233
  return host_write (devc, buf, 2);
234
}
235
 
236
static int
237
host_command3 (struct sscape_info *devc, int cmd, int parm1, int parm2)
238
{
239
  unsigned char   buf[10];
240
 
241
  buf[0] = (unsigned char) (cmd & 0xff);
242
  buf[1] = (unsigned char) (parm1 & 0xff);
243
  buf[2] = (unsigned char) (parm2 & 0xff);
244
 
245
  return host_write (devc, buf, 3);
246
}
247
 
248
static void
249
set_mt32 (struct sscape_info *devc, int value)
250
{
251
  host_open (devc);
252
  host_command2 (devc, CMD_SET_MT32,
253
                 value ? 1 : 0);
254
  if (host_read (devc) != CMD_ACK)
255
    {
256
      /* printk ("SNDSCAPE: Setting MT32 mode failed\n"); */
257
    }
258
  host_close (devc);
259
}
260
 
261
static void
262
set_control (struct sscape_info *devc, int ctrl, int value)
263
{
264
  host_open (devc);
265
  host_command3 (devc, CMD_SET_CONTROL, ctrl, value);
266
  if (host_read (devc) != CMD_ACK)
267
    {
268
      /* printk ("SNDSCAPE: Setting control (%d) failed\n", ctrl); */
269
    }
270
  host_close (devc);
271
}
272
 
273
static int
274
get_board_type (struct sscape_info *devc)
275
{
276
  int             tmp;
277
 
278
  host_open (devc);
279
  if (!host_command1 (devc, CMD_GET_BOARD_TYPE))
280
    tmp = -1;
281
  else
282
    tmp = host_read (devc);
283
  host_close (devc);
284
  return tmp;
285
}
286
 
287
void
288
sscapeintr (int irq, void *dev_id, struct pt_regs *dummy)
289
{
290
  unsigned char   bits, tmp;
291
  static int      debug = 0;
292
 
293
  bits = sscape_read (devc, GA_INTSTAT_REG);
294
  if ((sscape_sleep_flag.flags & WK_SLEEP))
295
    {
296
      {
297
        sscape_sleep_flag.flags = WK_WAKEUP;
298
        module_wake_up (&sscape_sleeper);
299
      };
300
    }
301
 
302
  if (bits & 0x02)              /* Host interface interrupt */
303
    {
304
      printk ("SSCAPE: Host interrupt, data=%02x\n", host_read (devc));
305
    }
306
 
307
#if defined(CONFIG_MPU_EMU) && defined(CONFIG_MIDI)
308
  if (bits & 0x01)
309
    {
310
      mpuintr (irq, NULL, NULL);
311
      if (debug++ > 10)         /* Temporary debugging hack */
312
        {
313
          sscape_write (devc, GA_INTENA_REG, 0x00);     /* Disable all interrupts */
314
        }
315
    }
316
#endif
317
 
318
  /*
319
     * Acknowledge interrupts (toggle the interrupt bits)
320
   */
321
 
322
  tmp = sscape_read (devc, GA_INTENA_REG);
323
  sscape_write (devc, GA_INTENA_REG, (~bits & 0x0e) | (tmp & 0xf1));
324
 
325
}
326
 
327
 
328
static void
329
do_dma (struct sscape_info *devc, int dma_chan, unsigned long buf, int blk_size, int mode)
330
{
331
  unsigned char   temp;
332
 
333
  if (dma_chan != SSCAPE_DMA_A)
334
    {
335
      printk ("SSCAPE: Tried to use DMA channel  != A. Why?\n");
336
      return;
337
    }
338
 
339
  audio_devs[devc->my_audiodev]->flags &= ~DMA_AUTOMODE;
340
  DMAbuf_start_dma (devc->my_audiodev,
341
                    buf,
342
                    blk_size, mode);
343
  audio_devs[devc->my_audiodev]->flags |= DMA_AUTOMODE;
344
 
345
  temp = devc->dma << 4;        /* Setup DMA channel select bits */
346
  if (devc->dma <= 3)
347
    temp |= 0x80;               /* 8 bit DMA channel */
348
 
349
  temp |= 1;                    /* Trigger DMA */
350
  sscape_write (devc, GA_DMAA_REG, temp);
351
  temp &= 0xfe;                 /* Clear DMA trigger */
352
  sscape_write (devc, GA_DMAA_REG, temp);
353
}
354
 
355
static int
356
verify_mpu (struct sscape_info *devc)
357
{
358
  /*
359
     * The SoundScape board could be in three modes (MPU, 8250 and host).
360
     * If the card is not in the MPU mode, enabling the MPU driver will
361
     * cause infinite loop (the driver believes that there is always some
362
     * received data in the buffer.
363
     *
364
     * Detect this by looking if there are more than 10 received MIDI bytes
365
     * (0x00) in the buffer.
366
   */
367
 
368
  int             i;
369
 
370
  for (i = 0; i < 10; i++)
371
    {
372
      if (inb (devc->base + HOST_CTRL) & 0x80)
373
        return 1;
374
 
375
      if (inb (devc->base) != 0x00)
376
        return 1;
377
    }
378
 
379
  printk ("SoundScape: The device is not in the MPU-401 mode\n");
380
  return 0;
381
}
382
 
383
static int
384
sscape_coproc_open (void *dev_info, int sub_device)
385
{
386
  if (sub_device == COPR_MIDI)
387
    {
388
      set_mt32 (devc, 0);
389
      if (!verify_mpu (devc))
390
        return -(EIO);
391
    }
392
 
393
  sscape_sleep_flag.flags = WK_NONE;
394
  return 0;
395
}
396
 
397
static void
398
sscape_coproc_close (void *dev_info, int sub_device)
399
{
400
  struct sscape_info *devc = dev_info;
401
  unsigned long   flags;
402
 
403
  save_flags (flags);
404
  cli ();
405
  if (devc->dma_allocated)
406
    {
407
      sscape_write (devc, GA_DMAA_REG, 0x20);   /* DMA channel disabled */
408
      devc->dma_allocated = 0;
409
    }
410
  sscape_sleep_flag.flags = WK_NONE;
411
  restore_flags (flags);
412
 
413
  return;
414
}
415
 
416
static void
417
sscape_coproc_reset (void *dev_info)
418
{
419
}
420
 
421
static int
422
sscape_download_boot (struct sscape_info *devc, unsigned char *block, int size, int flag)
423
{
424
  unsigned long   flags;
425
  unsigned char   temp;
426
  int             done, timeout_val;
427
  static unsigned char codec_dma_bits = 0;
428
 
429
  if (flag & CPF_FIRST)
430
    {
431
      /*
432
         * First block. Have to allocate DMA and to reset the board
433
         * before continuing.
434
       */
435
 
436
      save_flags (flags);
437
      cli ();
438
      codec_dma_bits = sscape_read (devc, GA_CDCFG_REG);
439
#if 0
440
      sscape_write (devc, GA_CDCFG_REG,
441
                    codec_dma_bits & ~0x08);    /* Disable codec DMA */
442
#endif
443
 
444
      if (devc->dma_allocated == 0)
445
        {
446
          devc->dma_allocated = 1;
447
        }
448
      restore_flags (flags);
449
 
450
      sscape_write (devc, GA_HMCTL_REG,
451
                    (temp = sscape_read (devc, GA_HMCTL_REG)) & 0x3f);  /*Reset */
452
 
453
      for (timeout_val = 10000; timeout_val > 0; timeout_val--)
454
        sscape_read (devc, GA_HMCTL_REG);       /* Delay */
455
 
456
      /* Take board out of reset */
457
      sscape_write (devc, GA_HMCTL_REG,
458
                    (temp = sscape_read (devc, GA_HMCTL_REG)) | 0x80);
459
    }
460
 
461
  /*
462
   * Transfer one code block using DMA
463
   */
464
  memcpy (audio_devs[devc->my_audiodev]->dmap_out->raw_buf, block, size);
465
 
466
  save_flags (flags);
467
  cli ();
468
/******** INTERRUPTS DISABLED NOW ********/
469
  do_dma (devc, SSCAPE_DMA_A,
470
          audio_devs[devc->my_audiodev]->dmap_out->raw_buf_phys,
471
          size, DMA_MODE_WRITE);
472
 
473
  /*
474
   * Wait until transfer completes.
475
   */
476
  sscape_sleep_flag.flags = WK_NONE;
477
  done = 0;
478
  timeout_val = 100;
479
  while (!done && timeout_val-- > 0)
480
    {
481
      int             resid;
482
 
483
 
484
      {
485
        unsigned long   tlimit;
486
 
487
        if (1)
488
          current_set_timeout (tlimit = jiffies + (1));
489
        else
490
          tlimit = (unsigned long) -1;
491
        sscape_sleep_flag.flags = WK_SLEEP;
492
        module_interruptible_sleep_on (&sscape_sleeper);
493
        if (!(sscape_sleep_flag.flags & WK_WAKEUP))
494
          {
495
            if (jiffies >= tlimit)
496
              sscape_sleep_flag.flags |= WK_TIMEOUT;
497
          }
498
        sscape_sleep_flag.flags &= ~WK_SLEEP;
499
      };
500
      clear_dma_ff (devc->dma);
501
      if ((resid = get_dma_residue (devc->dma)) == 0)
502
        {
503
          done = 1;
504
        }
505
    }
506
 
507
  restore_flags (flags);
508
  if (!done)
509
    return 0;
510
 
511
  if (flag & CPF_LAST)
512
    {
513
      /*
514
         * Take the board out of reset
515
       */
516
      outb (0x00, PORT (HOST_CTRL));
517
      outb (0x00, PORT (MIDI_CTRL));
518
 
519
      temp = sscape_read (devc, GA_HMCTL_REG);
520
      temp |= 0x40;
521
      sscape_write (devc, GA_HMCTL_REG, temp);  /* Kickstart the board */
522
 
523
      /*
524
         * Wait until the ODB wakes up
525
       */
526
 
527
      save_flags (flags);
528
      cli ();
529
      done = 0;
530
      timeout_val = 5 * HZ;
531
      while (!done && timeout_val-- > 0)
532
        {
533
 
534
          {
535
            unsigned long   tlimit;
536
 
537
            if (1)
538
              current_set_timeout (tlimit = jiffies + (1));
539
            else
540
              tlimit = (unsigned long) -1;
541
            sscape_sleep_flag.flags = WK_SLEEP;
542
            module_interruptible_sleep_on (&sscape_sleeper);
543
            if (!(sscape_sleep_flag.flags & WK_WAKEUP))
544
              {
545
                if (jiffies >= tlimit)
546
                  sscape_sleep_flag.flags |= WK_TIMEOUT;
547
              }
548
            sscape_sleep_flag.flags &= ~WK_SLEEP;
549
          };
550
          if (inb (PORT (HOST_DATA)) == 0xff)   /* OBP startup acknowledge */
551
            done = 1;
552
        }
553
      sscape_write (devc, GA_CDCFG_REG, codec_dma_bits);
554
 
555
      restore_flags (flags);
556
      if (!done)
557
        {
558
          printk ("SoundScape: The OBP didn't respond after code download\n");
559
          return 0;
560
        }
561
 
562
      save_flags (flags);
563
      cli ();
564
      done = 0;
565
      timeout_val = 5 * HZ;
566
      while (!done && timeout_val-- > 0)
567
        {
568
 
569
          {
570
            unsigned long   tlimit;
571
 
572
            if (1)
573
              current_set_timeout (tlimit = jiffies + (1));
574
            else
575
              tlimit = (unsigned long) -1;
576
            sscape_sleep_flag.flags = WK_SLEEP;
577
            module_interruptible_sleep_on (&sscape_sleeper);
578
            if (!(sscape_sleep_flag.flags & WK_WAKEUP))
579
              {
580
                if (jiffies >= tlimit)
581
                  sscape_sleep_flag.flags |= WK_TIMEOUT;
582
              }
583
            sscape_sleep_flag.flags &= ~WK_SLEEP;
584
          };
585
          if (inb (PORT (HOST_DATA)) == 0xfe)   /* Host startup acknowledge */
586
            done = 1;
587
        }
588
      restore_flags (flags);
589
      if (!done)
590
        {
591
          printk ("SoundScape: OBP Initialization failed.\n");
592
          return 0;
593
        }
594
 
595
      printk ("SoundScape board of type %d initialized OK\n",
596
              get_board_type (devc));
597
 
598
      set_control (devc, CTL_MASTER_VOL, 100);
599
      set_control (devc, CTL_SYNTH_VOL, 100);
600
 
601
#ifdef SSCAPE_DEBUG3
602
      /*
603
         * Temporary debugging aid. Print contents of the registers after
604
         * downloading the code.
605
       */
606
      {
607
        int             i;
608
 
609
        for (i = 0; i < 13; i++)
610
          printk ("I%d = %02x (new value)\n", i, sscape_read (devc, i));
611
      }
612
#endif
613
 
614
    }
615
 
616
  return 1;
617
}
618
 
619
static int
620
download_boot_block (void *dev_info, copr_buffer * buf)
621
{
622
  if (buf->len <= 0 || buf->len > sizeof (buf->data))
623
    return -(EINVAL);
624
 
625
  if (!sscape_download_boot (devc, buf->data, buf->len, buf->flags))
626
    {
627
      printk ("SSCAPE: Unable to load microcode block to the OBP.\n");
628
      return -(EIO);
629
    }
630
 
631
  return 0;
632
}
633
 
634
static int
635
sscape_coproc_ioctl (void *dev_info, unsigned int cmd, caddr_t arg, int local)
636
{
637
 
638
  switch (cmd)
639
    {
640
    case SNDCTL_COPR_RESET:
641
      sscape_coproc_reset (dev_info);
642
      return 0;
643
      break;
644
 
645
    case SNDCTL_COPR_LOAD:
646
      {
647
        copr_buffer    *buf;
648
        int             err;
649
 
650
        buf = (copr_buffer *) vmalloc (sizeof (copr_buffer));
651
        if (buf == NULL)
652
          return -(ENOSPC);
653
        memcpy_fromfs ((char *) buf, &((char *) arg)[0], sizeof (*buf));
654
        err = download_boot_block (dev_info, buf);
655
        vfree (buf);
656
        return err;
657
      }
658
      break;
659
 
660
    default:
661
      return -(EINVAL);
662
    }
663
 
664
}
665
 
666
static coproc_operations sscape_coproc_operations =
667
{
668
  "SoundScape M68K",
669
  sscape_coproc_open,
670
  sscape_coproc_close,
671
  sscape_coproc_ioctl,
672
  sscape_coproc_reset,
673
  &dev_info
674
};
675
 
676
static int      sscape_detected = 0;
677
 
678
void
679
attach_sscape (struct address_info *hw_config)
680
{
681
 
682
#ifndef SSCAPE_REGS
683
  /*
684
     * Config register values for Spea/V7 Media FX and Ensoniq S-2000.
685
     * These values are card
686
     * dependent. If you have another SoundScape based card, you have to
687
     * find the correct values. Do the following:
688
     *  - Compile this driver with SSCAPE_DEBUG1 defined.
689
     *  - Shut down and power off your machine.
690
     *  - Boot with DOS so that the SSINIT.EXE program is run.
691
     *  - Warm boot to {Linux|SYSV|BSD} and write down the lines displayed
692
     *    when detecting the SoundScape.
693
     *  - Modify the following list to use the values printed during boot.
694
     *    Undefine the SSCAPE_DEBUG1
695
   */
696
#define SSCAPE_REGS { \
697
/* I0 */        0x00, \
698
                0xf0, /* Note! Ignored. Set always to 0xf0 */ \
699
                0x20, /* Note! Ignored. Set always to 0x20 */ \
700
                0x20, /* Note! Ignored. Set always to 0x20 */ \
701
                0xf5, /* Ignored */ \
702
                0x10, \
703
                0x00, \
704
                0x2e, /* I7 MEM config A. Likely to vary between models */ \
705
                0x00, /* I8 MEM config B. Likely to vary between models */ \
706
/* I9 */        0x40 /* Ignored */ \
707
        }
708
#endif
709
 
710
  unsigned long   flags;
711
  static unsigned char regs[10] = SSCAPE_REGS;
712
 
713
  int             i, irq_bits = 0xff;
714
 
715
  if (sscape_detected != hw_config->io_base)
716
    return;
717
 
718
  if (old_hardware)
719
    {
720
      valid_interrupts = valid_interrupts_old;
721
      conf_printf ("Ensoniq SoundScape (old)", hw_config);
722
    }
723
  else
724
    conf_printf ("Ensoniq SoundScape", hw_config);
725
 
726
  for (i = 0; i < sizeof (valid_interrupts); i++)
727
    if (hw_config->irq == valid_interrupts[i])
728
      {
729
        irq_bits = i;
730
        break;
731
      }
732
 
733
  if (hw_config->irq > 15 || (regs[4] = irq_bits == 0xff))
734
    {
735
      printk ("Invalid IRQ%d\n", hw_config->irq);
736
      return;
737
    }
738
 
739
  save_flags (flags);
740
  cli ();
741
 
742
  for (i = 1; i < 10; i++)
743
    switch (i)
744
      {
745
      case 1:                   /* Host interrupt enable */
746
        sscape_write (devc, i, 0xf0);   /* All interrupts enabled */
747
        break;
748
 
749
      case 2:                   /* DMA A status/trigger register */
750
      case 3:                   /* DMA B status/trigger register */
751
        sscape_write (devc, i, 0x20);   /* DMA channel disabled */
752
        break;
753
 
754
      case 4:                   /* Host interrupt config reg */
755
        sscape_write (devc, i, 0xf0 | (irq_bits << 2) | irq_bits);
756
        break;
757
 
758
      case 5:                   /* Don't destroy CD-ROM DMA config bits (0xc0) */
759
        sscape_write (devc, i, (regs[i] & 0x3f) |
760
                      (sscape_read (devc, i) & 0xc0));
761
        break;
762
 
763
      case 6:                   /* CD-ROM config. Don't touch. */
764
        break;
765
 
766
      case 9:                   /* Master control reg. Don't modify CR-ROM bits. Disable SB emul */
767
        sscape_write (devc, i,
768
                      (sscape_read (devc, i) & 0xf0) | 0x08);
769
        break;
770
 
771
      default:
772
        sscape_write (devc, i, regs[i]);
773
      }
774
 
775
  restore_flags (flags);
776
 
777
#ifdef SSCAPE_DEBUG2
778
  /*
779
     * Temporary debugging aid. Print contents of the registers after
780
     * changing them.
781
   */
782
  {
783
    int             i;
784
 
785
    for (i = 0; i < 13; i++)
786
      printk ("I%d = %02x (new value)\n", i, sscape_read (devc, i));
787
  }
788
#endif
789
 
790
#if defined(CONFIG_MIDI) && defined(CONFIG_MPU_EMU)
791
  if (probe_mpu401 (hw_config))
792
    hw_config->always_detect = 1;
793
  {
794
    int             prev_devs;
795
 
796
    prev_devs = num_midis;
797
    hw_config->name = "SoundScape";
798
 
799
    hw_config->irq *= -1;       /* Negative value signals IRQ sharing */
800
    attach_mpu401 (hw_config);
801
    hw_config->irq *= -1;       /* Restore it */
802
 
803
    if (num_midis == (prev_devs + 1))   /* The MPU driver installed itself */
804
      midi_devs[prev_devs]->coproc = &sscape_coproc_operations;
805
  }
806
#endif
807
 
808
  sscape_write (devc, GA_INTENA_REG, 0x80);     /* Master IRQ enable */
809
  devc->ok = 1;
810
  devc->failed = 0;
811
}
812
 
813
int
814
probe_sscape (struct address_info *hw_config)
815
{
816
  unsigned char   save;
817
 
818
  devc->failed = 1;
819
  devc->base = hw_config->io_base;
820
  devc->irq = hw_config->irq;
821
  devc->dma = hw_config->dma;
822
  devc->osp = hw_config->osp;
823
 
824
  if (sscape_detected != 0 && sscape_detected != hw_config->io_base)
825
    return 0;
826
 
827
  /*
828
     * First check that the address register of "ODIE" is
829
     * there and that it has exactly 4 writable bits.
830
     * First 4 bits
831
   */
832
  if ((save = inb (PORT (ODIE_ADDR))) & 0xf0)
833
    return 0;
834
 
835
  outb (0x00, PORT (ODIE_ADDR));
836
  if (inb (PORT (ODIE_ADDR)) != 0x00)
837
    return 0;
838
 
839
  outb (0xff, PORT (ODIE_ADDR));
840
  if (inb (PORT (ODIE_ADDR)) != 0x0f)
841
    return 0;
842
 
843
  outb (save, PORT (ODIE_ADDR));
844
 
845
  /*
846
     * Now verify that some indirect registers return zero on some bits.
847
     * This may break the driver with some future revisions of "ODIE" but...
848
   */
849
 
850
  if (sscape_read (devc, 0) & 0x0c)
851
    return 0;
852
 
853
  if (sscape_read (devc, 1) & 0x0f)
854
    return 0;
855
 
856
  if (sscape_read (devc, 5) & 0x0f)
857
    return 0;
858
 
859
#ifdef SSCAPE_DEBUG1
860
  /*
861
     * Temporary debugging aid. Print contents of the registers before
862
     * changing them.
863
   */
864
  {
865
    int             i;
866
 
867
    for (i = 0; i < 13; i++)
868
      printk ("I%d = %02x (old value)\n", i, sscape_read (devc, i));
869
  }
870
#endif
871
 
872
  if (old_hardware)             /* Check that it's really an old Spea/Reveal card. */
873
    {
874
      unsigned char   tmp;
875
      int             cc;
876
 
877
      if (!((tmp = sscape_read (devc, GA_HMCTL_REG)) & 0xc0))
878
        {
879
          sscape_write (devc, GA_HMCTL_REG, tmp | 0x80);
880
          for (cc = 0; cc < 200000; ++cc)
881
            inb (devc->base + ODIE_ADDR);
882
        }
883
      else
884
        old_hardware = 0;
885
    }
886
 
887
 
888
  sscape_detected = hw_config->io_base;
889
 
890
  return 1;
891
}
892
 
893
int
894
probe_ss_ms_sound (struct address_info *hw_config)
895
{
896
  int             i, irq_bits = 0xff;
897
 
898
  if (devc->failed)
899
    return 0;
900
 
901
  if (devc->ok == 0)
902
    {
903
      printk ("SoundScape: Invalid initialization order.\n");
904
      return 0;
905
    }
906
 
907
  for (i = 0; i < sizeof (valid_interrupts); i++)
908
    if (hw_config->irq == valid_interrupts[i])
909
      {
910
        irq_bits = i;
911
        break;
912
      }
913
  if (hw_config->irq > 15 || irq_bits == 0xff)
914
    {
915
      printk ("SoundScape: Invalid MSS IRQ%d\n", hw_config->irq);
916
      return 0;
917
    }
918
 
919
  return ad1848_detect (hw_config->io_base, NULL, hw_config->osp);
920
}
921
 
922
void
923
attach_ss_ms_sound (struct address_info *hw_config)
924
{
925
  /*
926
     * This routine configures the SoundScape card for use with the
927
     * Win Sound System driver. The AD1848 codec interface uses the CD-ROM
928
     * config registers of the "ODIE".
929
   */
930
 
931
  int             i, irq_bits = 0xff;
932
 
933
  int             prev_devs = num_audiodevs;
934
 
935
  hw_config->dma = devc->dma;   /* Share the DMA with the ODIE/OPUS chip */
936
 
937
  /*
938
   * Setup the DMA polarity.
939
   */
940
  sscape_write (devc, GA_DMACFG_REG, 0x50);
941
 
942
  /*
943
     * Take the gate-array off of the DMA channel.
944
   */
945
  sscape_write (devc, GA_DMAB_REG, 0x20);
946
 
947
  /*
948
     * Init the AD1848 (CD-ROM) config reg.
949
   */
950
 
951
  for (i = 0; i < sizeof (valid_interrupts); i++)
952
    if (hw_config->irq == valid_interrupts[i])
953
      {
954
        irq_bits = i;
955
        break;
956
      }
957
 
958
  sscape_write (devc, GA_CDCFG_REG, 0x89 | (hw_config->dma << 4) |
959
                (irq_bits << 1));
960
 
961
  if (hw_config->irq == devc->irq)
962
    printk ("SoundScape: Warning! The WSS mode can't share IRQ with MIDI\n");
963
 
964
  ad1848_init ("SoundScape", hw_config->io_base,
965
               hw_config->irq,
966
               hw_config->dma,
967
               hw_config->dma,
968
               0,
969
               devc->osp);
970
 
971
  if (num_audiodevs == (prev_devs + 1))         /* The AD1848 driver installed itself */
972
    audio_devs[prev_devs]->coproc = &sscape_coproc_operations;
973
  devc->my_audiodev = prev_devs;
974
 
975
#ifdef SSCAPE_DEBUG5
976
  /*
977
     * Temporary debugging aid. Print contents of the registers
978
     * after the AD1848 device has been initialized.
979
   */
980
  {
981
    int             i;
982
 
983
    for (i = 0; i < 13; i++)
984
      printk ("I%d = %02x\n", i, sscape_read (devc, i));
985
  }
986
#endif
987
 
988
}
989
 
990
void
991
unload_sscape (struct address_info *hw_config)
992
{
993
#if defined(CONFIG_MPU_EMU) && defined(CONFIG_MIDI)
994
  unload_mpu401 (hw_config);
995
#endif
996
  snd_release_irq (hw_config->irq);
997
}
998
 
999
void
1000
unload_ss_ms_sound (struct address_info *hw_config)
1001
{
1002
  ad1848_unload (hw_config->io_base,
1003
                 hw_config->irq,
1004
                 devc->dma,
1005
                 devc->dma,
1006
                 0);
1007
}
1008
 
1009
 
1010
#endif

powered by: WebSVN 2.1.0

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