Commit 9dc9120c authored by Krzysztof Helt's avatar Krzysztof Helt Committed by Takashi Iwai

ALSA: opti-miro: expose ACI mixer to outside drivers

The ACI mixer is used to control the radio FM module
installed on the Miro PCM20 sound card. Expose ACI mixer
outside the sound card driver.
Signed-off-by: default avatarKrzysztof Helt <krzysztof.h1@wp.pl>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 9aeba629
...@@ -70,4 +70,21 @@ ...@@ -70,4 +70,21 @@
#define ACI_SET_EQ6 0x45 #define ACI_SET_EQ6 0x45
#define ACI_SET_EQ7 0x46 /* ... to Treble */ #define ACI_SET_EQ7 0x46 /* ... to Treble */
struct snd_miro_aci {
unsigned long aci_port;
int aci_vendor;
int aci_product;
int aci_version;
int aci_amp;
int aci_preamp;
int aci_solomode;
struct mutex aci_mutex;
};
int snd_aci_cmd(struct snd_miro_aci *aci, int write1, int write2, int write3);
struct snd_miro_aci *snd_aci_get_aci(void);
#endif /* _ACI_H_ */ #endif /* _ACI_H_ */
...@@ -96,7 +96,6 @@ MODULE_PARM_DESC(ide, "enable ide port"); ...@@ -96,7 +96,6 @@ MODULE_PARM_DESC(ide, "enable ide port");
#define OPTi9XX_MC_REG(n) n #define OPTi9XX_MC_REG(n) n
struct snd_miro { struct snd_miro {
unsigned short hardware; unsigned short hardware;
unsigned char password; unsigned char password;
...@@ -120,17 +119,11 @@ struct snd_miro { ...@@ -120,17 +119,11 @@ struct snd_miro {
long mpu_port; long mpu_port;
int mpu_irq; int mpu_irq;
unsigned long aci_port; struct snd_miro_aci *aci;
int aci_vendor;
int aci_product;
int aci_version;
int aci_amp;
int aci_preamp;
int aci_solomode;
struct mutex aci_mutex;
}; };
static struct snd_miro_aci aci_device;
static char * snd_opti9xx_names[] = { static char * snd_opti9xx_names[] = {
"unkown", "unkown",
"82C928", "82C929", "82C928", "82C929",
...@@ -142,13 +135,14 @@ static char * snd_opti9xx_names[] = { ...@@ -142,13 +135,14 @@ static char * snd_opti9xx_names[] = {
* ACI control * ACI control
*/ */
static int aci_busy_wait(struct snd_miro * miro) static int aci_busy_wait(struct snd_miro_aci *aci)
{ {
long timeout; long timeout;
unsigned char byte; unsigned char byte;
for (timeout = 1; timeout <= ACI_MINTIME+30; timeout++) { for (timeout = 1; timeout <= ACI_MINTIME + 30; timeout++) {
if (((byte=inb(miro->aci_port + ACI_REG_BUSY)) & 1) == 0) { byte = inb(aci->aci_port + ACI_REG_BUSY);
if ((byte & 1) == 0) {
if (timeout >= ACI_MINTIME) if (timeout >= ACI_MINTIME)
snd_printd("aci ready in round %ld.\n", snd_printd("aci ready in round %ld.\n",
timeout-ACI_MINTIME); timeout-ACI_MINTIME);
...@@ -174,10 +168,10 @@ static int aci_busy_wait(struct snd_miro * miro) ...@@ -174,10 +168,10 @@ static int aci_busy_wait(struct snd_miro * miro)
return -EBUSY; return -EBUSY;
} }
static inline int aci_write(struct snd_miro * miro, unsigned char byte) static inline int aci_write(struct snd_miro_aci *aci, unsigned char byte)
{ {
if (aci_busy_wait(miro) >= 0) { if (aci_busy_wait(aci) >= 0) {
outb(byte, miro->aci_port + ACI_REG_COMMAND); outb(byte, aci->aci_port + ACI_REG_COMMAND);
return 0; return 0;
} else { } else {
snd_printk(KERN_ERR "aci busy, aci_write(0x%x) stopped.\n", byte); snd_printk(KERN_ERR "aci busy, aci_write(0x%x) stopped.\n", byte);
...@@ -185,12 +179,12 @@ static inline int aci_write(struct snd_miro * miro, unsigned char byte) ...@@ -185,12 +179,12 @@ static inline int aci_write(struct snd_miro * miro, unsigned char byte)
} }
} }
static inline int aci_read(struct snd_miro * miro) static inline int aci_read(struct snd_miro_aci *aci)
{ {
unsigned char byte; unsigned char byte;
if (aci_busy_wait(miro) >= 0) { if (aci_busy_wait(aci) >= 0) {
byte=inb(miro->aci_port + ACI_REG_STATUS); byte = inb(aci->aci_port + ACI_REG_STATUS);
return byte; return byte;
} else { } else {
snd_printk(KERN_ERR "aci busy, aci_read() stopped.\n"); snd_printk(KERN_ERR "aci busy, aci_read() stopped.\n");
...@@ -198,39 +192,49 @@ static inline int aci_read(struct snd_miro * miro) ...@@ -198,39 +192,49 @@ static inline int aci_read(struct snd_miro * miro)
} }
} }
static int aci_cmd(struct snd_miro * miro, int write1, int write2, int write3) int snd_aci_cmd(struct snd_miro_aci *aci, int write1, int write2, int write3)
{ {
int write[] = {write1, write2, write3}; int write[] = {write1, write2, write3};
int value, i; int value, i;
if (mutex_lock_interruptible(&miro->aci_mutex)) if (mutex_lock_interruptible(&aci->aci_mutex))
return -EINTR; return -EINTR;
for (i=0; i<3; i++) { for (i=0; i<3; i++) {
if (write[i]< 0 || write[i] > 255) if (write[i]< 0 || write[i] > 255)
break; break;
else { else {
value = aci_write(miro, write[i]); value = aci_write(aci, write[i]);
if (value < 0) if (value < 0)
goto out; goto out;
} }
} }
value = aci_read(miro); value = aci_read(aci);
out: mutex_unlock(&miro->aci_mutex); out: mutex_unlock(&aci->aci_mutex);
return value; return value;
} }
EXPORT_SYMBOL(snd_aci_cmd);
static int aci_getvalue(struct snd_miro_aci *aci, unsigned char index)
{
return snd_aci_cmd(aci, ACI_STATUS, index, -1);
}
static int aci_getvalue(struct snd_miro * miro, unsigned char index) static int aci_setvalue(struct snd_miro_aci *aci, unsigned char index,
int value)
{ {
return aci_cmd(miro, ACI_STATUS, index, -1); return snd_aci_cmd(aci, index, value, -1);
} }
static int aci_setvalue(struct snd_miro * miro, unsigned char index, int value) struct snd_miro_aci *snd_aci_get_aci(void)
{ {
return aci_cmd(miro, index, value, -1); if (aci_device.aci_port == 0)
return NULL;
return &aci_device;
} }
EXPORT_SYMBOL(snd_aci_get_aci);
/* /*
* MIXER part * MIXER part
...@@ -244,8 +248,10 @@ static int snd_miro_get_capture(struct snd_kcontrol *kcontrol, ...@@ -244,8 +248,10 @@ static int snd_miro_get_capture(struct snd_kcontrol *kcontrol,
struct snd_miro *miro = snd_kcontrol_chip(kcontrol); struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
int value; int value;
if ((value = aci_getvalue(miro, ACI_S_GENERAL)) < 0) { value = aci_getvalue(miro->aci, ACI_S_GENERAL);
snd_printk(KERN_ERR "snd_miro_get_capture() failed: %d\n", value); if (value < 0) {
snd_printk(KERN_ERR "snd_miro_get_capture() failed: %d\n",
value);
return value; return value;
} }
...@@ -262,13 +268,15 @@ static int snd_miro_put_capture(struct snd_kcontrol *kcontrol, ...@@ -262,13 +268,15 @@ static int snd_miro_put_capture(struct snd_kcontrol *kcontrol,
value = !(ucontrol->value.integer.value[0]); value = !(ucontrol->value.integer.value[0]);
if ((error = aci_setvalue(miro, ACI_SET_SOLOMODE, value)) < 0) { error = aci_setvalue(miro->aci, ACI_SET_SOLOMODE, value);
snd_printk(KERN_ERR "snd_miro_put_capture() failed: %d\n", error); if (error < 0) {
snd_printk(KERN_ERR "snd_miro_put_capture() failed: %d\n",
error);
return error; return error;
} }
change = (value != miro->aci_solomode); change = (value != miro->aci->aci_solomode);
miro->aci_solomode = value; miro->aci->aci_solomode = value;
return change; return change;
} }
...@@ -290,7 +298,7 @@ static int snd_miro_get_preamp(struct snd_kcontrol *kcontrol, ...@@ -290,7 +298,7 @@ static int snd_miro_get_preamp(struct snd_kcontrol *kcontrol,
struct snd_miro *miro = snd_kcontrol_chip(kcontrol); struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
int value; int value;
if (miro->aci_version <= 176) { if (miro->aci->aci_version <= 176) {
/* /*
OSS says it's not readable with versions < 176. OSS says it's not readable with versions < 176.
...@@ -298,12 +306,14 @@ static int snd_miro_get_preamp(struct snd_kcontrol *kcontrol, ...@@ -298,12 +306,14 @@ static int snd_miro_get_preamp(struct snd_kcontrol *kcontrol,
which is a PCM12 with aci_version = 176. which is a PCM12 with aci_version = 176.
*/ */
ucontrol->value.integer.value[0] = miro->aci_preamp; ucontrol->value.integer.value[0] = miro->aci->aci_preamp;
return 0; return 0;
} }
if ((value = aci_getvalue(miro, ACI_GET_PREAMP)) < 0) { value = aci_getvalue(miro->aci, ACI_GET_PREAMP);
snd_printk(KERN_ERR "snd_miro_get_preamp() failed: %d\n", value); if (value < 0) {
snd_printk(KERN_ERR "snd_miro_get_preamp() failed: %d\n",
value);
return value; return value;
} }
...@@ -320,13 +330,15 @@ static int snd_miro_put_preamp(struct snd_kcontrol *kcontrol, ...@@ -320,13 +330,15 @@ static int snd_miro_put_preamp(struct snd_kcontrol *kcontrol,
value = ucontrol->value.integer.value[0]; value = ucontrol->value.integer.value[0];
if ((error = aci_setvalue(miro, ACI_SET_PREAMP, value)) < 0) { error = aci_setvalue(miro->aci, ACI_SET_PREAMP, value);
snd_printk(KERN_ERR "snd_miro_put_preamp() failed: %d\n", error); if (error < 0) {
snd_printk(KERN_ERR "snd_miro_put_preamp() failed: %d\n",
error);
return error; return error;
} }
change = (value != miro->aci_preamp); change = (value != miro->aci->aci_preamp);
miro->aci_preamp = value; miro->aci->aci_preamp = value;
return change; return change;
} }
...@@ -337,7 +349,7 @@ static int snd_miro_get_amp(struct snd_kcontrol *kcontrol, ...@@ -337,7 +349,7 @@ static int snd_miro_get_amp(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
struct snd_miro *miro = snd_kcontrol_chip(kcontrol); struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = miro->aci_amp; ucontrol->value.integer.value[0] = miro->aci->aci_amp;
return 0; return 0;
} }
...@@ -350,13 +362,14 @@ static int snd_miro_put_amp(struct snd_kcontrol *kcontrol, ...@@ -350,13 +362,14 @@ static int snd_miro_put_amp(struct snd_kcontrol *kcontrol,
value = ucontrol->value.integer.value[0]; value = ucontrol->value.integer.value[0];
if ((error = aci_setvalue(miro, ACI_SET_POWERAMP, value)) < 0) { error = aci_setvalue(miro->aci, ACI_SET_POWERAMP, value);
if (error < 0) {
snd_printk(KERN_ERR "snd_miro_put_amp() to %d failed: %d\n", value, error); snd_printk(KERN_ERR "snd_miro_put_amp() to %d failed: %d\n", value, error);
return error; return error;
} }
change = (value != miro->aci_amp); change = (value != miro->aci->aci_amp);
miro->aci_amp = value; miro->aci->aci_amp = value;
return change; return change;
} }
...@@ -405,12 +418,14 @@ static int snd_miro_get_double(struct snd_kcontrol *kcontrol, ...@@ -405,12 +418,14 @@ static int snd_miro_get_double(struct snd_kcontrol *kcontrol,
int right_reg = kcontrol->private_value & 0xff; int right_reg = kcontrol->private_value & 0xff;
int left_reg = right_reg + 1; int left_reg = right_reg + 1;
if ((right_val = aci_getvalue(miro, right_reg)) < 0) { right_val = aci_getvalue(miro->aci, right_reg);
if (right_val < 0) {
snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", right_reg, right_val); snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", right_reg, right_val);
return right_val; return right_val;
} }
if ((left_val = aci_getvalue(miro, left_reg)) < 0) { left_val = aci_getvalue(miro->aci, left_reg);
if (left_val < 0) {
snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", left_reg, left_val); snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", left_reg, left_val);
return left_val; return left_val;
} }
...@@ -446,6 +461,7 @@ static int snd_miro_put_double(struct snd_kcontrol *kcontrol, ...@@ -446,6 +461,7 @@ static int snd_miro_put_double(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
struct snd_miro *miro = snd_kcontrol_chip(kcontrol); struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
struct snd_miro_aci *aci = miro->aci;
int left, right, left_old, right_old; int left, right, left_old, right_old;
int setreg_left, setreg_right, getreg_left, getreg_right; int setreg_left, setreg_right, getreg_left, getreg_right;
int change, error; int change, error;
...@@ -461,12 +477,14 @@ static int snd_miro_put_double(struct snd_kcontrol *kcontrol, ...@@ -461,12 +477,14 @@ static int snd_miro_put_double(struct snd_kcontrol *kcontrol,
getreg_right = kcontrol->private_value & 0xff; getreg_right = kcontrol->private_value & 0xff;
getreg_left = getreg_right + 1; getreg_left = getreg_right + 1;
if ((left_old = aci_getvalue(miro, getreg_left)) < 0) { left_old = aci_getvalue(aci, getreg_left);
if (left_old < 0) {
snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", getreg_left, left_old); snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", getreg_left, left_old);
return left_old; return left_old;
} }
if ((right_old = aci_getvalue(miro, getreg_right)) < 0) { right_old = aci_getvalue(aci, getreg_right);
if (right_old < 0) {
snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", getreg_right, right_old); snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", getreg_right, right_old);
return right_old; return right_old;
} }
...@@ -485,13 +503,15 @@ static int snd_miro_put_double(struct snd_kcontrol *kcontrol, ...@@ -485,13 +503,15 @@ static int snd_miro_put_double(struct snd_kcontrol *kcontrol,
right_old = 0x80 - right_old; right_old = 0x80 - right_old;
if (left >= 0) { if (left >= 0) {
if ((error = aci_setvalue(miro, setreg_left, left)) < 0) { error = aci_setvalue(aci, setreg_left, left);
if (error < 0) {
snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
left, error); left, error);
return error; return error;
} }
} else { } else {
if ((error = aci_setvalue(miro, setreg_left, 0x80 - left)) < 0) { error = aci_setvalue(aci, setreg_left, 0x80 - left);
if (error < 0) {
snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
0x80 - left, error); 0x80 - left, error);
return error; return error;
...@@ -499,13 +519,15 @@ static int snd_miro_put_double(struct snd_kcontrol *kcontrol, ...@@ -499,13 +519,15 @@ static int snd_miro_put_double(struct snd_kcontrol *kcontrol,
} }
if (right >= 0) { if (right >= 0) {
if ((error = aci_setvalue(miro, setreg_right, right)) < 0) { error = aci_setvalue(aci, setreg_right, right);
if (error < 0) {
snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
right, error); right, error);
return error; return error;
} }
} else { } else {
if ((error = aci_setvalue(miro, setreg_right, 0x80 - right)) < 0) { error = aci_setvalue(aci, setreg_right, 0x80 - right);
if (error < 0) {
snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
0x80 - right, error); 0x80 - right, error);
return error; return error;
...@@ -523,12 +545,14 @@ static int snd_miro_put_double(struct snd_kcontrol *kcontrol, ...@@ -523,12 +545,14 @@ static int snd_miro_put_double(struct snd_kcontrol *kcontrol,
left_old = 0x20 - left_old; left_old = 0x20 - left_old;
right_old = 0x20 - right_old; right_old = 0x20 - right_old;
if ((error = aci_setvalue(miro, setreg_left, 0x20 - left)) < 0) { error = aci_setvalue(aci, setreg_left, 0x20 - left);
if (error < 0) {
snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
0x20 - left, error); 0x20 - left, error);
return error; return error;
} }
if ((error = aci_setvalue(miro, setreg_right, 0x20 - right)) < 0) { error = aci_setvalue(aci, setreg_right, 0x20 - right);
if (error < 0) {
snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
0x20 - right, error); 0x20 - right, error);
return error; return error;
...@@ -626,11 +650,13 @@ static unsigned char aci_init_values[][2] __devinitdata = { ...@@ -626,11 +650,13 @@ static unsigned char aci_init_values[][2] __devinitdata = {
static int __devinit snd_set_aci_init_values(struct snd_miro *miro) static int __devinit snd_set_aci_init_values(struct snd_miro *miro)
{ {
int idx, error; int idx, error;
struct snd_miro_aci *aci = miro->aci;
/* enable WSS on PCM1 */ /* enable WSS on PCM1 */
if ((miro->aci_product == 'A') && wss) { if ((aci->aci_product == 'A') && wss) {
if ((error = aci_setvalue(miro, ACI_SET_WSS, wss)) < 0) { error = aci_setvalue(aci, ACI_SET_WSS, wss);
if (error < 0) {
snd_printk(KERN_ERR "enabling WSS mode failed\n"); snd_printk(KERN_ERR "enabling WSS mode failed\n");
return error; return error;
} }
...@@ -639,7 +665,8 @@ static int __devinit snd_set_aci_init_values(struct snd_miro *miro) ...@@ -639,7 +665,8 @@ static int __devinit snd_set_aci_init_values(struct snd_miro *miro)
/* enable IDE port */ /* enable IDE port */
if (ide) { if (ide) {
if ((error = aci_setvalue(miro, ACI_SET_IDE, ide)) < 0) { error = aci_setvalue(aci, ACI_SET_IDE, ide);
if (error < 0) {
snd_printk(KERN_ERR "enabling IDE port failed\n"); snd_printk(KERN_ERR "enabling IDE port failed\n");
return error; return error;
} }
...@@ -647,17 +674,18 @@ static int __devinit snd_set_aci_init_values(struct snd_miro *miro) ...@@ -647,17 +674,18 @@ static int __devinit snd_set_aci_init_values(struct snd_miro *miro)
/* set common aci values */ /* set common aci values */
for (idx = 0; idx < ARRAY_SIZE(aci_init_values); idx++) for (idx = 0; idx < ARRAY_SIZE(aci_init_values); idx++) {
if ((error = aci_setvalue(miro, aci_init_values[idx][0], error = aci_setvalue(aci, aci_init_values[idx][0],
aci_init_values[idx][1])) < 0) { aci_init_values[idx][1]);
if (error < 0) {
snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
aci_init_values[idx][0], error); aci_init_values[idx][0], error);
return error; return error;
} }
}
miro->aci_amp = 0; aci->aci_amp = 0;
miro->aci_preamp = 0; aci->aci_preamp = 0;
miro->aci_solomode = 1; aci->aci_solomode = 1;
return 0; return 0;
} }
...@@ -688,7 +716,8 @@ static int __devinit snd_miro_mixer(struct snd_card *card, ...@@ -688,7 +716,8 @@ static int __devinit snd_miro_mixer(struct snd_card *card,
return err; return err;
} }
if ((miro->aci_product == 'A') || (miro->aci_product == 'B')) { if ((miro->aci->aci_product == 'A') ||
(miro->aci->aci_product == 'B')) {
/* PCM1/PCM12 with power-amp and Line 2 */ /* PCM1/PCM12 with power-amp and Line 2 */
if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_line_control[0], miro))) < 0) if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_line_control[0], miro))) < 0)
return err; return err;
...@@ -696,16 +725,17 @@ static int __devinit snd_miro_mixer(struct snd_card *card, ...@@ -696,16 +725,17 @@ static int __devinit snd_miro_mixer(struct snd_card *card,
return err; return err;
} }
if ((miro->aci_product == 'B') || (miro->aci_product == 'C')) { if ((miro->aci->aci_product == 'B') ||
(miro->aci->aci_product == 'C')) {
/* PCM12/PCM20 with mic-preamp */ /* PCM12/PCM20 with mic-preamp */
if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_preamp_control[0], miro))) < 0) if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_preamp_control[0], miro))) < 0)
return err; return err;
if (miro->aci_version >= 176) if (miro->aci->aci_version >= 176)
if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_capture_control[0], miro))) < 0) if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_capture_control[0], miro))) < 0)
return err; return err;
} }
if (miro->aci_product == 'C') { if (miro->aci->aci_product == 'C') {
/* PCM20 with radio and 7 band equalizer */ /* PCM20 with radio and 7 band equalizer */
if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_radio_control[0], miro))) < 0) if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_radio_control[0], miro))) < 0)
return err; return err;
...@@ -843,14 +873,15 @@ static void snd_miro_proc_read(struct snd_info_entry * entry, ...@@ -843,14 +873,15 @@ static void snd_miro_proc_read(struct snd_info_entry * entry,
struct snd_info_buffer *buffer) struct snd_info_buffer *buffer)
{ {
struct snd_miro *miro = (struct snd_miro *) entry->private_data; struct snd_miro *miro = (struct snd_miro *) entry->private_data;
struct snd_miro_aci *aci = miro->aci;
char* model = "unknown"; char* model = "unknown";
/* miroSOUND PCM1 pro, early PCM12 */ /* miroSOUND PCM1 pro, early PCM12 */
if ((miro->hardware == OPTi9XX_HW_82C929) && if ((miro->hardware == OPTi9XX_HW_82C929) &&
(miro->aci_vendor == 'm') && (aci->aci_vendor == 'm') &&
(miro->aci_product == 'A')) { (aci->aci_product == 'A')) {
switch(miro->aci_version) { switch (aci->aci_version) {
case 3: case 3:
model = "miroSOUND PCM1 pro"; model = "miroSOUND PCM1 pro";
break; break;
...@@ -863,9 +894,9 @@ static void snd_miro_proc_read(struct snd_info_entry * entry, ...@@ -863,9 +894,9 @@ static void snd_miro_proc_read(struct snd_info_entry * entry,
/* miroSOUND PCM12, PCM12 (Rev. E), PCM12 pnp */ /* miroSOUND PCM12, PCM12 (Rev. E), PCM12 pnp */
if ((miro->hardware == OPTi9XX_HW_82C924) && if ((miro->hardware == OPTi9XX_HW_82C924) &&
(miro->aci_vendor == 'm') && (aci->aci_vendor == 'm') &&
(miro->aci_product == 'B')) { (aci->aci_product == 'B')) {
switch(miro->aci_version) { switch (aci->aci_version) {
case 4: case 4:
model = "miroSOUND PCM12"; model = "miroSOUND PCM12";
break; break;
...@@ -881,9 +912,9 @@ static void snd_miro_proc_read(struct snd_info_entry * entry, ...@@ -881,9 +912,9 @@ static void snd_miro_proc_read(struct snd_info_entry * entry,
/* miroSOUND PCM20 radio */ /* miroSOUND PCM20 radio */
if ((miro->hardware == OPTi9XX_HW_82C924) && if ((miro->hardware == OPTi9XX_HW_82C924) &&
(miro->aci_vendor == 'm') && (aci->aci_vendor == 'm') &&
(miro->aci_product == 'C')) { (aci->aci_product == 'C')) {
switch(miro->aci_version) { switch (aci->aci_version) {
case 7: case 7:
model = "miroSOUND PCM20 radio (Rev. E)"; model = "miroSOUND PCM20 radio (Rev. E)";
break; break;
...@@ -907,17 +938,17 @@ static void snd_miro_proc_read(struct snd_info_entry * entry, ...@@ -907,17 +938,17 @@ static void snd_miro_proc_read(struct snd_info_entry * entry,
snd_iprintf(buffer, "ACI information:\n"); snd_iprintf(buffer, "ACI information:\n");
snd_iprintf(buffer, " vendor : "); snd_iprintf(buffer, " vendor : ");
switch(miro->aci_vendor) { switch (aci->aci_vendor) {
case 'm': case 'm':
snd_iprintf(buffer, "Miro\n"); snd_iprintf(buffer, "Miro\n");
break; break;
default: default:
snd_iprintf(buffer, "unknown (0x%x)\n", miro->aci_vendor); snd_iprintf(buffer, "unknown (0x%x)\n", aci->aci_vendor);
break; break;
} }
snd_iprintf(buffer, " product : "); snd_iprintf(buffer, " product : ");
switch(miro->aci_product) { switch (aci->aci_product) {
case 'A': case 'A':
snd_iprintf(buffer, "miroSOUND PCM1 pro / (early) PCM12\n"); snd_iprintf(buffer, "miroSOUND PCM1 pro / (early) PCM12\n");
break; break;
...@@ -928,19 +959,19 @@ static void snd_miro_proc_read(struct snd_info_entry * entry, ...@@ -928,19 +959,19 @@ static void snd_miro_proc_read(struct snd_info_entry * entry,
snd_iprintf(buffer, "miroSOUND PCM20 radio\n"); snd_iprintf(buffer, "miroSOUND PCM20 radio\n");
break; break;
default: default:
snd_iprintf(buffer, "unknown (0x%x)\n", miro->aci_product); snd_iprintf(buffer, "unknown (0x%x)\n", aci->aci_product);
break; break;
} }
snd_iprintf(buffer, " firmware: %d (0x%x)\n", snd_iprintf(buffer, " firmware: %d (0x%x)\n",
miro->aci_version, miro->aci_version); aci->aci_version, aci->aci_version);
snd_iprintf(buffer, " port : 0x%lx-0x%lx\n", snd_iprintf(buffer, " port : 0x%lx-0x%lx\n",
miro->aci_port, miro->aci_port+2); aci->aci_port, aci->aci_port+2);
snd_iprintf(buffer, " wss : 0x%x\n", wss); snd_iprintf(buffer, " wss : 0x%x\n", wss);
snd_iprintf(buffer, " ide : 0x%x\n", ide); snd_iprintf(buffer, " ide : 0x%x\n", ide);
snd_iprintf(buffer, " solomode: 0x%x\n", miro->aci_solomode); snd_iprintf(buffer, " solomode: 0x%x\n", aci->aci_solomode);
snd_iprintf(buffer, " amp : 0x%x\n", miro->aci_amp); snd_iprintf(buffer, " amp : 0x%x\n", aci->aci_amp);
snd_iprintf(buffer, " preamp : 0x%x\n", miro->aci_preamp); snd_iprintf(buffer, " preamp : 0x%x\n", aci->aci_preamp);
} }
static void __devinit snd_miro_proc_init(struct snd_card *card, static void __devinit snd_miro_proc_init(struct snd_card *card,
...@@ -1139,46 +1170,53 @@ static int __devinit snd_card_miro_detect(struct snd_card *card, ...@@ -1139,46 +1170,53 @@ static int __devinit snd_card_miro_detect(struct snd_card *card,
} }
static int __devinit snd_card_miro_aci_detect(struct snd_card *card, static int __devinit snd_card_miro_aci_detect(struct snd_card *card,
struct snd_miro * miro) struct snd_miro *miro)
{ {
unsigned char regval; unsigned char regval;
int i; int i;
struct snd_miro_aci *aci = &aci_device;
miro->aci = aci;
mutex_init(&miro->aci_mutex); mutex_init(&aci->aci_mutex);
/* get ACI port from OPTi9xx MC 4 */ /* get ACI port from OPTi9xx MC 4 */
regval=inb(miro->mc_base + 4); regval=inb(miro->mc_base + 4);
miro->aci_port = (regval & 0x10) ? 0x344: 0x354; aci->aci_port = (regval & 0x10) ? 0x344 : 0x354;
if ((miro->res_aci_port = request_region(miro->aci_port, 3, "miro aci")) == NULL) { miro->res_aci_port = request_region(aci->aci_port, 3, "miro aci");
if (miro->res_aci_port == NULL) {
snd_printk(KERN_ERR "aci i/o area 0x%lx-0x%lx already used.\n", snd_printk(KERN_ERR "aci i/o area 0x%lx-0x%lx already used.\n",
miro->aci_port, miro->aci_port+2); aci->aci_port, aci->aci_port+2);
return -ENOMEM; return -ENOMEM;
} }
/* force ACI into a known state */ /* force ACI into a known state */
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
if (aci_cmd(miro, ACI_ERROR_OP, -1, -1) < 0) { if (snd_aci_cmd(aci, ACI_ERROR_OP, -1, -1) < 0) {
snd_printk(KERN_ERR "can't force aci into known state.\n"); snd_printk(KERN_ERR "can't force aci into known state.\n");
return -ENXIO; return -ENXIO;
} }
if ((miro->aci_vendor=aci_cmd(miro, ACI_READ_IDCODE, -1, -1)) < 0 || aci->aci_vendor = snd_aci_cmd(aci, ACI_READ_IDCODE, -1, -1);
(miro->aci_product=aci_cmd(miro, ACI_READ_IDCODE, -1, -1)) < 0) { aci->aci_product = snd_aci_cmd(aci, ACI_READ_IDCODE, -1, -1);
snd_printk(KERN_ERR "can't read aci id on 0x%lx.\n", miro->aci_port); if (aci->aci_vendor < 0 || aci->aci_product < 0) {
snd_printk(KERN_ERR "can't read aci id on 0x%lx.\n",
aci->aci_port);
return -ENXIO; return -ENXIO;
} }
if ((miro->aci_version=aci_cmd(miro, ACI_READ_VERSION, -1, -1)) < 0) { aci->aci_version = snd_aci_cmd(aci, ACI_READ_VERSION, -1, -1);
if (aci->aci_version < 0) {
snd_printk(KERN_ERR "can't read aci version on 0x%lx.\n", snd_printk(KERN_ERR "can't read aci version on 0x%lx.\n",
miro->aci_port); aci->aci_port);
return -ENXIO; return -ENXIO;
} }
if (aci_cmd(miro, ACI_INIT, -1, -1) < 0 || if (snd_aci_cmd(aci, ACI_INIT, -1, -1) < 0 ||
aci_cmd(miro, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP) < 0 || snd_aci_cmd(aci, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP) < 0 ||
aci_cmd(miro, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP) < 0) { snd_aci_cmd(aci, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP) < 0) {
snd_printk(KERN_ERR "can't initialize aci.\n"); snd_printk(KERN_ERR "can't initialize aci.\n");
return -ENXIO; return -ENXIO;
} }
...@@ -1191,6 +1229,7 @@ static void snd_card_miro_free(struct snd_card *card) ...@@ -1191,6 +1229,7 @@ static void snd_card_miro_free(struct snd_card *card)
struct snd_miro *miro = card->private_data; struct snd_miro *miro = card->private_data;
release_and_free_resource(miro->res_aci_port); release_and_free_resource(miro->res_aci_port);
miro->aci->aci_port = 0;
release_and_free_resource(miro->res_mc_base); release_and_free_resource(miro->res_mc_base);
} }
...@@ -1250,7 +1289,6 @@ static int __devinit snd_miro_probe(struct device *devptr, unsigned int n) ...@@ -1250,7 +1289,6 @@ static int __devinit snd_miro_probe(struct device *devptr, unsigned int n)
} }
miro->wss_base = port; miro->wss_base = port;
miro->mpu_port = mpu_port;
miro->irq = irq; miro->irq = irq;
miro->mpu_irq = mpu_irq; miro->mpu_irq = mpu_irq;
miro->dma1 = dma1; miro->dma1 = dma1;
...@@ -1272,6 +1310,8 @@ static int __devinit snd_miro_probe(struct device *devptr, unsigned int n) ...@@ -1272,6 +1310,8 @@ static int __devinit snd_miro_probe(struct device *devptr, unsigned int n)
return -EBUSY; return -EBUSY;
} }
} }
miro->mpu_port = mpu_port;
if (miro->irq == SNDRV_AUTO_IRQ) { if (miro->irq == SNDRV_AUTO_IRQ) {
if ((miro->irq = snd_legacy_find_free_irq(possible_irqs)) < 0) { if ((miro->irq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
snd_card_free(card); snd_card_free(card);
...@@ -1339,9 +1379,9 @@ static int __devinit snd_miro_probe(struct device *devptr, unsigned int n) ...@@ -1339,9 +1379,9 @@ static int __devinit snd_miro_probe(struct device *devptr, unsigned int n)
return error; return error;
} }
if (miro->aci_vendor == 'm') { if (miro->aci->aci_vendor == 'm') {
/* It looks like a miro sound card. */ /* It looks like a miro sound card. */
switch (miro->aci_product) { switch (miro->aci->aci_product) {
case 'A': case 'A':
sprintf(card->shortname, sprintf(card->shortname,
"miroSOUND PCM1 pro / PCM12"); "miroSOUND PCM1 pro / PCM12");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment