vac.c revision 1.1 1 /* $NetBSD: vac.c,v 1.1 2026/06/18 00:44:21 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.1 2026/06/18 00:44:21 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 if (!sc->sc_8051_ok)
470 return ENXIO;
471
472 /*
473 * Restart the 8051 cleanly for this playback
474 */
475 VAC_WRITE(sc, SM502_uC_RESET, 0);
476 for (i = 0; i < 16; i++)
477 VAC_DP_W8(sc, i, 0);
478 VAC_WRITE(sc, SM502_uC_RESET, SM502_uC_ENABLE);
479 for (i = 0; i < 5000 &&
480 VAC_DP_R8(sc, VAC_DP_H_ALIVE) != VAC_DP_ALIVE_MAGIC; i++)
481 DELAY(10);
482
483 mutex_enter(&sc->sc_intr_lock);
484 sc->sc_pstart = start;
485 sc->sc_pend = end;
486 sc->sc_pcur = start;
487 sc->sc_pblksize = blksize;
488 sc->sc_pint = intr;
489 sc->sc_pintarg = intrarg;
490
491 sc->sc_cmd_seq = 0;
492 sc->sc_done_seen = 0;
493 sc->sc_underruns = 0;
494 sc->sc_active = true;
495
496 /* Prime both buffers, then poll for completion from the callout. */
497 vac_dp_queue(sc);
498 vac_dp_queue(sc);
499 callout_schedule(&sc->sc_feed_ch, sc->sc_feed_ticks);
500 mutex_exit(&sc->sc_intr_lock);
501
502 return 0;
503 }
504
505 static int
506 vac_halt_output(void *priv)
507 {
508 struct vac_softc * const sc = priv;
509
510 mutex_enter(&sc->sc_intr_lock);
511 sc->sc_active = false;
512 sc->sc_pint = NULL;
513 mutex_exit(&sc->sc_intr_lock);
514
515 callout_halt(&sc->sc_feed_ch, NULL);
516
517 /* Park the 8051 so the host codec/mixer path is live while idle. */
518 VAC_WRITE(sc, SM502_uC_RESET, 0);
519 return 0;
520 }
521
522 static void
523 vac_get_locks(void *priv, kmutex_t **intr, kmutex_t **thread)
524 {
525 struct vac_softc * const sc = priv;
526
527 *intr = &sc->sc_intr_lock;
528 *thread = &sc->sc_lock;
529 }
530
531 static const struct audio_hw_if vac_hw_if = {
532 .query_format = vac_query_format,
533 .set_format = vac_set_format,
534 .getdev = vac_getdev,
535 .set_port = vac_set_port,
536 .get_port = vac_get_port,
537 .query_devinfo = vac_query_devinfo,
538 .get_props = vac_get_props,
539 .round_blocksize = vac_round_blocksize,
540 .trigger_output = vac_trigger_output,
541 .halt_output = vac_halt_output,
542 .get_locks = vac_get_locks,
543 };
544
545 /* Load the firmware blob as 32-bit LE words at (h, base). */
546 static void
547 vac_load_fw(struct vac_softc *sc, bus_space_handle_t h, bus_size_t base)
548 {
549 size_t i;
550
551 for (i = 0; i < sizeof(vac8051_fw); i += 4) {
552 uint8_t b0 = vac8051_fw[i];
553 uint8_t b1 = (i + 1 < sizeof(vac8051_fw)) ? vac8051_fw[i + 1] : 0;
554 uint8_t b2 = (i + 2 < sizeof(vac8051_fw)) ? vac8051_fw[i + 2] : 0;
555 uint8_t b3 = (i + 3 < sizeof(vac8051_fw)) ? vac8051_fw[i + 3] : 0;
556
557 bus_space_write_4(sc->sc_memt, h, base + i,
558 b0 | (b1 << 8) | (b2 << 16) | (b3 << 24));
559 }
560 }
561
562 static void
563 vac_8051_bringup(struct vac_softc *sc)
564 {
565 uint32_t v;
566 uint8_t alive;
567 int i;
568
569 /* Hold the 8051 in reset... mode = SRAM on, AC97, fastest clock (div2). */
570 VAC_WRITE(sc, SM502_uC_RESET, 0);
571 v = VAC_READ(sc, SM502_uC_MODE_SELECT);
572 v &= ~(SM502_uC_SRAM_DISABLE | SM502_uC_CODEC_I2S | SM502_uC_CLOCK_MASK);
573 VAC_WRITE(sc, SM502_uC_MODE_SELECT, v);
574
575 /* Load the feeder into the program SRAM (host R/W only while in reset). */
576 vac_load_fw(sc, sc->sc_regh, SM502_uC_SRAM_PROG);
577
578 /* Clear the dual-port protocol header before the 8051 starts. */
579 for (i = 0; i < 16; i++)
580 VAC_DP_W8(sc, i, 0);
581
582 /* Release the 8051 and give it time to post its alive marker. */
583 VAC_WRITE(sc, SM502_uC_RESET, SM502_uC_ENABLE);
584 DELAY(2000);
585
586 alive = VAC_DP_R8(sc, VAC_DP_H_ALIVE);
587 sc->sc_8051_ok = (alive == VAC_DP_ALIVE_MAGIC);
588 aprint_verbose_dev(sc->sc_dev, "8051 feeder %s (alive=0x%02x)\n",
589 sc->sc_8051_ok ? "loaded" : "not responding", alive);
590 if (!sc->sc_8051_ok)
591 aprint_error_dev(sc->sc_dev,
592 "8051 feeder did not start; playback unavailable\n");
593
594 /* Park the 8051 while idle (keeps the host codec/mixer path live). */
595 VAC_WRITE(sc, SM502_uC_RESET, 0);
596 }
597
598 #ifdef VAC_DEBUG
599 /*
600 * Diagnostics: dump the AC97 link control + key codec registers (read while the
601 * 8051 is idle; codec access is dead while it runs).
602 */
603 static int
604 vac_sysctl_diag(SYSCTLFN_ARGS)
605 {
606 struct sysctlnode node = *rnode;
607 struct vac_softc * const sc = node.sysctl_data;
608 uint16_t r02 = 0, r04 = 0, r18 = 0, r26 = 0, r2a = 0, r2c = 0, r7a = 0;
609 char buf[200];
610
611 vac_ac97_read(sc, 0x02, &r02); /* master volume */
612 vac_ac97_read(sc, 0x04, &r04); /* aux/headphone volume */
613 vac_ac97_read(sc, 0x18, &r18); /* PCM out volume */
614 vac_ac97_read(sc, 0x26, &r26); /* powerdown ctrl/status */
615 vac_ac97_read(sc, 0x2a, &r2a); /* extended audio ctrl (VRA) */
616 vac_ac97_read(sc, 0x2c, &r2c); /* PCM front DAC rate */
617 vac_ac97_read(sc, 0x7a, &r7a); /* ALC655 vendor (EAPD etc.) */
618
619 snprintf(buf, sizeof(buf),
620 "acctl=%08x mode=%08x reset=%08x | "
621 "m02=%04x hp04=%04x pcm18=%04x pwr26=%04x ext2a=%04x rate2c=%04x ven7a=%04x",
622 VAC_READ(sc, SM502_AC97_CONTROL),
623 VAC_READ(sc, SM502_uC_MODE_SELECT),
624 VAC_READ(sc, SM502_uC_RESET),
625 r02, r04, r18, r26, r2a, r2c, r7a);
626 node.sysctl_data = buf;
627 node.sysctl_size = strlen(buf) + 1;
628 return sysctl_lookup(SYSCTLFN_CALL(&node));
629 }
630 #endif /* VAC_DEBUG */
631
632 static void
633 vac_sysctl_setup(struct vac_softc *sc)
634 {
635 const struct sysctlnode *node = NULL;
636
637 if (sysctl_createv(&sc->sc_sysctllog, 0, NULL, &node,
638 0, CTLTYPE_NODE, "vac", SYSCTL_DESCR("SM502 AC97-link audio"),
639 NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL) != 0 || node == NULL)
640 return;
641
642 sysctl_createv(&sc->sc_sysctllog, 0, NULL, NULL,
643 CTLFLAG_READONLY, CTLTYPE_INT, "underruns",
644 SYSCTL_DESCR("times the 8051 ran dry during the last playback"),
645 NULL, 0, &sc->sc_underruns, 0, CTL_HW, node->sysctl_num,
646 CTL_CREATE, CTL_EOL);
647 #ifdef VAC_DEBUG
648 sysctl_createv(&sc->sc_sysctllog, 0, NULL, NULL,
649 CTLFLAG_READONLY, CTLTYPE_STRING, "diag",
650 SYSCTL_DESCR("AC97 link + codec register dump (read while idle)"),
651 vac_sysctl_diag, 0, (void *)sc, 0, CTL_HW, node->sysctl_num,
652 CTL_CREATE, CTL_EOL);
653 #endif
654 }
655
656 static int
657 vac_match(device_t parent, cfdata_t match, void *aux)
658 {
659 struct voyager_attach_args *vaa = aux;
660
661 if (strcmp(vaa->vaa_name, "vac") == 0)
662 return 100;
663 return 0;
664 }
665
666 static void
667 vac_attach(device_t parent, device_t self, void *aux)
668 {
669 struct vac_softc * const sc = device_private(self);
670 struct voyager_attach_args *vaa = aux;
671 int error;
672
673 sc->sc_dev = self;
674 sc->sc_memt = vaa->vaa_tag;
675 sc->sc_regh = vaa->vaa_regh;
676 sc->sc_parent = device_private(parent);
677
678 aprint_naive("\n");
679 aprint_normal(": SM502 AC97-link\n");
680
681 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
682 mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_AUDIO);
683
684 callout_init(&sc->sc_feed_ch, CALLOUT_MPSAFE);
685 callout_setfunc(&sc->sc_feed_ch, vac_feed_callout, sc);
686 sc->sc_feed_ticks = mstohz(5);
687 if (sc->sc_feed_ticks < 1)
688 sc->sc_feed_ticks = 1;
689 sc->sc_dpstage = kmem_alloc(VAC_DP_BUFBYTES, KM_SLEEP);
690
691 aprint_debug_dev(self,
692 "power: ctrl 0x%08x cur-gate 0x%08x gate0 0x%08x gate1 0x%08x\n",
693 VAC_READ(sc, SM502_POWER_MODE_CONTROL),
694 VAC_READ(sc, SM502_CURRENT_GATE),
695 VAC_READ(sc, SM502_POWER_MODE0_GATE),
696 VAC_READ(sc, SM502_POWER_MODE1_GATE));
697
698 VAC_WRITE(sc, SM502_POWER_MODE0_GATE,
699 VAC_READ(sc, SM502_POWER_MODE0_GATE) |
700 SM502_GATE_AUDIO_ENABLE | SM502_GATE_8051_ENABLE);
701 VAC_WRITE(sc, SM502_POWER_MODE1_GATE,
702 VAC_READ(sc, SM502_POWER_MODE1_GATE) |
703 SM502_GATE_AUDIO_ENABLE | SM502_GATE_8051_ENABLE);
704 DELAY(1000);
705
706 /* Route the shared audio pins to the AC97-link (not GPIO). */
707 voyager_control_gpio(sc->sc_parent, 0xffffffff, SM502_AUDIO_GPIO_MASK);
708
709 /* Select AC97 mode for the link (CODEC_I2S clear). */
710 VAC_WRITE(sc, SM502_uC_MODE_SELECT,
711 VAC_READ(sc, SM502_uC_MODE_SELECT) & ~SM502_uC_CODEC_I2S);
712
713 sc->sc_ac97_host.arg = sc;
714 sc->sc_ac97_host.attach = vac_ac97_attach;
715 sc->sc_ac97_host.read = vac_ac97_read;
716 sc->sc_ac97_host.write = vac_ac97_write;
717 sc->sc_ac97_host.reset = vac_ac97_reset;
718
719 error = ac97_attach(&sc->sc_ac97_host, self, &sc->sc_lock);
720 if (error) {
721 aprint_error_dev(self, "couldn't attach codec (%d)\n", error);
722 return;
723 }
724
725 vac_sysctl_setup(sc);
726
727 /* Load the 8051 binary. */
728 vac_8051_bringup(sc);
729
730 sc->sc_audiodev = audio_attach_mi(&vac_hw_if, sc, self);
731
732 /* Unmute master + DAC now that the codec/mixer stack is up (8051 idle). */
733 vac_unmute(sc);
734 }
735