Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

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