Bug Summary

File:dev/pci/envy.c
Warning:line 1873, column 3
Value stored to 'dir' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name envy.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -target-feature +retpoline-external-thunk -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/legacy-dpm -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu13 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/inc -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc/pmfw_if -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D SUSPEND -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /home/ben/Projects/scan/2024-01-11-110808-61670-1 -x c /usr/src/sys/dev/pci/envy.c
1/* $OpenBSD: envy.c,v 1.87 2022/10/26 20:19:08 kn Exp $ */
2/*
3 * Copyright (c) 2007 Alexandre Ratchov <alex@caoua.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18/*
19 * TODO:
20 *
21 * - add nspdin, nspdout, to struct envy_card
22 *
23 * - use eeprom version rather isht flag
24 *
25 * - implement HT mixer, midi uart, spdif, init ADC/DACs for >48kHz modes
26 *
27 */
28
29#include "midi.h"
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/device.h>
33#include <sys/audioio.h>
34#include <sys/malloc.h>
35#include <sys/kernel.h>
36#include <dev/audio_if.h>
37#include <dev/midi_if.h>
38#include <dev/ic/ac97.h>
39#include <dev/pci/pcivar.h>
40#include <dev/pci/pcidevs.h>
41#include <dev/pci/envyvar.h>
42#include <dev/pci/envyreg.h>
43#include <machine/bus.h>
44#include <uvm/uvm.h>
45
46#ifdef ENVY_DEBUG
47#define DPRINTF(...)do {} while(0) do { if (envydebug) printf(__VA_ARGS__); } while(0)
48#define DPRINTFN(n, ...)do {} while(0) do { if (envydebug > (n)) printf(__VA_ARGS__); } while(0)
49int envydebug = 1;
50#else
51#define DPRINTF(...)do {} while(0) do {} while(0)
52#define DPRINTFN(n, ...)do {} while(0) do {} while(0)
53#endif
54#define DEVNAME(sc)((sc)->dev.dv_xname) ((sc)->dev.dv_xname)
55
56int envymatch(struct device *, void *, void *);
57void envyattach(struct device *, struct device *, void *);
58int envydetach(struct device *, int);
59int envyactivate(struct device *, int);
60
61int envy_ccs_read(struct envy_softc *, int);
62void envy_ccs_write(struct envy_softc *, int, int);
63int envy_mt_read_1(struct envy_softc *, int);
64void envy_mt_write_1(struct envy_softc *, int, int);
65int envy_mt_read_2(struct envy_softc *, int);
66void envy_mt_write_2(struct envy_softc *, int, int);
67int envy_mt_read_4(struct envy_softc *, int);
68void envy_mt_write_4(struct envy_softc *, int, int);
69int envy_cci_read(struct envy_softc *, int);
70void envy_cci_write(struct envy_softc *, int, int);
71void envy_i2c_wait(struct envy_softc *);
72int envy_i2c_read(struct envy_softc *, int, int);
73void envy_i2c_write(struct envy_softc *, int, int, int);
74int envy_gpio_getstate(struct envy_softc *);
75void envy_gpio_setstate(struct envy_softc *, int);
76int envy_gpio_getmask(struct envy_softc *);
77void envy_gpio_setmask(struct envy_softc *, int);
78int envy_gpio_getdir(struct envy_softc *);
79void envy_gpio_setdir(struct envy_softc *, int);
80void envy_gpio_i2c_start_bit(struct envy_softc *, int, int);
81void envy_gpio_i2c_stop_bit(struct envy_softc *, int, int);
82void envy_gpio_i2c_byte_out(struct envy_softc *, int, int, int);
83int envy_eeprom_gpioxxx(struct envy_softc *, int);
84void envy_midi_wait(struct envy_softc *);
85void envy_reset(struct envy_softc *);
86int envy_codec_read(struct envy_softc *, int, int);
87void envy_codec_write(struct envy_softc *, int, int, int);
88void envy_pintr(struct envy_softc *);
89int envy_intr(void *);
90
91int envy_lineout_getsrc(struct envy_softc *, int);
92void envy_lineout_setsrc(struct envy_softc *, int, int);
93int envy_spdout_getsrc(struct envy_softc *, int);
94void envy_spdout_setsrc(struct envy_softc *, int, int);
95void envy_mon_getvol(struct envy_softc *, int, int, int *);
96void envy_mon_setvol(struct envy_softc *, int, int, int);
97
98int envy_open(void *, int);
99void envy_close(void *);
100void *envy_allocm(void *, int, size_t, int, int);
101void envy_freem(void *, void *, int);
102int envy_set_params(void *, int, int, struct audio_params *,
103 struct audio_params *);
104int envy_round_blocksize(void *, int);
105int envy_trigger_output(void *, void *, void *, int,
106 void (*)(void *), void *, struct audio_params *);
107int envy_trigger_input(void *, void *, void *, int,
108 void (*)(void *), void *, struct audio_params *);
109int envy_halt_output(void *);
110int envy_halt_input(void *);
111int envy_query_devinfo(void *, struct mixer_devinfo *);
112int envy_get_port(void *, struct mixer_ctrl *);
113int envy_set_port(void *, struct mixer_ctrl *);
114#if NMIDI1 > 0
115int envy_midi_open(void *, int, void (*)(void *, int),
116 void (*)(void *), void *);
117void envy_midi_close(void *);
118int envy_midi_output(void *, int);
119void envy_midi_getinfo(void *, struct midi_info *);
120#endif
121
122int envy_ac97_wait(struct envy_softc *);
123int envy_ac97_attach_codec(void *, struct ac97_codec_if *);
124int envy_ac97_read_codec(void *, u_int8_t, u_int16_t *);
125int envy_ac97_write_codec(void *, u_int8_t, u_int16_t);
126void envy_ac97_reset_codec(void *);
127enum ac97_host_flags envy_ac97_flags_codec(void *);
128
129void delta_init(struct envy_softc *);
130void delta_codec_write(struct envy_softc *, int, int, int);
131
132void ap192k_init(struct envy_softc *);
133void ap192k_codec_write(struct envy_softc *, int, int, int);
134void ap192k_set_rate(struct envy_softc *, int);
135
136void ewx_codec_write(struct envy_softc *, int, int, int);
137
138void revo51_init(struct envy_softc *);
139void revo51_codec_write(struct envy_softc *, int, int, int);
140
141void envy_ac97_init(struct envy_softc *);
142void dynex_sc51_init(struct envy_softc *);
143
144void julia_init(struct envy_softc *);
145void julia_codec_write(struct envy_softc *, int, int, int);
146void julia_set_rate(struct envy_softc *, int);
147
148void unkenvy_init(struct envy_softc *);
149void unkenvy_codec_write(struct envy_softc *, int, int, int);
150int unkenvy_codec_ndev(struct envy_softc *);
151
152int ak4524_dac_ndev(struct envy_softc *);
153void ak4524_dac_devinfo(struct envy_softc *, struct mixer_devinfo *, int);
154void ak4524_dac_get(struct envy_softc *, struct mixer_ctrl *, int);
155int ak4524_dac_set(struct envy_softc *, struct mixer_ctrl *, int);
156int ak4524_adc_ndev(struct envy_softc *);
157void ak4524_adc_devinfo(struct envy_softc *, struct mixer_devinfo *, int);
158void ak4524_adc_get(struct envy_softc *, struct mixer_ctrl *, int);
159int ak4524_adc_set(struct envy_softc *, struct mixer_ctrl *, int);
160
161int ak4358_dac_ndev(struct envy_softc *);
162void ak4358_dac_devinfo(struct envy_softc *, struct mixer_devinfo *, int);
163void ak4358_dac_get(struct envy_softc *, struct mixer_ctrl *, int);
164int ak4358_dac_set(struct envy_softc *, struct mixer_ctrl *, int);
165void ak4358_set_rate(struct envy_softc *, int);
166
167int ak5365_adc_ndev(struct envy_softc *);
168void ak5365_adc_devinfo(struct envy_softc *, struct mixer_devinfo *, int);
169void ak5365_adc_get(struct envy_softc *, struct mixer_ctrl *, int);
170int ak5365_adc_set(struct envy_softc *, struct mixer_ctrl *, int);
171
172const struct cfattach envy_ca = {
173 sizeof(struct envy_softc), envymatch, envyattach, envydetach,
174 envyactivate
175};
176
177struct cfdriver envy_cd = {
178 NULL((void *)0), "envy", DV_DULL
179};
180
181const struct audio_hw_if envy_hw_if = {
182 .open = envy_open,
183 .close = envy_close,
184 .set_params = envy_set_params,
185 .round_blocksize = envy_round_blocksize,
186 .halt_output = envy_halt_output,
187 .halt_input = envy_halt_input,
188 .set_port = envy_set_port,
189 .get_port = envy_get_port,
190 .query_devinfo = envy_query_devinfo,
191 .allocm = envy_allocm,
192 .freem = envy_freem,
193 .trigger_output = envy_trigger_output,
194 .trigger_input = envy_trigger_input,
195};
196
197#if NMIDI1 > 0
198const struct midi_hw_if envy_midi_hw_if = {
199 envy_midi_open,
200 envy_midi_close,
201 envy_midi_output,
202 NULL((void *)0), /* flush */
203 envy_midi_getinfo,
204 NULL((void *)0) /* ioctl */
205};
206#endif
207
208struct pci_matchid envy_matchids[] = {
209 { PCI_VENDOR_ICENSEMBLE0x1412, PCI_PRODUCT_ICENSEMBLE_ICE17120x1712 },
210 { PCI_VENDOR_ICENSEMBLE0x1412, PCI_PRODUCT_ICENSEMBLE_VT172X0x1724 }
211};
212
213/*
214 * correspondence between rates (in frames per second)
215 * and values of rate register
216 */
217struct {
218 int rate, reg;
219} envy_rates[] = {
220 { 8000, 0x6}, { 9600, 0x3}, {11025, 0xa}, {12000, 2}, {16000, 5},
221 {22050, 0x9}, {24000, 0x1}, {32000, 0x4}, {44100, 8}, {48000, 0},
222 {64000, 0xf}, {88200, 0xb}, {96000, 0x7},
223 {176400, 0xc}, {192000, 0xe},
224 {-1, -1}
225};
226
227/*
228 * ESI Julia cards don't have EEPROM, use this copy
229 */
230static unsigned char julia_eeprom[ENVY_EEPROM_MAXSZ32] = {
231 /* gpio mask/dir/state is from linux */
232 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
233 0x20, 0x80, 0xf8, 0xc3,
234 0x9f, 0xff, 0x7f,
235 0x60, 0x00, 0x7f,
236 0x0a, 0x00, 0x00
237};
238
239struct envy_codec ak4524_dac = {
240 "ak4524 dac", ak4524_dac_ndev, ak4524_dac_devinfo, ak4524_dac_get, ak4524_dac_set
241}, ak4524_adc = {
242 "ak4524 adc", ak4524_adc_ndev, ak4524_adc_devinfo, ak4524_adc_get, ak4524_adc_set
243}, ak4358_dac = {
244 "ak4358 dac", ak4358_dac_ndev, ak4358_dac_devinfo, ak4358_dac_get, ak4358_dac_set
245}, ak5365_adc = {
246 "ak5365 adc", ak5365_adc_ndev, ak5365_adc_devinfo, ak5365_adc_get, ak5365_adc_set
247}, unkenvy_codec = {
248 "unknown codec", unkenvy_codec_ndev, NULL((void *)0), NULL((void *)0), NULL((void *)0)
249};
250
251/*
252 * array with vendor/product sub-IDs to card info
253 */
254struct envy_card envy_cards[] = {
255 {
256 PCI_ID_CODE(0x1412, 0xd630)((((0x1412) & 0xffff) << 0) | (((0xd630) & 0xffff
) << 16))
,
257 "M-Audio Delta 1010",
258 8, &ak4524_adc, 8, &ak4524_dac, 1,
259 delta_init,
260 delta_codec_write,
261 }, {
262 PCI_ID_CODE(0x1412, 0xd632)((((0x1412) & 0xffff) << 0) | (((0xd632) & 0xffff
) << 16))
,
263 "M-Audio Delta 66",
264 4, &ak4524_adc, 4, &ak4524_dac, 0,
265 delta_init,
266 delta_codec_write,
267 }, {
268#define ENVY_SUBID_DELTA44(((((0x1412) & 0xffff) << 0) | (((0xd633) & 0xffff
) << 16)))
(PCI_ID_CODE(0x1412, 0xd633)((((0x1412) & 0xffff) << 0) | (((0xd633) & 0xffff
) << 16))
)
269 PCI_ID_CODE(0x1412, 0xd633)((((0x1412) & 0xffff) << 0) | (((0xd633) & 0xffff
) << 16))
,
270 "M-Audio Delta 44",
271 4, &ak4524_adc, 4, &ak4524_dac, 0,
272 delta_init,
273 delta_codec_write,
274 }, {
275 PCI_ID_CODE(0x1412, 0xd63b)((((0x1412) & 0xffff) << 0) | (((0xd63b) & 0xffff
) << 16))
,
276 "M-Audio Delta 1010LT",
277 8, &ak4524_adc, 8, &ak4524_dac, 1,
278 delta_init,
279 delta_codec_write,
280 }, {
281 PCI_ID_CODE(0x1412, 0xd634)((((0x1412) & 0xffff) << 0) | (((0xd634) & 0xffff
) << 16))
,
282 "M-Audio Audiophile 2496",
283 2, &ak4524_adc, 2, &ak4524_dac, 1,
284 delta_init,
285 delta_codec_write,
286 }, {
287 PCI_ID_CODE(0x153b, 0x1130)((((0x153b) & 0xffff) << 0) | (((0x1130) & 0xffff
) << 16))
,
288 "Terratec EWX 24/96",
289 2, &ak4524_adc, 2, &ak4524_dac, 1,
290 delta_init,
291 ewx_codec_write,
292 }, {
293 0,
294 "unknown 1712-based card",
295 8, &unkenvy_codec, 8, &unkenvy_codec, 1,
296 unkenvy_init,
297 unkenvy_codec_write
298 }
299}, envy_cards_ht[] = {
300 {
301 PCI_ID_CODE(0x3031, 0x4553)((((0x3031) & 0xffff) << 0) | (((0x4553) & 0xffff
) << 16))
,
302 "ESI Julia",
303 2, &unkenvy_codec, 2, &ak4358_dac, 1,
304 julia_init,
305 julia_codec_write,
306 julia_set_rate,
307 julia_eeprom
308 }, {
309 PCI_ID_CODE(0x1412, 0x3632)((((0x1412) & 0xffff) << 0) | (((0x3632) & 0xffff
) << 16))
,
310 "M-Audio Audiophile 192k",
311 2, &unkenvy_codec, 2, &ak4358_dac, 1,
312 ap192k_init,
313 ap192k_codec_write,
314 ap192k_set_rate
315 }, {
316 PCI_ID_CODE(0x1412, 0x3631)((((0x1412) & 0xffff) << 0) | (((0x3631) & 0xffff
) << 16))
,
317 "M-Audio Revolution 5.1",
318 2, &ak5365_adc, 6, &ak4358_dac, 1,
319 revo51_init,
320 revo51_codec_write
321 }, {
322 PCI_ID_CODE(0x1412, 0x2403)((((0x1412) & 0xffff) << 0) | (((0x2403) & 0xffff
) << 16))
,
323 "VIA Tremor 5.1",
324 2, &unkenvy_codec, 6, &unkenvy_codec, 1,
325 envy_ac97_init,
326 unkenvy_codec_write
327 }, {
328 PCI_ID_CODE(0x14c3, 0x1705)((((0x14c3) & 0xffff) << 0) | (((0x1705) & 0xffff
) << 16))
,
329 "Dynex DX-SC51",
330 2, &unkenvy_codec, 6, &unkenvy_codec, 0,
331 dynex_sc51_init,
332 unkenvy_codec_write
333 }, {
334 0,
335 "unknown 1724-based card",
336 2, &unkenvy_codec, 8, &unkenvy_codec, 1,
337 unkenvy_init,
338 unkenvy_codec_write
339 }
340};
341
342
343/*
344 * M-Audio Delta specific code
345 */
346
347void
348delta_init(struct envy_softc *sc)
349{
350 int dev;
351
352 for (dev = 0; dev < sc->card->noch / 2; dev++) {
353 envy_codec_write(sc, dev, AK4524_RST0x01, 0x0);
354 delay(300)(*delay_func)(300);
355 envy_codec_write(sc, dev, AK4524_RST0x01,
356 AK4524_RST_AD0x02 | AK4524_RST_DA0x01);
357 envy_codec_write(sc, dev, AK4524_FMT0x02,
358 AK4524_FMT_IIS240x60);
359 sc->shadow[dev][AK4524_DEEMVOL0x03] = AK4524_DEEM_OFF0x01;
360 sc->shadow[dev][AK4524_ADC_GAIN00x04] = 0x7f;
361 sc->shadow[dev][AK4524_ADC_GAIN10x05] = 0x7f;
362 sc->shadow[dev][AK4524_DAC_GAIN00x06] = 0x7f;
363 sc->shadow[dev][AK4524_DAC_GAIN10x07] = 0x7f;
364 }
365}
366
367void
368delta_codec_write(struct envy_softc *sc, int dev, int addr, int data)
369{
370 int bits, i, reg;
371 int clk, dout, csmask, cs;
372
373 /*
374 * GPIO pin numbers
375 */
376 if (sc->card->subid == ENVY_SUBID_DELTA44(((((0x1412) & 0xffff) << 0) | (((0xd633) & 0xffff
) << 16)))
) {
377 clk = 0x20;
378 dout = 0x10;
379 csmask = 0xc0;
380 cs = dev ? 0x40 : 0x80;
381 } else {
382 clk = 0x2;
383 dout = 0x8;
384 csmask = 0x70;
385 cs = dev << 4;
386 }
387
388 reg = envy_gpio_getstate(sc);
389 reg &= ~csmask;
390 reg |= cs;
391 envy_gpio_setstate(sc, reg);
392 delay(1)(*delay_func)(1);
393
394 bits = 0xa000 | (addr << 8) | data;
395 for (i = 0; i < 16; i++) {
396 reg &= ~(clk | dout);
397 reg |= (bits & 0x8000) ? dout : 0;
398 envy_gpio_setstate(sc, reg);
399 delay(1)(*delay_func)(1);
400
401 reg |= clk;
402 envy_gpio_setstate(sc, reg);
403 delay(1)(*delay_func)(1);
404 bits <<= 1;
405 }
406
407 reg |= csmask;
408 envy_gpio_setstate(sc, reg);
409 delay(1)(*delay_func)(1);
410}
411
412/*
413 * M-Audio Audiophile 192 specific code
414 */
415
416/*
417 * GPIO pin numbers
418 */
419#define AP192K_GPIO_CLK0x2 0x2
420#define AP192K_GPIO_DOUT0x8 0x8
421#define AP192K_GPIO_CSMASK0x30 0x30
422#define AP192K_GPIO_CS(dev)((dev) << 4) ((dev) << 4)
423
424#define AP192K_AK5385_CKS0(1 << 8) (1 << 8)
425#define AP192K_AK5385_DFS0(1 << 9) (1 << 9)
426#define AP192K_AK5385_DFS1(1 << 10) (1 << 10)
427#define AP192K_AK5385_PWR(1 << 11) (1 << 11)
428#define AP192K_AK5385_SPD_MASK0x700 0x700
429
430void
431ap192k_init(struct envy_softc *sc)
432{
433 int i, reg;
434
435 /* AK4358 */
436 envy_codec_write(sc, 0, 0, 0); /* reset */
437 delay(300)(*delay_func)(300);
438 envy_codec_write(sc, 0, 0, 0x87); /* i2s mode */
439 delay(1)(*delay_func)(1);
440 for (i = 0; i < sc->card->noch; i++) {
441 sc->shadow[0][AK4358_ATT(i)((i) <= 5 ? 0x4 + (i) : 0xb - 6 + (i))] = 0xff;
442 }
443
444 /* AK5385 */
445 delay(1)(*delay_func)(1);
446 reg = envy_gpio_getstate(sc);
447 reg &= ~(AP192K_AK5385_PWR(1 << 11) | AP192K_AK5385_SPD_MASK0x700);
448 envy_gpio_setstate(sc, reg);
449 reg |= AP192K_AK5385_PWR(1 << 11);
450 envy_gpio_setstate(sc, reg);
451}
452
453void
454ap192k_codec_write(struct envy_softc *sc, int dev, int addr, int data)
455{
456 int bits, i, reg;
457
458 reg = envy_gpio_getstate(sc);
459 reg &= ~AP192K_GPIO_CSMASK0x30;
460 reg |= AP192K_GPIO_CS(dev)((dev) << 4);
461 envy_gpio_setstate(sc, reg);
462 delay(1)(*delay_func)(1);
463
464 bits = 0xa000 | (addr << 8) | data;
465 for (i = 0; i < 16; i++) {
466 reg &= ~(AP192K_GPIO_CLK0x2 | AP192K_GPIO_DOUT0x8);
467 reg |= (bits & 0x8000) ? AP192K_GPIO_DOUT0x8 : 0;
468 envy_gpio_setstate(sc, reg);
469 delay(1)(*delay_func)(1);
470
471 reg |= AP192K_GPIO_CLK0x2;
472 envy_gpio_setstate(sc, reg);
473 delay(1)(*delay_func)(1);
474 bits <<= 1;
475 }
476
477 reg |= AP192K_GPIO_CSMASK0x30;
478 envy_gpio_setstate(sc, reg);
479 delay(1)(*delay_func)(1);
480}
481
482void
483ap192k_set_rate(struct envy_softc *sc, int rate)
484{
485 int reg;
486
487 /* set AK5385 clock params */
488 reg = envy_gpio_getstate(sc) & ~(AP192K_AK5385_SPD_MASK0x700);
489 if (rate > 96000)
490 reg |= AP192K_AK5385_CKS0(1 << 8) | AP192K_AK5385_DFS1(1 << 10);
491 else if (rate > 48000)
492 reg |= AP192K_AK5385_DFS0(1 << 9);
493 envy_gpio_setstate(sc, reg);
494
495 ak4358_set_rate(sc, rate);
496}
497
498/*
499 * Terratec EWX specific code
500 */
501
502/*
503 * GPIO pin numbers
504 */
505#define EWX_GPIO_CSMASK0x01 0x01
506#define EWX_GPIO_DOUT0x10 0x10
507#define EWX_GPIO_CLK0x20 0x20
508
509void
510ewx_codec_write(struct envy_softc *sc, int dev, int addr, int data)
511{
512 int bits, i, reg;
513
514 reg = envy_gpio_getstate(sc);
515 reg |= (EWX_GPIO_CSMASK0x01 | EWX_GPIO_CLK0x20);
516 envy_gpio_setstate(sc, reg);
517 delay(1)(*delay_func)(1);
518
519 bits = 0xa000 | (addr << 8) | data;
520 for (i = 0; i < 16; i++) {
521 reg &= ~(EWX_GPIO_CLK0x20 | EWX_GPIO_DOUT0x10);
522 reg |= (bits & 0x8000) ? EWX_GPIO_DOUT0x10 : 0;
523 envy_gpio_setstate(sc, reg);
524 delay(1)(*delay_func)(1);
525
526 reg |= EWX_GPIO_CLK0x20;
527 envy_gpio_setstate(sc, reg);
528 delay(1)(*delay_func)(1);
529 bits <<= 1;
530 }
531
532 reg &= ~EWX_GPIO_CSMASK0x01;
533 envy_gpio_setstate(sc, reg);
534 delay(1)(*delay_func)(1);
535
536 reg |= EWX_GPIO_CSMASK0x01;
537 envy_gpio_setstate(sc, reg);
538 delay(1)(*delay_func)(1);
539}
540
541
542/*
543 * M-Audio Revolution 5.1 specific code
544 */
545
546#define REVO51_GPIO_CLK0x2 0x2
547#define REVO51_GPIO_DOUT0x8 0x8
548#define REVO51_GPIO_CSMASK0x30 0x30
549#define REVO51_GPIO_CS(dev)((dev) ? 0x10 : 0x20) ((dev) ? 0x10 : 0x20)
550#define REVO51_MUTE0x400000 0x400000
551#define REVO51_PT2258S_SDA0x40 0x40
552#define REVO51_PT2258S_SCL0x80 0x80
553#define REVO51_PT2258S_ADDR0x80 0x80
554#define REVO51_PT2258S_MUTE6 6
555
556void
557revo51_init(struct envy_softc *sc)
558{
559 int i, reg;
560
561 /* AK4358 */
562 envy_codec_write(sc, 0, 0, 0); /* reset */
563 delay(300)(*delay_func)(300);
564 envy_codec_write(sc, 0, 0, 0x87); /* i2s mode */
565 for (i = 0; i < sc->card->noch; i++) {
566 sc->shadow[0][AK4358_ATT(i)((i) <= 5 ? 0x4 + (i) : 0xb - 6 + (i))] = 0xff;
567 }
568
569 /* AK5365 */
570 envy_codec_write(sc, 1, AK5365_RST0x00, 0); /* reset */
571 delay(300)(*delay_func)(300);
572 envy_codec_write(sc, 1, AK5365_CTRL0x02, AK5365_CTRL_I2S0x08); /* i2s mode */
573 envy_codec_write(sc, 1, AK5365_RST0x00 , AK5365_RST_NORM0x01);
574 sc->shadow[1][AK5365_ATT(0)(0x4 + (0))] = 0x7f;
575 sc->shadow[1][AK5365_ATT(1)(0x4 + (1))] = 0x7f;
576
577 /* PT2258S */
578 envy_codec_write(sc, 2, REVO51_PT2258S_MUTE6, 0xc0); /* reset */
579 envy_codec_write(sc, 2, REVO51_PT2258S_MUTE6, 0xf9); /* mute */
580
581 reg = envy_gpio_getstate(sc);
582 reg |= REVO51_MUTE0x400000;
583 envy_gpio_setstate(sc, reg);
584}
585
586void
587revo51_codec_write(struct envy_softc *sc, int dev, int addr, int data)
588{
589 int attn, bits, mask, reg;
590 int xlat[6] = {0x90, 0x50, 0x10, 0x30, 0x70, 0xb0};
591
592 /* AK4358 & AK5365 */
593 if (dev < 2) {
594 reg = envy_gpio_getstate(sc);
595 reg &= ~REVO51_GPIO_CSMASK0x30;
596 reg |= REVO51_GPIO_CS(dev)((dev) ? 0x10 : 0x20);
597 envy_gpio_setstate(sc, reg);
598 delay(1)(*delay_func)(1);
599
600 bits = 0xa000 | (addr << 8) | data;
601 for (mask = 0x8000; mask != 0; mask >>= 1) {
602 reg &= ~(REVO51_GPIO_CLK0x2 | REVO51_GPIO_DOUT0x8);
603 reg |= (bits & mask) ? REVO51_GPIO_DOUT0x8 : 0;
604 envy_gpio_setstate(sc, reg);
605 delay(1)(*delay_func)(1);
606
607 reg |= REVO51_GPIO_CLK0x2;
608 envy_gpio_setstate(sc, reg);
609 delay(1)(*delay_func)(1);
610 }
611
612 reg |= REVO51_GPIO_CSMASK0x30;
613 envy_gpio_setstate(sc, reg);
614 delay(1)(*delay_func)(1);
615 return;
616 }
617
618 /* PT2258S */
619 envy_gpio_i2c_start_bit(sc, REVO51_PT2258S_SDA0x40, REVO51_PT2258S_SCL0x80);
620 envy_gpio_i2c_byte_out(sc, REVO51_PT2258S_SDA0x40, REVO51_PT2258S_SCL0x80,
621 REVO51_PT2258S_ADDR0x80);
622
623 if (addr == REVO51_PT2258S_MUTE6) {
624 envy_gpio_i2c_byte_out(sc, REVO51_PT2258S_SDA0x40,
625 REVO51_PT2258S_SCL0x80, data);
626 } else {
627 /* 1's digit */
628 attn = data % 10;
629 attn += xlat[addr];
630 envy_gpio_i2c_byte_out(sc, REVO51_PT2258S_SDA0x40,
631 REVO51_PT2258S_SCL0x80, attn);
632
633 /* 10's digit */
634 attn = data / 10;
635 attn += xlat[addr] - 0x10;
636 envy_gpio_i2c_byte_out(sc, REVO51_PT2258S_SDA0x40,
637 REVO51_PT2258S_SCL0x80, attn);
638 }
639
640 envy_gpio_i2c_stop_bit(sc, REVO51_PT2258S_SDA0x40, REVO51_PT2258S_SCL0x80);
641}
642
643/*
644 * Generic AC'97 initialization
645 */
646
647void
648envy_ac97_init(struct envy_softc *sc)
649{
650 sc->isac97 = 1;
651 sc->host_if.arg = sc;
652 sc->host_if.attach = envy_ac97_attach_codec;
653 sc->host_if.read = envy_ac97_read_codec;
654 sc->host_if.write = envy_ac97_write_codec;
655 sc->host_if.reset = envy_ac97_reset_codec;
656 sc->host_if.flags = envy_ac97_flags_codec;
657
658 if (ac97_attach(&sc->host_if) != 0)
659 printf("%s: can't attach ac97\n", DEVNAME(sc)((sc)->dev.dv_xname));
660}
661
662/*
663 * Dynex
664 */
665
666void
667dynex_sc51_init(struct envy_softc *sc)
668{
669 sc->codec_flags |= AC97_HOST_VT1616_DYNEX;
670 envy_ac97_init(sc);
671}
672
673/*
674 * ESI Julia specific code
675 */
676
677#define JULIA_AK5385_CKS0(1 << 8) (1 << 8)
678#define JULIA_AK5385_DFS1(1 << 9) (1 << 9)
679#define JULIA_AK5385_DFS0(1 << 10) (1 << 10)
680#define JULIA_AK5385_CKS1(1 << 14) (1 << 14)
681#define JULIA_AK5385_MASK0x4700 0x4700
682
683void
684julia_init(struct envy_softc *sc)
685{
686 int i;
687
688 envy_codec_write(sc, 0, 0, 0); /* reset */
689 delay(300)(*delay_func)(300);
690 envy_codec_write(sc, 0, 0, 0x87); /* i2s mode */
691 for (i = 0; i < sc->card->noch; i++) {
692 sc->shadow[0][AK4358_ATT(i)((i) <= 5 ? 0x4 + (i) : 0xb - 6 + (i))] = 0xff;
693 }
694}
695
696void
697julia_codec_write(struct envy_softc *sc, int dev, int addr, int data)
698{
699#define JULIA_AK4358_ADDR0x11 0x11
700 envy_i2c_write(sc, JULIA_AK4358_ADDR0x11, addr, data);
701}
702
703void
704julia_set_rate(struct envy_softc *sc, int rate)
705{
706 int reg;
707
708 /* set AK5385 clock params */
709 reg = envy_gpio_getstate(sc) & ~(JULIA_AK5385_MASK0x4700);
710 if (rate > 96000)
711 reg |= JULIA_AK5385_CKS0(1 << 8) | JULIA_AK5385_DFS1(1 << 9);
712 else if (rate > 48000)
713 reg |= JULIA_AK5385_DFS0(1 << 10);
714 envy_gpio_setstate(sc, reg);
715
716 ak4358_set_rate(sc, rate);
717}
718
719/*
720 * unknown card, ignore codecs setup and hope it works with the power on
721 * settings
722 */
723
724void
725unkenvy_init(struct envy_softc *sc)
726{
727}
728
729void
730unkenvy_codec_write(struct envy_softc *sc, int dev, int addr, int data)
731{
732}
733
734int
735unkenvy_codec_ndev(struct envy_softc *sc)
736{
737 return 0;
738}
739
740/*
741 * AK 4358 DAC specific code
742 */
743int
744ak4358_dac_ndev(struct envy_softc *sc)
745{
746 /* 1 volume knob per channel */
747 return sc->card->noch;
748}
749
750void
751ak4358_dac_devinfo(struct envy_softc *sc, struct mixer_devinfo *dev, int idx)
752{
753 dev->type = AUDIO_MIXER_VALUE3;
754 dev->mixer_class = ENVY_MIX_CLASSOUT1;
755 dev->un.v.delta = 2;
756 dev->un.v.num_channels = 1;
757 snprintf(dev->label.name, MAX_AUDIO_DEV_LEN16,
758 AudioNline"line" "-%d", idx);
759 strlcpy(dev->un.v.units.name, AudioNvolume"volume",
760 MAX_AUDIO_DEV_LEN16);
761}
762
763void
764ak4358_dac_get(struct envy_softc *sc, struct mixer_ctrl *ctl, int idx)
765{
766 int val;
767
768 val = envy_codec_read(sc, 0, AK4358_ATT(idx)((idx) <= 5 ? 0x4 + (idx) : 0xb - 6 + (idx))) & ~AK4358_ATT_EN0x80;
769 ctl->un.value.num_channels = 1;
770 ctl->un.value.level[0] = 2 * val;
771}
772
773int
774ak4358_dac_set(struct envy_softc *sc, struct mixer_ctrl *ctl, int idx)
775{
776 int val;
777
778 if (ctl->un.value.num_channels != 1)
779 return EINVAL22;
780 val = ctl->un.value.level[0] / 2;
781 envy_codec_write(sc, 0, AK4358_ATT(idx)((idx) <= 5 ? 0x4 + (idx) : 0xb - 6 + (idx)), val | AK4358_ATT_EN0x80);
782 return 0;
783}
784
785void
786ak4358_set_rate(struct envy_softc *sc, int rate)
787{
788 int reg;
789
790 reg = AK4358_SPEED_DEFAULT0x4f & ~(AK4358_SPEED_DFS00x10 | AK4358_SPEED_DFS10x20);
791 if (rate > 96000)
792 reg |= AK4358_SPEED_DFS10x20;
793 else if (rate > 48000)
794 reg |= AK4358_SPEED_DFS00x10;
795
796 /* put in reset state */
797 reg &= ~AK4358_SPEED_RSTN0x01;
798 envy_codec_write(sc, 0, AK4358_SPEED2, reg);
799
800 /* back in normal state */
801 reg |= AK4358_SPEED_RSTN0x01;
802 envy_codec_write(sc, 0, AK4358_SPEED2, reg);
803}
804
805/*
806 * AK 4524 DAC specific code
807 */
808int
809ak4524_dac_ndev(struct envy_softc *sc)
810{
811 /* 1 mute + 2 volume knobs per channel pair */
812 return 3 * (sc->card->noch / 2);
813}
814
815void
816ak4524_dac_devinfo(struct envy_softc *sc, struct mixer_devinfo *dev, int idx)
817{
818 int ndev;
819
820 ndev = sc->card->noch;
821 if (idx < ndev) {
822 dev->type = AUDIO_MIXER_VALUE3;
823 dev->mixer_class = ENVY_MIX_CLASSOUT1;
824 dev->un.v.delta = 2;
825 dev->un.v.num_channels = 1;
826 snprintf(dev->label.name, MAX_AUDIO_DEV_LEN16,
827 AudioNline"line" "-%d", idx);
828 strlcpy(dev->un.v.units.name, AudioNvolume"volume",
829 MAX_AUDIO_DEV_LEN16);
830 } else {
831 idx -= ndev;
832 dev->type = AUDIO_MIXER_ENUM1;
833 dev->mixer_class = ENVY_MIX_CLASSOUT1;
834 dev->un.e.member[0].ord = 0;
835 strlcpy(dev->un.e.member[0].label.name, AudioNoff"off",
836 MAX_AUDIO_DEV_LEN16);
837 dev->un.e.member[1].ord = 1;
838 strlcpy(dev->un.e.member[1].label.name, AudioNon"on",
839 MAX_AUDIO_DEV_LEN16);
840 dev->un.e.num_mem = 2;
841 snprintf(dev->label.name, MAX_AUDIO_DEV_LEN16,
842 AudioNline"line" "-%d:%d_" AudioNmute"mute", 2 * idx, 2 * idx + 1);
843 }
844}
845
846void
847ak4524_dac_get(struct envy_softc *sc, struct mixer_ctrl *ctl, int idx)
848{
849 int val, ndev;
850
851 ndev = sc->card->noch;
852 if (idx < ndev) {
853 val = envy_codec_read(sc, idx / 2,
854 (idx % 2) + AK4524_DAC_GAIN00x06);
855 ctl->un.value.num_channels = 1;
856 ctl->un.value.level[0] = 2 * val;
857 } else {
858 idx -= ndev;
859 val = envy_codec_read(sc, idx, AK4524_DEEMVOL0x03);
860 ctl->un.ord = (val & AK4524_MUTE0x80) ? 1 : 0;
861 }
862}
863
864int
865ak4524_dac_set(struct envy_softc *sc, struct mixer_ctrl *ctl, int idx)
866{
867 int val, ndev;
868
869 ndev = sc->card->noch;
870 if (idx < ndev) {
871 if (ctl->un.value.num_channels != 1)
872 return EINVAL22;
873 val = ctl->un.value.level[0] / 2;
874 envy_codec_write(sc, idx / 2,
875 (idx % 2) + AK4524_DAC_GAIN00x06, val);
876 } else {
877 idx -= ndev;
878 if (ctl->un.ord >= 2)
879 return EINVAL22;
880 val = AK4524_DEEM_OFF0x01 | (ctl->un.ord ? AK4524_MUTE0x80 : 0);
881 envy_codec_write(sc, idx, AK4524_DEEMVOL0x03, val);
882 }
883 return 0;
884}
885
886/*
887 * AK 4524 ADC specific code
888 */
889int
890ak4524_adc_ndev(struct envy_softc *sc)
891{
892 /* one volume per channel */
893 return sc->card->nich;
894}
895
896void
897ak4524_adc_devinfo(struct envy_softc *sc, struct mixer_devinfo *dev, int idx)
898{
899 dev->type = AUDIO_MIXER_VALUE3;
900 dev->mixer_class = ENVY_MIX_CLASSIN0;
901 dev->un.v.delta = 2;
902 dev->un.v.num_channels = 1;
903 snprintf(dev->label.name, MAX_AUDIO_DEV_LEN16, AudioNline"line" "-%d", idx);
904 strlcpy(dev->un.v.units.name, AudioNvolume"volume", MAX_AUDIO_DEV_LEN16);
905}
906
907void
908ak4524_adc_get(struct envy_softc *sc, struct mixer_ctrl *ctl, int idx)
909{
910 int val;
911
912 val = envy_codec_read(sc, idx / 2, (idx % 2) + AK4524_ADC_GAIN00x04);
913 ctl->un.value.num_channels = 1;
914 ctl->un.value.level[0] = 2 * val;
915}
916
917int
918ak4524_adc_set(struct envy_softc *sc, struct mixer_ctrl *ctl, int idx)
919{
920 int val;
921
922 if (ctl->un.value.num_channels != 1)
923 return EINVAL22;
924 val = ctl->un.value.level[0] / 2;
925 envy_codec_write(sc, idx / 2, (idx % 2) + AK4524_ADC_GAIN00x04, val);
926 return 0;
927}
928
929/*
930 * AK 5365 ADC specific code
931 */
932int
933ak5365_adc_ndev(struct envy_softc *sc)
934{
935 /* 1 source + 2 volume knobs per channel pair */
936 return (sc->card->nich + 1);
937}
938
939void
940ak5365_adc_devinfo(struct envy_softc *sc, struct mixer_devinfo *dev, int idx)
941{
942 int ndev, i;
943
944 ndev = sc->card->nich;
945 if (idx < ndev) {
946 dev->type = AUDIO_MIXER_VALUE3;
947 dev->mixer_class = ENVY_MIX_CLASSIN0;
948 dev->un.v.delta = 2;
949 dev->un.v.num_channels = 1;
950 snprintf(dev->label.name, MAX_AUDIO_DEV_LEN16,
951 AudioNline"line" "-%d", idx);
952 strlcpy(dev->un.v.units.name, AudioNvolume"volume",
953 MAX_AUDIO_DEV_LEN16);
954 } else {
955 dev->type = AUDIO_MIXER_ENUM1;
956 dev->mixer_class = ENVY_MIX_CLASSIN0;
957 for (i = 0; i < 5; i++) {
958 dev->un.e.member[i].ord = i;
959 snprintf(dev->un.e.member[i].label.name,
960 MAX_AUDIO_DEV_LEN16, AudioNline"line" "-%d", i);
961 }
962 dev->un.e.num_mem = 5;
963 strlcpy(dev->label.name, AudioNsource"source",
964 MAX_AUDIO_DEV_LEN16);
965 }
966}
967
968void
969ak5365_adc_get(struct envy_softc *sc, struct mixer_ctrl *ctl, int idx)
970{
971 int val, ndev;
972
973 ndev = sc->card->nich;
974 if (idx < ndev) {
975 val = envy_codec_read(sc, 1, AK5365_ATT(idx)(0x4 + (idx)));
976 ctl->un.value.num_channels = 1;
977 ctl->un.value.level[0] = 2 * val;
978 } else {
979 ctl->un.ord = envy_codec_read(sc, 1, AK5365_SRC0x01);
980 }
981}
982
983int
984ak5365_adc_set(struct envy_softc *sc, struct mixer_ctrl *ctl, int idx)
985{
986 int val, ndev;
987
988 ndev = sc->card->nich;
989 if (idx < ndev) {
990 if (ctl->un.value.num_channels != 1)
991 return EINVAL22;
992 val = ctl->un.value.level[0] / 2;
993 envy_codec_write(sc, 1, AK5365_ATT(idx)(0x4 + (idx)), val);
994 } else {
995 if (ctl->un.ord >= 5)
996 return EINVAL22;
997 val = ctl->un.ord & AK5365_SRC_MASK0x07;
998 envy_codec_write(sc, 1, AK5365_SRC0x01, val);
999 }
1000 return 0;
1001}
1002
1003/*
1004 * generic Envy24 and Envy24HT code, common to all cards
1005 */
1006
1007int
1008envy_ccs_read(struct envy_softc *sc, int reg)
1009{
1010 int val;
1011
1012 val = bus_space_read_1(sc->ccs_iot, sc->ccs_ioh, reg)((sc->ccs_iot)->read_1((sc->ccs_ioh), (reg)));
1013 bus_space_barrier(sc->ccs_iot, sc->ccs_ioh, 0, sc->ccs_iosz,
1014 BUS_SPACE_BARRIER_READ0x01 | BUS_SPACE_BARRIER_WRITE0x02);
1015 return val;
1016}
1017
1018void
1019envy_ccs_write(struct envy_softc *sc, int reg, int val)
1020{
1021 bus_space_write_1(sc->ccs_iot, sc->ccs_ioh, reg, val)((sc->ccs_iot)->write_1((sc->ccs_ioh), (reg), (val))
)
;
1022 bus_space_barrier(sc->ccs_iot, sc->ccs_ioh, 0, sc->ccs_iosz,
1023 BUS_SPACE_BARRIER_READ0x01 | BUS_SPACE_BARRIER_WRITE0x02);
1024}
1025
1026int
1027envy_mt_read_1(struct envy_softc *sc, int reg)
1028{
1029 int val;
1030
1031 val = bus_space_read_1(sc->mt_iot, sc->mt_ioh, reg)((sc->mt_iot)->read_1((sc->mt_ioh), (reg)));
1032 bus_space_barrier(sc->mt_iot, sc->mt_ioh, 0, sc->mt_iosz,
1033 BUS_SPACE_BARRIER_READ0x01 | BUS_SPACE_BARRIER_WRITE0x02);
1034 return val;
1035}
1036
1037void
1038envy_mt_write_1(struct envy_softc *sc, int reg, int val)
1039{
1040 bus_space_write_1(sc->mt_iot, sc->mt_ioh, reg, val)((sc->mt_iot)->write_1((sc->mt_ioh), (reg), (val)));
1041 bus_space_barrier(sc->mt_iot, sc->mt_ioh, 0, sc->mt_iosz,
1042 BUS_SPACE_BARRIER_READ0x01 | BUS_SPACE_BARRIER_WRITE0x02);
1043}
1044
1045int
1046envy_mt_read_2(struct envy_softc *sc, int reg)
1047{
1048 int val;
1049
1050 val = bus_space_read_2(sc->mt_iot, sc->mt_ioh, reg)((sc->mt_iot)->read_2((sc->mt_ioh), (reg)));
1051 bus_space_barrier(sc->mt_iot, sc->mt_ioh, 0, sc->mt_iosz,
1052 BUS_SPACE_BARRIER_READ0x01 | BUS_SPACE_BARRIER_WRITE0x02);
1053 return val;
1054}
1055
1056void
1057envy_mt_write_2(struct envy_softc *sc, int reg, int val)
1058{
1059 bus_space_write_2(sc->mt_iot, sc->mt_ioh, reg, val)((sc->mt_iot)->write_2((sc->mt_ioh), (reg), (val)));
1060 bus_space_barrier(sc->mt_iot, sc->mt_ioh, 0, sc->mt_iosz,
1061 BUS_SPACE_BARRIER_READ0x01 | BUS_SPACE_BARRIER_WRITE0x02);
1062}
1063
1064int
1065envy_mt_read_4(struct envy_softc *sc, int reg)
1066{
1067 int val;
1068
1069 val = bus_space_read_4(sc->mt_iot, sc->mt_ioh, reg)((sc->mt_iot)->read_4((sc->mt_ioh), (reg)));
1070 bus_space_barrier(sc->mt_iot, sc->mt_ioh, 0, sc->mt_iosz,
1071 BUS_SPACE_BARRIER_READ0x01 | BUS_SPACE_BARRIER_WRITE0x02);
1072 return val;
1073}
1074
1075void
1076envy_mt_write_4(struct envy_softc *sc, int reg, int val)
1077{
1078 bus_space_write_4(sc->mt_iot, sc->mt_ioh, reg, val)((sc->mt_iot)->write_4((sc->mt_ioh), (reg), (val)));
1079 bus_space_barrier(sc->mt_iot, sc->mt_ioh, 0, sc->mt_iosz,
1080 BUS_SPACE_BARRIER_READ0x01 | BUS_SPACE_BARRIER_WRITE0x02);
1081}
1082
1083int
1084envy_cci_read(struct envy_softc *sc, int index)
1085{
1086 envy_ccs_write(sc, ENVY_CCI_INDEX0x3, index);
1087 return (envy_ccs_read(sc, ENVY_CCI_DATA0x4));
1088}
1089
1090void
1091envy_cci_write(struct envy_softc *sc, int index, int data)
1092{
1093 envy_ccs_write(sc, ENVY_CCI_INDEX0x3, index);
1094 envy_ccs_write(sc, ENVY_CCI_DATA0x4, data);
1095}
1096
1097int
1098envy_gpio_getstate(struct envy_softc *sc)
1099{
1100 if (sc->isht) {
1101 return envy_ccs_read(sc, ENVY_CCS_GPIODATA00x14) |
1102 (envy_ccs_read(sc, ENVY_CCS_GPIODATA10x15) << 8) |
1103 (envy_ccs_read(sc, ENVY_CCS_GPIODATA20x1e) << 16);
1104 } else
1105 return envy_cci_read(sc, ENVY_CCI_GPIODATA0x20);
1106}
1107
1108void
1109envy_gpio_setstate(struct envy_softc *sc, int reg)
1110{
1111 if (sc->isht) {
1112 envy_ccs_write(sc, ENVY_CCS_GPIODATA00x14, reg & 0xff);
1113 envy_ccs_write(sc, ENVY_CCS_GPIODATA10x15, (reg >> 8) & 0xff);
1114 envy_ccs_write(sc, ENVY_CCS_GPIODATA20x1e, (reg >> 16) & 0xff);
1115 } else
1116 envy_cci_write(sc, ENVY_CCI_GPIODATA0x20, reg);
1117}
1118
1119int
1120envy_gpio_getmask(struct envy_softc *sc)
1121{
1122 if (sc->isht) {
1123 return envy_ccs_read(sc, ENVY_CCS_GPIOMASK00x16) |
1124 (envy_ccs_read(sc, ENVY_CCS_GPIOMASK10x17) << 8) |
1125 (envy_ccs_read(sc, ENVY_CCS_GPIOMASK20x1f) << 16);
1126 } else
1127 return envy_cci_read(sc, ENVY_CCI_GPIOMASK0x21);
1128}
1129
1130void
1131envy_gpio_setmask(struct envy_softc *sc, int mask)
1132{
1133 if (sc->isht) {
1134 envy_ccs_write(sc, ENVY_CCS_GPIOMASK00x16, mask & 0xff);
1135 envy_ccs_write(sc, ENVY_CCS_GPIOMASK10x17, (mask >> 8) & 0xff);
1136 envy_ccs_write(sc, ENVY_CCS_GPIOMASK20x1f, (mask >> 16) & 0xff);
1137 } else
1138 envy_cci_write(sc, ENVY_CCI_GPIOMASK0x21, mask);
1139}
1140
1141int
1142envy_gpio_getdir(struct envy_softc *sc)
1143{
1144 if (sc->isht) {
1145 return envy_ccs_read(sc, ENVY_CCS_GPIODIR00x18) |
1146 (envy_ccs_read(sc, ENVY_CCS_GPIODIR10x19) << 8) |
1147 (envy_ccs_read(sc, ENVY_CCS_GPIODIR20x1a) << 16);
1148 } else
1149 return envy_cci_read(sc, ENVY_CCI_GPIODIR0x22);
1150}
1151
1152void
1153envy_gpio_setdir(struct envy_softc *sc, int dir)
1154{
1155 if (sc->isht) {
1156 envy_ccs_write(sc, ENVY_CCS_GPIODIR00x18, dir & 0xff);
1157 envy_ccs_write(sc, ENVY_CCS_GPIODIR10x19, (dir >> 8) & 0xff);
1158 envy_ccs_write(sc, ENVY_CCS_GPIODIR20x1a, (dir >> 16) & 0xff);
1159 } else
1160 envy_cci_write(sc, ENVY_CCI_GPIODIR0x22, dir);
1161}
1162
1163void
1164envy_gpio_i2c_start_bit(struct envy_softc *sc, int sda, int scl)
1165{
1166 int reg;
1167
1168 reg = envy_gpio_getstate(sc);
1169 reg |= (sda | scl);
1170 envy_gpio_setstate(sc, reg);
1171 delay(5)(*delay_func)(5);
1172 reg &= ~sda;
1173 envy_gpio_setstate(sc, reg);
1174 delay(4)(*delay_func)(4);
1175 reg &= ~scl;
1176 envy_gpio_setstate(sc, reg);
1177 delay(5)(*delay_func)(5);
1178}
1179
1180void
1181envy_gpio_i2c_stop_bit(struct envy_softc *sc, int sda, int scl)
1182{
1183 int reg;
1184
1185 reg = envy_gpio_getstate(sc);
1186 reg &= ~sda;
1187 reg |= scl;
1188 envy_gpio_setstate(sc, reg);
1189 delay(4)(*delay_func)(4);
1190 reg |= sda;
1191 envy_gpio_setstate(sc, reg);
1192}
1193
1194void
1195envy_gpio_i2c_byte_out(struct envy_softc *sc, int sda, int scl, int val)
1196{
1197 int mask, reg;
1198
1199 reg = envy_gpio_getstate(sc);
1200
1201 for (mask = 0x80; mask != 0; mask >>= 1) {
1202 reg &= ~sda;
1203 reg |= (val & mask) ? sda : 0;
1204 envy_gpio_setstate(sc, reg);
1205 delay(1)(*delay_func)(1);
1206 reg |= scl;
1207 envy_gpio_setstate(sc, reg);
1208 delay(4)(*delay_func)(4);
1209 reg &= ~scl;
1210 envy_gpio_setstate(sc, reg);
1211 delay(5)(*delay_func)(5);
1212 }
1213
1214 reg |= scl;
1215 envy_gpio_setstate(sc, reg);
1216 delay(4)(*delay_func)(4);
1217 reg &= ~scl;
1218 envy_gpio_setstate(sc, reg);
1219 delay(5)(*delay_func)(5);
1220}
1221
1222void
1223envy_i2c_wait(struct envy_softc *sc)
1224{
1225 int timeout = 50, st;
1226
1227 for (;;) {
1228 st = envy_ccs_read(sc, ENVY_I2C_CTL0x13);
1229 if (!(st & ENVY_I2C_CTL_BUSY0x1))
1230 break;
1231 if (timeout == 0) {
1232 printf("%s: i2c busy timeout\n", DEVNAME(sc)((sc)->dev.dv_xname));
1233 break;
1234 }
1235 delay(50)(*delay_func)(50);
1236 timeout--;
1237 }
1238}
1239
1240int
1241envy_i2c_read(struct envy_softc *sc, int dev, int addr)
1242{
1243 envy_i2c_wait(sc);
1244 envy_ccs_write(sc, ENVY_I2C_ADDR0x11, addr);
1245 envy_i2c_wait(sc);
1246 envy_ccs_write(sc, ENVY_I2C_DEV0x10, dev << 1);
1247 envy_i2c_wait(sc);
1248 return envy_ccs_read(sc, ENVY_I2C_DATA0x12);
1249}
1250
1251void
1252envy_i2c_write(struct envy_softc *sc, int dev, int addr, int data)
1253{
1254 if (dev == 0x50) {
1255 printf("%s: writing on eeprom is evil...\n", DEVNAME(sc)((sc)->dev.dv_xname));
1256 return;
1257 }
1258 envy_i2c_wait(sc);
1259 envy_ccs_write(sc, ENVY_I2C_ADDR0x11, addr);
1260 envy_i2c_wait(sc);
1261 envy_ccs_write(sc, ENVY_I2C_DATA0x12, data);
1262 envy_i2c_wait(sc);
1263 envy_ccs_write(sc, ENVY_I2C_DEV0x10, (dev << 1) | 1);
1264}
1265
1266int
1267envy_codec_read(struct envy_softc *sc, int dev, int addr) {
1268 return sc->shadow[dev][addr];
1269}
1270
1271void
1272envy_codec_write(struct envy_softc *sc, int dev, int addr, int data)
1273{
1274 DPRINTFN(2, "envy_codec_write: %d, %d, 0x%x\n", dev, addr, data)do {} while(0);
1275 sc->shadow[dev][addr] = data;
1276 sc->card->codec_write(sc, dev, addr, data);
1277}
1278
1279int
1280envy_eeprom_gpioxxx(struct envy_softc *sc, int addr)
1281{
1282 int val;
1283
1284 val = sc->eeprom[addr];
1285 if (sc->isht) {
1286 val |= sc->eeprom[++addr] << 8;
1287 val |= sc->eeprom[++addr] << 16;
1288 }
1289 return val;
1290}
1291
1292int
1293envy_ac97_wait(struct envy_softc *sc)
1294{
1295 int timeout = 50, st;
1296
1297 for (;;) {
1298 st = envy_mt_read_1(sc, ENVY_MT_AC97_CMD5);
1299 if ((st & ENVY_MT_AC97_READY0x08) && !(st & ENVY_MT_AC97_CMD_MASK0x30)) {
1300 st = 0;
1301 break;
1302 }
1303 if (timeout == 0) {
1304 st = -1;
1305 break;
1306 }
1307 delay(50)(*delay_func)(50);
1308 timeout--;
1309 }
1310
1311 return (st);
1312}
1313
1314int
1315envy_ac97_attach_codec(void *hdl, struct ac97_codec_if *codec_if)
1316{
1317 struct envy_softc *sc = hdl;
1318
1319 sc->codec_if = codec_if;
1320
1321 return (0);
1322}
1323
1324int
1325envy_ac97_read_codec(void *hdl, u_int8_t reg, u_int16_t *result)
1326{
1327 struct envy_softc *sc = hdl;
1328
1329 if (envy_ac97_wait(sc)) {
1330 printf("%s: envy_ac97_read_codec: timed out\n", DEVNAME(sc)((sc)->dev.dv_xname));
1331 return (-1);
1332 }
1333
1334 envy_mt_write_1(sc, ENVY_MT_AC97_IDX4, reg & 0x7f);
1335 envy_mt_write_1(sc, ENVY_MT_AC97_CMD5,
1336 ENVY_MT_AC97_CMD_RD0x10);
1337 delay(50)(*delay_func)(50);
1338
1339 if (envy_ac97_wait(sc)) {
1340 printf("%s: envy_ac97_read_codec: timed out\n", DEVNAME(sc)((sc)->dev.dv_xname));
1341 return (-1);
1342 }
1343
1344 *result = envy_mt_read_2(sc, ENVY_MT_AC97_DATA6);
1345
1346 return (0);
1347}
1348
1349int
1350envy_ac97_write_codec(void *hdl, u_int8_t reg, u_int16_t data)
1351{
1352 struct envy_softc *sc = hdl;
1353
1354 if (envy_ac97_wait(sc)) {
1355 printf("%s: envy_ac97_write_codec: timed out\n", DEVNAME(sc)((sc)->dev.dv_xname));
1356 return (-1);
1357 }
1358
1359 envy_mt_write_1(sc, ENVY_MT_AC97_IDX4, reg & 0x7f);
1360 envy_mt_write_2(sc, ENVY_MT_AC97_DATA6, data);
1361 envy_mt_write_1(sc, ENVY_MT_AC97_CMD5,
1362 ENVY_MT_AC97_CMD_WR0x20);
1363 delay(50)(*delay_func)(50);
1364
1365 return (0);
1366}
1367
1368void
1369envy_ac97_reset_codec(void *hdl)
1370{
1371 struct envy_softc *sc = hdl;
1372
1373 envy_mt_write_1(sc, ENVY_MT_AC97_CMD5, ENVY_MT_AC97_CMD_RST0x80);
1374 delay(50)(*delay_func)(50);
1375 envy_mt_write_1(sc, ENVY_MT_AC97_CMD5, 0);
1376 delay(50)(*delay_func)(50);
1377
1378 if (envy_ac97_wait(sc)) {
1379 printf("%s: envy_ac97_reset_codec: timed out\n", DEVNAME(sc)((sc)->dev.dv_xname));
1380 }
1381
1382 return;
1383}
1384
1385enum ac97_host_flags
1386envy_ac97_flags_codec(void *hdl)
1387{
1388 struct envy_softc *sc = hdl;
1389
1390 return (sc->codec_flags);
1391}
1392
1393void
1394envy_midi_wait(struct envy_softc *sc)
1395{
1396 int i, st;
1397
1398 for (i = 100;; i--) {
1399 st = envy_ccs_read(sc, ENVY_CCS_MIDISTAT00x0d);
1400 if (!(st & ENVY_MIDISTAT_OBUSY(sc)((sc)->isht ? 0x4 : 0x40)))
1401 break;
1402 if (i == 0) {
1403 printf("%s: midi wait timeout\n", DEVNAME(sc)((sc)->dev.dv_xname));
1404 break;
1405 }
1406 delay(10)(*delay_func)(10);
1407 }
1408}
1409
1410void
1411envy_reset(struct envy_softc *sc)
1412{
1413 int i, reg;
1414
1415 /*
1416 * full reset
1417 */
1418 envy_ccs_write(sc, ENVY_CTL0x00, ENVY_CTL_RESET0x80 | ENVY_CTL_NATIVE0x01);
1419 delay(200)(*delay_func)(200);
1420 envy_ccs_write(sc, ENVY_CTL0x00, ENVY_CTL_NATIVE0x01);
1421 delay(200)(*delay_func)(200);
1422
1423 /*
1424 * read EEPROM using i2c device or from a static array
1425 */
1426 if (sc->card->eeprom == NULL((void *)0)) {
1427 for (i = 0; i < ENVY_EEPROM_MAXSZ32; i++) {
1428 sc->eeprom[i] = envy_i2c_read(sc, ENVY_I2C_DEV_EEPROM0x50, i);
1429 }
1430#ifdef ENVY_DEBUG
1431 printf("%s: eeprom: ", DEVNAME(sc)((sc)->dev.dv_xname));
1432 for (i = 0; i < ENVY_EEPROM_MAXSZ32; i++) {
1433 printf(" %02x", (unsigned)sc->eeprom[i]);
1434 }
1435 printf("\n");
1436#endif
1437 } else
1438 memcpy(sc->eeprom, sc->card->eeprom, ENVY_EEPROM_MAXSZ)__builtin_memcpy((sc->eeprom), (sc->card->eeprom), (
32))
;
1439
1440 /*
1441 * write EEPROM values to corresponding registers
1442 */
1443 if (sc->isht) {
1444 envy_ccs_write(sc, ENVY_CCS_CONF0x04,
1445 sc->eeprom[ENVY_EEPROM_CONF6]);
1446 envy_ccs_write(sc, ENVY_CCS_ACLINK0x05,
1447 sc->eeprom[ENVY_EEPROM_ACLINK7]);
1448 envy_ccs_write(sc, ENVY_CCS_I2S0x06,
1449 sc->eeprom[ENVY_EEPROM_I2S8]);
1450 envy_ccs_write(sc, ENVY_CCS_SPDIF0x07,
1451 sc->eeprom[ENVY_EEPROM_SPDIF9]);
1452 } else {
1453 pci_conf_write(sc->pci_pc, sc->pci_tag, ENVY_CONF0x60,
1454 sc->eeprom[ENVY_EEPROM_CONF6] |
1455 (sc->eeprom[ENVY_EEPROM_ACLINK7] << 8) |
1456 (sc->eeprom[ENVY_EEPROM_I2S8] << 16) |
1457 (sc->eeprom[ENVY_EEPROM_SPDIF9] << 24));
1458 }
1459
1460 envy_gpio_setmask(sc, envy_eeprom_gpioxxx(sc, ENVY_EEPROM_GPIOMASK(sc)((sc)->isht ? 13 : 10)));
1461 envy_gpio_setdir(sc, envy_eeprom_gpioxxx(sc, ENVY_EEPROM_GPIODIR(sc)((sc)->isht ? 10 : 12)));
1462 envy_gpio_setstate(sc, envy_eeprom_gpioxxx(sc, ENVY_EEPROM_GPIOST(sc)((sc)->isht ? 16 : 11)));
1463
1464 DPRINTF("%s: gpio_mask = %02x\n", DEVNAME(sc),do {} while(0)
1465 envy_gpio_getmask(sc))do {} while(0);
1466 DPRINTF("%s: gpio_dir = %02x\n", DEVNAME(sc),do {} while(0)
1467 envy_gpio_getdir(sc))do {} while(0);
1468 DPRINTF("%s: gpio_state = %02x\n", DEVNAME(sc),do {} while(0)
1469 envy_gpio_getstate(sc))do {} while(0);
1470
1471 if (sc->isht) {
1472 /*
1473 * set water marks so we get an interrupt for each byte
1474 */
1475 envy_ccs_write(sc, ENVY_CCS_MIDIWAT0x0e, 1);
1476 envy_ccs_write(sc, ENVY_CCS_MIDIWAT0x0e, 1 | ENVY_CCS_MIDIWAT_RX0x20);
1477 }
1478
1479 /*
1480 * switch to UART mode
1481 */
1482 envy_ccs_write(sc, ENVY_CCS_MIDISTAT00x0d, 0xff);
1483 envy_midi_wait(sc);
1484 envy_ccs_write(sc, ENVY_CCS_MIDISTAT00x0d, ENVY_MIDISTAT_UART0x3f);
1485 envy_midi_wait(sc);
1486 if (!sc->isht)
1487 (void)envy_ccs_read(sc, ENVY_CCS_MIDIDATA00x0c);
1488
1489 /*
1490 * clear all interrupts and unmask used ones
1491 */
1492 envy_ccs_write(sc, ENVY_CCS_INTSTAT0x02, 0xff);
1493 reg = ~ENVY_CCS_INT_MT0x10;
1494 if (sc->midi_isopen)
1495 reg &= ~ENVY_CCS_INT_MIDI00x80;
1496 envy_ccs_write(sc, ENVY_CCS_INTMASK0x01, ~ENVY_CCS_INT_MT0x10);
1497 if (sc->isht) {
1498 envy_mt_write_1(sc, ENVY_MT_NSTREAM0x19, 4 - sc->card->noch / 2);
1499 envy_mt_write_1(sc, ENVY_MT_IMASK3, ~(ENVY_MT_IMASK_PDMA00x1 |
1500 ENVY_MT_IMASK_RDMA00x2 | ENVY_MT_IMASK_ERR0x8));
1501 }
1502 sc->iactive = 0;
1503 sc->oactive = 0;
1504 sc->card->init(sc);
1505}
1506
1507int
1508envy_lineout_getsrc(struct envy_softc *sc, int out)
1509{
1510 int reg, shift, src;
1511
1512 if (sc->isht) {
1513 reg = envy_mt_read_4(sc, ENVY_MT_HTSRC0x2c);
1514 DPRINTF("%s: outsrc=%x\n", DEVNAME(sc), reg)do {} while(0);
1515 shift = 3 * (out / 2) + ((out & 1) ? 20 : 8);
1516 src = (reg >> shift) & ENVY_MT_HTSRC_MASK0x07;
1517 if (src == ENVY_MT_HTSRC_DMA0x00) {
1518 return ENVY_MIX_OUTSRC_DMA10;
1519 } else {
1520 src -= ENVY_MT_HTSRC_LINE0x02;
1521 return ENVY_MIX_OUTSRC_LINEIN0 + src;
1522 }
1523 }
1524
1525 reg = envy_mt_read_2(sc, ENVY_MT_OUTSRC0x30);
1526 DPRINTF("%s: outsrc=%x\n", DEVNAME(sc), reg)do {} while(0);
1527 shift = (out & 1) ? (out & ~1) + 8 : out;
1528 src = (reg >> shift) & 3;
1529 if (src == ENVY_MT_OUTSRC_DMA0x00) {
1530 return ENVY_MIX_OUTSRC_DMA10;
1531 } else if (src == ENVY_MT_OUTSRC_MON0x01) {
1532 return ENVY_MIX_OUTSRC_MON11;
1533 }
1534 reg = envy_mt_read_4(sc, ENVY_MT_INSEL0x34);
1535 DPRINTF("%s: insel=%x\n", DEVNAME(sc), reg)do {} while(0);
1536 reg = (reg >> (out * 4)) & 0xf;
1537 if (src == ENVY_MT_OUTSRC_LINE0x02)
1538 return ENVY_MIX_OUTSRC_LINEIN0 + (reg & 7);
1539 else
1540 return ENVY_MIX_OUTSRC_SPDIN8 + (reg >> 3);
1541}
1542
1543void
1544envy_lineout_setsrc(struct envy_softc *sc, int out, int src)
1545{
1546 int reg, shift, mask, sel;
1547
1548 if (sc->isht) {
1549 if (src < ENVY_MIX_OUTSRC_SPDIN8) {
1550 sel = ENVY_MT_HTSRC_LINE0x02;
1551 sel += src;
1552 } else if (src < ENVY_MIX_OUTSRC_DMA10) {
1553 sel = ENVY_MT_HTSRC_SPD0x04;
1554 sel += src - ENVY_MIX_OUTSRC_SPDIN8;
1555 } else {
1556 sel = ENVY_MT_HTSRC_DMA0x00;
1557 }
1558 shift = 3 * (out / 2) + ((out & 1) ? 20 : 8);
1559 mask = ENVY_MT_HTSRC_MASK0x07 << shift;
1560 reg = envy_mt_read_4(sc, ENVY_MT_HTSRC0x2c);
1561 reg = (reg & ~mask) | (sel << shift);
1562 envy_mt_write_4(sc, ENVY_MT_HTSRC0x2c, reg);
1563 DPRINTF("%s: outsrc <- %x\n", DEVNAME(sc), reg)do {} while(0);
1564 return;
1565 }
1566
1567 if (src < ENVY_MIX_OUTSRC_DMA10) {
1568 /*
1569 * linein and spdin are used as output source so we
1570 * must select the input source channel number
1571 */
1572 if (src < ENVY_MIX_OUTSRC_SPDIN8)
1573 sel = src - ENVY_MIX_OUTSRC_LINEIN0;
1574 else
1575 sel = (src - ENVY_MIX_OUTSRC_SPDIN8) << 3;
1576
1577 shift = out * ENVY_MT_INSEL_BITS0x4;
1578 mask = ENVY_MT_INSEL_MASK((1 << 0x4) - 1) << shift;
1579 reg = envy_mt_read_4(sc, ENVY_MT_INSEL0x34);
1580 reg = (reg & ~mask) | (sel << shift);
1581 envy_mt_write_4(sc, ENVY_MT_INSEL0x34, reg);
1582 DPRINTF("%s: insel <- %x\n", DEVNAME(sc), reg)do {} while(0);
1583 }
1584
1585 /*
1586 * set the lineout route register
1587 */
1588 if (src < ENVY_MIX_OUTSRC_SPDIN8) {
1589 sel = ENVY_MT_OUTSRC_LINE0x02;
1590 } else if (src < ENVY_MIX_OUTSRC_DMA10) {
1591 sel = ENVY_MT_OUTSRC_SPD0x03;
1592 } else if (src == ENVY_MIX_OUTSRC_DMA10) {
1593 sel = ENVY_MT_OUTSRC_DMA0x00;
1594 } else {
1595 sel = ENVY_MT_OUTSRC_MON0x01;
1596 }
1597 shift = (out & 1) ? (out & ~1) + 8 : out;
1598 mask = ENVY_MT_OUTSRC_MASK0x03 << shift;
1599 reg = envy_mt_read_2(sc, ENVY_MT_OUTSRC0x30);
1600 reg = (reg & ~mask) | (sel << shift);
1601 envy_mt_write_2(sc, ENVY_MT_OUTSRC0x30, reg);
1602 DPRINTF("%s: outsrc <- %x\n", DEVNAME(sc), reg)do {} while(0);
1603}
1604
1605
1606int
1607envy_spdout_getsrc(struct envy_softc *sc, int out)
1608{
1609 int reg, src, sel;
1610
1611 reg = envy_mt_read_2(sc, ENVY_MT_SPDROUTE0x32);
1612 DPRINTF("%s: spdroute=%x\n", DEVNAME(sc), reg)do {} while(0);
1613 src = (out == 0) ? reg : reg >> 2;
1614 src &= ENVY_MT_SPDSRC_MASK((1 << 0x02) - 1);
1615 if (src == ENVY_MT_SPDSRC_DMA0x00) {
1616 return ENVY_MIX_OUTSRC_DMA10;
1617 } else if (src == ENVY_MT_SPDSRC_MON0x01) {
1618 return ENVY_MIX_OUTSRC_MON11;
1619 }
1620
1621 sel = (out == 0) ? reg >> 8 : reg >> 12;
1622 sel &= ENVY_MT_SPDSEL_MASK((1 << 0x4) - 1);
1623 if (src == ENVY_MT_SPDSRC_LINE0x02)
1624 return ENVY_MIX_OUTSRC_LINEIN0 + (sel & 7);
1625 else
1626 return ENVY_MIX_OUTSRC_SPDIN8 + (sel >> 3);
1627}
1628
1629void
1630envy_spdout_setsrc(struct envy_softc *sc, int out, int src)
1631{
1632 int reg, shift, mask, sel;
1633
1634 reg = envy_mt_read_2(sc, ENVY_MT_SPDROUTE0x32);
1635 if (src < ENVY_MIX_OUTSRC_DMA10) {
1636 /*
1637 * linein and spdin are used as output source so we
1638 * must select the input source channel number
1639 */
1640 if (src < ENVY_MIX_OUTSRC_SPDIN8)
1641 sel = src - ENVY_MIX_OUTSRC_LINEIN0;
1642 else
1643 sel = (src - ENVY_MIX_OUTSRC_SPDIN8) << 3;
1644
1645 shift = 8 + out * ENVY_MT_SPDSEL_BITS0x4;
1646 mask = ENVY_MT_SPDSEL_MASK((1 << 0x4) - 1) << shift;
1647 reg = (reg & ~mask) | (sel << shift);
1648 }
1649
1650 /*
1651 * set the lineout route register
1652 */
1653 if (src < ENVY_MIX_OUTSRC_SPDIN8) {
1654 sel = ENVY_MT_OUTSRC_LINE0x02;
1655 } else if (src < ENVY_MIX_OUTSRC_DMA10) {
1656 sel = ENVY_MT_OUTSRC_SPD0x03;
1657 } else if (src == ENVY_MIX_OUTSRC_DMA10) {
1658 sel = ENVY_MT_OUTSRC_DMA0x00;
1659 } else {
1660 sel = ENVY_MT_OUTSRC_MON0x01;
1661 }
1662 shift = out * 2;
1663 mask = ENVY_MT_SPDSRC_MASK((1 << 0x02) - 1) << shift;
1664 reg = (reg & ~mask) | (sel << shift);
1665 envy_mt_write_2(sc, ENVY_MT_SPDROUTE0x32, reg);
1666 DPRINTF("%s: spdroute <- %x\n", DEVNAME(sc), reg)do {} while(0);
1667}
1668
1669void
1670envy_mon_getvol(struct envy_softc *sc, int idx, int ch, int *val)
1671{
1672 int reg;
1673
1674 envy_mt_write_2(sc, ENVY_MT_MONIDX0x3a, idx);
1675 reg = envy_mt_read_1(sc, ENVY_MT_MONDATA0x38 + ch);
1676 *val = 0x7f - (reg & 0x7f);
1677}
1678
1679void
1680envy_mon_setvol(struct envy_softc *sc, int idx, int ch, int val)
1681{
1682 int reg;
1683
1684 envy_mt_write_2(sc, ENVY_MT_MONIDX0x3a, idx);
1685 reg = 0x7f - val;
1686 DPRINTF("%s: mon=%d/%d <- %d\n", DEVNAME(sc), reg, ch, val)do {} while(0);
1687 envy_mt_write_1(sc, ENVY_MT_MONDATA0x38 + ch, reg);
1688}
1689
1690int
1691envymatch(struct device *parent, void *match, void *aux)
1692{
1693 return pci_matchbyid((struct pci_attach_args *)aux, envy_matchids,
1694 sizeof(envy_matchids) / sizeof(envy_matchids[0]));
1695}
1696
1697void
1698envyattach(struct device *parent, struct device *self, void *aux)
1699{
1700 struct envy_softc *sc = (struct envy_softc *)self;
1701 struct pci_attach_args *pa = (struct pci_attach_args *)aux;
1702 pci_intr_handle_t ih;
1703 const char *intrstr;
1704 int subid;
1705
1706#if NMIDI1 > 0
1707 sc->midi_isopen = 0;
1708#endif
1709 sc->pci_tag = pa->pa_tag;
1710 sc->pci_pc = pa->pa_pc;
1711 sc->pci_dmat = pa->pa_dmat;
1712 sc->pci_ih = NULL((void *)0);
1713 sc->ibuf.addr = sc->obuf.addr = NULL((void *)0);
1714 sc->ccs_iosz = 0;
1715 sc->mt_iosz = 0;
1716 sc->isht = (PCI_PRODUCT(pa->pa_id)(((pa->pa_id) >> 16) & 0xffff) == PCI_PRODUCT_ICENSEMBLE_VT172X0x1724);
1717
1718 if (pci_mapreg_map(pa, ENVY_CTL_BAR0x10, PCI_MAPREG_TYPE_IO0x00000001, 0,
1719 &sc->ccs_iot, &sc->ccs_ioh, NULL((void *)0), &sc->ccs_iosz, 0)) {
1720 printf(": can't map ctl i/o space\n");
1721 sc->ccs_iosz = 0;
1722 return;
1723 }
1724 if (pci_mapreg_map(pa, ENVY_MT_BAR(sc->isht)((sc->isht) ? 0x14 : 0x1c), PCI_MAPREG_TYPE_IO0x00000001, 0,
1725 &sc->mt_iot, &sc->mt_ioh, NULL((void *)0), &sc->mt_iosz, 0)) {
1726 printf(": can't map mt i/o space\n");
1727 sc->mt_iosz = 0;
1728 return;
1729 }
1730 if (pci_intr_map(pa, &ih)) {
1731 printf(": can't map interrupt\n");
1732 }
1733 intrstr = pci_intr_string(sc->pci_pc, ih);
1734 sc->pci_ih = pci_intr_establish(sc->pci_pc, ih, IPL_AUDIO0xb | IPL_MPSAFE0x100,
1735 envy_intr, sc, sc->dev.dv_xname);
1736 if (sc->pci_ih == NULL((void *)0)) {
1737 printf(": can't establish interrupt");
1738 if (intrstr)
1739 printf(" at %s", intrstr);
1740 printf("\n");
1741 return;
1742 }
1743 printf(": %s\n", intrstr);
1744 subid = pci_conf_read(sc->pci_pc, sc->pci_tag, PCI_SUBVEND_00x2c);
1745 sc->card = sc->isht ? envy_cards_ht : envy_cards;
1746 while (sc->card->subid != subid) {
1747 if (sc->card->subid == 0)
1748 break;
1749 sc->card++;
1750 }
1751 printf("%s: %s, %u inputs, %u outputs\n", DEVNAME(sc)((sc)->dev.dv_xname),
1752 sc->card->name, sc->card->nich, sc->card->noch);
1753 envy_reset(sc);
1754 sc->audio = audio_attach_mi(&envy_hw_if, sc, NULL((void *)0), &sc->dev);
1755#if NMIDI1 > 0
1756 if (sc->card->nmidi > 0 && (!sc->isht ||
1757 sc->eeprom[ENVY_EEPROM_CONF6] & ENVY_CONF_MIDI0x20)) {
1758 sc->midi = midi_attach_mi(&envy_midi_hw_if, sc, &sc->dev);
1759 }
1760#endif
1761}
1762
1763int
1764envydetach(struct device *self, int flags)
1765{
1766 struct envy_softc *sc = (struct envy_softc *)self;
1767
1768 if (sc->pci_ih != NULL((void *)0)) {
1769 pci_intr_disestablish(sc->pci_pc, sc->pci_ih);
1770 sc->pci_ih = NULL((void *)0);
1771 }
1772 if (sc->ccs_iosz) {
1773 bus_space_unmap(sc->ccs_iot, sc->ccs_ioh, sc->ccs_iosz);
1774 }
1775 if (sc->mt_iosz) {
1776 bus_space_unmap(sc->mt_iot, sc->mt_ioh, sc->mt_iosz);
1777 }
1778 return 0;
1779}
1780
1781int
1782envyactivate(struct device *self, int act)
1783{
1784 struct envy_softc *sc = (struct envy_softc *)self;
1785
1786 if (act == DVACT_RESUME4) {
1787 /*
1788 * The audio(4) layer will restore parameters and, if
1789 * needed, start DMA. So we only need to reach the
1790 * same device state as after the audio_attach() call.
1791 */
1792 envy_reset(sc);
1793 }
1794 return config_activate_children(self, act);
1795}
1796
1797int
1798envy_open(void *self, int flags)
1799{
1800 return 0;
1801}
1802
1803void
1804envy_close(void *self)
1805{
1806}
1807
1808void *
1809envy_allocm(void *self, int dir, size_t size, int type, int flags)
1810{
1811 struct envy_softc *sc = (struct envy_softc *)self;
1812 int err, wait;
1813 struct envy_buf *buf;
1814 bus_addr_t dma_addr;
1815
1816 buf = (dir == AUMODE_RECORD0x02) ? &sc->ibuf : &sc->obuf;
1817 if (buf->addr != NULL((void *)0)) {
1818 DPRINTF("%s: multiple alloc, dir = %d\n", DEVNAME(sc), dir)do {} while(0);
1819 return NULL((void *)0);
1820 }
1821 buf->size = size;
1822 wait = (flags & M_NOWAIT0x0002) ? BUS_DMA_NOWAIT0x0001 : BUS_DMA_WAITOK0x0000;
1823
1824#define ENVY_ALIGN4 4
1825#define ENVY_MAXADDR((1 << 28) - 1) ((1 << 28) - 1)
1826
1827 buf->addr = (caddr_t)uvm_km_kmemalloc_pla(kernel_map,
1828 uvm.kernel_object, buf->size, 0, UVM_KMF_NOWAIT0x1, 0,
1829 (paddr_t)ENVY_MAXADDR((1 << 28) - 1), 0, 0, 1);
1830 if (buf->addr == NULL((void *)0)) {
1831 DPRINTF("%s: unable to alloc dma segment\n", DEVNAME(sc))do {} while(0);
1832 goto err_ret;
1833 }
1834 err = bus_dmamap_create(sc->pci_dmat, buf->size, 1, buf->size, 0,(*(sc->pci_dmat)->_dmamap_create)((sc->pci_dmat), (buf
->size), (1), (buf->size), (0), (wait), (&buf->map
))
1835 wait, &buf->map)(*(sc->pci_dmat)->_dmamap_create)((sc->pci_dmat), (buf
->size), (1), (buf->size), (0), (wait), (&buf->map
))
;
1836 if (err) {
1837 DPRINTF("%s: dmamap_create: failed %d\n", DEVNAME(sc), err)do {} while(0);
1838 goto err_unmap;
1839 }
1840 err = bus_dmamap_load(sc->pci_dmat, buf->map, buf->addr,(*(sc->pci_dmat)->_dmamap_load)((sc->pci_dmat), (buf
->map), (buf->addr), (buf->size), (((void *)0)), (wait
))
1841 buf->size, NULL, wait)(*(sc->pci_dmat)->_dmamap_load)((sc->pci_dmat), (buf
->map), (buf->addr), (buf->size), (((void *)0)), (wait
))
;
1842 if (err) {
1843 DPRINTF("%s: dmamap_load: failed %d\n", DEVNAME(sc), err)do {} while(0);
1844 goto err_destroy;
1845 }
1846 dma_addr = buf->map->dm_segs[0].ds_addr;
1847 DPRINTF("%s: allocated %zd bytes dir=%d, ka=%p, da=%lx\n", DEVNAME(sc),do {} while(0)
1848 buf->size, dir, buf->addr, dma_addr)do {} while(0);
1849 if (!sc->isht && (dma_addr & ~ENVY_MAXADDR((1 << 28) - 1))) {
1850 printf("%s: DMA address beyond 0x10000000\n", DEVNAME(sc)((sc)->dev.dv_xname));
1851 goto err_unload;
1852 }
1853 return buf->addr;
1854 err_unload:
1855 bus_dmamap_unload(sc->pci_dmat, buf->map)(*(sc->pci_dmat)->_dmamap_unload)((sc->pci_dmat), (buf
->map))
;
1856 err_destroy:
1857 bus_dmamap_destroy(sc->pci_dmat, buf->map)(*(sc->pci_dmat)->_dmamap_destroy)((sc->pci_dmat), (
buf->map))
;
1858 err_unmap:
1859 uvm_km_free(kernel_map, (vaddr_t)buf->addr, buf->size);
1860 err_ret:
1861 return NULL((void *)0);
1862}
1863
1864void
1865envy_freem(void *self, void *addr, int type)
1866{
1867 struct envy_buf *buf;
1868 struct envy_softc *sc = (struct envy_softc *)self;
1869 int dir;
1870
1871 if (sc->ibuf.addr == addr) {
1872 buf = &sc->ibuf;
1873 dir = AUMODE_RECORD0x02;
Value stored to 'dir' is never read
1874 } else if (sc->obuf.addr == addr) {
1875 buf = &sc->obuf;
1876 dir = AUMODE_PLAY0x01;
1877 } else {
1878 DPRINTF("%s: no buf to free\n", DEVNAME(sc))do {} while(0);
1879 return;
1880 }
1881 bus_dmamap_unload(sc->pci_dmat, buf->map)(*(sc->pci_dmat)->_dmamap_unload)((sc->pci_dmat), (buf
->map))
;
1882 bus_dmamap_destroy(sc->pci_dmat, buf->map)(*(sc->pci_dmat)->_dmamap_destroy)((sc->pci_dmat), (
buf->map))
;
1883 uvm_km_free(kernel_map, (vaddr_t)&buf->addr, buf->size);
1884 buf->addr = NULL((void *)0);
1885 DPRINTF("%s: freed buffer (mode=%d)\n", DEVNAME(sc), dir)do {} while(0);
1886}
1887
1888int
1889envy_set_params(void *self, int setmode, int usemode,
1890 struct audio_params *p, struct audio_params *r)
1891{
1892 struct envy_softc *sc = (struct envy_softc *)self;
1893 int i, rate, reg;
1894
1895 if (setmode == 0)
1896 return 0;
1897 if (setmode == (AUMODE_PLAY0x01 | AUMODE_RECORD0x02) &&
1898 p->sample_rate != r->sample_rate) {
1899 DPRINTF("%s: play/rec rates mismatch\n", DEVNAME(sc))do {} while(0);
1900 r->sample_rate = p->sample_rate;
1901 }
1902
1903 rate = (setmode & AUMODE_PLAY0x01) ? p->sample_rate : r->sample_rate;
1904
1905 /* only HT model supports rates above 96kHz */
1906 if (!sc->isht && rate > 96000)
1907 rate = 96000;
1908
1909 for (i = 0; envy_rates[i].rate < rate; i++) {
1910 if (envy_rates[i].rate == -1) {
1911 i--;
1912 DPRINTF("%s: rate: %d -> %d\n", DEVNAME(sc), rate, i)do {} while(0);
1913 break;
1914 }
1915 }
1916
1917 if (sc->isht) {
1918 reg = envy_mt_read_1(sc, ENVY_MT_FMT2);
1919 if (rate > 96000)
1920 reg |= ENVY_MT_FMT_128X0x08;
1921 else
1922 reg &= ~ENVY_MT_FMT_128X0x08;
1923 envy_mt_write_1(sc, ENVY_MT_FMT2, reg);
1924 }
1925
1926 if (sc->card->set_rate)
1927 sc->card->set_rate(sc, rate);
1928
1929 reg = envy_mt_read_1(sc, ENVY_MT_RATE1);
1930 reg &= ~ENVY_MT_RATEMASK0x0f;
1931 reg |= envy_rates[i].reg;
1932 envy_mt_write_1(sc, ENVY_MT_RATE1, reg);
1933
1934 if (setmode & AUMODE_PLAY0x01) {
1935 p->sample_rate = envy_rates[i].rate;
1936 p->encoding = AUDIO_ENCODING_SLINEAR_LE6;
1937 p->precision = 24;
1938 p->bps = 4;
1939 p->msb = 1;
1940 p->channels = sc->isht ? sc->card->noch : ENVY_PCHANS10;
1941 }
1942 if (setmode & AUMODE_RECORD0x02) {
1943 r->sample_rate = envy_rates[i].rate;
1944 r->encoding = AUDIO_ENCODING_SLINEAR_LE6;
1945 r->precision = 24;
1946 r->bps = 4;
1947 r->msb = 1;
1948 r->channels = sc->isht ? sc->card->nich : ENVY_RCHANS12;
1949 }
1950 return 0;
1951}
1952
1953int
1954envy_round_blocksize(void *self, int blksz)
1955{
1956 return (blksz + 0x1f) & ~0x1f;
1957}
1958
1959#ifdef ENVY_DEBUG
1960void
1961envy_pintr(struct envy_softc *sc)
1962{
1963 int i;
1964
1965 if (sc->spurious > 0 || envydebug >= 2) {
1966 printf("%s: spurious = %u, start = %lld.%ld\n",
1967 DEVNAME(sc)((sc)->dev.dv_xname), sc->spurious,
1968 (long long)sc->start_ts.tv_sec, sc->start_ts.tv_nsec);
1969 for (i = 0; i < sc->nintr; i++) {
1970 printf("%lld.%09ld: "
1971 "active=%d/%d pos=%d/%d st=%x/%x, ctl=%x\n",
1972 (long long)sc->intrs[i].ts.tv_sec,
1973 sc->intrs[i].ts.tv_nsec,
1974 sc->intrs[i].iactive,
1975 sc->intrs[i].oactive,
1976 sc->intrs[i].ipos,
1977 sc->intrs[i].opos,
1978 sc->intrs[i].st,
1979 sc->intrs[i].mask,
1980 sc->intrs[i].ctl);
1981 }
1982 }
1983}
1984#endif
1985
1986int
1987envy_intr(void *self)
1988{
1989 struct envy_softc *sc = (struct envy_softc *)self;
1990 unsigned int reg, hwpos, cnt;
1991 int mintr, mstat, mdata;
1992 int st, err, ctl;
1993 int max;
1994
1995 mtx_enter(&audio_lock);
1996 st = envy_mt_read_1(sc, ENVY_MT_INTR0);
1997 mintr = envy_ccs_read(sc, ENVY_CCS_INTSTAT0x02);
1998 if (!(st & ENVY_MT_INTR_ALL0x0b) && !(mintr & ENVY_CCS_INT_MIDI00x80)) {
1999 mtx_leave(&audio_lock);
2000 return 0;
2001 }
2002 if (st & ENVY_MT_INTR_ERR0x08) {
2003 err = envy_mt_read_1(sc, ENVY_MT_ERR0x1a);
2004 envy_mt_write_1(sc, ENVY_MT_ERR0x1a, err);
2005 }
2006 envy_mt_write_1(sc, ENVY_MT_INTR0, st);
2007 envy_ccs_write(sc, ENVY_CCS_INTSTAT0x02, mintr);
2008
2009#ifdef ENVY_DEBUG
2010 if (sc->nintr < ENVY_NINTR) {
2011 sc->intrs[sc->nintr].iactive = sc->iactive;
2012 sc->intrs[sc->nintr].oactive = sc->oactive;
2013 sc->intrs[sc->nintr].st = st;
2014 sc->intrs[sc->nintr].ipos = envy_mt_read_2(sc, ENVY_MT_RBUFSZ0x24);
2015 sc->intrs[sc->nintr].opos = envy_mt_read_2(sc, ENVY_MT_PBUFSZ0x14);
2016 sc->intrs[sc->nintr].ctl = envy_mt_read_1(sc, ENVY_MT_CTL0x18);
2017 sc->intrs[sc->nintr].mask = envy_mt_read_1(sc, ENVY_MT_IMASK3);
2018 nanouptime(&sc->intrs[sc->nintr].ts);
2019 sc->nintr++;
2020 }
2021#endif
2022 if (mintr & ENVY_CCS_INT_MIDI00x80) {
2023 for (max = 128; max > 0; max--) {
2024 mstat = envy_ccs_read(sc, ENVY_CCS_MIDISTAT00x0d);
2025 if (mstat & ENVY_MIDISTAT_IEMPTY(sc)((sc)->isht ? 0x8 : 0x80))
2026 break;
2027 mdata = envy_ccs_read(sc, ENVY_CCS_MIDIDATA00x0c);
2028#if NMIDI1 > 0
2029 if (sc->midi_in)
2030 sc->midi_in(sc->midi_arg, mdata);
2031#endif
2032 }
2033 }
2034 if (st & ENVY_MT_INTR_PACK0x01) {
2035 if (sc->oactive) {
2036 reg = envy_mt_read_2(sc, ENVY_MT_PBUFSZ0x14);
2037 hwpos = sc->obuf.bufsz - 4 * (reg + 1);
2038 if (hwpos >= sc->obuf.bufsz)
2039 hwpos -= sc->obuf.bufsz;
2040 DPRINTFN(2, "%s: play: reg = %u, pos: %u -> %u\n",do {} while(0)
2041 DEVNAME(sc), reg, sc->obuf.swpos, hwpos)do {} while(0);
2042 cnt = 0;
2043 while (hwpos - sc->obuf.swpos >= sc->obuf.blksz) {
2044 sc->ointr(sc->oarg);
2045 sc->obuf.swpos += sc->obuf.blksz;
2046 if (sc->obuf.swpos == sc->obuf.bufsz)
2047 sc->obuf.swpos = 0;
2048 cnt++;
2049 }
2050 if (cnt != 1) {
2051 DPRINTFN(2, "%s: play: %u intrs\n",do {} while(0)
2052 DEVNAME(sc), cnt)do {} while(0);
2053 }
2054 } else {
2055 ctl = envy_mt_read_1(sc, ENVY_MT_CTL0x18);
2056 if (ctl & ENVY_MT_CTL_PSTART0x01) {
2057 envy_mt_write_1(sc,
2058 ENVY_MT_CTL0x18, ctl & ~ENVY_MT_CTL_PSTART0x01);
2059 st &= ~ENVY_MT_INTR_PACK0x01;
2060 sc->obusy = 0;
2061 wakeup(&sc->obusy);
2062 }
2063#ifdef ENVY_DEBUG
2064 else
2065 sc->spurious++;
2066#endif
2067 }
2068 }
2069 if (st & ENVY_MT_INTR_RACK0x02) {
2070 if (sc->iactive) {
2071 reg = envy_mt_read_2(sc, ENVY_MT_RBUFSZ0x24);
2072 hwpos = sc->ibuf.bufsz - 4 * (reg + 1);
2073 if (hwpos >= sc->ibuf.bufsz)
2074 hwpos -= sc->ibuf.bufsz;
2075 DPRINTFN(2, "%s: rec: reg = %u, pos: %u -> %u\n",do {} while(0)
2076 DEVNAME(sc), reg, sc->ibuf.swpos, hwpos)do {} while(0);
2077 cnt = 0;
2078 while (hwpos - sc->ibuf.swpos >= sc->ibuf.blksz) {
2079 sc->iintr(sc->iarg);
2080 sc->ibuf.swpos += sc->ibuf.blksz;
2081 if (sc->ibuf.swpos == sc->ibuf.bufsz)
2082 sc->ibuf.swpos = 0;
2083 cnt++;
2084 }
2085 if (cnt != 1) {
2086 DPRINTFN(2, "%s: rec: %u intrs\n",do {} while(0)
2087 DEVNAME(sc), cnt)do {} while(0);
2088 }
2089 } else {
2090 ctl = envy_mt_read_1(sc, ENVY_MT_CTL0x18);
2091 if (ctl & ENVY_MT_CTL_RSTART(sc)((sc)->isht ? 0x02 : 0x04)) {
2092 envy_mt_write_1(sc,
2093 ENVY_MT_CTL0x18, ctl & ~ENVY_MT_CTL_RSTART(sc)((sc)->isht ? 0x02 : 0x04));
2094 st &= ~ENVY_MT_INTR_RACK0x02;
2095 sc->ibusy = 0;
2096 wakeup(&sc->ibusy);
2097 }
2098#ifdef ENVY_DEBUG
2099 else
2100 sc->spurious++;
2101#endif
2102 }
2103 }
2104 mtx_leave(&audio_lock);
2105 return 1;
2106}
2107
2108int
2109envy_trigger_output(void *self, void *start, void *end, int blksz,
2110 void (*intr)(void *), void *arg, struct audio_params *param)
2111{
2112 struct envy_softc *sc = (struct envy_softc *)self;
2113 size_t bufsz;
2114 int st;
2115
2116 bufsz = (char *)end - (char *)start;
2117#ifdef ENVY_DEBUG
2118 if (blksz % (sc->isht ? sc->card->noch * 4 : ENVY_PFRAME_SIZE(4 * 10)) != 0) {
2119 printf("%s: %d: bad output blksz\n", DEVNAME(sc)((sc)->dev.dv_xname), blksz);
2120 return EINVAL22;
2121 }
2122 if (bufsz % blksz) {
2123 printf("%s: %ld: bad output bufsz\n", DEVNAME(sc)((sc)->dev.dv_xname), bufsz);
2124 return EINVAL22;
2125 }
2126#endif
2127 mtx_enter(&audio_lock);
2128 envy_mt_write_4(sc, ENVY_MT_PADDR0x10, sc->obuf.map->dm_segs[0].ds_addr);
2129 envy_mt_write_2(sc, ENVY_MT_PBUFSZ0x14, bufsz / 4 - 1);
2130 envy_mt_write_2(sc, ENVY_MT_PBLKSZ(sc)((sc)->isht ? 0x1c : 0x16), blksz / 4 - 1);
2131
2132#ifdef ENVY_DEBUG
2133 if (!sc->iactive) {
2134 sc->nintr = 0;
2135 sc->spurious = 0;
2136 nanouptime(&sc->start_ts);
2137 }
2138#endif
2139 sc->obuf.bufsz = bufsz;
2140 sc->obuf.blksz = blksz;
2141 sc->obuf.swpos = 0;
2142 sc->ointr = intr;
2143 sc->oarg = arg;
2144 sc->oactive = 1;
2145 sc->obusy = 1;
2146 st = ENVY_MT_INTR_PACK0x01;
2147 envy_mt_write_1(sc, ENVY_MT_INTR0, st);
2148 st = envy_mt_read_1(sc, ENVY_MT_CTL0x18);
2149 st |= ENVY_MT_CTL_PSTART0x01;
2150 envy_mt_write_1(sc, ENVY_MT_CTL0x18, st);
2151 mtx_leave(&audio_lock);
2152 return 0;
2153}
2154
2155int
2156envy_trigger_input(void *self, void *start, void *end, int blksz,
2157 void (*intr)(void *), void *arg, struct audio_params *param)
2158{
2159 struct envy_softc *sc = (struct envy_softc *)self;
2160 size_t bufsz;
2161 int st;
2162
2163 bufsz = (char *)end - (char *)start;
2164#ifdef ENVY_DEBUG
2165 if (blksz % (sc->isht ? sc->card->nich * 4 : ENVY_RFRAME_SIZE(4 * 12)) != 0) {
2166 printf("%s: %d: bad input blksz\n", DEVNAME(sc)((sc)->dev.dv_xname), blksz);
2167 return EINVAL22;
2168 }
2169 if (bufsz % blksz != 0) {
2170 printf("%s: %ld: bad input bufsz\n", DEVNAME(sc)((sc)->dev.dv_xname), bufsz);
2171 return EINVAL22;
2172 }
2173#endif
2174 mtx_enter(&audio_lock);
2175 envy_mt_write_4(sc, ENVY_MT_RADDR0x20, sc->ibuf.map->dm_segs[0].ds_addr);
2176 envy_mt_write_2(sc, ENVY_MT_RBUFSZ0x24, bufsz / 4 - 1);
2177 envy_mt_write_2(sc, ENVY_MT_RBLKSZ0x26, blksz / 4 - 1);
2178
2179#ifdef ENVY_DEBUG
2180 if (!sc->oactive) {
2181 sc->nintr = 0;
2182 sc->spurious = 0;
2183 nanouptime(&sc->start_ts);
2184 }
2185#endif
2186 sc->ibuf.bufsz = bufsz;
2187 sc->ibuf.blksz = blksz;
2188 sc->ibuf.swpos = 0;
2189 sc->iintr = intr;
2190 sc->iarg = arg;
2191 sc->iactive = 1;
2192 sc->ibusy = 1;
2193 st = ENVY_MT_INTR_RACK0x02;
2194 envy_mt_write_1(sc, ENVY_MT_INTR0, st);
2195 st = envy_mt_read_1(sc, ENVY_MT_CTL0x18);
2196 st |= ENVY_MT_CTL_RSTART(sc)((sc)->isht ? 0x02 : 0x04);
2197 envy_mt_write_1(sc, ENVY_MT_CTL0x18, st);
2198 mtx_leave(&audio_lock);
2199 return 0;
2200}
2201
2202int
2203envy_halt_output(void *self)
2204{
2205 struct envy_softc *sc = (struct envy_softc *)self;
2206 int err;
2207
2208 mtx_enter(&audio_lock);
2209 sc->oactive = 0;
2210 if (sc->obusy) {
2211 err = msleep_nsec(&sc->obusy, &audio_lock, PWAIT32, "envyobus",
2212 SEC_TO_NSEC(4));
2213 if (err)
2214 printf("%s: output DMA halt timeout\n", DEVNAME(sc)((sc)->dev.dv_xname));
2215 }
2216#ifdef ENVY_DEBUG
2217 if (!sc->iactive)
2218 envy_pintr(sc);
2219#endif
2220 mtx_leave(&audio_lock);
2221 return 0;
2222}
2223
2224int
2225envy_halt_input(void *self)
2226{
2227 struct envy_softc *sc = (struct envy_softc *)self;
2228 int err;
2229
2230 mtx_enter(&audio_lock);
2231 sc->iactive = 0;
2232 if (sc->ibusy) {
2233 err = msleep_nsec(&sc->ibusy, &audio_lock, PWAIT32, "envyibus",
2234 SEC_TO_NSEC(4));
2235 if (err)
2236 printf("%s: input DMA halt timeout\n", DEVNAME(sc)((sc)->dev.dv_xname));
2237 }
2238#ifdef ENVY_DEBUG
2239 if (!sc->oactive)
2240 envy_pintr(sc);
2241#endif
2242 mtx_leave(&audio_lock);
2243 return 0;
2244}
2245
2246int
2247envy_query_devinfo(void *self, struct mixer_devinfo *dev)
2248{
2249 struct envy_softc *sc = (struct envy_softc *)self;
2250 int i, n, idx, ndev;
2251 char *classes[] = {
2252 AudioCinputs"inputs", AudioCoutputs"outputs", AudioCmonitor"monitor"
2253 };
2254
2255 if (sc->isac97)
2256 return (sc->codec_if->vtbl->query_devinfo(sc->codec_if, dev));
2257
2258 if (dev->index < 0)
2259 return ENXIO6;
2260
2261 idx = dev->index;
2262 ndev = ENVY_MIX_NCLASS3;
2263 dev->prev = dev->next = AUDIO_MIXER_LAST-1;
2264
2265 /*
2266 * classes
2267 */
2268 if (idx < ndev) {
2269 dev->type = AUDIO_MIXER_CLASS0;
2270 dev->mixer_class = idx;
2271 strlcpy(dev->label.name, classes[idx], MAX_AUDIO_DEV_LEN16);
2272 return 0;
2273 }
2274 idx -= ndev;
2275
2276 /*
2277 * output.lineX_source
2278 */
2279 ndev = sc->card->noch;
2280 if (idx < ndev) {
2281 n = 0;
2282 dev->type = AUDIO_MIXER_ENUM1;
2283 dev->mixer_class = ENVY_MIX_CLASSOUT1;
2284 for (i = 0; i < sc->card->nich; i++) {
2285 dev->un.e.member[n].ord = n;
2286 snprintf(dev->un.e.member[n++].label.name,
2287 MAX_AUDIO_DEV_LEN16, AudioNline"line" "-%d", i);
2288 }
2289 dev->un.e.member[n].ord = n;
2290 snprintf(dev->un.e.member[n++].label.name,
2291 MAX_AUDIO_DEV_LEN16, "play-%d", idx);
2292 if (!sc->isht && idx < 2) {
2293 dev->un.e.member[n].ord = n;
2294 snprintf(dev->un.e.member[n++].label.name,
2295 MAX_AUDIO_DEV_LEN16, "mon-%d", idx);
2296 }
2297 snprintf(dev->label.name, MAX_AUDIO_DEV_LEN16,
2298 AudioNline"line" "-%d_" AudioNsource"source", idx);
2299 dev->un.s.num_mem = n;
2300 return 0;
2301 }
2302 idx -= ndev;
2303
2304 /*
2305 * envy monitor level
2306 */
2307 ndev = sc->isht ? 0 : ENVY_MIX_NMONITOR20;
2308 if (idx < ndev) {
2309 dev->type = AUDIO_MIXER_VALUE3;
2310 dev->mixer_class = ENVY_MIX_CLASSMON2;
2311 dev->un.v.delta = 2;
2312 dev->un.v.num_channels = 1;
2313 snprintf(dev->label.name, MAX_AUDIO_DEV_LEN16,
2314 "%s-%d", idx < 10 ? "play" : "rec", idx % 10);
2315 strlcpy(dev->un.v.units.name, AudioNvolume"volume", MAX_AUDIO_DEV_LEN16);
2316 return 0;
2317 }
2318 idx -= ndev;
2319
2320 /*
2321 * inputs.xxx
2322 */
2323 ndev = sc->card->adc->ndev(sc);
2324 if (idx < ndev) {
2325 sc->card->adc->devinfo(sc, dev, idx);
2326 return 0;
2327 }
2328 idx -= ndev;
2329
2330 /*
2331 * outputs.xxx
2332 */
2333 ndev = sc->card->dac->ndev(sc);
2334 if (idx < ndev) {
2335 sc->card->dac->devinfo(sc, dev, idx);
2336 return 0;
2337 }
2338 return ENXIO6;
2339}
2340
2341int
2342envy_get_port(void *self, struct mixer_ctrl *ctl)
2343{
2344 struct envy_softc *sc = (struct envy_softc *)self;
2345 int val, idx, ndev;
2346
2347 if (sc->isac97)
2348 return (sc->codec_if->vtbl->mixer_get_port(sc->codec_if, ctl));
2349
2350 if (ctl->dev < ENVY_MIX_NCLASS3) {
2351 return EINVAL22;
2352 }
2353
2354 idx = ctl->dev - ENVY_MIX_NCLASS3;
2355 ndev = sc->card->noch;
2356 if (idx < ndev) {
2357 ctl->un.ord = envy_lineout_getsrc(sc, idx);
2358 if (ctl->un.ord >= ENVY_MIX_NOUTSRC10)
2359 ctl->un.ord -= ENVY_MIX_NOUTSRC10 - sc->card->nich;
2360 return 0;
2361 }
2362 idx -= ndev;
2363 ndev = sc->isht ? 0 : ENVY_MIX_NMONITOR20;
2364 if (idx < ndev) {
2365 envy_mon_getvol(sc, idx / 2, idx % 2, &val);
2366 ctl->un.value.num_channels = 1;
2367 ctl->un.value.level[0] = 2 * val;
2368 return 0;
2369 }
2370 idx -= ndev;
2371 ndev = sc->card->adc->ndev(sc);
2372 if (idx < ndev) {
2373 sc->card->adc->get(sc, ctl, idx);
2374 return 0;
2375 }
2376 idx -= ndev;
2377 ndev = sc->card->dac->ndev(sc);
2378 if (idx < ndev) {
2379 sc->card->dac->get(sc, ctl, idx);
2380 return 0;
2381 }
2382 return ENXIO6;
2383}
2384
2385int
2386envy_set_port(void *self, struct mixer_ctrl *ctl)
2387{
2388 struct envy_softc *sc = (struct envy_softc *)self;
2389 int maxsrc, val, idx, ndev;
2390
2391 if (sc->isac97)
2392 return (sc->codec_if->vtbl->mixer_set_port(sc->codec_if, ctl));
2393
2394 if (ctl->dev < ENVY_MIX_NCLASS3) {
2395 return EINVAL22;
2396 }
2397
2398 idx = ctl->dev - ENVY_MIX_NCLASS3;
2399 ndev = sc->card->noch;
2400 if (idx < ndev) {
2401 maxsrc = sc->card->nich + 1;
2402 if (idx < 2)
2403 maxsrc++;
2404 if (ctl->un.ord < 0 || ctl->un.ord >= maxsrc)
2405 return EINVAL22;
2406 if (ctl->un.ord >= sc->card->nich)
2407 ctl->un.ord += ENVY_MIX_NOUTSRC10 - sc->card->nich;
2408 envy_lineout_setsrc(sc, idx, ctl->un.ord);
2409 return 0;
2410 }
2411 idx -= ndev;
2412 ndev = sc->isht ? 0 : ENVY_MIX_NMONITOR20;
2413 if (idx < ndev) {
2414 if (ctl->un.value.num_channels != 1) {
2415 return EINVAL22;
2416 }
2417 val = ctl->un.value.level[0] / 2;
2418 envy_mon_setvol(sc, idx / 2, idx % 2, val);
2419 return 0;
2420 }
2421 idx -= ndev;
2422 ndev = sc->card->adc->ndev(sc);
2423 if (idx < ndev)
2424 return sc->card->adc->set(sc, ctl, idx);
2425 idx -= ndev;
2426 ndev = sc->card->dac->ndev(sc);
2427 if (idx < ndev)
2428 return sc->card->dac->set(sc, ctl, idx);
2429 return ENXIO6;
2430}
2431
2432#if NMIDI1 > 0
2433int
2434envy_midi_open(void *self, int flags,
2435 void (*in)(void *, int),
2436 void (*out)(void *),
2437 void *arg)
2438{
2439 struct envy_softc *sc = (struct envy_softc *)self;
2440 unsigned int i, reg;
2441
2442 /* discard pending data */
2443 for (i = 0; i < 128; i++) {
2444 reg = envy_ccs_read(sc, ENVY_CCS_MIDISTAT00x0d);
2445 if (reg & ENVY_MIDISTAT_IEMPTY(sc)((sc)->isht ? 0x8 : 0x80))
2446 break;
2447 (void)envy_ccs_read(sc, ENVY_CCS_MIDIDATA00x0c);
2448 }
2449#ifdef ENVY_DEBUG
2450 if (i > 0)
2451 DPRINTF("%s: midi: discarded %u bytes\n", DEVNAME(sc), i)do {} while(0);
2452#endif
2453
2454 /* clear pending midi interrupt */
2455 envy_ccs_write(sc, ENVY_CCS_INTSTAT0x02, ENVY_CCS_INT_MIDI00x80);
2456
2457 /* interrupts are disabled, it safe to manipulate these */
2458 sc->midi_in = in;
2459 sc->midi_out = out;
2460 sc->midi_arg = arg;
2461 sc->midi_isopen = 1;
2462
2463 /* enable interrupts */
2464 reg = envy_ccs_read(sc, ENVY_CCS_INTMASK0x01);
2465 reg &= ~ENVY_CCS_INT_MIDI00x80;
2466 envy_ccs_write(sc, ENVY_CCS_INTMASK0x01, reg);
2467 return 0;
2468}
2469
2470void
2471envy_midi_close(void *self)
2472{
2473 struct envy_softc *sc = (struct envy_softc *)self;
2474 unsigned int reg;
2475
2476 /* wait for output fifo to drain */
2477 tsleep_nsec(sc, PWAIT32, "envymid", MSEC_TO_NSEC(100));
2478
2479 /* disable interrupts */
2480 reg = envy_ccs_read(sc, ENVY_CCS_INTMASK0x01);
2481 reg |= ENVY_CCS_INT_MIDI00x80;
2482 envy_ccs_write(sc, ENVY_CCS_INTMASK0x01, reg);
2483
2484 /* interrupts are disabled, it safe to manipulate these */
2485 sc->midi_in = NULL((void *)0);
2486 sc->midi_out = NULL((void *)0);
2487 sc->midi_isopen = 0;
2488}
2489
2490int
2491envy_midi_output(void *self, int data)
2492{
2493 struct envy_softc *sc = (struct envy_softc *)self;
2494 int st;
2495
2496 st = envy_ccs_read(sc, ENVY_CCS_MIDISTAT00x0d);
2497 if (st & ENVY_MIDISTAT_OBUSY(sc)((sc)->isht ? 0x4 : 0x40))
2498 return 0;
2499 envy_ccs_write(sc, ENVY_CCS_MIDIDATA00x0c, data);
2500 return 1;
2501}
2502
2503void
2504envy_midi_getinfo(void *self, struct midi_info *mi)
2505{
2506 mi->props = MIDI_PROP_CAN_INPUT2;
2507 mi->name = "Envy24 MIDI UART";
2508}
2509#endif