diff options
author | Takashi Iwai <tiwai@suse.de> | 2009-11-27 07:27:03 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-11-27 07:27:03 -0500 |
commit | abe6becb7c603991b925c0d2dd908e31dd6611f5 (patch) | |
tree | d5bfdd328f87b82fbf50e338b227c54be05245b9 | |
parent | bbb3c644bd9967753ce8c214c5e64b27c361d2a4 (diff) | |
parent | 8366fc390865bfb1497fe19a518fe5713f96ba3b (diff) |
Merge branch 'next/isa' into topic/misc
-rw-r--r-- | drivers/media/radio/Kconfig | 18 | ||||
-rw-r--r-- | drivers/media/radio/Makefile | 1 | ||||
-rw-r--r-- | drivers/media/radio/radio-miropcm20.c | 270 | ||||
-rw-r--r-- | include/sound/aci.h (renamed from sound/isa/opti9xx/miro.h) | 23 | ||||
-rw-r--r-- | sound/isa/opti9xx/miro.c | 253 |
5 files changed, 456 insertions, 109 deletions
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index a87a477c87f2..b134553eb3b5 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig | |||
@@ -195,6 +195,24 @@ config RADIO_MAESTRO | |||
195 | To compile this driver as a module, choose M here: the | 195 | To compile this driver as a module, choose M here: the |
196 | module will be called radio-maestro. | 196 | module will be called radio-maestro. |
197 | 197 | ||
198 | config RADIO_MIROPCM20 | ||
199 | tristate "miroSOUND PCM20 radio" | ||
200 | depends on ISA && VIDEO_V4L2 | ||
201 | select SND_MIRO | ||
202 | ---help--- | ||
203 | Choose Y here if you have this FM radio card. You also need to enable | ||
204 | the ALSA sound system. This choice automatically selects the ALSA | ||
205 | sound card driver "Miro miroSOUND PCM1pro/PCM12/PCM20radio" as this | ||
206 | is required for the radio-miropcm20. | ||
207 | |||
208 | In order to control your radio card, you will need to use programs | ||
209 | that are compatible with the Video For Linux API. Information on | ||
210 | this API and pointers to "v4l" programs may be found at | ||
211 | <file:Documentation/video4linux/API.html>. | ||
212 | |||
213 | To compile this driver as a module, choose M here: the | ||
214 | module will be called radio-miropcm20. | ||
215 | |||
198 | config RADIO_SF16FMI | 216 | config RADIO_SF16FMI |
199 | tristate "SF16FMI Radio" | 217 | tristate "SF16FMI Radio" |
200 | depends on ISA && VIDEO_V4L2 | 218 | depends on ISA && VIDEO_V4L2 |
diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile index 2a1be3bf4f7c..8a63d543ae41 100644 --- a/drivers/media/radio/Makefile +++ b/drivers/media/radio/Makefile | |||
@@ -18,6 +18,7 @@ obj-$(CONFIG_RADIO_TRUST) += radio-trust.o | |||
18 | obj-$(CONFIG_I2C_SI4713) += si4713-i2c.o | 18 | obj-$(CONFIG_I2C_SI4713) += si4713-i2c.o |
19 | obj-$(CONFIG_RADIO_SI4713) += radio-si4713.o | 19 | obj-$(CONFIG_RADIO_SI4713) += radio-si4713.o |
20 | obj-$(CONFIG_RADIO_MAESTRO) += radio-maestro.o | 20 | obj-$(CONFIG_RADIO_MAESTRO) += radio-maestro.o |
21 | obj-$(CONFIG_RADIO_MIROPCM20) += radio-miropcm20.o | ||
21 | obj-$(CONFIG_USB_DSBR) += dsbr100.o | 22 | obj-$(CONFIG_USB_DSBR) += dsbr100.o |
22 | obj-$(CONFIG_RADIO_SI470X) += si470x/ | 23 | obj-$(CONFIG_RADIO_SI470X) += si470x/ |
23 | obj-$(CONFIG_USB_MR800) += radio-mr800.o | 24 | obj-$(CONFIG_USB_MR800) += radio-mr800.o |
diff --git a/drivers/media/radio/radio-miropcm20.c b/drivers/media/radio/radio-miropcm20.c new file mode 100644 index 000000000000..4ff885445fd4 --- /dev/null +++ b/drivers/media/radio/radio-miropcm20.c | |||
@@ -0,0 +1,270 @@ | |||
1 | /* Miro PCM20 radio driver for Linux radio support | ||
2 | * (c) 1998 Ruurd Reitsma <R.A.Reitsma@wbmt.tudelft.nl> | ||
3 | * Thanks to Norberto Pellici for the ACI device interface specification | ||
4 | * The API part is based on the radiotrack driver by M. Kirkwood | ||
5 | * This driver relies on the aci mixer provided by the snd-miro | ||
6 | * ALSA driver. | ||
7 | * Look there for further info... | ||
8 | */ | ||
9 | |||
10 | /* What ever you think about the ACI, version 0x07 is not very well! | ||
11 | * I can't get frequency, 'tuner status', 'tuner flags' or mute/mono | ||
12 | * conditions... Robert | ||
13 | */ | ||
14 | |||
15 | #include <linux/module.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/videodev2.h> | ||
18 | #include <media/v4l2-device.h> | ||
19 | #include <media/v4l2-ioctl.h> | ||
20 | #include <sound/aci.h> | ||
21 | |||
22 | static int radio_nr = -1; | ||
23 | module_param(radio_nr, int, 0); | ||
24 | MODULE_PARM_DESC(radio_nr, "Set radio device number (/dev/radioX). Default: -1 (autodetect)"); | ||
25 | |||
26 | static int mono; | ||
27 | module_param(mono, bool, 0); | ||
28 | MODULE_PARM_DESC(mono, "Force tuner into mono mode."); | ||
29 | |||
30 | struct pcm20 { | ||
31 | struct v4l2_device v4l2_dev; | ||
32 | struct video_device vdev; | ||
33 | unsigned long freq; | ||
34 | int muted; | ||
35 | struct snd_miro_aci *aci; | ||
36 | }; | ||
37 | |||
38 | static struct pcm20 pcm20_card = { | ||
39 | .freq = 87*16000, | ||
40 | .muted = 1, | ||
41 | }; | ||
42 | |||
43 | static int pcm20_mute(struct pcm20 *dev, unsigned char mute) | ||
44 | { | ||
45 | dev->muted = mute; | ||
46 | return snd_aci_cmd(dev->aci, ACI_SET_TUNERMUTE, mute, -1); | ||
47 | } | ||
48 | |||
49 | static int pcm20_stereo(struct pcm20 *dev, unsigned char stereo) | ||
50 | { | ||
51 | return snd_aci_cmd(dev->aci, ACI_SET_TUNERMONO, !stereo, -1); | ||
52 | } | ||
53 | |||
54 | static int pcm20_setfreq(struct pcm20 *dev, unsigned long freq) | ||
55 | { | ||
56 | unsigned char freql; | ||
57 | unsigned char freqh; | ||
58 | struct snd_miro_aci *aci = dev->aci; | ||
59 | |||
60 | dev->freq = freq; | ||
61 | |||
62 | freq /= 160; | ||
63 | if (!(aci->aci_version == 0x07 || aci->aci_version >= 0xb0)) | ||
64 | freq /= 10; /* I don't know exactly which version | ||
65 | * needs this hack */ | ||
66 | freql = freq & 0xff; | ||
67 | freqh = freq >> 8; | ||
68 | |||
69 | pcm20_stereo(dev, !mono); | ||
70 | return snd_aci_cmd(aci, ACI_WRITE_TUNE, freql, freqh); | ||
71 | } | ||
72 | |||
73 | static const struct v4l2_file_operations pcm20_fops = { | ||
74 | .owner = THIS_MODULE, | ||
75 | .ioctl = video_ioctl2, | ||
76 | }; | ||
77 | |||
78 | static int vidioc_querycap(struct file *file, void *priv, | ||
79 | struct v4l2_capability *v) | ||
80 | { | ||
81 | strlcpy(v->driver, "Miro PCM20", sizeof(v->driver)); | ||
82 | strlcpy(v->card, "Miro PCM20", sizeof(v->card)); | ||
83 | strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); | ||
84 | v->version = 0x1; | ||
85 | v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; | ||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | static int vidioc_g_tuner(struct file *file, void *priv, | ||
90 | struct v4l2_tuner *v) | ||
91 | { | ||
92 | if (v->index) /* Only 1 tuner */ | ||
93 | return -EINVAL; | ||
94 | strlcpy(v->name, "FM", sizeof(v->name)); | ||
95 | v->type = V4L2_TUNER_RADIO; | ||
96 | v->rangelow = 87*16000; | ||
97 | v->rangehigh = 108*16000; | ||
98 | v->signal = 0xffff; | ||
99 | v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; | ||
100 | v->capability = V4L2_TUNER_CAP_LOW; | ||
101 | v->audmode = V4L2_TUNER_MODE_MONO; | ||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | static int vidioc_s_tuner(struct file *file, void *priv, | ||
106 | struct v4l2_tuner *v) | ||
107 | { | ||
108 | return v->index ? -EINVAL : 0; | ||
109 | } | ||
110 | |||
111 | static int vidioc_g_frequency(struct file *file, void *priv, | ||
112 | struct v4l2_frequency *f) | ||
113 | { | ||
114 | struct pcm20 *dev = video_drvdata(file); | ||
115 | |||
116 | if (f->tuner != 0) | ||
117 | return -EINVAL; | ||
118 | |||
119 | f->type = V4L2_TUNER_RADIO; | ||
120 | f->frequency = dev->freq; | ||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | |||
125 | static int vidioc_s_frequency(struct file *file, void *priv, | ||
126 | struct v4l2_frequency *f) | ||
127 | { | ||
128 | struct pcm20 *dev = video_drvdata(file); | ||
129 | |||
130 | if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) | ||
131 | return -EINVAL; | ||
132 | |||
133 | dev->freq = f->frequency; | ||
134 | pcm20_setfreq(dev, f->frequency); | ||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | static int vidioc_queryctrl(struct file *file, void *priv, | ||
139 | struct v4l2_queryctrl *qc) | ||
140 | { | ||
141 | switch (qc->id) { | ||
142 | case V4L2_CID_AUDIO_MUTE: | ||
143 | return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); | ||
144 | } | ||
145 | return -EINVAL; | ||
146 | } | ||
147 | |||
148 | static int vidioc_g_ctrl(struct file *file, void *priv, | ||
149 | struct v4l2_control *ctrl) | ||
150 | { | ||
151 | struct pcm20 *dev = video_drvdata(file); | ||
152 | |||
153 | switch (ctrl->id) { | ||
154 | case V4L2_CID_AUDIO_MUTE: | ||
155 | ctrl->value = dev->muted; | ||
156 | break; | ||
157 | default: | ||
158 | return -EINVAL; | ||
159 | } | ||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | static int vidioc_s_ctrl(struct file *file, void *priv, | ||
164 | struct v4l2_control *ctrl) | ||
165 | { | ||
166 | struct pcm20 *dev = video_drvdata(file); | ||
167 | |||
168 | switch (ctrl->id) { | ||
169 | case V4L2_CID_AUDIO_MUTE: | ||
170 | pcm20_mute(dev, ctrl->value); | ||
171 | break; | ||
172 | default: | ||
173 | return -EINVAL; | ||
174 | } | ||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) | ||
179 | { | ||
180 | *i = 0; | ||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) | ||
185 | { | ||
186 | return i ? -EINVAL : 0; | ||
187 | } | ||
188 | |||
189 | static int vidioc_g_audio(struct file *file, void *priv, | ||
190 | struct v4l2_audio *a) | ||
191 | { | ||
192 | a->index = 0; | ||
193 | strlcpy(a->name, "Radio", sizeof(a->name)); | ||
194 | a->capability = V4L2_AUDCAP_STEREO; | ||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | static int vidioc_s_audio(struct file *file, void *priv, | ||
199 | struct v4l2_audio *a) | ||
200 | { | ||
201 | return a->index ? -EINVAL : 0; | ||
202 | } | ||
203 | |||
204 | static const struct v4l2_ioctl_ops pcm20_ioctl_ops = { | ||
205 | .vidioc_querycap = vidioc_querycap, | ||
206 | .vidioc_g_tuner = vidioc_g_tuner, | ||
207 | .vidioc_s_tuner = vidioc_s_tuner, | ||
208 | .vidioc_g_frequency = vidioc_g_frequency, | ||
209 | .vidioc_s_frequency = vidioc_s_frequency, | ||
210 | .vidioc_queryctrl = vidioc_queryctrl, | ||
211 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
212 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
213 | .vidioc_g_audio = vidioc_g_audio, | ||
214 | .vidioc_s_audio = vidioc_s_audio, | ||
215 | .vidioc_g_input = vidioc_g_input, | ||
216 | .vidioc_s_input = vidioc_s_input, | ||
217 | }; | ||
218 | |||
219 | static int __init pcm20_init(void) | ||
220 | { | ||
221 | struct pcm20 *dev = &pcm20_card; | ||
222 | struct v4l2_device *v4l2_dev = &dev->v4l2_dev; | ||
223 | int res; | ||
224 | |||
225 | dev->aci = snd_aci_get_aci(); | ||
226 | if (dev->aci == NULL) { | ||
227 | v4l2_err(v4l2_dev, | ||
228 | "you must load the snd-miro driver first!\n"); | ||
229 | return -ENODEV; | ||
230 | } | ||
231 | strlcpy(v4l2_dev->name, "miropcm20", sizeof(v4l2_dev->name)); | ||
232 | |||
233 | |||
234 | res = v4l2_device_register(NULL, v4l2_dev); | ||
235 | if (res < 0) { | ||
236 | v4l2_err(v4l2_dev, "could not register v4l2_device\n"); | ||
237 | return -EINVAL; | ||
238 | } | ||
239 | |||
240 | strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name)); | ||
241 | dev->vdev.v4l2_dev = v4l2_dev; | ||
242 | dev->vdev.fops = &pcm20_fops; | ||
243 | dev->vdev.ioctl_ops = &pcm20_ioctl_ops; | ||
244 | dev->vdev.release = video_device_release_empty; | ||
245 | video_set_drvdata(&dev->vdev, dev); | ||
246 | |||
247 | if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) | ||
248 | goto fail; | ||
249 | |||
250 | v4l2_info(v4l2_dev, "Mirosound PCM20 Radio tuner\n"); | ||
251 | return 0; | ||
252 | fail: | ||
253 | v4l2_device_unregister(v4l2_dev); | ||
254 | return -EINVAL; | ||
255 | } | ||
256 | |||
257 | MODULE_AUTHOR("Ruurd Reitsma, Krzysztof Helt"); | ||
258 | MODULE_DESCRIPTION("A driver for the Miro PCM20 radio card."); | ||
259 | MODULE_LICENSE("GPL"); | ||
260 | |||
261 | static void __exit pcm20_cleanup(void) | ||
262 | { | ||
263 | struct pcm20 *dev = &pcm20_card; | ||
264 | |||
265 | video_unregister_device(&dev->vdev); | ||
266 | v4l2_device_unregister(&dev->v4l2_dev); | ||
267 | } | ||
268 | |||
269 | module_init(pcm20_init); | ||
270 | module_exit(pcm20_cleanup); | ||
diff --git a/sound/isa/opti9xx/miro.h b/include/sound/aci.h index 6e1385b8e07e..ee639d355ef0 100644 --- a/sound/isa/opti9xx/miro.h +++ b/include/sound/aci.h | |||
@@ -1,5 +1,5 @@ | |||
1 | #ifndef _MIRO_H_ | 1 | #ifndef _ACI_H_ |
2 | #define _MIRO_H_ | 2 | #define _ACI_H_ |
3 | 3 | ||
4 | #define ACI_REG_COMMAND 0 /* write register offset */ | 4 | #define ACI_REG_COMMAND 0 /* write register offset */ |
5 | #define ACI_REG_STATUS 1 /* read register offset */ | 5 | #define ACI_REG_STATUS 1 /* read register offset */ |
@@ -70,4 +70,21 @@ | |||
70 | #define ACI_SET_EQ6 0x45 | 70 | #define ACI_SET_EQ6 0x45 |
71 | #define ACI_SET_EQ7 0x46 /* ... to Treble */ | 71 | #define ACI_SET_EQ7 0x46 /* ... to Treble */ |
72 | 72 | ||
73 | #endif /* _MIRO_H_ */ | 73 | struct snd_miro_aci { |
74 | unsigned long aci_port; | ||
75 | int aci_vendor; | ||
76 | int aci_product; | ||
77 | int aci_version; | ||
78 | int aci_amp; | ||
79 | int aci_preamp; | ||
80 | int aci_solomode; | ||
81 | |||
82 | struct mutex aci_mutex; | ||
83 | }; | ||
84 | |||
85 | int snd_aci_cmd(struct snd_miro_aci *aci, int write1, int write2, int write3); | ||
86 | |||
87 | struct snd_miro_aci *snd_aci_get_aci(void); | ||
88 | |||
89 | #endif /* _ACI_H_ */ | ||
90 | |||
diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c index db4a4fbdc5ca..e374869e3e21 100644 --- a/sound/isa/opti9xx/miro.c +++ b/sound/isa/opti9xx/miro.c | |||
@@ -40,7 +40,7 @@ | |||
40 | #define SNDRV_LEGACY_FIND_FREE_IRQ | 40 | #define SNDRV_LEGACY_FIND_FREE_IRQ |
41 | #define SNDRV_LEGACY_FIND_FREE_DMA | 41 | #define SNDRV_LEGACY_FIND_FREE_DMA |
42 | #include <sound/initval.h> | 42 | #include <sound/initval.h> |
43 | #include "miro.h" | 43 | #include <sound/aci.h> |
44 | 44 | ||
45 | MODULE_AUTHOR("Martin Langer <martin-langer@gmx.de>"); | 45 | MODULE_AUTHOR("Martin Langer <martin-langer@gmx.de>"); |
46 | MODULE_LICENSE("GPL"); | 46 | MODULE_LICENSE("GPL"); |
@@ -96,7 +96,6 @@ MODULE_PARM_DESC(ide, "enable ide port"); | |||
96 | 96 | ||
97 | #define OPTi9XX_MC_REG(n) n | 97 | #define OPTi9XX_MC_REG(n) n |
98 | 98 | ||
99 | |||
100 | struct snd_miro { | 99 | struct snd_miro { |
101 | unsigned short hardware; | 100 | unsigned short hardware; |
102 | unsigned char password; | 101 | unsigned char password; |
@@ -120,17 +119,11 @@ struct snd_miro { | |||
120 | long mpu_port; | 119 | long mpu_port; |
121 | int mpu_irq; | 120 | int mpu_irq; |
122 | 121 | ||
123 | unsigned long aci_port; | 122 | struct snd_miro_aci *aci; |
124 | int aci_vendor; | ||
125 | int aci_product; | ||
126 | int aci_version; | ||
127 | int aci_amp; | ||
128 | int aci_preamp; | ||
129 | int aci_solomode; | ||
130 | |||
131 | struct mutex aci_mutex; | ||
132 | }; | 123 | }; |
133 | 124 | ||
125 | static struct snd_miro_aci aci_device; | ||
126 | |||
134 | static char * snd_opti9xx_names[] = { | 127 | static char * snd_opti9xx_names[] = { |
135 | "unkown", | 128 | "unkown", |
136 | "82C928", "82C929", | 129 | "82C928", "82C929", |
@@ -142,13 +135,14 @@ static char * snd_opti9xx_names[] = { | |||
142 | * ACI control | 135 | * ACI control |
143 | */ | 136 | */ |
144 | 137 | ||
145 | static int aci_busy_wait(struct snd_miro * miro) | 138 | static int aci_busy_wait(struct snd_miro_aci *aci) |
146 | { | 139 | { |
147 | long timeout; | 140 | long timeout; |
148 | unsigned char byte; | 141 | unsigned char byte; |
149 | 142 | ||
150 | for (timeout = 1; timeout <= ACI_MINTIME+30; timeout++) { | 143 | for (timeout = 1; timeout <= ACI_MINTIME + 30; timeout++) { |
151 | if (((byte=inb(miro->aci_port + ACI_REG_BUSY)) & 1) == 0) { | 144 | byte = inb(aci->aci_port + ACI_REG_BUSY); |
145 | if ((byte & 1) == 0) { | ||
152 | if (timeout >= ACI_MINTIME) | 146 | if (timeout >= ACI_MINTIME) |
153 | snd_printd("aci ready in round %ld.\n", | 147 | snd_printd("aci ready in round %ld.\n", |
154 | timeout-ACI_MINTIME); | 148 | timeout-ACI_MINTIME); |
@@ -174,10 +168,10 @@ static int aci_busy_wait(struct snd_miro * miro) | |||
174 | return -EBUSY; | 168 | return -EBUSY; |
175 | } | 169 | } |
176 | 170 | ||
177 | static inline int aci_write(struct snd_miro * miro, unsigned char byte) | 171 | static inline int aci_write(struct snd_miro_aci *aci, unsigned char byte) |
178 | { | 172 | { |
179 | if (aci_busy_wait(miro) >= 0) { | 173 | if (aci_busy_wait(aci) >= 0) { |
180 | outb(byte, miro->aci_port + ACI_REG_COMMAND); | 174 | outb(byte, aci->aci_port + ACI_REG_COMMAND); |
181 | return 0; | 175 | return 0; |
182 | } else { | 176 | } else { |
183 | snd_printk(KERN_ERR "aci busy, aci_write(0x%x) stopped.\n", byte); | 177 | 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 | } | 179 | } |
186 | } | 180 | } |
187 | 181 | ||
188 | static inline int aci_read(struct snd_miro * miro) | 182 | static inline int aci_read(struct snd_miro_aci *aci) |
189 | { | 183 | { |
190 | unsigned char byte; | 184 | unsigned char byte; |
191 | 185 | ||
192 | if (aci_busy_wait(miro) >= 0) { | 186 | if (aci_busy_wait(aci) >= 0) { |
193 | byte=inb(miro->aci_port + ACI_REG_STATUS); | 187 | byte = inb(aci->aci_port + ACI_REG_STATUS); |
194 | return byte; | 188 | return byte; |
195 | } else { | 189 | } else { |
196 | snd_printk(KERN_ERR "aci busy, aci_read() stopped.\n"); | 190 | snd_printk(KERN_ERR "aci busy, aci_read() stopped.\n"); |
@@ -198,39 +192,49 @@ static inline int aci_read(struct snd_miro * miro) | |||
198 | } | 192 | } |
199 | } | 193 | } |
200 | 194 | ||
201 | static int aci_cmd(struct snd_miro * miro, int write1, int write2, int write3) | 195 | int snd_aci_cmd(struct snd_miro_aci *aci, int write1, int write2, int write3) |
202 | { | 196 | { |
203 | int write[] = {write1, write2, write3}; | 197 | int write[] = {write1, write2, write3}; |
204 | int value, i; | 198 | int value, i; |
205 | 199 | ||
206 | if (mutex_lock_interruptible(&miro->aci_mutex)) | 200 | if (mutex_lock_interruptible(&aci->aci_mutex)) |
207 | return -EINTR; | 201 | return -EINTR; |
208 | 202 | ||
209 | for (i=0; i<3; i++) { | 203 | for (i=0; i<3; i++) { |
210 | if (write[i]< 0 || write[i] > 255) | 204 | if (write[i]< 0 || write[i] > 255) |
211 | break; | 205 | break; |
212 | else { | 206 | else { |
213 | value = aci_write(miro, write[i]); | 207 | value = aci_write(aci, write[i]); |
214 | if (value < 0) | 208 | if (value < 0) |
215 | goto out; | 209 | goto out; |
216 | } | 210 | } |
217 | } | 211 | } |
218 | 212 | ||
219 | value = aci_read(miro); | 213 | value = aci_read(aci); |
220 | 214 | ||
221 | out: mutex_unlock(&miro->aci_mutex); | 215 | out: mutex_unlock(&aci->aci_mutex); |
222 | return value; | 216 | return value; |
223 | } | 217 | } |
218 | EXPORT_SYMBOL(snd_aci_cmd); | ||
219 | |||
220 | static int aci_getvalue(struct snd_miro_aci *aci, unsigned char index) | ||
221 | { | ||
222 | return snd_aci_cmd(aci, ACI_STATUS, index, -1); | ||
223 | } | ||
224 | 224 | ||
225 | static int aci_getvalue(struct snd_miro * miro, unsigned char index) | 225 | static int aci_setvalue(struct snd_miro_aci *aci, unsigned char index, |
226 | int value) | ||
226 | { | 227 | { |
227 | return aci_cmd(miro, ACI_STATUS, index, -1); | 228 | return snd_aci_cmd(aci, index, value, -1); |
228 | } | 229 | } |
229 | 230 | ||
230 | static int aci_setvalue(struct snd_miro * miro, unsigned char index, int value) | 231 | struct snd_miro_aci *snd_aci_get_aci(void) |
231 | { | 232 | { |
232 | return aci_cmd(miro, index, value, -1); | 233 | if (aci_device.aci_port == 0) |
234 | return NULL; | ||
235 | return &aci_device; | ||
233 | } | 236 | } |
237 | EXPORT_SYMBOL(snd_aci_get_aci); | ||
234 | 238 | ||
235 | /* | 239 | /* |
236 | * MIXER part | 240 | * MIXER part |
@@ -244,8 +248,10 @@ static int snd_miro_get_capture(struct snd_kcontrol *kcontrol, | |||
244 | struct snd_miro *miro = snd_kcontrol_chip(kcontrol); | 248 | struct snd_miro *miro = snd_kcontrol_chip(kcontrol); |
245 | int value; | 249 | int value; |
246 | 250 | ||
247 | if ((value = aci_getvalue(miro, ACI_S_GENERAL)) < 0) { | 251 | value = aci_getvalue(miro->aci, ACI_S_GENERAL); |
248 | snd_printk(KERN_ERR "snd_miro_get_capture() failed: %d\n", value); | 252 | if (value < 0) { |
253 | snd_printk(KERN_ERR "snd_miro_get_capture() failed: %d\n", | ||
254 | value); | ||
249 | return value; | 255 | return value; |
250 | } | 256 | } |
251 | 257 | ||
@@ -262,13 +268,15 @@ static int snd_miro_put_capture(struct snd_kcontrol *kcontrol, | |||
262 | 268 | ||
263 | value = !(ucontrol->value.integer.value[0]); | 269 | value = !(ucontrol->value.integer.value[0]); |
264 | 270 | ||
265 | if ((error = aci_setvalue(miro, ACI_SET_SOLOMODE, value)) < 0) { | 271 | error = aci_setvalue(miro->aci, ACI_SET_SOLOMODE, value); |
266 | snd_printk(KERN_ERR "snd_miro_put_capture() failed: %d\n", error); | 272 | if (error < 0) { |
273 | snd_printk(KERN_ERR "snd_miro_put_capture() failed: %d\n", | ||
274 | error); | ||
267 | return error; | 275 | return error; |
268 | } | 276 | } |
269 | 277 | ||
270 | change = (value != miro->aci_solomode); | 278 | change = (value != miro->aci->aci_solomode); |
271 | miro->aci_solomode = value; | 279 | miro->aci->aci_solomode = value; |
272 | 280 | ||
273 | return change; | 281 | return change; |
274 | } | 282 | } |
@@ -290,7 +298,7 @@ static int snd_miro_get_preamp(struct snd_kcontrol *kcontrol, | |||
290 | struct snd_miro *miro = snd_kcontrol_chip(kcontrol); | 298 | struct snd_miro *miro = snd_kcontrol_chip(kcontrol); |
291 | int value; | 299 | int value; |
292 | 300 | ||
293 | if (miro->aci_version <= 176) { | 301 | if (miro->aci->aci_version <= 176) { |
294 | 302 | ||
295 | /* | 303 | /* |
296 | OSS says it's not readable with versions < 176. | 304 | OSS says it's not readable with versions < 176. |
@@ -298,12 +306,14 @@ static int snd_miro_get_preamp(struct snd_kcontrol *kcontrol, | |||
298 | which is a PCM12 with aci_version = 176. | 306 | which is a PCM12 with aci_version = 176. |
299 | */ | 307 | */ |
300 | 308 | ||
301 | ucontrol->value.integer.value[0] = miro->aci_preamp; | 309 | ucontrol->value.integer.value[0] = miro->aci->aci_preamp; |
302 | return 0; | 310 | return 0; |
303 | } | 311 | } |
304 | 312 | ||
305 | if ((value = aci_getvalue(miro, ACI_GET_PREAMP)) < 0) { | 313 | value = aci_getvalue(miro->aci, ACI_GET_PREAMP); |
306 | snd_printk(KERN_ERR "snd_miro_get_preamp() failed: %d\n", value); | 314 | if (value < 0) { |
315 | snd_printk(KERN_ERR "snd_miro_get_preamp() failed: %d\n", | ||
316 | value); | ||
307 | return value; | 317 | return value; |
308 | } | 318 | } |
309 | 319 | ||
@@ -320,13 +330,15 @@ static int snd_miro_put_preamp(struct snd_kcontrol *kcontrol, | |||
320 | 330 | ||
321 | value = ucontrol->value.integer.value[0]; | 331 | value = ucontrol->value.integer.value[0]; |
322 | 332 | ||
323 | if ((error = aci_setvalue(miro, ACI_SET_PREAMP, value)) < 0) { | 333 | error = aci_setvalue(miro->aci, ACI_SET_PREAMP, value); |
324 | snd_printk(KERN_ERR "snd_miro_put_preamp() failed: %d\n", error); | 334 | if (error < 0) { |
335 | snd_printk(KERN_ERR "snd_miro_put_preamp() failed: %d\n", | ||
336 | error); | ||
325 | return error; | 337 | return error; |
326 | } | 338 | } |
327 | 339 | ||
328 | change = (value != miro->aci_preamp); | 340 | change = (value != miro->aci->aci_preamp); |
329 | miro->aci_preamp = value; | 341 | miro->aci->aci_preamp = value; |
330 | 342 | ||
331 | return change; | 343 | return change; |
332 | } | 344 | } |
@@ -337,7 +349,7 @@ static int snd_miro_get_amp(struct snd_kcontrol *kcontrol, | |||
337 | struct snd_ctl_elem_value *ucontrol) | 349 | struct snd_ctl_elem_value *ucontrol) |
338 | { | 350 | { |
339 | struct snd_miro *miro = snd_kcontrol_chip(kcontrol); | 351 | struct snd_miro *miro = snd_kcontrol_chip(kcontrol); |
340 | ucontrol->value.integer.value[0] = miro->aci_amp; | 352 | ucontrol->value.integer.value[0] = miro->aci->aci_amp; |
341 | 353 | ||
342 | return 0; | 354 | return 0; |
343 | } | 355 | } |
@@ -350,13 +362,14 @@ static int snd_miro_put_amp(struct snd_kcontrol *kcontrol, | |||
350 | 362 | ||
351 | value = ucontrol->value.integer.value[0]; | 363 | value = ucontrol->value.integer.value[0]; |
352 | 364 | ||
353 | if ((error = aci_setvalue(miro, ACI_SET_POWERAMP, value)) < 0) { | 365 | error = aci_setvalue(miro->aci, ACI_SET_POWERAMP, value); |
366 | if (error < 0) { | ||
354 | snd_printk(KERN_ERR "snd_miro_put_amp() to %d failed: %d\n", value, error); | 367 | snd_printk(KERN_ERR "snd_miro_put_amp() to %d failed: %d\n", value, error); |
355 | return error; | 368 | return error; |
356 | } | 369 | } |
357 | 370 | ||
358 | change = (value != miro->aci_amp); | 371 | change = (value != miro->aci->aci_amp); |
359 | miro->aci_amp = value; | 372 | miro->aci->aci_amp = value; |
360 | 373 | ||
361 | return change; | 374 | return change; |
362 | } | 375 | } |
@@ -405,12 +418,14 @@ static int snd_miro_get_double(struct snd_kcontrol *kcontrol, | |||
405 | int right_reg = kcontrol->private_value & 0xff; | 418 | int right_reg = kcontrol->private_value & 0xff; |
406 | int left_reg = right_reg + 1; | 419 | int left_reg = right_reg + 1; |
407 | 420 | ||
408 | if ((right_val = aci_getvalue(miro, right_reg)) < 0) { | 421 | right_val = aci_getvalue(miro->aci, right_reg); |
422 | if (right_val < 0) { | ||
409 | snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", right_reg, right_val); | 423 | snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", right_reg, right_val); |
410 | return right_val; | 424 | return right_val; |
411 | } | 425 | } |
412 | 426 | ||
413 | if ((left_val = aci_getvalue(miro, left_reg)) < 0) { | 427 | left_val = aci_getvalue(miro->aci, left_reg); |
428 | if (left_val < 0) { | ||
414 | snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", left_reg, left_val); | 429 | snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", left_reg, left_val); |
415 | return left_val; | 430 | return left_val; |
416 | } | 431 | } |
@@ -446,6 +461,7 @@ static int snd_miro_put_double(struct snd_kcontrol *kcontrol, | |||
446 | struct snd_ctl_elem_value *ucontrol) | 461 | struct snd_ctl_elem_value *ucontrol) |
447 | { | 462 | { |
448 | struct snd_miro *miro = snd_kcontrol_chip(kcontrol); | 463 | struct snd_miro *miro = snd_kcontrol_chip(kcontrol); |
464 | struct snd_miro_aci *aci = miro->aci; | ||
449 | int left, right, left_old, right_old; | 465 | int left, right, left_old, right_old; |
450 | int setreg_left, setreg_right, getreg_left, getreg_right; | 466 | int setreg_left, setreg_right, getreg_left, getreg_right; |
451 | int change, error; | 467 | int change, error; |
@@ -461,12 +477,14 @@ static int snd_miro_put_double(struct snd_kcontrol *kcontrol, | |||
461 | getreg_right = kcontrol->private_value & 0xff; | 477 | getreg_right = kcontrol->private_value & 0xff; |
462 | getreg_left = getreg_right + 1; | 478 | getreg_left = getreg_right + 1; |
463 | 479 | ||
464 | if ((left_old = aci_getvalue(miro, getreg_left)) < 0) { | 480 | left_old = aci_getvalue(aci, getreg_left); |
481 | if (left_old < 0) { | ||
465 | snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", getreg_left, left_old); | 482 | snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", getreg_left, left_old); |
466 | return left_old; | 483 | return left_old; |
467 | } | 484 | } |
468 | 485 | ||
469 | if ((right_old = aci_getvalue(miro, getreg_right)) < 0) { | 486 | right_old = aci_getvalue(aci, getreg_right); |
487 | if (right_old < 0) { | ||
470 | snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", getreg_right, right_old); | 488 | snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", getreg_right, right_old); |
471 | return right_old; | 489 | return right_old; |
472 | } | 490 | } |
@@ -485,13 +503,15 @@ static int snd_miro_put_double(struct snd_kcontrol *kcontrol, | |||
485 | right_old = 0x80 - right_old; | 503 | right_old = 0x80 - right_old; |
486 | 504 | ||
487 | if (left >= 0) { | 505 | if (left >= 0) { |
488 | if ((error = aci_setvalue(miro, setreg_left, left)) < 0) { | 506 | error = aci_setvalue(aci, setreg_left, left); |
507 | if (error < 0) { | ||
489 | snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", | 508 | snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", |
490 | left, error); | 509 | left, error); |
491 | return error; | 510 | return error; |
492 | } | 511 | } |
493 | } else { | 512 | } else { |
494 | if ((error = aci_setvalue(miro, setreg_left, 0x80 - left)) < 0) { | 513 | error = aci_setvalue(aci, setreg_left, 0x80 - left); |
514 | if (error < 0) { | ||
495 | snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", | 515 | snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", |
496 | 0x80 - left, error); | 516 | 0x80 - left, error); |
497 | return error; | 517 | return error; |
@@ -499,13 +519,15 @@ static int snd_miro_put_double(struct snd_kcontrol *kcontrol, | |||
499 | } | 519 | } |
500 | 520 | ||
501 | if (right >= 0) { | 521 | if (right >= 0) { |
502 | if ((error = aci_setvalue(miro, setreg_right, right)) < 0) { | 522 | error = aci_setvalue(aci, setreg_right, right); |
523 | if (error < 0) { | ||
503 | snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", | 524 | snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", |
504 | right, error); | 525 | right, error); |
505 | return error; | 526 | return error; |
506 | } | 527 | } |
507 | } else { | 528 | } else { |
508 | if ((error = aci_setvalue(miro, setreg_right, 0x80 - right)) < 0) { | 529 | error = aci_setvalue(aci, setreg_right, 0x80 - right); |
530 | if (error < 0) { | ||
509 | snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", | 531 | snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", |
510 | 0x80 - right, error); | 532 | 0x80 - right, error); |
511 | return error; | 533 | return error; |
@@ -523,12 +545,14 @@ static int snd_miro_put_double(struct snd_kcontrol *kcontrol, | |||
523 | left_old = 0x20 - left_old; | 545 | left_old = 0x20 - left_old; |
524 | right_old = 0x20 - right_old; | 546 | right_old = 0x20 - right_old; |
525 | 547 | ||
526 | if ((error = aci_setvalue(miro, setreg_left, 0x20 - left)) < 0) { | 548 | error = aci_setvalue(aci, setreg_left, 0x20 - left); |
549 | if (error < 0) { | ||
527 | snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", | 550 | snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", |
528 | 0x20 - left, error); | 551 | 0x20 - left, error); |
529 | return error; | 552 | return error; |
530 | } | 553 | } |
531 | if ((error = aci_setvalue(miro, setreg_right, 0x20 - right)) < 0) { | 554 | error = aci_setvalue(aci, setreg_right, 0x20 - right); |
555 | if (error < 0) { | ||
532 | snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", | 556 | snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", |
533 | 0x20 - right, error); | 557 | 0x20 - right, error); |
534 | return error; | 558 | return error; |
@@ -626,11 +650,13 @@ static unsigned char aci_init_values[][2] __devinitdata = { | |||
626 | static int __devinit snd_set_aci_init_values(struct snd_miro *miro) | 650 | static int __devinit snd_set_aci_init_values(struct snd_miro *miro) |
627 | { | 651 | { |
628 | int idx, error; | 652 | int idx, error; |
653 | struct snd_miro_aci *aci = miro->aci; | ||
629 | 654 | ||
630 | /* enable WSS on PCM1 */ | 655 | /* enable WSS on PCM1 */ |
631 | 656 | ||
632 | if ((miro->aci_product == 'A') && wss) { | 657 | if ((aci->aci_product == 'A') && wss) { |
633 | if ((error = aci_setvalue(miro, ACI_SET_WSS, wss)) < 0) { | 658 | error = aci_setvalue(aci, ACI_SET_WSS, wss); |
659 | if (error < 0) { | ||
634 | snd_printk(KERN_ERR "enabling WSS mode failed\n"); | 660 | snd_printk(KERN_ERR "enabling WSS mode failed\n"); |
635 | return error; | 661 | return error; |
636 | } | 662 | } |
@@ -639,7 +665,8 @@ static int __devinit snd_set_aci_init_values(struct snd_miro *miro) | |||
639 | /* enable IDE port */ | 665 | /* enable IDE port */ |
640 | 666 | ||
641 | if (ide) { | 667 | if (ide) { |
642 | if ((error = aci_setvalue(miro, ACI_SET_IDE, ide)) < 0) { | 668 | error = aci_setvalue(aci, ACI_SET_IDE, ide); |
669 | if (error < 0) { | ||
643 | snd_printk(KERN_ERR "enabling IDE port failed\n"); | 670 | snd_printk(KERN_ERR "enabling IDE port failed\n"); |
644 | return error; | 671 | return error; |
645 | } | 672 | } |
@@ -647,17 +674,18 @@ static int __devinit snd_set_aci_init_values(struct snd_miro *miro) | |||
647 | 674 | ||
648 | /* set common aci values */ | 675 | /* set common aci values */ |
649 | 676 | ||
650 | for (idx = 0; idx < ARRAY_SIZE(aci_init_values); idx++) | 677 | for (idx = 0; idx < ARRAY_SIZE(aci_init_values); idx++) { |
651 | if ((error = aci_setvalue(miro, aci_init_values[idx][0], | 678 | error = aci_setvalue(aci, aci_init_values[idx][0], |
652 | aci_init_values[idx][1])) < 0) { | 679 | aci_init_values[idx][1]); |
680 | if (error < 0) { | ||
653 | snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", | 681 | snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", |
654 | aci_init_values[idx][0], error); | 682 | aci_init_values[idx][0], error); |
655 | return error; | 683 | return error; |
656 | } | 684 | } |
657 | 685 | } | |
658 | miro->aci_amp = 0; | 686 | aci->aci_amp = 0; |
659 | miro->aci_preamp = 0; | 687 | aci->aci_preamp = 0; |
660 | miro->aci_solomode = 1; | 688 | aci->aci_solomode = 1; |
661 | 689 | ||
662 | return 0; | 690 | return 0; |
663 | } | 691 | } |
@@ -688,7 +716,8 @@ static int __devinit snd_miro_mixer(struct snd_card *card, | |||
688 | return err; | 716 | return err; |
689 | } | 717 | } |
690 | 718 | ||
691 | if ((miro->aci_product == 'A') || (miro->aci_product == 'B')) { | 719 | if ((miro->aci->aci_product == 'A') || |
720 | (miro->aci->aci_product == 'B')) { | ||
692 | /* PCM1/PCM12 with power-amp and Line 2 */ | 721 | /* PCM1/PCM12 with power-amp and Line 2 */ |
693 | if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_line_control[0], miro))) < 0) | 722 | if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_line_control[0], miro))) < 0) |
694 | return err; | 723 | return err; |
@@ -696,16 +725,17 @@ static int __devinit snd_miro_mixer(struct snd_card *card, | |||
696 | return err; | 725 | return err; |
697 | } | 726 | } |
698 | 727 | ||
699 | if ((miro->aci_product == 'B') || (miro->aci_product == 'C')) { | 728 | if ((miro->aci->aci_product == 'B') || |
729 | (miro->aci->aci_product == 'C')) { | ||
700 | /* PCM12/PCM20 with mic-preamp */ | 730 | /* PCM12/PCM20 with mic-preamp */ |
701 | if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_preamp_control[0], miro))) < 0) | 731 | if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_preamp_control[0], miro))) < 0) |
702 | return err; | 732 | return err; |
703 | if (miro->aci_version >= 176) | 733 | if (miro->aci->aci_version >= 176) |
704 | if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_capture_control[0], miro))) < 0) | 734 | if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_capture_control[0], miro))) < 0) |
705 | return err; | 735 | return err; |
706 | } | 736 | } |
707 | 737 | ||
708 | if (miro->aci_product == 'C') { | 738 | if (miro->aci->aci_product == 'C') { |
709 | /* PCM20 with radio and 7 band equalizer */ | 739 | /* PCM20 with radio and 7 band equalizer */ |
710 | if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_radio_control[0], miro))) < 0) | 740 | if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_radio_control[0], miro))) < 0) |
711 | return err; | 741 | return err; |
@@ -843,14 +873,15 @@ static void snd_miro_proc_read(struct snd_info_entry * entry, | |||
843 | struct snd_info_buffer *buffer) | 873 | struct snd_info_buffer *buffer) |
844 | { | 874 | { |
845 | struct snd_miro *miro = (struct snd_miro *) entry->private_data; | 875 | struct snd_miro *miro = (struct snd_miro *) entry->private_data; |
876 | struct snd_miro_aci *aci = miro->aci; | ||
846 | char* model = "unknown"; | 877 | char* model = "unknown"; |
847 | 878 | ||
848 | /* miroSOUND PCM1 pro, early PCM12 */ | 879 | /* miroSOUND PCM1 pro, early PCM12 */ |
849 | 880 | ||
850 | if ((miro->hardware == OPTi9XX_HW_82C929) && | 881 | if ((miro->hardware == OPTi9XX_HW_82C929) && |
851 | (miro->aci_vendor == 'm') && | 882 | (aci->aci_vendor == 'm') && |
852 | (miro->aci_product == 'A')) { | 883 | (aci->aci_product == 'A')) { |
853 | switch(miro->aci_version) { | 884 | switch (aci->aci_version) { |
854 | case 3: | 885 | case 3: |
855 | model = "miroSOUND PCM1 pro"; | 886 | model = "miroSOUND PCM1 pro"; |
856 | break; | 887 | break; |
@@ -863,9 +894,9 @@ static void snd_miro_proc_read(struct snd_info_entry * entry, | |||
863 | /* miroSOUND PCM12, PCM12 (Rev. E), PCM12 pnp */ | 894 | /* miroSOUND PCM12, PCM12 (Rev. E), PCM12 pnp */ |
864 | 895 | ||
865 | if ((miro->hardware == OPTi9XX_HW_82C924) && | 896 | if ((miro->hardware == OPTi9XX_HW_82C924) && |
866 | (miro->aci_vendor == 'm') && | 897 | (aci->aci_vendor == 'm') && |
867 | (miro->aci_product == 'B')) { | 898 | (aci->aci_product == 'B')) { |
868 | switch(miro->aci_version) { | 899 | switch (aci->aci_version) { |
869 | case 4: | 900 | case 4: |
870 | model = "miroSOUND PCM12"; | 901 | model = "miroSOUND PCM12"; |
871 | break; | 902 | break; |
@@ -881,9 +912,9 @@ static void snd_miro_proc_read(struct snd_info_entry * entry, | |||
881 | /* miroSOUND PCM20 radio */ | 912 | /* miroSOUND PCM20 radio */ |
882 | 913 | ||
883 | if ((miro->hardware == OPTi9XX_HW_82C924) && | 914 | if ((miro->hardware == OPTi9XX_HW_82C924) && |
884 | (miro->aci_vendor == 'm') && | 915 | (aci->aci_vendor == 'm') && |
885 | (miro->aci_product == 'C')) { | 916 | (aci->aci_product == 'C')) { |
886 | switch(miro->aci_version) { | 917 | switch (aci->aci_version) { |
887 | case 7: | 918 | case 7: |
888 | model = "miroSOUND PCM20 radio (Rev. E)"; | 919 | model = "miroSOUND PCM20 radio (Rev. E)"; |
889 | break; | 920 | break; |
@@ -907,17 +938,17 @@ static void snd_miro_proc_read(struct snd_info_entry * entry, | |||
907 | 938 | ||
908 | snd_iprintf(buffer, "ACI information:\n"); | 939 | snd_iprintf(buffer, "ACI information:\n"); |
909 | snd_iprintf(buffer, " vendor : "); | 940 | snd_iprintf(buffer, " vendor : "); |
910 | switch(miro->aci_vendor) { | 941 | switch (aci->aci_vendor) { |
911 | case 'm': | 942 | case 'm': |
912 | snd_iprintf(buffer, "Miro\n"); | 943 | snd_iprintf(buffer, "Miro\n"); |
913 | break; | 944 | break; |
914 | default: | 945 | default: |
915 | snd_iprintf(buffer, "unknown (0x%x)\n", miro->aci_vendor); | 946 | snd_iprintf(buffer, "unknown (0x%x)\n", aci->aci_vendor); |
916 | break; | 947 | break; |
917 | } | 948 | } |
918 | 949 | ||
919 | snd_iprintf(buffer, " product : "); | 950 | snd_iprintf(buffer, " product : "); |
920 | switch(miro->aci_product) { | 951 | switch (aci->aci_product) { |
921 | case 'A': | 952 | case 'A': |
922 | snd_iprintf(buffer, "miroSOUND PCM1 pro / (early) PCM12\n"); | 953 | snd_iprintf(buffer, "miroSOUND PCM1 pro / (early) PCM12\n"); |
923 | break; | 954 | break; |
@@ -928,19 +959,19 @@ static void snd_miro_proc_read(struct snd_info_entry * entry, | |||
928 | snd_iprintf(buffer, "miroSOUND PCM20 radio\n"); | 959 | snd_iprintf(buffer, "miroSOUND PCM20 radio\n"); |
929 | break; | 960 | break; |
930 | default: | 961 | default: |
931 | snd_iprintf(buffer, "unknown (0x%x)\n", miro->aci_product); | 962 | snd_iprintf(buffer, "unknown (0x%x)\n", aci->aci_product); |
932 | break; | 963 | break; |
933 | } | 964 | } |
934 | 965 | ||
935 | snd_iprintf(buffer, " firmware: %d (0x%x)\n", | 966 | snd_iprintf(buffer, " firmware: %d (0x%x)\n", |
936 | miro->aci_version, miro->aci_version); | 967 | aci->aci_version, aci->aci_version); |
937 | snd_iprintf(buffer, " port : 0x%lx-0x%lx\n", | 968 | snd_iprintf(buffer, " port : 0x%lx-0x%lx\n", |
938 | miro->aci_port, miro->aci_port+2); | 969 | aci->aci_port, aci->aci_port+2); |
939 | snd_iprintf(buffer, " wss : 0x%x\n", wss); | 970 | snd_iprintf(buffer, " wss : 0x%x\n", wss); |
940 | snd_iprintf(buffer, " ide : 0x%x\n", ide); | 971 | snd_iprintf(buffer, " ide : 0x%x\n", ide); |
941 | snd_iprintf(buffer, " solomode: 0x%x\n", miro->aci_solomode); | 972 | snd_iprintf(buffer, " solomode: 0x%x\n", aci->aci_solomode); |
942 | snd_iprintf(buffer, " amp : 0x%x\n", miro->aci_amp); | 973 | snd_iprintf(buffer, " amp : 0x%x\n", aci->aci_amp); |
943 | snd_iprintf(buffer, " preamp : 0x%x\n", miro->aci_preamp); | 974 | snd_iprintf(buffer, " preamp : 0x%x\n", aci->aci_preamp); |
944 | } | 975 | } |
945 | 976 | ||
946 | static void __devinit snd_miro_proc_init(struct snd_card *card, | 977 | 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 | } | 1170 | } |
1140 | 1171 | ||
1141 | static int __devinit snd_card_miro_aci_detect(struct snd_card *card, | 1172 | static int __devinit snd_card_miro_aci_detect(struct snd_card *card, |
1142 | struct snd_miro * miro) | 1173 | struct snd_miro *miro) |
1143 | { | 1174 | { |
1144 | unsigned char regval; | 1175 | unsigned char regval; |
1145 | int i; | 1176 | int i; |
1177 | struct snd_miro_aci *aci = &aci_device; | ||
1178 | |||
1179 | miro->aci = aci; | ||
1146 | 1180 | ||
1147 | mutex_init(&miro->aci_mutex); | 1181 | mutex_init(&aci->aci_mutex); |
1148 | 1182 | ||
1149 | /* get ACI port from OPTi9xx MC 4 */ | 1183 | /* get ACI port from OPTi9xx MC 4 */ |
1150 | 1184 | ||
1151 | regval=inb(miro->mc_base + 4); | 1185 | regval=inb(miro->mc_base + 4); |
1152 | miro->aci_port = (regval & 0x10) ? 0x344: 0x354; | 1186 | aci->aci_port = (regval & 0x10) ? 0x344 : 0x354; |
1153 | 1187 | ||
1154 | if ((miro->res_aci_port = request_region(miro->aci_port, 3, "miro aci")) == NULL) { | 1188 | miro->res_aci_port = request_region(aci->aci_port, 3, "miro aci"); |
1189 | if (miro->res_aci_port == NULL) { | ||
1155 | snd_printk(KERN_ERR "aci i/o area 0x%lx-0x%lx already used.\n", | 1190 | snd_printk(KERN_ERR "aci i/o area 0x%lx-0x%lx already used.\n", |
1156 | miro->aci_port, miro->aci_port+2); | 1191 | aci->aci_port, aci->aci_port+2); |
1157 | return -ENOMEM; | 1192 | return -ENOMEM; |
1158 | } | 1193 | } |
1159 | 1194 | ||
1160 | /* force ACI into a known state */ | 1195 | /* force ACI into a known state */ |
1161 | for (i = 0; i < 3; i++) | 1196 | for (i = 0; i < 3; i++) |
1162 | if (aci_cmd(miro, ACI_ERROR_OP, -1, -1) < 0) { | 1197 | if (snd_aci_cmd(aci, ACI_ERROR_OP, -1, -1) < 0) { |
1163 | snd_printk(KERN_ERR "can't force aci into known state.\n"); | 1198 | snd_printk(KERN_ERR "can't force aci into known state.\n"); |
1164 | return -ENXIO; | 1199 | return -ENXIO; |
1165 | } | 1200 | } |
1166 | 1201 | ||
1167 | if ((miro->aci_vendor=aci_cmd(miro, ACI_READ_IDCODE, -1, -1)) < 0 || | 1202 | aci->aci_vendor = snd_aci_cmd(aci, ACI_READ_IDCODE, -1, -1); |
1168 | (miro->aci_product=aci_cmd(miro, ACI_READ_IDCODE, -1, -1)) < 0) { | 1203 | aci->aci_product = snd_aci_cmd(aci, ACI_READ_IDCODE, -1, -1); |
1169 | snd_printk(KERN_ERR "can't read aci id on 0x%lx.\n", miro->aci_port); | 1204 | if (aci->aci_vendor < 0 || aci->aci_product < 0) { |
1205 | snd_printk(KERN_ERR "can't read aci id on 0x%lx.\n", | ||
1206 | aci->aci_port); | ||
1170 | return -ENXIO; | 1207 | return -ENXIO; |
1171 | } | 1208 | } |
1172 | 1209 | ||
1173 | if ((miro->aci_version=aci_cmd(miro, ACI_READ_VERSION, -1, -1)) < 0) { | 1210 | aci->aci_version = snd_aci_cmd(aci, ACI_READ_VERSION, -1, -1); |
1211 | if (aci->aci_version < 0) { | ||
1174 | snd_printk(KERN_ERR "can't read aci version on 0x%lx.\n", | 1212 | snd_printk(KERN_ERR "can't read aci version on 0x%lx.\n", |
1175 | miro->aci_port); | 1213 | aci->aci_port); |
1176 | return -ENXIO; | 1214 | return -ENXIO; |
1177 | } | 1215 | } |
1178 | 1216 | ||
1179 | if (aci_cmd(miro, ACI_INIT, -1, -1) < 0 || | 1217 | if (snd_aci_cmd(aci, ACI_INIT, -1, -1) < 0 || |
1180 | aci_cmd(miro, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP) < 0 || | 1218 | snd_aci_cmd(aci, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP) < 0 || |
1181 | aci_cmd(miro, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP) < 0) { | 1219 | snd_aci_cmd(aci, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP) < 0) { |
1182 | snd_printk(KERN_ERR "can't initialize aci.\n"); | 1220 | snd_printk(KERN_ERR "can't initialize aci.\n"); |
1183 | return -ENXIO; | 1221 | return -ENXIO; |
1184 | } | 1222 | } |
@@ -1191,6 +1229,8 @@ static void snd_card_miro_free(struct snd_card *card) | |||
1191 | struct snd_miro *miro = card->private_data; | 1229 | struct snd_miro *miro = card->private_data; |
1192 | 1230 | ||
1193 | release_and_free_resource(miro->res_aci_port); | 1231 | release_and_free_resource(miro->res_aci_port); |
1232 | if (miro->aci) | ||
1233 | miro->aci->aci_port = 0; | ||
1194 | release_and_free_resource(miro->res_mc_base); | 1234 | release_and_free_resource(miro->res_mc_base); |
1195 | } | 1235 | } |
1196 | 1236 | ||
@@ -1250,7 +1290,6 @@ static int __devinit snd_miro_probe(struct device *devptr, unsigned int n) | |||
1250 | } | 1290 | } |
1251 | 1291 | ||
1252 | miro->wss_base = port; | 1292 | miro->wss_base = port; |
1253 | miro->mpu_port = mpu_port; | ||
1254 | miro->irq = irq; | 1293 | miro->irq = irq; |
1255 | miro->mpu_irq = mpu_irq; | 1294 | miro->mpu_irq = mpu_irq; |
1256 | miro->dma1 = dma1; | 1295 | miro->dma1 = dma1; |
@@ -1272,6 +1311,8 @@ static int __devinit snd_miro_probe(struct device *devptr, unsigned int n) | |||
1272 | return -EBUSY; | 1311 | return -EBUSY; |
1273 | } | 1312 | } |
1274 | } | 1313 | } |
1314 | miro->mpu_port = mpu_port; | ||
1315 | |||
1275 | if (miro->irq == SNDRV_AUTO_IRQ) { | 1316 | if (miro->irq == SNDRV_AUTO_IRQ) { |
1276 | if ((miro->irq = snd_legacy_find_free_irq(possible_irqs)) < 0) { | 1317 | if ((miro->irq = snd_legacy_find_free_irq(possible_irqs)) < 0) { |
1277 | snd_card_free(card); | 1318 | snd_card_free(card); |
@@ -1339,9 +1380,9 @@ static int __devinit snd_miro_probe(struct device *devptr, unsigned int n) | |||
1339 | return error; | 1380 | return error; |
1340 | } | 1381 | } |
1341 | 1382 | ||
1342 | if (miro->aci_vendor == 'm') { | 1383 | if (miro->aci->aci_vendor == 'm') { |
1343 | /* It looks like a miro sound card. */ | 1384 | /* It looks like a miro sound card. */ |
1344 | switch (miro->aci_product) { | 1385 | switch (miro->aci->aci_product) { |
1345 | case 'A': | 1386 | case 'A': |
1346 | sprintf(card->shortname, | 1387 | sprintf(card->shortname, |
1347 | "miroSOUND PCM1 pro / PCM12"); | 1388 | "miroSOUND PCM1 pro / PCM12"); |