/* * 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; }
/* * This function writes to the SoundScape's control registers, * but doesn't do any locking. It's up to the caller to do that. * This is why this function is "unsafe" ... */ static inline void sscape_write_unsafe(unsigned io_base, enum GA_REG reg, unsigned char val) { outb(reg, ODIE_ADDR_IO(io_base)); outb(val, ODIE_DATA_IO(io_base)); }
/* * Read from the SoundScape's control registers, but leave any * locking to the caller. This is why the function is "unsafe" ... */ static inline unsigned char sscape_read_unsafe(unsigned io_base, enum GA_REG reg) { outb(reg, ODIE_ADDR_IO(io_base)); return inb(ODIE_DATA_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; }