static int snd_opl4_detect(struct snd_opl4 *opl4) { u8 id1, id2; snd_opl4_enable_opl4(opl4); id1 = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION); snd_printdd("OPL4[02]=%02x\n", id1); switch (id1 & OPL4_DEVICE_ID_MASK) { case 0x20: opl4->hardware = OPL3_HW_OPL4; break; case 0x40: opl4->hardware = OPL3_HW_OPL4_ML; break; default: return -ENODEV; } snd_opl4_write(opl4, OPL4_REG_MIX_CONTROL_FM, 0x00); snd_opl4_write(opl4, OPL4_REG_MIX_CONTROL_PCM, 0xff); id1 = snd_opl4_read(opl4, OPL4_REG_MIX_CONTROL_FM); id2 = snd_opl4_read(opl4, OPL4_REG_MIX_CONTROL_PCM); snd_printdd("OPL4 id1=%02x id2=%02x\n", id1, id2); if (id1 != 0x00 || id2 != 0xff) return -ENODEV; snd_opl4_write(opl4, OPL4_REG_MIX_CONTROL_FM, 0x3f); snd_opl4_write(opl4, OPL4_REG_MIX_CONTROL_PCM, 0x3f); snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, 0x00); return 0; }
void snd_opl4_read_memory(opl4_t *opl4, char *buf, int offset, int size) { u8 memcfg = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION); snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg | OPL4_MODE_BIT); snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_HIGH, offset >> 16); snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_MID, offset >> 8); snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_LOW, offset); for (; size > 0; size--) *buf++ = snd_opl4_read(opl4, OPL4_REG_MEMORY_DATA); snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg); }
static int snd_opl4_ctl_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) { opl4_t *opl4 = snd_kcontrol_chip(kcontrol); u8 reg = kcontrol->private_value; u8 value; value = snd_opl4_read(opl4, reg); ucontrol->value.integer.value[0] = 7 - (value & 7); ucontrol->value.integer.value[1] = 7 - ((value >> 3) & 7); return 0; }
static int snd_opl4_ctl_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) { opl4_t *opl4 = snd_kcontrol_chip(kcontrol); u8 reg = kcontrol->private_value; u8 value, old_value; value = (7 - (ucontrol->value.integer.value[0] & 7)) | ((7 - (ucontrol->value.integer.value[1] & 7)) << 3); old_value = snd_opl4_read(opl4, reg); snd_opl4_write(opl4, reg, value); return value != old_value; }
static int snd_opl4_ctl_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) { opl4_t *opl4 = snd_kcontrol_chip(kcontrol); unsigned long flags; u8 reg = kcontrol->private_value; u8 value; spin_lock_irqsave(&opl4->reg_lock, flags); value = snd_opl4_read(opl4, reg); spin_unlock_irqrestore(&opl4->reg_lock, flags); ucontrol->value.integer.value[0] = 7 - (value & 7); ucontrol->value.integer.value[1] = 7 - ((value >> 3) & 7); return 0; }
static int snd_opl4_ctl_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) { opl4_t *opl4 = snd_kcontrol_chip(kcontrol); unsigned long flags; u8 reg = kcontrol->private_value; u8 value, old_value; value = (7 - (ucontrol->value.integer.value[0] & 7)) | ((7 - (ucontrol->value.integer.value[1] & 7)) << 3); spin_lock_irqsave(&opl4->reg_lock, flags); old_value = snd_opl4_read(opl4, reg); snd_opl4_write(opl4, reg, value); spin_unlock_irqrestore(&opl4->reg_lock, flags); return value != old_value; }
void snd_opl4_write_memory(struct snd_opl4 *opl4, const char *buf, int offset, int size) { unsigned long flags; u8 memcfg; spin_lock_irqsave(&opl4->reg_lock, flags); memcfg = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION); snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg | OPL4_MODE_BIT); snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_HIGH, offset >> 16); snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_MID, offset >> 8); snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_LOW, offset); snd_opl4_wait(opl4); outb(OPL4_REG_MEMORY_DATA, opl4->pcm_port); snd_opl4_wait(opl4); outsb(opl4->pcm_port + 1, buf, size); snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg); spin_unlock_irqrestore(&opl4->reg_lock, flags); }