vac.c revision 1.2 1 /* $NetBSD: vac.c,v 1.2 2026/06/22 15:12:59 rkujawa Exp $ */
2
3 /*-
4 * Copyright (c) 2026 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /*
30 * Driver for the SM502 AC'97 audio interface
31 */
32
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: vac.c,v 1.2 2026/06/22 15:12:59 rkujawa Exp $");
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/device.h>
39 #include <sys/kmem.h>
40 #include <sys/bus.h>
41 #include <sys/callout.h>
42 #include <sys/sysctl.h>
43 #include <sys/audioio.h>
44
45 #include <dev/audio/audio_if.h>
46
47 #include <dev/ic/ac97var.h>
48 #include <dev/ic/ac97reg.h>
49
50 #include <dev/ic/sm502reg.h>
51 #include <dev/pci/voyagervar.h>
52
53 /* PCM playback format: AC'97 fixed 48 kHz, 16-bit, stereo. */
54 #define VAC_RATE 48000
55 #define VAC_CHANNELS 2
56 #define VAC_PRECISION 16
57 #define VAC_FRAMESIZE (VAC_CHANNELS * (VAC_PRECISION / 8)) /* 4 bytes */
58
59 /* poll when waiting on the codec */
60 #define VAC_CODEC_TIMEOUT 1000
61
62 /*
63 * 8051 polled protocol, via 4KB dual-port SRAM
64 *
65 * Two PCM buffers selected by command parity
66 */
67 #define VAC_DP_BASE SM502_uC_SRAM_DUALPORT
68 #define VAC_DP_H_CMD 0x00 /* u8 host: command sequence */
69 #define VAC_DP_H_DONE 0x01 /* u8 8051: last finished command */
70 #define VAC_DP_H_ALIVE 0x03 /* u8 8051: VAC_DP_ALIVE_MAGIC when up */
71 #define VAC_DP_H_FC0L 0x04 /* u16 host: buf0 frame count, LE */
72 #define VAC_DP_H_FC0H 0x05
73 #define VAC_DP_H_FC1L 0x06 /* u16 host: buf1 frame count, LE */
74 #define VAC_DP_H_FC1H 0x07
75 #define VAC_DP_BUF0 0x10
76 #define VAC_DP_MAXFRAMES 504 /* per buffer; 504*4=0x7e0, both fit 4KB */
77 #define VAC_DP_BUFBYTES (VAC_DP_MAXFRAMES * VAC_FRAMESIZE)
78 #define VAC_DP_BUF1 (VAC_DP_BUF0 + VAC_DP_BUFBYTES) /* 0x7f0 */
79 #define VAC_DP_ALIVE_MAGIC 0x51
80
81 struct vac_softc {
82 device_t sc_dev;
83 bus_space_tag_t sc_memt;
84 bus_space_handle_t sc_regh; /* BAR 0x14: MMIO registers */
85 void *sc_parent; /* voyager softc, for gpio/power */
86
87 kmutex_t sc_lock; /* thread context */
88 kmutex_t sc_intr_lock; /* "interrupt" context */
89
90 struct ac97_host_if sc_ac97_host;
91 struct ac97_codec_if *sc_ac97_codec;
92 device_t sc_audiodev;
93
94 /* MI playback ring (filled by the audio layer, consumed by the feeder) */
95 bool sc_active; /* playback in progress */
96 uint8_t *sc_pstart;
97 uint8_t *sc_pend;
98 uint8_t *sc_pcur;
99 int sc_pblksize;
100 void (*sc_pint)(void *);
101 void *sc_pintarg;
102
103 /* 8051 interface */
104 callout_t sc_feed_ch; /* polls H_DONE, refills buffers */
105 int sc_feed_ticks; /* callout period */
106 uint8_t *sc_dpstage; /* staging for one dual-port buf */
107 uint8_t sc_cmd_seq; /* last command we queued */
108 uint8_t sc_done_seen; /* last H_DONE we acted on */
109 bool sc_8051_ok; /* feeder firmware responded */
110 int sc_underruns; /* 8051 ran dry while playing */
111
112 struct sysctllog *sc_sysctllog;
113 };
114
115 #define VAC_READ(sc, reg) \
116 bus_space_read_4((sc)->sc_memt, (sc)->sc_regh, (reg))
117 #define VAC_WRITE(sc, reg, val) \
118 bus_space_write_4((sc)->sc_memt, (sc)->sc_regh, (reg), (val))
119 #define VAC_DP_R8(sc, off) \
120 bus_space_read_1((sc)->sc_memt, (sc)->sc_regh, VAC_DP_BASE + (off))
121 #define VAC_DP_W8(sc, off, v) \
122 bus_space_write_1((sc)->sc_memt, (sc)->sc_regh, VAC_DP_BASE + (off), (v))
123
124 /*
125 * Embedded 8051 firmware
126 * assemble from vac8051.asm with naken_asm (-type bin)
127 */
128 static const uint8_t vac8051_fw[] = {
129 0x90, 0x30, 0x03, 0x74, 0x51, 0xf0, 0x90, 0x30, 0x01, 0xe4, 0xf0, 0x7f,
130 0x00, 0x90, 0x30, 0x00, 0xe0, 0xfe, 0x6f, 0x60, 0xf8, 0xee, 0x54, 0x01,
131 0x60, 0x10, 0x90, 0x30, 0x06, 0xe0, 0xfc, 0x90, 0x30, 0x07, 0xe0, 0xfd,
132 0x7a, 0xf0, 0x7b, 0x37, 0x80, 0x0e, 0x90, 0x30, 0x04, 0xe0, 0xfc, 0x90,
133 0x30, 0x05, 0xe0, 0xfd, 0x7a, 0x10, 0x7b, 0x30, 0x78, 0x00, 0x79, 0x00,
134 0x90, 0x91, 0x45, 0xe0, 0x54, 0x08, 0x60, 0x04, 0xd9, 0xf6, 0xd8, 0xf4,
135 0x8a, 0x82, 0x8b, 0x83, 0xe0, 0xf5, 0x20, 0xa3, 0xe0, 0xf5, 0x21, 0xa3,
136 0xe0, 0xf5, 0x24, 0xa3, 0xe0, 0xf5, 0x25, 0xa3, 0xaa, 0x82, 0xab, 0x83,
137 0x90, 0x91, 0x00, 0xe4, 0xf0, 0xa3, 0x74, 0x98, 0xf0, 0xe5, 0x20, 0xc4,
138 0xf5, 0x22, 0xe5, 0x21, 0xc4, 0xf5, 0x23, 0x90, 0x91, 0x0c, 0xe5, 0x22,
139 0x54, 0xf0, 0xf0, 0xa3, 0xe5, 0x22, 0x54, 0x0f, 0xf5, 0x26, 0xe5, 0x23,
140 0x54, 0xf0, 0x45, 0x26, 0xf0, 0xa3, 0xe5, 0x23, 0x54, 0x0f, 0xf0, 0xa3,
141 0xe4, 0xf0, 0xe5, 0x24, 0xc4, 0xf5, 0x22, 0xe5, 0x25, 0xc4, 0xf5, 0x23,
142 0x90, 0x91, 0x10, 0xe5, 0x22, 0x54, 0xf0, 0xf0, 0xa3, 0xe5, 0x22, 0x54,
143 0x0f, 0xf5, 0x26, 0xe5, 0x23, 0x54, 0xf0, 0x45, 0x26, 0xf0, 0xa3, 0xe5,
144 0x23, 0x54, 0x0f, 0xf0, 0xa3, 0xe4, 0xf0, 0xec, 0x70, 0x01, 0x1d, 0x1c,
145 0xec, 0x4d, 0x60, 0x03, 0x02, 0x00, 0x38, 0x90, 0x30, 0x01, 0xee, 0xf0,
146 0xff, 0x02, 0x00, 0x0d
147 };
148
149 static int vac_match(device_t, cfdata_t, void *);
150 static void vac_attach(device_t, device_t, void *);
151
152 CFATTACH_DECL_NEW(vac, sizeof(struct vac_softc),
153 vac_match, vac_attach, NULL, NULL);
154
155 static const struct audio_format vac_format = {
156 .mode = AUMODE_PLAY,
157 .encoding = AUDIO_ENCODING_SLINEAR_LE,
158 .validbits = VAC_PRECISION,
159 .precision = VAC_PRECISION,
160 .channels = VAC_CHANNELS,
161 .channel_mask = AUFMT_STEREO,
162 .frequency_type = 1,
163 .frequency = { VAC_RATE }
164 };
165
166 /*
167 * AC'97 codec register access.
168 */
169 static int
170 vac_ac97_read(void *priv, uint8_t reg, uint16_t *val)
171 {
172 struct vac_softc * const sc = priv;
173 uint32_t addr, rx;
174 int i;
175
176 addr = ((uint32_t)reg << SM502_AC97_ADDR_SHIFT) & SM502_AC97_ADDR_MASK;
177
178 /* Mark frame + slot 1 valid and issue a read of the register. */
179 VAC_WRITE(sc, SM502_AC97_TX_TAG,
180 SM502_AC97_FRAME_VALID | SM502_AC97_S1_VALID);
181 VAC_WRITE(sc, SM502_AC97_TX_ADDR, addr | SM502_AC97_READ);
182
183 /* Wait for the codec to echo the register index back in RX slot 1. */
184 for (i = 0; i < VAC_CODEC_TIMEOUT; i++) {
185 rx = VAC_READ(sc, SM502_AC97_RX_ADDR);
186 if ((rx & SM502_AC97_ADDR_MASK) == addr)
187 break;
188 DELAY(1);
189 }
190 if (i == VAC_CODEC_TIMEOUT)
191 return 1;
192
193 *val = (VAC_READ(sc, SM502_AC97_RX_DATA) & SM502_AC97_DATA_MASK) >> 4;
194 return 0;
195 }
196
197 static int
198 vac_ac97_write(void *priv, uint8_t reg, uint16_t val)
199 {
200 struct vac_softc * const sc = priv;
201 uint32_t addr;
202
203 addr = ((uint32_t)reg << SM502_AC97_ADDR_SHIFT) & SM502_AC97_ADDR_MASK;
204
205 /* Mark frame + slots 1 (address) and 2 (data) valid. */
206 VAC_WRITE(sc, SM502_AC97_TX_TAG,
207 SM502_AC97_FRAME_VALID | SM502_AC97_S1_VALID | SM502_AC97_S2_VALID);
208 VAC_WRITE(sc, SM502_AC97_TX_DATA,
209 ((uint32_t)val << 4) & SM502_AC97_DATA_MASK);
210 VAC_WRITE(sc, SM502_AC97_TX_ADDR, addr);
211
212 DELAY(100);
213 return 0;
214 }
215
216 static int
217 vac_ac97_reset(void *priv)
218 {
219 struct vac_softc * const sc = priv;
220 uint32_t reg;
221 int i;
222
223 aprint_debug_dev(sc->sc_dev, "ac97 control at reset entry 0x%08x\n",
224 VAC_READ(sc, SM502_AC97_CONTROL));
225
226 /*
227 * Cold reset the codec with the controller enabled: assert RESET#
228 * (COLD_RESET) for well over the 1us minimum, then release it.
229 */
230 VAC_WRITE(sc, SM502_AC97_CONTROL,
231 SM502_AC97_ENABLE | SM502_AC97_COLD_RESET);
232 DELAY(20);
233 VAC_WRITE(sc, SM502_AC97_CONTROL, SM502_AC97_ENABLE);
234
235 /*
236 * Wait (up to ~250ms) for the codec to start the bit clock and the
237 * link to reach the active state.
238 */
239 for (i = 0; i < 2500; i++) {
240 reg = VAC_READ(sc, SM502_AC97_CONTROL);
241 if ((reg & SM502_AC97_BCLK_RUNNING) != 0 &&
242 (reg & SM502_AC97_STATUS_MASK) == SM502_AC97_STATUS_ON) {
243 aprint_debug_dev(sc->sc_dev,
244 "AC-link up (control 0x%08x)\n", reg);
245 return 0;
246 }
247 DELAY(100);
248 }
249
250 aprint_error_dev(sc->sc_dev,
251 "AC-link did not come ready (control 0x%08x)\n", reg);
252 return 1;
253 }
254
255 static int
256 vac_ac97_attach(void *priv, struct ac97_codec_if *codec)
257 {
258 struct vac_softc * const sc = priv;
259
260 sc->sc_ac97_codec = codec;
261 return 0;
262 }
263
264 static void
265 vac_unmute(struct vac_softc *sc)
266 {
267 struct ac97_codec_if * const codec = sc->sc_ac97_codec;
268 static const struct {
269 const char *class;
270 const char *device;
271 } ports[] = {
272 { AudioCoutputs, AudioNmaster },
273 { AudioCinputs, AudioNdac },
274 };
275 mixer_ctrl_t mc;
276 int i, idx;
277
278 mutex_enter(&sc->sc_lock);
279 for (i = 0; i < (int)__arraycount(ports); i++) {
280 idx = codec->vtbl->get_portnum_by_name(codec,
281 ports[i].class, ports[i].device, NULL);
282 if (idx >= 0) {
283 memset(&mc, 0, sizeof(mc));
284 mc.dev = idx;
285 mc.type = AUDIO_MIXER_VALUE;
286 mc.un.value.num_channels = 2;
287 mc.un.value.level[AUDIO_MIXER_LEVEL_LEFT] = 200;
288 mc.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 200;
289 (void)codec->vtbl->mixer_set_port(codec, &mc);
290 }
291 idx = codec->vtbl->get_portnum_by_name(codec,
292 ports[i].class, ports[i].device, AudioNmute);
293 if (idx >= 0) {
294 memset(&mc, 0, sizeof(mc));
295 mc.dev = idx;
296 mc.type = AUDIO_MIXER_ENUM;
297 mc.un.ord = 0; /* off = not muted */
298 (void)codec->vtbl->mixer_set_port(codec, &mc);
299 }
300 }
301 mutex_exit(&sc->sc_lock);
302 }
303
304 /*
305 * MI audio interface.
306 */
307
308 static int
309 vac_query_format(void *priv, audio_format_query_t *afp)
310 {
311
312 return audio_query_format(&vac_format, 1, afp);
313 }
314
315 static int
316 vac_set_format(void *priv, int setmode,
317 const audio_params_t *play, const audio_params_t *rec,
318 audio_filter_reg_t *pfil, audio_filter_reg_t *rfil)
319 {
320
321 /* Only one format; nothing to do. */
322 return 0;
323 }
324
325 static int
326 vac_getdev(void *priv, struct audio_device *ad)
327 {
328
329 snprintf(ad->name, sizeof(ad->name), "SM502");
330 snprintf(ad->version, sizeof(ad->version), "AC97");
331 snprintf(ad->config, sizeof(ad->config), "vac");
332 return 0;
333 }
334
335 static int
336 vac_set_port(void *priv, mixer_ctrl_t *mc)
337 {
338 struct vac_softc * const sc = priv;
339
340 return sc->sc_ac97_codec->vtbl->mixer_set_port(sc->sc_ac97_codec, mc);
341 }
342
343 static int
344 vac_get_port(void *priv, mixer_ctrl_t *mc)
345 {
346 struct vac_softc * const sc = priv;
347
348 return sc->sc_ac97_codec->vtbl->mixer_get_port(sc->sc_ac97_codec, mc);
349 }
350
351 static int
352 vac_query_devinfo(void *priv, mixer_devinfo_t *di)
353 {
354 struct vac_softc * const sc = priv;
355
356 return sc->sc_ac97_codec->vtbl->query_devinfo(sc->sc_ac97_codec, di);
357 }
358
359 static int
360 vac_get_props(void *priv)
361 {
362
363 return AUDIO_PROP_PLAYBACK;
364 }
365
366 static int
367 vac_round_blocksize(void *priv, int blk, int mode,
368 const audio_params_t *param)
369 {
370
371 /*
372 * Play one MI block per dual-port buffer
373 */
374 if (blk > VAC_DP_BUFBYTES)
375 blk = VAC_DP_BUFBYTES;
376 blk &= ~(VAC_FRAMESIZE - 1);
377 if (blk < VAC_FRAMESIZE)
378 blk = VAC_FRAMESIZE;
379 return blk;
380 }
381
382 /*
383 * Queue one block from the MI ring
384 */
385 static void
386 vac_dp_queue(struct vac_softc *sc)
387 {
388 const uint8_t cmd = sc->sc_cmd_seq + 1;
389 uint8_t *p = sc->sc_pcur;
390 bus_size_t base;
391 int n, i;
392
393 n = sc->sc_pblksize / VAC_FRAMESIZE;
394 if (n > VAC_DP_MAXFRAMES)
395 n = VAC_DP_MAXFRAMES;
396
397 /* Copy PCM into the staging buffer (raw 16-bit LE), handling wrap. */
398 for (i = 0; i < n; i++) {
399 uint8_t * const d = sc->sc_dpstage + i * VAC_FRAMESIZE;
400
401 d[0] = p[0]; /* left low */
402 d[1] = p[1]; /* left high */
403 d[2] = p[2]; /* right low */
404 d[3] = p[3]; /* right high */
405 p += VAC_FRAMESIZE;
406 if (p >= sc->sc_pend)
407 p = sc->sc_pstart;
408 }
409 sc->sc_pcur = p;
410
411 base = VAC_DP_BASE + ((cmd & 1) ? VAC_DP_BUF1 : VAC_DP_BUF0);
412 bus_space_write_region_1(sc->sc_memt, sc->sc_regh, base,
413 sc->sc_dpstage, n * VAC_FRAMESIZE);
414
415 if (cmd & 1) {
416 VAC_DP_W8(sc, VAC_DP_H_FC1L, n & 0xff);
417 VAC_DP_W8(sc, VAC_DP_H_FC1H, (n >> 8) & 0xff);
418 } else {
419 VAC_DP_W8(sc, VAC_DP_H_FC0L, n & 0xff);
420 VAC_DP_W8(sc, VAC_DP_H_FC0H, (n >> 8) & 0xff);
421 }
422
423 /* The data and count must be visible before the command bump. */
424 bus_space_barrier(sc->sc_memt, sc->sc_regh, VAC_DP_BASE, 0x1000,
425 BUS_SPACE_BARRIER_WRITE);
426 VAC_DP_W8(sc, VAC_DP_H_CMD, cmd);
427 sc->sc_cmd_seq = cmd;
428 }
429
430 /*
431 * Poll the 8051's done counter
432 */
433 static void
434 vac_feed_callout(void *arg)
435 {
436 struct vac_softc * const sc = arg;
437 uint8_t done;
438 int n;
439
440 mutex_enter(&sc->sc_intr_lock);
441 if (!sc->sc_active) {
442 mutex_exit(&sc->sc_intr_lock);
443 return;
444 }
445
446 done = VAC_DP_R8(sc, VAC_DP_H_DONE);
447 if (sc->sc_cmd_seq == done)
448 sc->sc_underruns++; /* 8051 caught up: nothing queued */
449
450 n = (uint8_t)(done - sc->sc_done_seen);
451 sc->sc_done_seen = done;
452 while (n-- > 0 && sc->sc_active && sc->sc_pint != NULL)
453 sc->sc_pint(sc->sc_pintarg);
454
455 while ((uint8_t)(sc->sc_cmd_seq - done) <= 1 && sc->sc_active)
456 vac_dp_queue(sc);
457
458 callout_schedule(&sc->sc_feed_ch, sc->sc_feed_ticks);
459 mutex_exit(&sc->sc_intr_lock);
460 }
461
462 static int
463 vac_trigger_output(void *priv, void *start, void *end, int blksize,
464 void (*intr)(void *), void *intrarg, const audio_params_t *params)
465 {
466 struct vac_softc * const sc = priv;
467 int i;
468
469 /*
470 * audio calls trigger_output with both sc_lock and sc_intr_lock held
471 */
472 KASSERT(mutex_owned(&sc->sc_intr_lock));
473 KASSERT(mutex_owned(&sc->sc_lock));
474
475 if (!sc->sc_8051_ok)
476 return ENXIO;
477
478 /*
479 * Restart the 8051 cleanly for this playback
480 */
481 VAC_WRITE(sc, SM502_uC_RESET, 0);
482 for (i = 0; i < 16; i++)
483 VAC_DP_W8(sc, i, 0);
484 VAC_WRITE(sc, SM502_uC_RESET, SM502_uC_ENABLE);
485 for (i = 0; i < 5000 &&
486 VAC_DP_R8(sc, VAC_DP_H_ALIVE) != VAC_DP_ALIVE_MAGIC; i++)
487 DELAY(10);
488
489 sc->sc_pstart = start;
490 sc->sc_pend = end;
491 sc->sc_pcur = start;
492 sc->sc_pblksize = blksize;
493 sc->sc_pint = intr;
494 sc->sc_pintarg = intrarg;
495
496 sc->sc_cmd_seq = 0;
497 sc->sc_done_seen = 0;
498 sc->sc_underruns = 0;
499 sc->sc_active = true;
500
501 /* Prime both buffers, then poll for completion from the callout. */
502 vac_dp_queue(sc);
503 vac_dp_queue(sc);
504 callout_schedule(&sc->sc_feed_ch, sc->sc_feed_ticks);
505
506 return 0;
507 }
508
509 static int
510 vac_halt_output(void *priv)
511 {
512 struct vac_softc * const sc = priv;
513
514 /*
515 * called with both sc_lock and sc_intr_lock held
516 */
517 KASSERT(mutex_owned(&sc->sc_intr_lock));
518
519 sc->sc_active = false;
520 sc->sc_pint = NULL;
521 callout_stop(&sc->sc_feed_ch);
522
523 /* Park the 8051 so the host codec/mixer path is live while idle. */
524 VAC_WRITE(sc, SM502_uC_RESET, 0);
525 return 0;
526 }
527
528 static void
529 vac_get_locks(void *priv, kmutex_t **intr, kmutex_t **thread)
530 {
531 struct vac_softc * const sc = priv;
532
533 *intr = &sc->sc_intr_lock;
534 *thread = &sc->sc_lock;
535 }
536
537 static const struct audio_hw_if vac_hw_if = {
538 .query_format = vac_query_format,
539 .set_format = vac_set_format,
540 .getdev = vac_getdev,
541 .set_port = vac_set_port,
542 .get_port = vac_get_port,
543 .query_devinfo = vac_query_devinfo,
544 .get_props = vac_get_props,
545 .round_blocksize = vac_round_blocksize,
546 .trigger_output = vac_trigger_output,
547 .halt_output = vac_halt_output,
548 .get_locks = vac_get_locks,
549 };
550
551 /* Load the firmware blob as 32-bit LE words at (h, base). */
552 static void
553 vac_load_fw(struct vac_softc *sc, bus_space_handle_t h, bus_size_t base)
554 {
555 size_t i;
556
557 for (i = 0; i < sizeof(vac8051_fw); i += 4) {
558 uint8_t b0 = vac8051_fw[i];
559 uint8_t b1 = (i + 1 < sizeof(vac8051_fw)) ? vac8051_fw[i + 1] : 0;
560 uint8_t b2 = (i + 2 < sizeof(vac8051_fw)) ? vac8051_fw[i + 2] : 0;
561 uint8_t b3 = (i + 3 < sizeof(vac8051_fw)) ? vac8051_fw[i + 3] : 0;
562
563 bus_space_write_4(sc->sc_memt, h, base + i,
564 b0 | (b1 << 8) | (b2 << 16) | (b3 << 24));
565 }
566 }
567
568 static void
569 vac_8051_bringup(struct vac_softc *sc)
570 {
571 uint32_t v;
572 uint8_t alive;
573 int i;
574
575 /* Hold the 8051 in reset... mode = SRAM on, AC97, fastest clock (div2). */
576 VAC_WRITE(sc, SM502_uC_RESET, 0);
577 v = VAC_READ(sc, SM502_uC_MODE_SELECT);
578 v &= ~(SM502_uC_SRAM_DISABLE | SM502_uC_CODEC_I2S | SM502_uC_CLOCK_MASK);
579 VAC_WRITE(sc, SM502_uC_MODE_SELECT, v);
580
581 /* Load the feeder into the program SRAM (host R/W only while in reset). */
582 vac_load_fw(sc, sc->sc_regh, SM502_uC_SRAM_PROG);
583
584 /* Clear the dual-port protocol header before the 8051 starts. */
585 for (i = 0; i < 16; i++)
586 VAC_DP_W8(sc, i, 0);
587
588 /* Release the 8051 and give it time to post its alive marker. */
589 VAC_WRITE(sc, SM502_uC_RESET, SM502_uC_ENABLE);
590 DELAY(2000);
591
592 alive = VAC_DP_R8(sc, VAC_DP_H_ALIVE);
593 sc->sc_8051_ok = (alive == VAC_DP_ALIVE_MAGIC);
594 aprint_verbose_dev(sc->sc_dev, "8051 feeder %s (alive=0x%02x)\n",
595 sc->sc_8051_ok ? "loaded" : "not responding", alive);
596 if (!sc->sc_8051_ok)
597 aprint_error_dev(sc->sc_dev,
598 "8051 feeder did not start; playback unavailable\n");
599
600 /* Park the 8051 while idle (keeps the host codec/mixer path live). */
601 VAC_WRITE(sc, SM502_uC_RESET, 0);
602 }
603
604 #ifdef VAC_DEBUG
605 /*
606 * Diagnostics: dump the AC97 link control + key codec registers (read while the
607 * 8051 is idle; codec access is dead while it runs).
608 */
609 static int
610 vac_sysctl_diag(SYSCTLFN_ARGS)
611 {
612 struct sysctlnode node = *rnode;
613 struct vac_softc * const sc = node.sysctl_data;
614 uint16_t r02 = 0, r04 = 0, r18 = 0, r26 = 0, r2a = 0, r2c = 0, r7a = 0;
615 char buf[200];
616
617 vac_ac97_read(sc, 0x02, &r02); /* master volume */
618 vac_ac97_read(sc, 0x04, &r04); /* aux/headphone volume */
619 vac_ac97_read(sc, 0x18, &r18); /* PCM out volume */
620 vac_ac97_read(sc, 0x26, &r26); /* powerdown ctrl/status */
621 vac_ac97_read(sc, 0x2a, &r2a); /* extended audio ctrl (VRA) */
622 vac_ac97_read(sc, 0x2c, &r2c); /* PCM front DAC rate */
623 vac_ac97_read(sc, 0x7a, &r7a); /* ALC655 vendor (EAPD etc.) */
624
625 snprintf(buf, sizeof(buf),
626 "acctl=%08x mode=%08x reset=%08x | "
627 "m02=%04x hp04=%04x pcm18=%04x pwr26=%04x ext2a=%04x rate2c=%04x ven7a=%04x",
628 VAC_READ(sc, SM502_AC97_CONTROL),
629 VAC_READ(sc, SM502_uC_MODE_SELECT),
630 VAC_READ(sc, SM502_uC_RESET),
631 r02, r04, r18, r26, r2a, r2c, r7a);
632 node.sysctl_data = buf;
633 node.sysctl_size = strlen(buf) + 1;
634 return sysctl_lookup(SYSCTLFN_CALL(&node));
635 }
636 #endif /* VAC_DEBUG */
637
638 static void
639 vac_sysctl_setup(struct vac_softc *sc)
640 {
641 const struct sysctlnode *node = NULL;
642
643 if (sysctl_createv(&sc->sc_sysctllog, 0, NULL, &node,
644 0, CTLTYPE_NODE, "vac", SYSCTL_DESCR("SM502 AC97-link audio"),
645 NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL) != 0 || node == NULL)
646 return;
647
648 sysctl_createv(&sc->sc_sysctllog, 0, NULL, NULL,
649 CTLFLAG_READONLY, CTLTYPE_INT, "underruns",
650 SYSCTL_DESCR("times the 8051 ran dry during the last playback"),
651 NULL, 0, &sc->sc_underruns, 0, CTL_HW, node->sysctl_num,
652 CTL_CREATE, CTL_EOL);
653 #ifdef VAC_DEBUG
654 sysctl_createv(&sc->sc_sysctllog, 0, NULL, NULL,
655 CTLFLAG_READONLY, CTLTYPE_STRING, "diag",
656 SYSCTL_DESCR("AC97 link + codec register dump (read while idle)"),
657 vac_sysctl_diag, 0, (void *)sc, 0, CTL_HW, node->sysctl_num,
658 CTL_CREATE, CTL_EOL);
659 #endif
660 }
661
662 static int
663 vac_match(device_t parent, cfdata_t match, void *aux)
664 {
665 struct voyager_attach_args *vaa = aux;
666
667 if (strcmp(vaa->vaa_name, "vac") == 0)
668 return 100;
669 return 0;
670 }
671
672 static void
673 vac_attach(device_t parent, device_t self, void *aux)
674 {
675 struct vac_softc * const sc = device_private(self);
676 struct voyager_attach_args *vaa = aux;
677 int error;
678
679 sc->sc_dev = self;
680 sc->sc_memt = vaa->vaa_tag;
681 sc->sc_regh = vaa->vaa_regh;
682 sc->sc_parent = device_private(parent);
683
684 aprint_naive("\n");
685 aprint_normal(": SM502 AC97-link\n");
686
687 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
688 mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_AUDIO);
689
690 callout_init(&sc->sc_feed_ch, CALLOUT_MPSAFE);
691 callout_setfunc(&sc->sc_feed_ch, vac_feed_callout, sc);
692 sc->sc_feed_ticks = mstohz(5);
693 if (sc->sc_feed_ticks < 1)
694 sc->sc_feed_ticks = 1;
695 sc->sc_dpstage = kmem_alloc(VAC_DP_BUFBYTES, KM_SLEEP);
696
697 aprint_debug_dev(self,
698 "power: ctrl 0x%08x cur-gate 0x%08x gate0 0x%08x gate1 0x%08x\n",
699 VAC_READ(sc, SM502_POWER_MODE_CONTROL),
700 VAC_READ(sc, SM502_CURRENT_GATE),
701 VAC_READ(sc, SM502_POWER_MODE0_GATE),
702 VAC_READ(sc, SM502_POWER_MODE1_GATE));
703
704 VAC_WRITE(sc, SM502_POWER_MODE0_GATE,
705 VAC_READ(sc, SM502_POWER_MODE0_GATE) |
706 SM502_GATE_AUDIO_ENABLE | SM502_GATE_8051_ENABLE);
707 VAC_WRITE(sc, SM502_POWER_MODE1_GATE,
708 VAC_READ(sc, SM502_POWER_MODE1_GATE) |
709 SM502_GATE_AUDIO_ENABLE | SM502_GATE_8051_ENABLE);
710 DELAY(1000);
711
712 /* Route the shared audio pins to the AC97-link (not GPIO). */
713 voyager_control_gpio(sc->sc_parent, 0xffffffff, SM502_AUDIO_GPIO_MASK);
714
715 /* Select AC97 mode for the link (CODEC_I2S clear). */
716 VAC_WRITE(sc, SM502_uC_MODE_SELECT,
717 VAC_READ(sc, SM502_uC_MODE_SELECT) & ~SM502_uC_CODEC_I2S);
718
719 sc->sc_ac97_host.arg = sc;
720 sc->sc_ac97_host.attach = vac_ac97_attach;
721 sc->sc_ac97_host.read = vac_ac97_read;
722 sc->sc_ac97_host.write = vac_ac97_write;
723 sc->sc_ac97_host.reset = vac_ac97_reset;
724
725 error = ac97_attach(&sc->sc_ac97_host, self, &sc->sc_lock);
726 if (error) {
727 aprint_error_dev(self, "couldn't attach codec (%d)\n", error);
728 return;
729 }
730
731 vac_sysctl_setup(sc);
732
733 /* Load the 8051 binary. */
734 vac_8051_bringup(sc);
735
736 sc->sc_audiodev = audio_attach_mi(&vac_hw_if, sc, self);
737
738 /* Unmute master + DAC now that the codec/mixer stack is up (8051 idle). */
739 vac_unmute(sc);
740 }
741