/* * Write to the SoundScape's host-mode control registers, but * leave any locking issues to the caller ... */ static inline int host_write_unsafe(unsigned io_base, unsigned char data) { if ((inb(HOST_CTRL_IO(io_base)) & TX_READY) != 0) { outb(data, HOST_DATA_IO(io_base)); return 1; } return 0; }
/* * Read the SoundScape's host-mode control register, but leave * any locking issues to the caller ... */ static inline int host_read_unsafe(unsigned io_base) { int data = -1; if ((inb(HOST_CTRL_IO(io_base)) & RX_READY) != 0) { data = inb(HOST_DATA_IO(io_base)); } return data; }
/* * Perform certain arcane port-checks to see whether there * is a SoundScape board lurking behind the given ports. */ static int __devinit detect_sscape(struct soundscape *s) { unsigned long flags; unsigned d; int retval = 0; spin_lock_irqsave(&s->lock, flags); /* * The following code is lifted from the original OSS driver, * and as I don't have a datasheet I cannot really comment * on what it is doing... */ if ((inb(HOST_CTRL_IO(s->io_base)) & 0x78) != 0) goto _done; d = inb(ODIE_ADDR_IO(s->io_base)) & 0xf0; if ((d & 0x80) != 0) goto _done; if (d == 0) { s->codec_type = 1; s->ic_type = IC_ODIE; } else if ((d & 0x60) != 0) { s->codec_type = 2; s->ic_type = IC_OPUS; } else goto _done; outb(0xfa, ODIE_ADDR_IO(s->io_base)); if ((inb(ODIE_ADDR_IO(s->io_base)) & 0x9f) != 0x0a) goto _done; outb(0xfe, ODIE_ADDR_IO(s->io_base)); if ((inb(ODIE_ADDR_IO(s->io_base)) & 0x9f) != 0x0e) goto _done; if ((inb(ODIE_DATA_IO(s->io_base)) & 0x9f) != 0x0e) goto _done; /* * SoundScape successfully detected! */ retval = 1; _done: spin_unlock_irqrestore(&s->lock, flags); return retval; }
/* * Puts the SoundScape into "MIDI" mode, as compared to "host" mode */ static inline void set_midi_mode_unsafe(unsigned io_base) { outb(0x3, HOST_CTRL_IO(io_base)); }
/* * Perform certain arcane port-checks to see whether there * is a SoundScape board lurking behind the given ports. */ static int __devinit detect_sscape(struct soundscape *s) { unsigned long flags; unsigned d; int retval = 0; int codec = s->wss_base; spin_lock_irqsave(&s->lock, flags); /* * The following code is lifted from the original OSS driver, * and as I don't have a datasheet I cannot really comment * on what it is doing... */ if ((inb(HOST_CTRL_IO(s->io_base)) & 0x78) != 0) goto _done; d = inb(ODIE_ADDR_IO(s->io_base)) & 0xf0; if ((d & 0x80) != 0) goto _done; if (d == 0) { s->codec_type = 1; s->ic_type = IC_ODIE; } else if ((d & 0x60) != 0) { s->codec_type = 2; s->ic_type = IC_OPUS; } else goto _done; outb(0xfa, ODIE_ADDR_IO(s->io_base)); if ((inb(ODIE_ADDR_IO(s->io_base)) & 0x9f) != 0x0a) goto _done; outb(0xfe, ODIE_ADDR_IO(s->io_base)); if ((inb(ODIE_ADDR_IO(s->io_base)) & 0x9f) != 0x0e) goto _done; outb(0xfe, ODIE_ADDR_IO(s->io_base)); d = inb(ODIE_DATA_IO(s->io_base)); if (s->type != SSCAPE_VIVO && (d & 0x9f) != 0x0e) goto _done; d = sscape_read_unsafe(s->io_base, GA_HMCTL_REG) & 0x3f; sscape_write_unsafe(s->io_base, GA_HMCTL_REG, d | 0xc0); if (s->type == SSCAPE_VIVO) codec += 4; /* wait for WSS codec */ for (d = 0; d < 500; d++) { if ((inb(codec) & 0x80) == 0) break; spin_unlock_irqrestore(&s->lock, flags); msleep(1); spin_lock_irqsave(&s->lock, flags); } snd_printd(KERN_INFO "init delay = %d ms\n", d); /* * SoundScape successfully detected! */ retval = 1; _done: spin_unlock_irqrestore(&s->lock, flags); return retval; }