mavb.c revision 1.13 1 1.13 isaki /* $NetBSD: mavb.c,v 1.13 2019/05/08 13:40:16 isaki Exp $ */
2 1.1 jmcneill /* $OpenBSD: mavb.c,v 1.6 2005/04/15 13:05:14 mickey Exp $ */
3 1.1 jmcneill
4 1.1 jmcneill /*
5 1.1 jmcneill * Copyright (c) 2005 Mark Kettenis
6 1.1 jmcneill *
7 1.1 jmcneill * Permission to use, copy, modify, and distribute this software for any
8 1.1 jmcneill * purpose with or without fee is hereby granted, provided that the above
9 1.1 jmcneill * copyright notice and this permission notice appear in all copies.
10 1.1 jmcneill *
11 1.1 jmcneill * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 1.1 jmcneill * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 1.1 jmcneill * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 1.1 jmcneill * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 1.1 jmcneill * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 1.1 jmcneill * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 1.1 jmcneill * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 1.1 jmcneill */
19 1.1 jmcneill
20 1.1 jmcneill #include <sys/param.h>
21 1.1 jmcneill #include <sys/systm.h>
22 1.1 jmcneill #include <sys/device.h>
23 1.1 jmcneill #include <sys/kernel.h>
24 1.8 jmcneill #include <sys/kmem.h>
25 1.1 jmcneill #include <sys/callout.h>
26 1.1 jmcneill
27 1.7 dyoung #include <sys/bus.h>
28 1.1 jmcneill #include <machine/intr.h>
29 1.1 jmcneill #include <machine/autoconf.h>
30 1.1 jmcneill
31 1.1 jmcneill #include <sys/audioio.h>
32 1.13 isaki #include <dev/audio/audio_if.h>
33 1.1 jmcneill
34 1.1 jmcneill #include <arch/sgimips/mace/macevar.h>
35 1.1 jmcneill #include <arch/sgimips/mace/macereg.h>
36 1.1 jmcneill #include <arch/sgimips/mace/mavbreg.h>
37 1.1 jmcneill
38 1.1 jmcneill #include <dev/ic/ad1843reg.h>
39 1.1 jmcneill
40 1.1 jmcneill #undef MAVB_DEBUG
41 1.1 jmcneill
42 1.1 jmcneill #ifdef MAVB_DEBUG
43 1.1 jmcneill #define DPRINTF(l,x) do { if (mavb_debug & (l)) printf x; } while (0)
44 1.1 jmcneill #define MAVB_DEBUG_INTR 0x0100
45 1.1 jmcneill int mavb_debug = ~MAVB_DEBUG_INTR;
46 1.1 jmcneill #else
47 1.1 jmcneill #define DPRINTF(l,x) /* nothing */
48 1.1 jmcneill #endif
49 1.1 jmcneill
50 1.1 jmcneill /* Repeat delays for volume buttons. */
51 1.1 jmcneill #define MAVB_VOLUME_BUTTON_REPEAT_DEL1 400 /* 400ms to start repeating */
52 1.1 jmcneill #define MAVB_VOLUME_BUTTON_REPEAT_DELN 100 /* 100ms between repeats */
53 1.1 jmcneill
54 1.1 jmcneill /* XXX We need access to some of the MACE ISA registers. */
55 1.1 jmcneill #define MAVB_ISA_NREGS 0x20
56 1.1 jmcneill
57 1.1 jmcneill /*
58 1.1 jmcneill * AD1843 Mixer.
59 1.1 jmcneill */
60 1.1 jmcneill
61 1.1 jmcneill enum {
62 1.1 jmcneill AD1843_RECORD_CLASS,
63 1.1 jmcneill AD1843_ADC_SOURCE, /* ADC Source Select */
64 1.1 jmcneill AD1843_ADC_GAIN, /* ADC Input Gain */
65 1.1 jmcneill
66 1.1 jmcneill AD1843_INPUT_CLASS,
67 1.1 jmcneill AD1843_DAC1_GAIN, /* DAC1 Analog/Digital Gain/Attenuation */
68 1.1 jmcneill AD1843_DAC1_MUTE, /* DAC1 Analog Mute */
69 1.1 jmcneill AD1843_DAC2_GAIN, /* DAC2 Mix Gain */
70 1.1 jmcneill AD1843_AUX1_GAIN, /* Auxilliary 1 Mix Gain */
71 1.1 jmcneill AD1843_AUX2_GAIN, /* Auxilliary 2 Mix Gain */
72 1.1 jmcneill AD1843_AUX3_GAIN, /* Auxilliary 3 Mix Gain */
73 1.1 jmcneill AD1843_MIC_GAIN, /* Microphone Mix Gain */
74 1.1 jmcneill AD1843_MONO_GAIN, /* Mono Mix Gain */
75 1.1 jmcneill AD1843_DAC2_MUTE, /* DAC2 Mix Mute */
76 1.1 jmcneill AD1843_AUX1_MUTE, /* Auxilliary 1 Mix Mute */
77 1.1 jmcneill AD1843_AUX2_MUTE, /* Auxilliary 2 Mix Mute */
78 1.1 jmcneill AD1843_AUX3_MUTE, /* Auxilliary 3 Mix Mute */
79 1.1 jmcneill AD1843_MIC_MUTE, /* Microphone Mix Mute */
80 1.1 jmcneill AD1843_MONO_MUTE, /* Mono Mix Mute */
81 1.1 jmcneill AD1843_SUM_MUTE, /* Sum Mute */
82 1.1 jmcneill
83 1.1 jmcneill AD1843_OUTPUT_CLASS,
84 1.1 jmcneill AD1843_MNO_MUTE, /* Mono Output Mute */
85 1.1 jmcneill AD1843_HPO_MUTE /* Headphone Output Mute */
86 1.1 jmcneill };
87 1.1 jmcneill
88 1.1 jmcneill /* ADC Source Select. The order matches the hardware bits. */
89 1.1 jmcneill const char *ad1843_source[] = {
90 1.1 jmcneill AudioNline,
91 1.1 jmcneill AudioNmicrophone,
92 1.1 jmcneill AudioNaux "1",
93 1.1 jmcneill AudioNaux "2",
94 1.1 jmcneill AudioNaux "3",
95 1.1 jmcneill AudioNmono,
96 1.1 jmcneill AudioNdac "1",
97 1.1 jmcneill AudioNdac "2"
98 1.1 jmcneill };
99 1.1 jmcneill
100 1.1 jmcneill /* Mix Control. The order matches the hardware register numbering. */
101 1.1 jmcneill const char *ad1843_input[] = {
102 1.1 jmcneill AudioNdac "2", /* AD1843_DAC2__TO_MIXER */
103 1.1 jmcneill AudioNaux "1",
104 1.1 jmcneill AudioNaux "2",
105 1.1 jmcneill AudioNaux "3",
106 1.1 jmcneill AudioNmicrophone,
107 1.1 jmcneill AudioNmono /* AD1843_MISC_SETTINGS */
108 1.1 jmcneill };
109 1.1 jmcneill
110 1.13 isaki static const struct audio_format mavb_formats[] = {
111 1.13 isaki {
112 1.13 isaki .mode = AUMODE_PLAY,
113 1.13 isaki .encoding = AUDIO_ENCODING_SLINEAR_BE,
114 1.13 isaki .validbits = 24,
115 1.13 isaki .precision = 32,
116 1.13 isaki .channels = 2,
117 1.13 isaki .channel_mask = AUFMT_STEREO,
118 1.13 isaki .frequency_type = 0,
119 1.13 isaki .frequency = { 8000, 48000 },
120 1.13 isaki },
121 1.5 jmcneill };
122 1.13 isaki #define MAVB_NFORMATS __arraycount(mavb_formats)
123 1.5 jmcneill
124 1.1 jmcneill struct mavb_softc {
125 1.9 chs device_t sc_dev;
126 1.8 jmcneill kmutex_t sc_lock;
127 1.8 jmcneill kmutex_t sc_intr_lock;
128 1.1 jmcneill bus_space_tag_t sc_st;
129 1.1 jmcneill bus_space_handle_t sc_sh;
130 1.1 jmcneill bus_dma_tag_t sc_dmat;
131 1.1 jmcneill bus_dmamap_t sc_dmamap;
132 1.1 jmcneill
133 1.1 jmcneill /* XXX We need access to some of the MACE ISA registers. */
134 1.1 jmcneill bus_space_handle_t sc_isash;
135 1.1 jmcneill
136 1.1 jmcneill #define MAVB_ISA_RING_SIZE 0x1000
137 1.1 jmcneill uint8_t *sc_ring;
138 1.1 jmcneill
139 1.1 jmcneill uint8_t *sc_start, *sc_end;
140 1.1 jmcneill int sc_blksize;
141 1.1 jmcneill void (*sc_intr)(void *);
142 1.1 jmcneill void *sc_intrarg;
143 1.1 jmcneill
144 1.1 jmcneill void *sc_get;
145 1.1 jmcneill int sc_count;
146 1.1 jmcneill
147 1.1 jmcneill u_long sc_play_rate;
148 1.1 jmcneill u_int sc_play_format;
149 1.1 jmcneill
150 1.1 jmcneill struct callout sc_volume_button_ch;
151 1.1 jmcneill };
152 1.1 jmcneill
153 1.6 tsutsui typedef uint64_t ad1843_addr_t;
154 1.1 jmcneill
155 1.6 tsutsui uint16_t ad1843_reg_read(struct mavb_softc *, ad1843_addr_t);
156 1.6 tsutsui uint16_t ad1843_reg_write(struct mavb_softc *, ad1843_addr_t, uint16_t);
157 1.1 jmcneill void ad1843_dump_regs(struct mavb_softc *);
158 1.1 jmcneill
159 1.9 chs int mavb_match(device_t, cfdata_t, void *);
160 1.9 chs void mavb_attach(device_t, device_t, void *);
161 1.1 jmcneill
162 1.9 chs CFATTACH_DECL_NEW(mavb, sizeof(struct mavb_softc),
163 1.1 jmcneill mavb_match, mavb_attach, NULL, NULL);
164 1.13 isaki
165 1.13 isaki int mavb_query_format(void *, audio_format_query_t *);
166 1.13 isaki int mavb_set_format(void *, int,
167 1.13 isaki const audio_params_t *, const audio_params_t *,
168 1.13 isaki audio_filter_reg_t *, audio_filter_reg_t *);
169 1.1 jmcneill int mavb_round_blocksize(void *hdl, int, int, const audio_params_t *);
170 1.1 jmcneill int mavb_halt_output(void *);
171 1.1 jmcneill int mavb_halt_input(void *);
172 1.1 jmcneill int mavb_getdev(void *, struct audio_device *);
173 1.1 jmcneill int mavb_set_port(void *, struct mixer_ctrl *);
174 1.1 jmcneill int mavb_get_port(void *, struct mixer_ctrl *);
175 1.1 jmcneill int mavb_query_devinfo(void *, struct mixer_devinfo *);
176 1.1 jmcneill int mavb_get_props(void *);
177 1.1 jmcneill int mavb_trigger_output(void *, void *, void *, int, void (*)(void *),
178 1.1 jmcneill void *, const audio_params_t *);
179 1.1 jmcneill int mavb_trigger_input(void *, void *, void *, int, void (*)(void *),
180 1.1 jmcneill void *, const audio_params_t *);
181 1.8 jmcneill void mavb_get_locks(void *, kmutex_t **, kmutex_t **);
182 1.1 jmcneill
183 1.1 jmcneill struct audio_hw_if mavb_sa_hw_if = {
184 1.13 isaki .query_format = mavb_query_format,
185 1.13 isaki .set_format = mavb_set_format,
186 1.12 isaki .round_blocksize = mavb_round_blocksize,
187 1.12 isaki .halt_output = mavb_halt_output,
188 1.12 isaki .halt_input = mavb_halt_input,
189 1.12 isaki .getdev = mavb_getdev,
190 1.12 isaki .set_port = mavb_set_port,
191 1.12 isaki .get_port = mavb_get_port,
192 1.12 isaki .query_devinfo = mavb_query_devinfo,
193 1.12 isaki .get_props = mavb_get_props,
194 1.12 isaki .trigger_output = mavb_trigger_output,
195 1.12 isaki .trigger_input = mavb_trigger_input,
196 1.12 isaki .get_locks = mavb_get_locks,
197 1.1 jmcneill };
198 1.1 jmcneill
199 1.1 jmcneill struct audio_device mavb_device = {
200 1.1 jmcneill "A3",
201 1.1 jmcneill "",
202 1.1 jmcneill "mavb"
203 1.1 jmcneill };
204 1.1 jmcneill
205 1.13 isaki static void
206 1.13 isaki mavb_internal_to_slinear24_32(audio_filter_arg_t *arg)
207 1.1 jmcneill {
208 1.13 isaki const aint_t *src;
209 1.13 isaki uint32_t *dst;
210 1.13 isaki u_int sample_count;
211 1.13 isaki u_int i;
212 1.13 isaki
213 1.13 isaki src = arg->src;
214 1.13 isaki dst = arg->dst;
215 1.13 isaki sample_count = arg->count * arg->srcfmt->channels;
216 1.13 isaki for (i = 0; i < sample_count; i++) {
217 1.13 isaki *dst++ = (*src++) << 8;
218 1.13 isaki }
219 1.1 jmcneill }
220 1.1 jmcneill
221 1.1 jmcneill int
222 1.13 isaki mavb_query_format(void *hdl, audio_format_query_t *afp)
223 1.1 jmcneill {
224 1.1 jmcneill
225 1.13 isaki return audio_query_format(mavb_formats, MAVB_NFORMATS, afp);
226 1.1 jmcneill }
227 1.1 jmcneill
228 1.1 jmcneill static int
229 1.1 jmcneill mavb_set_play_rate(struct mavb_softc *sc, u_long sample_rate)
230 1.1 jmcneill {
231 1.6 tsutsui
232 1.13 isaki KASSERT((4000 <= sample_rate && sample_rate <= 48000));
233 1.1 jmcneill
234 1.1 jmcneill if (sc->sc_play_rate != sample_rate) {
235 1.1 jmcneill ad1843_reg_write(sc, AD1843_CLOCK2_SAMPLE_RATE, sample_rate);
236 1.1 jmcneill sc->sc_play_rate = sample_rate;
237 1.1 jmcneill }
238 1.6 tsutsui return 0;
239 1.1 jmcneill }
240 1.1 jmcneill
241 1.1 jmcneill static int
242 1.1 jmcneill mavb_set_play_format(struct mavb_softc *sc, u_int encoding)
243 1.1 jmcneill {
244 1.6 tsutsui uint16_t value;
245 1.1 jmcneill u_int format;
246 1.1 jmcneill
247 1.1 jmcneill switch(encoding) {
248 1.1 jmcneill case AUDIO_ENCODING_SLINEAR_BE:
249 1.1 jmcneill format = AD1843_PCM16;
250 1.1 jmcneill break;
251 1.1 jmcneill default:
252 1.6 tsutsui return EINVAL;
253 1.1 jmcneill }
254 1.1 jmcneill
255 1.1 jmcneill if (sc->sc_play_format != format) {
256 1.1 jmcneill value = ad1843_reg_read(sc, AD1843_SERIAL_INTERFACE);
257 1.1 jmcneill value &= ~AD1843_DA1F_MASK;
258 1.1 jmcneill value |= (format << AD1843_DA1F_SHIFT);
259 1.1 jmcneill ad1843_reg_write(sc, AD1843_SERIAL_INTERFACE, value);
260 1.1 jmcneill sc->sc_play_format = format;
261 1.1 jmcneill }
262 1.6 tsutsui return 0;
263 1.1 jmcneill }
264 1.1 jmcneill
265 1.1 jmcneill int
266 1.13 isaki mavb_set_format(void *hdl, int setmode,
267 1.13 isaki const audio_params_t *play, const audio_params_t *rec,
268 1.13 isaki audio_filter_reg_t *pfil, audio_filter_reg_t *rfil)
269 1.1 jmcneill {
270 1.1 jmcneill struct mavb_softc *sc = (struct mavb_softc *)hdl;
271 1.1 jmcneill int error;
272 1.1 jmcneill
273 1.13 isaki DPRINTF(1, ("%s: %s: sample=%u precision=%d channels=%d\n",
274 1.13 isaki device_xname(sc->sc_dev), __func__,
275 1.13 isaki play->sample_rate, play->precision, play->channels));
276 1.1 jmcneill
277 1.1 jmcneill if (setmode & AUMODE_PLAY) {
278 1.13 isaki pfil->codec = mavb_internal_to_slinear24_32;
279 1.1 jmcneill
280 1.13 isaki error = mavb_set_play_rate(sc, play->sample_rate);
281 1.1 jmcneill if (error)
282 1.6 tsutsui return error;
283 1.1 jmcneill
284 1.13 isaki error = mavb_set_play_format(sc, play->encoding);
285 1.1 jmcneill if (error)
286 1.6 tsutsui return error;
287 1.1 jmcneill }
288 1.1 jmcneill
289 1.1 jmcneill #if 0
290 1.1 jmcneill if (setmode & AUMODE_RECORD) {
291 1.1 jmcneill }
292 1.1 jmcneill #endif
293 1.1 jmcneill
294 1.6 tsutsui return 0;
295 1.1 jmcneill }
296 1.1 jmcneill
297 1.1 jmcneill int
298 1.1 jmcneill mavb_round_blocksize(void *hdl, int bs, int mode, const audio_params_t *p)
299 1.1 jmcneill {
300 1.6 tsutsui
301 1.1 jmcneill /* Block size should be a multiple of 32. */
302 1.1 jmcneill return (bs + 0x1f) & ~0x1f;
303 1.1 jmcneill }
304 1.1 jmcneill
305 1.1 jmcneill int
306 1.1 jmcneill mavb_halt_output(void *hdl)
307 1.1 jmcneill {
308 1.1 jmcneill struct mavb_softc *sc = (struct mavb_softc *)hdl;
309 1.1 jmcneill
310 1.9 chs DPRINTF(1, ("%s: mavb_halt_output called\n", device_xname(sc->sc_dev)));
311 1.1 jmcneill
312 1.1 jmcneill bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CHANNEL2_CONTROL, 0);
313 1.6 tsutsui return 0;
314 1.1 jmcneill }
315 1.1 jmcneill
316 1.1 jmcneill int
317 1.1 jmcneill mavb_halt_input(void *hdl)
318 1.1 jmcneill {
319 1.6 tsutsui
320 1.6 tsutsui return 0;
321 1.1 jmcneill }
322 1.1 jmcneill
323 1.1 jmcneill int
324 1.1 jmcneill mavb_getdev(void *hdl, struct audio_device *ret)
325 1.1 jmcneill {
326 1.6 tsutsui
327 1.1 jmcneill *ret = mavb_device;
328 1.6 tsutsui return 0;
329 1.1 jmcneill }
330 1.1 jmcneill
331 1.1 jmcneill int
332 1.1 jmcneill mavb_set_port(void *hdl, struct mixer_ctrl *mc)
333 1.1 jmcneill {
334 1.1 jmcneill struct mavb_softc *sc = (struct mavb_softc *)hdl;
335 1.1 jmcneill u_char left, right;
336 1.1 jmcneill ad1843_addr_t reg;
337 1.6 tsutsui uint16_t value;
338 1.1 jmcneill
339 1.9 chs DPRINTF(1, ("%s: mavb_set_port: dev=%d\n", device_xname(sc->sc_dev),
340 1.1 jmcneill mc->dev));
341 1.1 jmcneill
342 1.1 jmcneill switch (mc->dev) {
343 1.1 jmcneill case AD1843_ADC_SOURCE:
344 1.1 jmcneill value = ad1843_reg_read(sc, AD1843_ADC_SOURCE_GAIN);
345 1.1 jmcneill value &= ~(AD1843_LSS_MASK | AD1843_RSS_MASK);
346 1.1 jmcneill value |= ((mc->un.ord << AD1843_LSS_SHIFT) & AD1843_LSS_MASK);
347 1.1 jmcneill value |= ((mc->un.ord << AD1843_RSS_SHIFT) & AD1843_RSS_MASK);
348 1.1 jmcneill ad1843_reg_write(sc, AD1843_ADC_SOURCE_GAIN, value);
349 1.1 jmcneill break;
350 1.1 jmcneill case AD1843_ADC_GAIN:
351 1.1 jmcneill left = mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
352 1.1 jmcneill right = mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
353 1.1 jmcneill value = ad1843_reg_read(sc, AD1843_ADC_SOURCE_GAIN);
354 1.1 jmcneill value &= ~(AD1843_LIG_MASK | AD1843_RIG_MASK);
355 1.1 jmcneill value |= ((left >> 4) << AD1843_LIG_SHIFT);
356 1.1 jmcneill value |= ((right >> 4) << AD1843_RIG_SHIFT);
357 1.1 jmcneill ad1843_reg_write(sc, AD1843_ADC_SOURCE_GAIN, value);
358 1.1 jmcneill break;
359 1.1 jmcneill
360 1.1 jmcneill case AD1843_DAC1_GAIN:
361 1.1 jmcneill left = AUDIO_MAX_GAIN -
362 1.1 jmcneill mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
363 1.1 jmcneill right = AUDIO_MAX_GAIN -
364 1.1 jmcneill mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
365 1.1 jmcneill value = ad1843_reg_read(sc, AD1843_DAC1_ANALOG_GAIN);
366 1.1 jmcneill value &= ~(AD1843_LDA1G_MASK | AD1843_RDA1G_MASK);
367 1.1 jmcneill value |= ((left >> 2) << AD1843_LDA1G_SHIFT);
368 1.1 jmcneill value |= ((right >> 2) << AD1843_RDA1G_SHIFT);
369 1.1 jmcneill ad1843_reg_write(sc, AD1843_DAC1_ANALOG_GAIN, value);
370 1.1 jmcneill break;
371 1.1 jmcneill case AD1843_DAC1_MUTE:
372 1.1 jmcneill value = ad1843_reg_read(sc, AD1843_DAC1_ANALOG_GAIN);
373 1.1 jmcneill if (mc->un.ord == 0)
374 1.1 jmcneill value &= ~(AD1843_LDA1GM | AD1843_RDA1GM);
375 1.1 jmcneill else
376 1.1 jmcneill value |= (AD1843_LDA1GM | AD1843_RDA1GM);
377 1.1 jmcneill ad1843_reg_write(sc, AD1843_DAC1_ANALOG_GAIN, value);
378 1.1 jmcneill break;
379 1.1 jmcneill
380 1.1 jmcneill case AD1843_DAC2_GAIN:
381 1.1 jmcneill case AD1843_AUX1_GAIN:
382 1.1 jmcneill case AD1843_AUX2_GAIN:
383 1.1 jmcneill case AD1843_AUX3_GAIN:
384 1.1 jmcneill case AD1843_MIC_GAIN:
385 1.1 jmcneill left = AUDIO_MAX_GAIN -
386 1.1 jmcneill mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
387 1.1 jmcneill right = AUDIO_MAX_GAIN -
388 1.1 jmcneill mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
389 1.1 jmcneill reg = AD1843_DAC2_TO_MIXER + mc->dev - AD1843_DAC2_GAIN;
390 1.1 jmcneill value = ad1843_reg_read(sc, reg);
391 1.1 jmcneill value &= ~(AD1843_LD2M_MASK | AD1843_RD2M_MASK);
392 1.1 jmcneill value |= ((left >> 3) << AD1843_LD2M_SHIFT);
393 1.1 jmcneill value |= ((right >> 3) << AD1843_RD2M_SHIFT);
394 1.1 jmcneill ad1843_reg_write(sc, reg, value);
395 1.1 jmcneill break;
396 1.1 jmcneill case AD1843_MONO_GAIN:
397 1.1 jmcneill left = AUDIO_MAX_GAIN -
398 1.1 jmcneill mc->un.value.level[AUDIO_MIXER_LEVEL_MONO];
399 1.1 jmcneill value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
400 1.1 jmcneill value &= ~AD1843_MNM_MASK;
401 1.1 jmcneill value |= ((left >> 3) << AD1843_MNM_SHIFT);
402 1.1 jmcneill ad1843_reg_write(sc, AD1843_MISC_SETTINGS, value);
403 1.1 jmcneill break;
404 1.1 jmcneill case AD1843_DAC2_MUTE:
405 1.1 jmcneill case AD1843_AUX1_MUTE:
406 1.1 jmcneill case AD1843_AUX2_MUTE:
407 1.1 jmcneill case AD1843_AUX3_MUTE:
408 1.1 jmcneill case AD1843_MIC_MUTE:
409 1.1 jmcneill case AD1843_MONO_MUTE: /* matches left channel */
410 1.1 jmcneill reg = AD1843_DAC2_TO_MIXER + mc->dev - AD1843_DAC2_MUTE;
411 1.1 jmcneill value = ad1843_reg_read(sc, reg);
412 1.1 jmcneill if (mc->un.ord == 0)
413 1.1 jmcneill value &= ~(AD1843_LD2MM | AD1843_RD2MM);
414 1.1 jmcneill else
415 1.1 jmcneill value |= (AD1843_LD2MM | AD1843_RD2MM);
416 1.1 jmcneill ad1843_reg_write(sc, reg, value);
417 1.1 jmcneill break;
418 1.1 jmcneill
419 1.1 jmcneill case AD1843_SUM_MUTE:
420 1.1 jmcneill value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
421 1.1 jmcneill if (mc->un.ord == 0)
422 1.1 jmcneill value &= ~AD1843_SUMM;
423 1.1 jmcneill else
424 1.1 jmcneill value |= AD1843_SUMM;
425 1.1 jmcneill ad1843_reg_write(sc, AD1843_MISC_SETTINGS, value);
426 1.1 jmcneill break;
427 1.1 jmcneill
428 1.1 jmcneill case AD1843_MNO_MUTE:
429 1.1 jmcneill value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
430 1.1 jmcneill if (mc->un.ord == 0)
431 1.1 jmcneill value &= ~AD1843_MNOM;
432 1.1 jmcneill else
433 1.1 jmcneill value |= AD1843_MNOM;
434 1.1 jmcneill ad1843_reg_write(sc, AD1843_MISC_SETTINGS, value);
435 1.1 jmcneill break;
436 1.1 jmcneill
437 1.1 jmcneill case AD1843_HPO_MUTE:
438 1.1 jmcneill value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
439 1.1 jmcneill if (mc->un.ord == 0)
440 1.1 jmcneill value &= ~AD1843_HPOM;
441 1.1 jmcneill else
442 1.1 jmcneill value |= AD1843_HPOM;
443 1.1 jmcneill ad1843_reg_write(sc, AD1843_MISC_SETTINGS, value);
444 1.1 jmcneill value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
445 1.1 jmcneill break;
446 1.1 jmcneill
447 1.1 jmcneill default:
448 1.6 tsutsui return EINVAL;
449 1.1 jmcneill }
450 1.1 jmcneill
451 1.6 tsutsui return 0;
452 1.1 jmcneill }
453 1.1 jmcneill
454 1.1 jmcneill int
455 1.1 jmcneill mavb_get_port(void *hdl, struct mixer_ctrl *mc)
456 1.1 jmcneill {
457 1.1 jmcneill struct mavb_softc *sc = (struct mavb_softc *)hdl;
458 1.1 jmcneill u_char left, right;
459 1.1 jmcneill ad1843_addr_t reg;
460 1.6 tsutsui uint16_t value;
461 1.1 jmcneill
462 1.9 chs DPRINTF(1, ("%s: mavb_get_port: dev=%d\n", device_xname(sc->sc_dev),
463 1.1 jmcneill mc->dev));
464 1.1 jmcneill
465 1.1 jmcneill switch (mc->dev) {
466 1.1 jmcneill case AD1843_ADC_SOURCE:
467 1.1 jmcneill value = ad1843_reg_read(sc, AD1843_ADC_SOURCE_GAIN);
468 1.1 jmcneill mc->un.ord = (value & AD1843_LSS_MASK) >> AD1843_LSS_SHIFT;
469 1.1 jmcneill break;
470 1.1 jmcneill case AD1843_ADC_GAIN:
471 1.1 jmcneill value = ad1843_reg_read(sc, AD1843_ADC_SOURCE_GAIN);
472 1.1 jmcneill left = (value & AD1843_LIG_MASK) >> AD1843_LIG_SHIFT;
473 1.1 jmcneill right = (value & AD1843_RIG_MASK) >> AD1843_RIG_SHIFT;
474 1.1 jmcneill mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
475 1.1 jmcneill (left << 4) | left;
476 1.1 jmcneill mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
477 1.1 jmcneill (right << 2) | right;
478 1.1 jmcneill break;
479 1.1 jmcneill
480 1.1 jmcneill case AD1843_DAC1_GAIN:
481 1.1 jmcneill value = ad1843_reg_read(sc, AD1843_DAC1_ANALOG_GAIN);
482 1.1 jmcneill left = (value & AD1843_LDA1G_MASK) >> AD1843_LDA1G_SHIFT;
483 1.1 jmcneill right = (value & AD1843_RDA1G_MASK) >> AD1843_RDA1G_SHIFT;
484 1.1 jmcneill mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
485 1.1 jmcneill AUDIO_MAX_GAIN - (left << 2);
486 1.1 jmcneill mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
487 1.1 jmcneill AUDIO_MAX_GAIN - (right << 2);
488 1.1 jmcneill break;
489 1.1 jmcneill case AD1843_DAC1_MUTE:
490 1.1 jmcneill value = ad1843_reg_read(sc, AD1843_DAC1_ANALOG_GAIN);
491 1.1 jmcneill mc->un.ord = (value & AD1843_LDA1GM) ? 1 : 0;
492 1.1 jmcneill break;
493 1.1 jmcneill
494 1.1 jmcneill case AD1843_DAC2_GAIN:
495 1.1 jmcneill case AD1843_AUX1_GAIN:
496 1.1 jmcneill case AD1843_AUX2_GAIN:
497 1.1 jmcneill case AD1843_AUX3_GAIN:
498 1.1 jmcneill case AD1843_MIC_GAIN:
499 1.1 jmcneill reg = AD1843_DAC2_TO_MIXER + mc->dev - AD1843_DAC2_GAIN;
500 1.1 jmcneill value = ad1843_reg_read(sc, reg);
501 1.1 jmcneill left = (value & AD1843_LD2M_MASK) >> AD1843_LD2M_SHIFT;
502 1.1 jmcneill right = (value & AD1843_RD2M_MASK) >> AD1843_RD2M_SHIFT;
503 1.1 jmcneill mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
504 1.1 jmcneill AUDIO_MAX_GAIN - (left << 3);
505 1.1 jmcneill mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
506 1.1 jmcneill AUDIO_MAX_GAIN - (right << 3);
507 1.1 jmcneill break;
508 1.1 jmcneill case AD1843_MONO_GAIN:
509 1.1 jmcneill if (mc->un.value.num_channels != 1)
510 1.6 tsutsui return EINVAL;
511 1.1 jmcneill
512 1.1 jmcneill value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
513 1.1 jmcneill left = (value & AD1843_MNM_MASK) >> AD1843_MNM_SHIFT;
514 1.1 jmcneill mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
515 1.1 jmcneill AUDIO_MAX_GAIN - (left << 3);
516 1.1 jmcneill break;
517 1.1 jmcneill case AD1843_DAC2_MUTE:
518 1.1 jmcneill case AD1843_AUX1_MUTE:
519 1.1 jmcneill case AD1843_AUX2_MUTE:
520 1.1 jmcneill case AD1843_AUX3_MUTE:
521 1.1 jmcneill case AD1843_MIC_MUTE:
522 1.1 jmcneill case AD1843_MONO_MUTE: /* matches left channel */
523 1.1 jmcneill reg = AD1843_DAC2_TO_MIXER + mc->dev - AD1843_DAC2_MUTE;
524 1.1 jmcneill value = ad1843_reg_read(sc, reg);
525 1.1 jmcneill mc->un.ord = (value & AD1843_LD2MM) ? 1 : 0;
526 1.1 jmcneill break;
527 1.1 jmcneill
528 1.1 jmcneill case AD1843_SUM_MUTE:
529 1.1 jmcneill value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
530 1.1 jmcneill mc->un.ord = (value & AD1843_SUMM) ? 1 : 0;
531 1.1 jmcneill break;
532 1.1 jmcneill
533 1.1 jmcneill case AD1843_MNO_MUTE:
534 1.1 jmcneill value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
535 1.1 jmcneill mc->un.ord = (value & AD1843_MNOM) ? 1 : 0;
536 1.1 jmcneill break;
537 1.1 jmcneill
538 1.1 jmcneill case AD1843_HPO_MUTE:
539 1.1 jmcneill value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
540 1.1 jmcneill mc->un.ord = (value & AD1843_HPOM) ? 1 : 0;
541 1.1 jmcneill break;
542 1.1 jmcneill
543 1.1 jmcneill default:
544 1.6 tsutsui return EINVAL;
545 1.1 jmcneill }
546 1.1 jmcneill
547 1.6 tsutsui return 0;
548 1.1 jmcneill }
549 1.1 jmcneill
550 1.1 jmcneill int
551 1.1 jmcneill mavb_query_devinfo(void *hdl, struct mixer_devinfo *di)
552 1.1 jmcneill {
553 1.1 jmcneill int i;
554 1.1 jmcneill
555 1.1 jmcneill di->prev = di->next = AUDIO_MIXER_LAST;
556 1.1 jmcneill
557 1.1 jmcneill switch (di->index) {
558 1.1 jmcneill case AD1843_RECORD_CLASS:
559 1.1 jmcneill di->type = AUDIO_MIXER_CLASS;
560 1.1 jmcneill di->mixer_class = AD1843_RECORD_CLASS;
561 1.1 jmcneill strlcpy(di->label.name, AudioCrecord, sizeof di->label.name);
562 1.1 jmcneill break;
563 1.1 jmcneill
564 1.1 jmcneill case AD1843_ADC_SOURCE:
565 1.1 jmcneill di->type = AUDIO_MIXER_ENUM;
566 1.1 jmcneill di->mixer_class = AD1843_RECORD_CLASS;
567 1.1 jmcneill di->next = AD1843_ADC_GAIN;
568 1.1 jmcneill strlcpy(di->label.name, AudioNsource, sizeof di->label.name);
569 1.1 jmcneill di->un.e.num_mem =
570 1.1 jmcneill sizeof ad1843_source / sizeof ad1843_source[1];
571 1.1 jmcneill for (i = 0; i < di->un.e.num_mem; i++) {
572 1.1 jmcneill strlcpy(di->un.e.member[i].label.name,
573 1.1 jmcneill ad1843_source[i],
574 1.1 jmcneill sizeof di->un.e.member[0].label.name);
575 1.1 jmcneill di->un.e.member[i].ord = i;
576 1.1 jmcneill }
577 1.1 jmcneill break;
578 1.1 jmcneill case AD1843_ADC_GAIN:
579 1.1 jmcneill di->type = AUDIO_MIXER_VALUE;
580 1.1 jmcneill di->mixer_class = AD1843_RECORD_CLASS;
581 1.1 jmcneill di->prev = AD1843_ADC_SOURCE;
582 1.1 jmcneill strlcpy(di->label.name, AudioNvolume, sizeof di->label.name);
583 1.1 jmcneill di->un.v.num_channels = 2;
584 1.1 jmcneill strlcpy(di->un.v.units.name, AudioNvolume,
585 1.1 jmcneill sizeof di->un.v.units.name);
586 1.1 jmcneill break;
587 1.1 jmcneill
588 1.1 jmcneill case AD1843_INPUT_CLASS:
589 1.1 jmcneill di->type = AUDIO_MIXER_CLASS;
590 1.1 jmcneill di->mixer_class = AD1843_INPUT_CLASS;
591 1.1 jmcneill strlcpy(di->label.name, AudioCinputs, sizeof di->label.name);
592 1.1 jmcneill break;
593 1.1 jmcneill
594 1.1 jmcneill case AD1843_DAC1_GAIN:
595 1.1 jmcneill di->type = AUDIO_MIXER_VALUE;
596 1.10 macallan di->mixer_class = AD1843_OUTPUT_CLASS;
597 1.1 jmcneill di->next = AD1843_DAC1_MUTE;
598 1.10 macallan strlcpy(di->label.name, AudioNmaster, sizeof di->label.name);
599 1.1 jmcneill di->un.v.num_channels = 2;
600 1.1 jmcneill strlcpy(di->un.v.units.name, AudioNvolume,
601 1.1 jmcneill sizeof di->un.v.units.name);
602 1.1 jmcneill break;
603 1.1 jmcneill case AD1843_DAC1_MUTE:
604 1.1 jmcneill di->type = AUDIO_MIXER_ENUM;
605 1.10 macallan di->mixer_class = AD1843_OUTPUT_CLASS;
606 1.1 jmcneill di->prev = AD1843_DAC1_GAIN;
607 1.1 jmcneill strlcpy(di->label.name, AudioNmute, sizeof di->label.name);
608 1.1 jmcneill di->un.e.num_mem = 2;
609 1.1 jmcneill strlcpy(di->un.e.member[0].label.name, AudioNoff,
610 1.1 jmcneill sizeof di->un.e.member[0].label.name);
611 1.1 jmcneill di->un.e.member[0].ord = 0;
612 1.1 jmcneill strlcpy(di->un.e.member[1].label.name, AudioNon,
613 1.1 jmcneill sizeof di->un.e.member[1].label.name);
614 1.1 jmcneill di->un.e.member[1].ord = 1;
615 1.1 jmcneill break;
616 1.1 jmcneill
617 1.1 jmcneill case AD1843_DAC2_GAIN:
618 1.1 jmcneill case AD1843_AUX1_GAIN:
619 1.1 jmcneill case AD1843_AUX2_GAIN:
620 1.1 jmcneill case AD1843_AUX3_GAIN:
621 1.1 jmcneill case AD1843_MIC_GAIN:
622 1.1 jmcneill case AD1843_MONO_GAIN:
623 1.1 jmcneill di->type = AUDIO_MIXER_VALUE;
624 1.1 jmcneill di->mixer_class = AD1843_INPUT_CLASS;
625 1.1 jmcneill di->next = di->index + AD1843_DAC2_MUTE - AD1843_DAC2_GAIN;
626 1.1 jmcneill strlcpy(di->label.name,
627 1.1 jmcneill ad1843_input[di->index - AD1843_DAC2_GAIN],
628 1.1 jmcneill sizeof di->label.name);
629 1.1 jmcneill if (di->index == AD1843_MONO_GAIN)
630 1.1 jmcneill di->un.v.num_channels = 1;
631 1.1 jmcneill else
632 1.1 jmcneill di->un.v.num_channels = 2;
633 1.1 jmcneill strlcpy(di->un.v.units.name, AudioNvolume,
634 1.1 jmcneill sizeof di->un.v.units.name);
635 1.1 jmcneill break;
636 1.1 jmcneill case AD1843_DAC2_MUTE:
637 1.1 jmcneill case AD1843_AUX1_MUTE:
638 1.1 jmcneill case AD1843_AUX2_MUTE:
639 1.1 jmcneill case AD1843_AUX3_MUTE:
640 1.1 jmcneill case AD1843_MIC_MUTE:
641 1.1 jmcneill case AD1843_MONO_MUTE:
642 1.1 jmcneill di->type = AUDIO_MIXER_ENUM;
643 1.1 jmcneill di->mixer_class = AD1843_INPUT_CLASS;
644 1.1 jmcneill di->prev = di->index + AD1843_DAC2_GAIN - AD1843_DAC2_MUTE;
645 1.1 jmcneill strlcpy(di->label.name, AudioNmute, sizeof di->label.name);
646 1.1 jmcneill di->un.e.num_mem = 2;
647 1.1 jmcneill strlcpy(di->un.e.member[0].label.name, AudioNoff,
648 1.1 jmcneill sizeof di->un.e.member[0].label.name);
649 1.1 jmcneill di->un.e.member[0].ord = 0;
650 1.1 jmcneill strlcpy(di->un.e.member[1].label.name, AudioNon,
651 1.1 jmcneill sizeof di->un.e.member[1].label.name);
652 1.1 jmcneill di->un.e.member[1].ord = 1;
653 1.1 jmcneill break;
654 1.1 jmcneill
655 1.1 jmcneill case AD1843_SUM_MUTE:
656 1.1 jmcneill di->type = AUDIO_MIXER_ENUM;
657 1.1 jmcneill di->mixer_class = AD1843_INPUT_CLASS;
658 1.1 jmcneill strlcpy(di->label.name, "sum." AudioNmute,
659 1.1 jmcneill sizeof di->label.name);
660 1.1 jmcneill di->un.e.num_mem = 2;
661 1.1 jmcneill strlcpy(di->un.e.member[0].label.name, AudioNoff,
662 1.1 jmcneill sizeof di->un.e.member[0].label.name);
663 1.1 jmcneill di->un.e.member[0].ord = 0;
664 1.1 jmcneill strlcpy(di->un.e.member[1].label.name, AudioNon,
665 1.1 jmcneill sizeof di->un.e.member[1].label.name);
666 1.1 jmcneill di->un.e.member[1].ord = 1;
667 1.1 jmcneill break;
668 1.1 jmcneill
669 1.1 jmcneill case AD1843_OUTPUT_CLASS:
670 1.1 jmcneill di->type = AUDIO_MIXER_CLASS;
671 1.1 jmcneill di->mixer_class = AD1843_OUTPUT_CLASS;
672 1.1 jmcneill strlcpy(di->label.name, AudioCoutputs, sizeof di->label.name);
673 1.1 jmcneill break;
674 1.1 jmcneill
675 1.1 jmcneill case AD1843_MNO_MUTE:
676 1.1 jmcneill di->type = AUDIO_MIXER_ENUM;
677 1.1 jmcneill di->mixer_class = AD1843_OUTPUT_CLASS;
678 1.1 jmcneill strlcpy(di->label.name, AudioNmono "." AudioNmute,
679 1.1 jmcneill sizeof di->label.name);
680 1.1 jmcneill di->un.e.num_mem = 2;
681 1.1 jmcneill strlcpy(di->un.e.member[0].label.name, AudioNoff,
682 1.1 jmcneill sizeof di->un.e.member[0].label.name);
683 1.1 jmcneill di->un.e.member[0].ord = 0;
684 1.1 jmcneill strlcpy(di->un.e.member[1].label.name, AudioNon,
685 1.1 jmcneill sizeof di->un.e.member[1].label.name);
686 1.1 jmcneill di->un.e.member[1].ord = 1;
687 1.1 jmcneill break;
688 1.1 jmcneill
689 1.1 jmcneill case AD1843_HPO_MUTE:
690 1.1 jmcneill di->type = AUDIO_MIXER_ENUM;
691 1.1 jmcneill di->mixer_class = AD1843_OUTPUT_CLASS;
692 1.1 jmcneill strlcpy(di->label.name, AudioNheadphone "." AudioNmute,
693 1.1 jmcneill sizeof di->label.name);
694 1.1 jmcneill di->un.e.num_mem = 2;
695 1.1 jmcneill strlcpy(di->un.e.member[0].label.name, AudioNoff,
696 1.1 jmcneill sizeof di->un.e.member[0].label.name);
697 1.1 jmcneill di->un.e.member[0].ord = 0;
698 1.1 jmcneill strlcpy(di->un.e.member[1].label.name, AudioNon,
699 1.1 jmcneill sizeof di->un.e.member[1].label.name);
700 1.1 jmcneill di->un.e.member[1].ord = 1;
701 1.1 jmcneill break;
702 1.1 jmcneill
703 1.1 jmcneill default:
704 1.6 tsutsui return EINVAL;
705 1.1 jmcneill }
706 1.1 jmcneill
707 1.6 tsutsui return 0;
708 1.1 jmcneill }
709 1.1 jmcneill
710 1.1 jmcneill int
711 1.1 jmcneill mavb_get_props(void *hdl)
712 1.1 jmcneill {
713 1.6 tsutsui
714 1.13 isaki return AUDIO_PROP_PLAYBACK |
715 1.13 isaki AUDIO_PROP_FULLDUPLEX | AUDIO_PROP_INDEPENDENT;
716 1.1 jmcneill }
717 1.1 jmcneill
718 1.1 jmcneill static void
719 1.1 jmcneill mavb_dma_output(struct mavb_softc *sc)
720 1.1 jmcneill {
721 1.1 jmcneill bus_space_tag_t st = sc->sc_st;
722 1.1 jmcneill bus_space_handle_t sh = sc->sc_sh;
723 1.6 tsutsui uint64_t write_ptr;
724 1.6 tsutsui uint64_t depth;
725 1.1 jmcneill uint8_t *src, *dst;
726 1.1 jmcneill int count;
727 1.1 jmcneill
728 1.8 jmcneill KASSERT(mutex_owned(&sc->sc_intr_lock));
729 1.8 jmcneill
730 1.1 jmcneill write_ptr = bus_space_read_8(st, sh, MAVB_CHANNEL2_WRITE_PTR);
731 1.1 jmcneill depth = bus_space_read_8(st, sh, MAVB_CHANNEL2_DEPTH);
732 1.1 jmcneill
733 1.1 jmcneill dst = sc->sc_ring + write_ptr;
734 1.1 jmcneill src = sc->sc_get;
735 1.1 jmcneill
736 1.1 jmcneill count = (MAVB_ISA_RING_SIZE - depth - 32);
737 1.1 jmcneill while (--count >= 0) {
738 1.1 jmcneill *dst++ = *src++;
739 1.1 jmcneill if (dst >= sc->sc_ring + MAVB_ISA_RING_SIZE)
740 1.1 jmcneill dst = sc->sc_ring;
741 1.1 jmcneill if (src >= sc->sc_end)
742 1.1 jmcneill src = sc->sc_start;
743 1.1 jmcneill if (++sc->sc_count >= sc->sc_blksize) {
744 1.1 jmcneill if (sc->sc_intr)
745 1.1 jmcneill sc->sc_intr(sc->sc_intrarg);
746 1.1 jmcneill sc->sc_count = 0;
747 1.1 jmcneill }
748 1.1 jmcneill }
749 1.1 jmcneill
750 1.1 jmcneill write_ptr = dst - sc->sc_ring;
751 1.1 jmcneill bus_space_write_8(st, sh, MAVB_CHANNEL2_WRITE_PTR, write_ptr);
752 1.1 jmcneill sc->sc_get = src;
753 1.1 jmcneill }
754 1.1 jmcneill
755 1.1 jmcneill int
756 1.1 jmcneill mavb_trigger_output(void *hdl, void *start, void *end, int blksize,
757 1.1 jmcneill void (*intr)(void *), void *intrarg,
758 1.1 jmcneill const audio_params_t *param)
759 1.1 jmcneill {
760 1.1 jmcneill struct mavb_softc *sc = (struct mavb_softc *)hdl;
761 1.1 jmcneill
762 1.1 jmcneill DPRINTF(1, ("%s: mavb_trigger_output: start=%p end=%p "
763 1.9 chs "blksize=%d intr=%p(%p)\n", device_xname(sc->sc_dev),
764 1.1 jmcneill start, end, blksize, intr, intrarg));
765 1.1 jmcneill
766 1.1 jmcneill sc->sc_blksize = blksize;
767 1.1 jmcneill sc->sc_intr = intr;
768 1.1 jmcneill sc->sc_intrarg = intrarg;
769 1.1 jmcneill
770 1.1 jmcneill sc->sc_start = sc->sc_get = start;
771 1.1 jmcneill sc->sc_end = end;
772 1.1 jmcneill
773 1.1 jmcneill sc->sc_count = 0;
774 1.1 jmcneill
775 1.1 jmcneill bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CHANNEL2_CONTROL,
776 1.1 jmcneill MAVB_CHANNEL_RESET);
777 1.1 jmcneill delay(1000);
778 1.1 jmcneill bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CHANNEL2_CONTROL, 0);
779 1.1 jmcneill
780 1.1 jmcneill mavb_dma_output(sc);
781 1.1 jmcneill
782 1.1 jmcneill bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CHANNEL2_CONTROL,
783 1.1 jmcneill MAVB_CHANNEL_DMA_ENABLE | MAVB_CHANNEL_INT_50);
784 1.8 jmcneill
785 1.6 tsutsui return 0;
786 1.1 jmcneill }
787 1.1 jmcneill
788 1.1 jmcneill int
789 1.1 jmcneill mavb_trigger_input(void *hdl, void *start, void *end, int blksize,
790 1.1 jmcneill void (*intr)(void *), void *intrarg,
791 1.1 jmcneill const audio_params_t *param)
792 1.1 jmcneill {
793 1.6 tsutsui
794 1.6 tsutsui return 0;
795 1.1 jmcneill }
796 1.1 jmcneill
797 1.8 jmcneill void
798 1.8 jmcneill mavb_get_locks(void *hdl, kmutex_t **intr, kmutex_t **thread)
799 1.8 jmcneill {
800 1.8 jmcneill struct mavb_softc *sc = (struct mavb_softc *)hdl;
801 1.8 jmcneill
802 1.8 jmcneill *intr = &sc->sc_intr_lock;
803 1.8 jmcneill *thread = &sc->sc_lock;
804 1.8 jmcneill }
805 1.8 jmcneill
806 1.1 jmcneill static void
807 1.1 jmcneill mavb_button_repeat(void *hdl)
808 1.1 jmcneill {
809 1.1 jmcneill struct mavb_softc *sc = (struct mavb_softc *)hdl;
810 1.6 tsutsui uint64_t intmask, control;
811 1.6 tsutsui uint16_t value, left, right;
812 1.1 jmcneill
813 1.9 chs DPRINTF(1, ("%s: mavb_repeat called\n", device_xname(sc->sc_dev)));
814 1.1 jmcneill
815 1.1 jmcneill #define MAVB_CONTROL_VOLUME_BUTTONS \
816 1.1 jmcneill (MAVB_CONTROL_VOLUME_BUTTON_UP | MAVB_CONTROL_VOLUME_BUTTON_DOWN)
817 1.1 jmcneill
818 1.1 jmcneill control = bus_space_read_8(sc->sc_st, sc->sc_sh, MAVB_CONTROL);
819 1.1 jmcneill if (control & MAVB_CONTROL_VOLUME_BUTTONS) {
820 1.1 jmcneill value = ad1843_reg_read(sc, AD1843_DAC1_ANALOG_GAIN);
821 1.1 jmcneill left = (value & AD1843_LDA1G_MASK) >> AD1843_LDA1G_SHIFT;
822 1.1 jmcneill right = (value & AD1843_RDA1G_MASK) >> AD1843_RDA1G_SHIFT;
823 1.1 jmcneill if (control & MAVB_CONTROL_VOLUME_BUTTON_UP) {
824 1.1 jmcneill control &= ~MAVB_CONTROL_VOLUME_BUTTON_UP;
825 1.1 jmcneill if (left > 0)
826 1.1 jmcneill left--; /* attenuation! */
827 1.1 jmcneill if (right > 0)
828 1.1 jmcneill right--;
829 1.1 jmcneill }
830 1.1 jmcneill if (control & MAVB_CONTROL_VOLUME_BUTTON_DOWN) {
831 1.1 jmcneill control &= ~MAVB_CONTROL_VOLUME_BUTTON_DOWN;
832 1.1 jmcneill if (left < 63)
833 1.1 jmcneill left++;
834 1.1 jmcneill if (right < 63)
835 1.1 jmcneill right++;
836 1.1 jmcneill }
837 1.1 jmcneill bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CONTROL, control);
838 1.1 jmcneill
839 1.1 jmcneill value &= ~(AD1843_LDA1G_MASK | AD1843_RDA1G_MASK);
840 1.1 jmcneill value |= (left << AD1843_LDA1G_SHIFT);
841 1.1 jmcneill value |= (right << AD1843_RDA1G_SHIFT);
842 1.1 jmcneill ad1843_reg_write(sc, AD1843_DAC1_ANALOG_GAIN, value);
843 1.1 jmcneill
844 1.1 jmcneill callout_reset(&sc->sc_volume_button_ch,
845 1.1 jmcneill (hz * MAVB_VOLUME_BUTTON_REPEAT_DELN) / 1000,
846 1.1 jmcneill mavb_button_repeat, sc);
847 1.1 jmcneill } else {
848 1.1 jmcneill /* Enable volume button interrupts again. */
849 1.1 jmcneill intmask = bus_space_read_8(sc->sc_st, sc->sc_isash,
850 1.1 jmcneill MACE_ISA_INT_MASK);
851 1.1 jmcneill bus_space_write_8(sc->sc_st, sc->sc_isash, MACE_ISA_INT_MASK,
852 1.1 jmcneill intmask | MACE_ISA_INT_AUDIO_SC);
853 1.1 jmcneill }
854 1.1 jmcneill }
855 1.1 jmcneill
856 1.1 jmcneill static int
857 1.1 jmcneill mavb_intr(void *arg)
858 1.1 jmcneill {
859 1.1 jmcneill struct mavb_softc *sc = arg;
860 1.6 tsutsui uint64_t stat, intmask;
861 1.1 jmcneill
862 1.8 jmcneill mutex_spin_enter(&sc->sc_intr_lock);
863 1.8 jmcneill
864 1.1 jmcneill stat = bus_space_read_8(sc->sc_st, sc->sc_isash, MACE_ISA_INT_STATUS);
865 1.1 jmcneill DPRINTF(MAVB_DEBUG_INTR, ("%s: mavb_intr: stat = 0x%llx\n",
866 1.9 chs device_xname(sc->sc_dev), stat));
867 1.1 jmcneill
868 1.1 jmcneill if (stat & MACE_ISA_INT_AUDIO_SC) {
869 1.1 jmcneill /* Disable volume button interrupts. */
870 1.1 jmcneill intmask = bus_space_read_8(sc->sc_st, sc->sc_isash,
871 1.1 jmcneill MACE_ISA_INT_MASK);
872 1.1 jmcneill bus_space_write_8(sc->sc_st, sc->sc_isash, MACE_ISA_INT_MASK,
873 1.1 jmcneill intmask & ~MACE_ISA_INT_AUDIO_SC);
874 1.1 jmcneill
875 1.1 jmcneill callout_reset(&sc->sc_volume_button_ch,
876 1.1 jmcneill (hz * MAVB_VOLUME_BUTTON_REPEAT_DEL1) / 1000,
877 1.1 jmcneill mavb_button_repeat, sc);
878 1.1 jmcneill }
879 1.1 jmcneill
880 1.1 jmcneill if (stat & MACE_ISA_INT_AUDIO_DMA2)
881 1.1 jmcneill mavb_dma_output(sc);
882 1.1 jmcneill
883 1.8 jmcneill mutex_spin_exit(&sc->sc_intr_lock);
884 1.8 jmcneill
885 1.1 jmcneill return 1;
886 1.1 jmcneill }
887 1.1 jmcneill
888 1.1 jmcneill int
889 1.9 chs mavb_match(device_t parent, cfdata_t match, void *aux)
890 1.1 jmcneill {
891 1.6 tsutsui
892 1.6 tsutsui return 1;
893 1.1 jmcneill }
894 1.1 jmcneill
895 1.1 jmcneill void
896 1.9 chs mavb_attach(device_t parent, device_t self, void *aux)
897 1.1 jmcneill {
898 1.9 chs struct mavb_softc *sc = device_private(self);
899 1.1 jmcneill struct mace_attach_args *maa = aux;
900 1.1 jmcneill bus_dma_segment_t seg;
901 1.6 tsutsui uint64_t control;
902 1.6 tsutsui uint16_t value;
903 1.13 isaki int rseg;
904 1.1 jmcneill
905 1.9 chs sc->sc_dev = self;
906 1.9 chs
907 1.8 jmcneill mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
908 1.8 jmcneill mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SCHED);
909 1.8 jmcneill
910 1.1 jmcneill sc->sc_st = maa->maa_st;
911 1.1 jmcneill if (bus_space_subregion(sc->sc_st, maa->maa_sh, maa->maa_offset,
912 1.1 jmcneill 0, &sc->sc_sh) != 0) {
913 1.1 jmcneill printf(": can't map i/o space\n");
914 1.1 jmcneill return;
915 1.1 jmcneill }
916 1.1 jmcneill
917 1.1 jmcneill /* XXX We need access to some of the MACE ISA registers. */
918 1.1 jmcneill if (bus_space_subregion(sc->sc_st, maa->maa_sh, 0, 0,
919 1.1 jmcneill &sc->sc_isash) != 0) {
920 1.1 jmcneill printf(": can't map isa i/o space\n");
921 1.1 jmcneill return;
922 1.1 jmcneill }
923 1.1 jmcneill
924 1.1 jmcneill /* Set up DMA structures. */
925 1.1 jmcneill sc->sc_dmat = maa->maa_dmat;
926 1.1 jmcneill if (bus_dmamap_create(sc->sc_dmat, 4 * MAVB_ISA_RING_SIZE, 1,
927 1.1 jmcneill 4 * MAVB_ISA_RING_SIZE, 0, 0, &sc->sc_dmamap)) {
928 1.1 jmcneill printf(": can't create MACE ISA DMA map\n");
929 1.1 jmcneill return;
930 1.1 jmcneill }
931 1.1 jmcneill
932 1.1 jmcneill if (bus_dmamem_alloc(sc->sc_dmat, 4 * MAVB_ISA_RING_SIZE,
933 1.1 jmcneill MACE_ISA_RING_ALIGN, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) {
934 1.1 jmcneill printf(": can't allocate ring buffer\n");
935 1.1 jmcneill return;
936 1.1 jmcneill }
937 1.1 jmcneill
938 1.1 jmcneill if (bus_dmamem_map(sc->sc_dmat, &seg, rseg, 4 * MAVB_ISA_RING_SIZE,
939 1.1 jmcneill (void *)&sc->sc_ring, BUS_DMA_COHERENT)) {
940 1.1 jmcneill printf(": can't map ring buffer\n");
941 1.1 jmcneill return;
942 1.1 jmcneill }
943 1.1 jmcneill
944 1.1 jmcneill if (bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap, sc->sc_ring,
945 1.1 jmcneill 4 * MAVB_ISA_RING_SIZE, NULL, BUS_DMA_NOWAIT)) {
946 1.1 jmcneill printf(": can't load MACE ISA DMA map\n");
947 1.1 jmcneill return;
948 1.1 jmcneill }
949 1.1 jmcneill
950 1.1 jmcneill sc->sc_ring += MAVB_ISA_RING_SIZE; /* XXX */
951 1.1 jmcneill
952 1.1 jmcneill bus_space_write_8(sc->sc_st, sc->sc_isash, MACE_ISA_RINGBASE,
953 1.1 jmcneill sc->sc_dmamap->dm_segs[0].ds_addr);
954 1.1 jmcneill
955 1.1 jmcneill /* Establish interrupt. */
956 1.1 jmcneill cpu_intr_establish(maa->maa_intr, maa->maa_intrmask,
957 1.1 jmcneill mavb_intr, sc);
958 1.1 jmcneill
959 1.1 jmcneill control = bus_space_read_8(sc->sc_st, sc->sc_sh, MAVB_CONTROL);
960 1.1 jmcneill if (!(control & MAVB_CONTROL_CODEC_PRESENT)) {
961 1.1 jmcneill printf(": no codec present\n");
962 1.1 jmcneill return;
963 1.1 jmcneill }
964 1.1 jmcneill
965 1.1 jmcneill /* 2. Assert the RESET signal. */
966 1.1 jmcneill bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CONTROL,
967 1.1 jmcneill MAVB_CONTROL_RESET);
968 1.1 jmcneill delay(1); /* at least 100 ns */
969 1.1 jmcneill
970 1.1 jmcneill /* 3. Deassert the RESET signal and enter a wait period to
971 1.1 jmcneill allow the AD1843 internal clocks and the external
972 1.1 jmcneill crystal oscillator to stabilize. */
973 1.1 jmcneill bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CONTROL, 0);
974 1.1 jmcneill delay(800); /* typically 400 us to 800 us */
975 1.1 jmcneill if (ad1843_reg_read(sc, AD1843_CODEC_STATUS) & AD1843_INIT) {
976 1.1 jmcneill printf(": codec not ready\n");
977 1.1 jmcneill return;
978 1.1 jmcneill }
979 1.1 jmcneill
980 1.1 jmcneill /* 4. Put the conversion sources into standby. */
981 1.1 jmcneill value = ad1843_reg_read(sc, AD1843_FUNDAMENTAL_SETTINGS);
982 1.1 jmcneill ad1843_reg_write(sc, AD1843_FUNDAMENTAL_SETTINGS,
983 1.1 jmcneill value & ~AD1843_PDNI);
984 1.1 jmcneill delay (500000); /* approximately 474 ms */
985 1.1 jmcneill if (ad1843_reg_read(sc, AD1843_CODEC_STATUS) & AD1843_PDNO) {
986 1.1 jmcneill printf(": can't power up conversion resources\n");
987 1.1 jmcneill return;
988 1.1 jmcneill }
989 1.1 jmcneill
990 1.1 jmcneill /* 5. Power up the clock generators and enable clock output pins. */
991 1.1 jmcneill value = ad1843_reg_read(sc, AD1843_FUNDAMENTAL_SETTINGS);
992 1.1 jmcneill ad1843_reg_write(sc, AD1843_FUNDAMENTAL_SETTINGS, value | AD1843_C2EN);
993 1.1 jmcneill
994 1.1 jmcneill /* 6. Configure conversion resources while they are in standby. */
995 1.1 jmcneill value = ad1843_reg_read(sc, AD1843_CHANNEL_SAMPLE_RATE);
996 1.1 jmcneill ad1843_reg_write(sc, AD1843_CHANNEL_SAMPLE_RATE,
997 1.1 jmcneill value | (2 << AD1843_DA1C_SHIFT));
998 1.1 jmcneill
999 1.1 jmcneill /* 7. Enable conversion resources. */
1000 1.1 jmcneill value = ad1843_reg_read(sc, AD1843_CHANNEL_POWER_DOWN);
1001 1.1 jmcneill ad1843_reg_write(sc, AD1843_CHANNEL_POWER_DOWN,
1002 1.1 jmcneill value | (AD1843_DA1EN | AD1843_AAMEN));
1003 1.1 jmcneill
1004 1.1 jmcneill /* 8. Configure conversion resources while they are enabled. */
1005 1.1 jmcneill value = ad1843_reg_read(sc, AD1843_DAC1_ANALOG_GAIN);
1006 1.1 jmcneill ad1843_reg_write(sc, AD1843_DAC1_ANALOG_GAIN,
1007 1.1 jmcneill value & ~(AD1843_LDA1GM | AD1843_RDA1GM));
1008 1.1 jmcneill value = ad1843_reg_read(sc, AD1843_DAC1_DIGITAL_GAIN);
1009 1.1 jmcneill ad1843_reg_write(sc, AD1843_DAC1_DIGITAL_GAIN,
1010 1.1 jmcneill value & ~(AD1843_LDA1AM | AD1843_RDA1AM));
1011 1.1 jmcneill value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
1012 1.1 jmcneill ad1843_reg_write(sc, AD1843_MISC_SETTINGS,
1013 1.1 jmcneill value & ~(AD1843_HPOM | AD1843_MNOM));
1014 1.1 jmcneill
1015 1.1 jmcneill value = ad1843_reg_read(sc, AD1843_CODEC_STATUS);
1016 1.1 jmcneill printf(": AD1843 rev %d\n", (u_int)value & AD1843_REVISION_MASK);
1017 1.1 jmcneill
1018 1.1 jmcneill sc->sc_play_rate = 48000;
1019 1.1 jmcneill sc->sc_play_format = AD1843_PCM8;
1020 1.1 jmcneill
1021 1.3 ad callout_init(&sc->sc_volume_button_ch, 0);
1022 1.1 jmcneill
1023 1.9 chs audio_attach_mi(&mavb_sa_hw_if, sc, self);
1024 1.1 jmcneill
1025 1.1 jmcneill return;
1026 1.1 jmcneill }
1027 1.1 jmcneill
1028 1.6 tsutsui uint16_t
1029 1.1 jmcneill ad1843_reg_read(struct mavb_softc *sc, ad1843_addr_t addr)
1030 1.1 jmcneill {
1031 1.1 jmcneill bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CODEC_CONTROL,
1032 1.1 jmcneill (addr & MAVB_CODEC_ADDRESS_MASK) << MAVB_CODEC_ADDRESS_SHIFT |
1033 1.1 jmcneill MAVB_CODEC_READ);
1034 1.1 jmcneill delay(200);
1035 1.1 jmcneill return bus_space_read_8(sc->sc_st, sc->sc_sh, MAVB_CODEC_STATUS);
1036 1.1 jmcneill }
1037 1.1 jmcneill
1038 1.6 tsutsui uint16_t
1039 1.6 tsutsui ad1843_reg_write(struct mavb_softc *sc, ad1843_addr_t addr, uint16_t value)
1040 1.1 jmcneill {
1041 1.1 jmcneill bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CODEC_CONTROL,
1042 1.1 jmcneill (addr & MAVB_CODEC_ADDRESS_MASK) << MAVB_CODEC_ADDRESS_SHIFT |
1043 1.1 jmcneill (value & MAVB_CODEC_WORD_MASK) << MAVB_CODEC_WORD_SHIFT);
1044 1.1 jmcneill delay(200);
1045 1.1 jmcneill return bus_space_read_8(sc->sc_st, sc->sc_sh, MAVB_CODEC_STATUS);
1046 1.1 jmcneill }
1047 1.1 jmcneill
1048 1.1 jmcneill void
1049 1.1 jmcneill ad1843_dump_regs(struct mavb_softc *sc)
1050 1.1 jmcneill {
1051 1.6 tsutsui uint16_t addr;
1052 1.1 jmcneill
1053 1.1 jmcneill for (addr = 0; addr < AD1843_NREGS; addr++)
1054 1.1 jmcneill printf("%d: 0x%04x\n", addr, ad1843_reg_read(sc, addr));
1055 1.1 jmcneill }
1056