1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
|
/* $Id: DevHDACommon.h $ */
/** @file
* DevHDACommon.h - Shared HDA device defines / functions.
*/
/*
* Copyright (C) 2016-2019 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* you can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
#ifndef VBOX_INCLUDED_SRC_Audio_DevHDACommon_h
#define VBOX_INCLUDED_SRC_Audio_DevHDACommon_h
#ifndef RT_WITHOUT_PRAGMA_ONCE
# pragma once
#endif
#include "AudioMixer.h"
#include <VBox/log.h> /* LOG_ENABLED */
/** See 302349 p 6.2. */
typedef struct HDAREGDESC
{
/** Register offset in the register space. */
uint32_t offset;
/** Size in bytes. Registers of size > 4 are in fact tables. */
uint32_t size;
/** Readable bits. */
uint32_t readable;
/** Writable bits. */
uint32_t writable;
/** Register descriptor (RD) flags of type HDA_RD_FLAG_.
* These are used to specify the handling (read/write)
* policy of the register. */
uint32_t fFlags;
/** Read callback. */
int (*pfnRead)(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
/** Write callback. */
int (*pfnWrite)(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
/** Index into the register storage array. */
uint32_t mem_idx;
/** Abbreviated name. */
const char *abbrev;
/** Descripton. */
const char *desc;
} HDAREGDESC, *PHDAREGDESC;
/**
* HDA register aliases (HDA spec 3.3.45).
* @remarks Sorted by offReg.
*/
typedef struct HDAREGALIAS
{
/** The alias register offset. */
uint32_t offReg;
/** The register index. */
int idxAlias;
} HDAREGALIAS, *PHDAREGALIAS;
/**
* At the moment we support 4 input + 4 output streams max, which is 8 in total.
* Bidirectional streams are currently *not* supported.
*
* Note: When changing any of those values, be prepared for some saved state
* fixups / trouble!
*/
#define HDA_MAX_SDI 4
#define HDA_MAX_SDO 4
#define HDA_MAX_STREAMS (HDA_MAX_SDI + HDA_MAX_SDO)
AssertCompile(HDA_MAX_SDI <= HDA_MAX_SDO);
/** Number of general registers. */
#define HDA_NUM_GENERAL_REGS 34
/** Number of total registers in the HDA's register map. */
#define HDA_NUM_REGS (HDA_NUM_GENERAL_REGS + (HDA_MAX_STREAMS * 10 /* Each stream descriptor has 10 registers */))
/** Total number of stream tags (channels). Index 0 is reserved / invalid. */
#define HDA_MAX_TAGS 16
/**
* ICH6 datasheet defines limits for FIFOS registers (18.2.39).
* Formula: size - 1
* Other values not listed are not supported.
*/
/** Maximum FIFO size (in bytes). */
#define HDA_FIFO_MAX 256
/** Default timer frequency (in Hz).
*
* Lowering this value can ask for trouble, as backends then can run
* into data underruns.
*
* Note: For handling surround setups (e.g. 5.1 speaker setups) we need
* a higher Hz rate, as the device emulation otherwise will come into
* timing trouble, making the output (DMA reads) crackling. */
#define HDA_TIMER_HZ_DEFAULT 100
/** Default position adjustment (in audio samples).
*
* For snd_hda_intel (Linux guests), the first BDL entry always is being used as
* so-called BDL adjustment, which can vary, and is being used for chipsets which
* misbehave and/or are incorrectly implemented.
*
* The BDL adjustment entry *always* has the IOC (Interrupt on Completion) bit set.
*
* For Intel Baytrail / Braswell implementations the BDL default adjustment is 32 frames, whereas
* for ICH / PCH it's only one (1) frame.
*
* See default_bdl_pos_adj() and snd_hdac_stream_setup_periods() for more information.
*
* By default we apply some simple heuristics in hdaStreamInit().
*/
#define HDA_POS_ADJUST_DEFAULT 0
/** HDA's (fixed) audio frame size in bytes.
* We only support 16-bit stereo frames at the moment. */
#define HDA_FRAME_SIZE_DEFAULT 4
/** Offset of the SD0 register map. */
#define HDA_REG_DESC_SD0_BASE 0x80
/** Turn a short global register name into an memory index and a stringized name. */
#define HDA_REG_IDX(abbrev) HDA_MEM_IND_NAME(abbrev), #abbrev
/** Turns a short stream register name into an memory index and a stringized name. */
#define HDA_REG_IDX_STRM(reg, suff) HDA_MEM_IND_NAME(reg ## suff), #reg #suff
/** Same as above for a register *not* stored in memory. */
#define HDA_REG_IDX_NOMEM(abbrev) 0, #abbrev
extern const HDAREGDESC g_aHdaRegMap[HDA_NUM_REGS];
/**
* NB: Register values stored in memory (au32Regs[]) are indexed through
* the HDA_RMX_xxx macros (also HDA_MEM_IND_NAME()). On the other hand, the
* register descriptors in g_aHdaRegMap[] are indexed through the
* HDA_REG_xxx macros (also HDA_REG_IND_NAME()).
*
* The au32Regs[] layout is kept unchanged for saved state
* compatibility.
*/
/* Registers */
#define HDA_REG_IND_NAME(x) HDA_REG_##x
#define HDA_MEM_IND_NAME(x) HDA_RMX_##x
#define HDA_REG_IND(pThis, x) ((pThis)->au32Regs[g_aHdaRegMap[x].mem_idx])
#define HDA_REG(pThis, x) (HDA_REG_IND((pThis), HDA_REG_IND_NAME(x)))
#define HDA_REG_GCAP 0 /* Range 0x00 - 0x01 */
#define HDA_RMX_GCAP 0
/**
* GCAP HDASpec 3.3.2 This macro encodes the following information about HDA in a compact manner:
*
* oss (15:12) - Number of output streams supported.
* iss (11:8) - Number of input streams supported.
* bss (7:3) - Number of bidirectional streams supported.
* bds (2:1) - Number of serial data out (SDO) signals supported.
* b64sup (0) - 64 bit addressing supported.
*/
#define HDA_MAKE_GCAP(oss, iss, bss, bds, b64sup) \
( (((oss) & 0xF) << 12) \
| (((iss) & 0xF) << 8) \
| (((bss) & 0x1F) << 3) \
| (((bds) & 0x3) << 2) \
| ((b64sup) & 1))
#define HDA_REG_VMIN 1 /* 0x02 */
#define HDA_RMX_VMIN 1
#define HDA_REG_VMAJ 2 /* 0x03 */
#define HDA_RMX_VMAJ 2
#define HDA_REG_OUTPAY 3 /* 0x04-0x05 */
#define HDA_RMX_OUTPAY 3
#define HDA_REG_INPAY 4 /* 0x06-0x07 */
#define HDA_RMX_INPAY 4
#define HDA_REG_GCTL 5 /* 0x08-0x0B */
#define HDA_RMX_GCTL 5
#define HDA_GCTL_UNSOL RT_BIT(8) /* Accept Unsolicited Response Enable */
#define HDA_GCTL_FCNTRL RT_BIT(1) /* Flush Control */
#define HDA_GCTL_CRST RT_BIT(0) /* Controller Reset */
#define HDA_REG_WAKEEN 6 /* 0x0C */
#define HDA_RMX_WAKEEN 6
#define HDA_REG_STATESTS 7 /* 0x0E */
#define HDA_RMX_STATESTS 7
#define HDA_STATESTS_SCSF_MASK 0x7 /* State Change Status Flags (6.2.8). */
#define HDA_REG_GSTS 8 /* 0x10-0x11*/
#define HDA_RMX_GSTS 8
#define HDA_GSTS_FSTS RT_BIT(1) /* Flush Status */
#define HDA_REG_OUTSTRMPAY 9 /* 0x18 */
#define HDA_RMX_OUTSTRMPAY 112
#define HDA_REG_INSTRMPAY 10 /* 0x1a */
#define HDA_RMX_INSTRMPAY 113
#define HDA_REG_INTCTL 11 /* 0x20 */
#define HDA_RMX_INTCTL 9
#define HDA_INTCTL_GIE RT_BIT(31) /* Global Interrupt Enable */
#define HDA_INTCTL_CIE RT_BIT(30) /* Controller Interrupt Enable */
/** Bits 0-29 correspond to streams 0-29. */
#define HDA_STRMINT_MASK 0xFF /* Streams 0-7 implemented. Applies to INTCTL and INTSTS. */
#define HDA_REG_INTSTS 12 /* 0x24 */
#define HDA_RMX_INTSTS 10
#define HDA_INTSTS_GIS RT_BIT(31) /* Global Interrupt Status */
#define HDA_INTSTS_CIS RT_BIT(30) /* Controller Interrupt Status */
#define HDA_REG_WALCLK 13 /* 0x30 */
/**NB: HDA_RMX_WALCLK is not defined because the register is not stored in memory. */
/**
* Note: The HDA specification defines a SSYNC register at offset 0x38. The
* ICH6/ICH9 datahseet defines SSYNC at offset 0x34. The Linux HDA driver matches
* the datasheet.
*/
#define HDA_REG_SSYNC 14 /* 0x34 */
#define HDA_RMX_SSYNC 12
#define HDA_REG_CORBLBASE 15 /* 0x40 */
#define HDA_RMX_CORBLBASE 13
#define HDA_REG_CORBUBASE 16 /* 0x44 */
#define HDA_RMX_CORBUBASE 14
#define HDA_REG_CORBWP 17 /* 0x48 */
#define HDA_RMX_CORBWP 15
#define HDA_REG_CORBRP 18 /* 0x4A */
#define HDA_RMX_CORBRP 16
#define HDA_CORBRP_RST RT_BIT(15) /* CORB Read Pointer Reset */
#define HDA_REG_CORBCTL 19 /* 0x4C */
#define HDA_RMX_CORBCTL 17
#define HDA_CORBCTL_DMA RT_BIT(1) /* Enable CORB DMA Engine */
#define HDA_CORBCTL_CMEIE RT_BIT(0) /* CORB Memory Error Interrupt Enable */
#define HDA_REG_CORBSTS 20 /* 0x4D */
#define HDA_RMX_CORBSTS 18
#define HDA_REG_CORBSIZE 21 /* 0x4E */
#define HDA_RMX_CORBSIZE 19
#define HDA_CORBSIZE_SZ_CAP 0xF0
#define HDA_CORBSIZE_SZ 0x3
/** Number of CORB buffer entries. */
#define HDA_CORB_SIZE 256
/** CORB element size (in bytes). */
#define HDA_CORB_ELEMENT_SIZE 4
/** Number of RIRB buffer entries. */
#define HDA_RIRB_SIZE 256
/** RIRB element size (in bytes). */
#define HDA_RIRB_ELEMENT_SIZE 8
#define HDA_REG_RIRBLBASE 22 /* 0x50 */
#define HDA_RMX_RIRBLBASE 20
#define HDA_REG_RIRBUBASE 23 /* 0x54 */
#define HDA_RMX_RIRBUBASE 21
#define HDA_REG_RIRBWP 24 /* 0x58 */
#define HDA_RMX_RIRBWP 22
#define HDA_RIRBWP_RST RT_BIT(15) /* RIRB Write Pointer Reset */
#define HDA_REG_RINTCNT 25 /* 0x5A */
#define HDA_RMX_RINTCNT 23
/** Maximum number of Response Interrupts. */
#define HDA_MAX_RINTCNT 256
#define HDA_REG_RIRBCTL 26 /* 0x5C */
#define HDA_RMX_RIRBCTL 24
#define HDA_RIRBCTL_ROIC RT_BIT(2) /* Response Overrun Interrupt Control */
#define HDA_RIRBCTL_RDMAEN RT_BIT(1) /* RIRB DMA Enable */
#define HDA_RIRBCTL_RINTCTL RT_BIT(0) /* Response Interrupt Control */
#define HDA_REG_RIRBSTS 27 /* 0x5D */
#define HDA_RMX_RIRBSTS 25
#define HDA_RIRBSTS_RIRBOIS RT_BIT(2) /* Response Overrun Interrupt Status */
#define HDA_RIRBSTS_RINTFL RT_BIT(0) /* Response Interrupt Flag */
#define HDA_REG_RIRBSIZE 28 /* 0x5E */
#define HDA_RMX_RIRBSIZE 26
#define HDA_REG_IC 29 /* 0x60 */
#define HDA_RMX_IC 27
#define HDA_REG_IR 30 /* 0x64 */
#define HDA_RMX_IR 28
#define HDA_REG_IRS 31 /* 0x68 */
#define HDA_RMX_IRS 29
#define HDA_IRS_IRV RT_BIT(1) /* Immediate Result Valid */
#define HDA_IRS_ICB RT_BIT(0) /* Immediate Command Busy */
#define HDA_REG_DPLBASE 32 /* 0x70 */
#define HDA_RMX_DPLBASE 30
#define HDA_REG_DPUBASE 33 /* 0x74 */
#define HDA_RMX_DPUBASE 31
#define DPBASE_ADDR_MASK (~(uint64_t)0x7f)
#define HDA_STREAM_REG_DEF(name, num) (HDA_REG_SD##num##name)
#define HDA_STREAM_RMX_DEF(name, num) (HDA_RMX_SD##num##name)
/** Note: sdnum here _MUST_ be stream reg number [0,7]. */
#define HDA_STREAM_REG(pThis, name, sdnum) (HDA_REG_IND((pThis), HDA_REG_SD0##name + (sdnum) * 10))
#define HDA_SD_NUM_FROM_REG(pThis, func, reg) ((reg - HDA_STREAM_REG_DEF(func, 0)) / 10)
/** @todo Condense marcos! */
#define HDA_REG_SD0CTL HDA_NUM_GENERAL_REGS /* 0x80; other streams offset by 0x20 */
#define HDA_RMX_SD0CTL 32
#define HDA_RMX_SD1CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 10)
#define HDA_RMX_SD2CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 20)
#define HDA_RMX_SD3CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 30)
#define HDA_RMX_SD4CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 40)
#define HDA_RMX_SD5CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 50)
#define HDA_RMX_SD6CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 60)
#define HDA_RMX_SD7CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 70)
#define HDA_SDCTL_NUM_MASK 0xF
#define HDA_SDCTL_NUM_SHIFT 20
#define HDA_SDCTL_DIR RT_BIT(19) /* Direction (Bidirectional streams only!) */
#define HDA_SDCTL_TP RT_BIT(18) /* Traffic Priority (PCI Express) */
#define HDA_SDCTL_STRIPE_MASK 0x3
#define HDA_SDCTL_STRIPE_SHIFT 16
#define HDA_SDCTL_DEIE RT_BIT(4) /* Descriptor Error Interrupt Enable */
#define HDA_SDCTL_FEIE RT_BIT(3) /* FIFO Error Interrupt Enable */
#define HDA_SDCTL_IOCE RT_BIT(2) /* Interrupt On Completion Enable */
#define HDA_SDCTL_RUN RT_BIT(1) /* Stream Run */
#define HDA_SDCTL_SRST RT_BIT(0) /* Stream Reset */
#define HDA_REG_SD0STS 35 /* 0x83; other streams offset by 0x20 */
#define HDA_RMX_SD0STS 33
#define HDA_RMX_SD1STS (HDA_STREAM_RMX_DEF(STS, 0) + 10)
#define HDA_RMX_SD2STS (HDA_STREAM_RMX_DEF(STS, 0) + 20)
#define HDA_RMX_SD3STS (HDA_STREAM_RMX_DEF(STS, 0) + 30)
#define HDA_RMX_SD4STS (HDA_STREAM_RMX_DEF(STS, 0) + 40)
#define HDA_RMX_SD5STS (HDA_STREAM_RMX_DEF(STS, 0) + 50)
#define HDA_RMX_SD6STS (HDA_STREAM_RMX_DEF(STS, 0) + 60)
#define HDA_RMX_SD7STS (HDA_STREAM_RMX_DEF(STS, 0) + 70)
#define HDA_SDSTS_FIFORDY RT_BIT(5) /* FIFO Ready */
#define HDA_SDSTS_DESE RT_BIT(4) /* Descriptor Error */
#define HDA_SDSTS_FIFOE RT_BIT(3) /* FIFO Error */
#define HDA_SDSTS_BCIS RT_BIT(2) /* Buffer Completion Interrupt Status */
#define HDA_REG_SD0LPIB 36 /* 0x84; other streams offset by 0x20 */
#define HDA_REG_SD1LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 10) /* 0xA4 */
#define HDA_REG_SD2LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 20) /* 0xC4 */
#define HDA_REG_SD3LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 30) /* 0xE4 */
#define HDA_REG_SD4LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 40) /* 0x104 */
#define HDA_REG_SD5LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 50) /* 0x124 */
#define HDA_REG_SD6LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 60) /* 0x144 */
#define HDA_REG_SD7LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 70) /* 0x164 */
#define HDA_RMX_SD0LPIB 34
#define HDA_RMX_SD1LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 10)
#define HDA_RMX_SD2LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 20)
#define HDA_RMX_SD3LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 30)
#define HDA_RMX_SD4LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 40)
#define HDA_RMX_SD5LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 50)
#define HDA_RMX_SD6LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 60)
#define HDA_RMX_SD7LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 70)
#define HDA_REG_SD0CBL 37 /* 0x88; other streams offset by 0x20 */
#define HDA_RMX_SD0CBL 35
#define HDA_RMX_SD1CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 10)
#define HDA_RMX_SD2CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 20)
#define HDA_RMX_SD3CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 30)
#define HDA_RMX_SD4CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 40)
#define HDA_RMX_SD5CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 50)
#define HDA_RMX_SD6CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 60)
#define HDA_RMX_SD7CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 70)
#define HDA_REG_SD0LVI 38 /* 0x8C; other streams offset by 0x20 */
#define HDA_RMX_SD0LVI 36
#define HDA_RMX_SD1LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 10)
#define HDA_RMX_SD2LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 20)
#define HDA_RMX_SD3LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 30)
#define HDA_RMX_SD4LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 40)
#define HDA_RMX_SD5LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 50)
#define HDA_RMX_SD6LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 60)
#define HDA_RMX_SD7LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 70)
#define HDA_REG_SD0FIFOW 39 /* 0x8E; other streams offset by 0x20 */
#define HDA_RMX_SD0FIFOW 37
#define HDA_RMX_SD1FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 10)
#define HDA_RMX_SD2FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 20)
#define HDA_RMX_SD3FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 30)
#define HDA_RMX_SD4FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 40)
#define HDA_RMX_SD5FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 50)
#define HDA_RMX_SD6FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 60)
#define HDA_RMX_SD7FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 70)
/*
* ICH6 datasheet defined limits for FIFOW values (18.2.38).
*/
#define HDA_SDFIFOW_8B 0x2
#define HDA_SDFIFOW_16B 0x3
#define HDA_SDFIFOW_32B 0x4
#define HDA_REG_SD0FIFOS 40 /* 0x90; other streams offset by 0x20 */
#define HDA_RMX_SD0FIFOS 38
#define HDA_RMX_SD1FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 10)
#define HDA_RMX_SD2FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 20)
#define HDA_RMX_SD3FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 30)
#define HDA_RMX_SD4FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 40)
#define HDA_RMX_SD5FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 50)
#define HDA_RMX_SD6FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 60)
#define HDA_RMX_SD7FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 70)
#define HDA_SDIFIFO_120B 0x77 /* 8-, 16-, 20-, 24-, 32-bit Input Streams */
#define HDA_SDIFIFO_160B 0x9F /* 20-, 24-bit Input Streams Streams */
#define HDA_SDOFIFO_16B 0x0F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
#define HDA_SDOFIFO_32B 0x1F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
#define HDA_SDOFIFO_64B 0x3F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
#define HDA_SDOFIFO_128B 0x7F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
#define HDA_SDOFIFO_192B 0xBF /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
#define HDA_SDOFIFO_256B 0xFF /* 20-, 24-bit Output Streams */
#define HDA_REG_SD0FMT 41 /* 0x92; other streams offset by 0x20 */
#define HDA_RMX_SD0FMT 39
#define HDA_RMX_SD1FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 10)
#define HDA_RMX_SD2FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 20)
#define HDA_RMX_SD3FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 30)
#define HDA_RMX_SD4FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 40)
#define HDA_RMX_SD5FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 50)
#define HDA_RMX_SD6FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 60)
#define HDA_RMX_SD7FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 70)
#define HDA_REG_SD0BDPL 42 /* 0x98; other streams offset by 0x20 */
#define HDA_RMX_SD0BDPL 40
#define HDA_RMX_SD1BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 10)
#define HDA_RMX_SD2BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 20)
#define HDA_RMX_SD3BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 30)
#define HDA_RMX_SD4BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 40)
#define HDA_RMX_SD5BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 50)
#define HDA_RMX_SD6BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 60)
#define HDA_RMX_SD7BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 70)
#define HDA_REG_SD0BDPU 43 /* 0x9C; other streams offset by 0x20 */
#define HDA_RMX_SD0BDPU 41
#define HDA_RMX_SD1BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 10)
#define HDA_RMX_SD2BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 20)
#define HDA_RMX_SD3BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 30)
#define HDA_RMX_SD4BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 40)
#define HDA_RMX_SD5BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 50)
#define HDA_RMX_SD6BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 60)
#define HDA_RMX_SD7BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 70)
#define HDA_CODEC_CAD_SHIFT 28
/** Encodes the (required) LUN into a codec command. */
#define HDA_CODEC_CMD(cmd, lun) ((cmd) | (lun << HDA_CODEC_CAD_SHIFT))
#define HDA_SDFMT_NON_PCM_SHIFT 15
#define HDA_SDFMT_NON_PCM_MASK 0x1
#define HDA_SDFMT_BASE_RATE_SHIFT 14
#define HDA_SDFMT_BASE_RATE_MASK 0x1
#define HDA_SDFMT_MULT_SHIFT 11
#define HDA_SDFMT_MULT_MASK 0x7
#define HDA_SDFMT_DIV_SHIFT 8
#define HDA_SDFMT_DIV_MASK 0x7
#define HDA_SDFMT_BITS_SHIFT 4
#define HDA_SDFMT_BITS_MASK 0x7
#define HDA_SDFMT_CHANNELS_MASK 0xF
#define HDA_SDFMT_TYPE RT_BIT(15)
#define HDA_SDFMT_TYPE_PCM (0)
#define HDA_SDFMT_TYPE_NON_PCM (1)
#define HDA_SDFMT_BASE RT_BIT(14)
#define HDA_SDFMT_BASE_48KHZ (0)
#define HDA_SDFMT_BASE_44KHZ (1)
#define HDA_SDFMT_MULT_1X (0)
#define HDA_SDFMT_MULT_2X (1)
#define HDA_SDFMT_MULT_3X (2)
#define HDA_SDFMT_MULT_4X (3)
#define HDA_SDFMT_DIV_1X (0)
#define HDA_SDFMT_DIV_2X (1)
#define HDA_SDFMT_DIV_3X (2)
#define HDA_SDFMT_DIV_4X (3)
#define HDA_SDFMT_DIV_5X (4)
#define HDA_SDFMT_DIV_6X (5)
#define HDA_SDFMT_DIV_7X (6)
#define HDA_SDFMT_DIV_8X (7)
#define HDA_SDFMT_8_BIT (0)
#define HDA_SDFMT_16_BIT (1)
#define HDA_SDFMT_20_BIT (2)
#define HDA_SDFMT_24_BIT (3)
#define HDA_SDFMT_32_BIT (4)
#define HDA_SDFMT_CHAN_MONO (0)
#define HDA_SDFMT_CHAN_STEREO (1)
/** Emits a SDnFMT register format.
* Also being used in the codec's converter format. */
#define HDA_SDFMT_MAKE(_afNonPCM, _aBaseRate, _aMult, _aDiv, _aBits, _aChan) \
( (((_afNonPCM) & HDA_SDFMT_NON_PCM_MASK) << HDA_SDFMT_NON_PCM_SHIFT) \
| (((_aBaseRate) & HDA_SDFMT_BASE_RATE_MASK) << HDA_SDFMT_BASE_RATE_SHIFT) \
| (((_aMult) & HDA_SDFMT_MULT_MASK) << HDA_SDFMT_MULT_SHIFT) \
| (((_aDiv) & HDA_SDFMT_DIV_MASK) << HDA_SDFMT_DIV_SHIFT) \
| (((_aBits) & HDA_SDFMT_BITS_MASK) << HDA_SDFMT_BITS_SHIFT) \
| ( (_aChan) & HDA_SDFMT_CHANNELS_MASK))
/** Interrupt on completion (IOC) flag. */
#define HDA_BDLE_FLAG_IOC RT_BIT(0)
/** The HDA controller. */
typedef struct HDASTATE *PHDASTATE;
/** The HDA stream. */
typedef struct HDASTREAM *PHDASTREAM;
typedef struct HDAMIXERSINK *PHDAMIXERSINK;
/**
* Internal state of a Buffer Descriptor List Entry (BDLE),
* needed to keep track of the data needed for the actual device
* emulation.
*/
typedef struct HDABDLESTATE
{
/** Own index within the BDL (Buffer Descriptor List). */
uint32_t u32BDLIndex;
/** Number of bytes below the stream's FIFO watermark (SDFIFOW).
* Used to check if we need fill up the FIFO again. */
uint32_t cbBelowFIFOW;
/** Current offset in DMA buffer (in bytes).*/
uint32_t u32BufOff;
uint32_t Padding;
} HDABDLESTATE, *PHDABDLESTATE;
/**
* BDL description structure.
* Do not touch this, as this must match to the HDA specs.
*/
typedef struct HDABDLEDESC
{
/** Starting address of the actual buffer. Must be 128-bit aligned. */
uint64_t u64BufAddr;
/** Size of the actual buffer (in bytes). */
uint32_t u32BufSize;
/** Bit 0: Interrupt on completion; the controller will generate
* an interrupt when the last byte of the buffer has been
* fetched by the DMA engine.
*
* Rest is reserved for further use and must be 0. */
uint32_t fFlags;
} HDABDLEDESC, *PHDABDLEDESC;
AssertCompileSize(HDABDLEDESC, 16); /* Always 16 byte. Also must be aligned on 128-byte boundary. */
/**
* Buffer Descriptor List Entry (BDLE) (3.6.3).
*/
typedef struct HDABDLE
{
/** The actual BDL description. */
HDABDLEDESC Desc;
/** Internal state of this BDLE.
* Not part of the actual BDLE registers. */
HDABDLESTATE State;
} HDABDLE;
AssertCompileSizeAlignment(HDABDLE, 8);
/** Pointer to a buffer descriptor list entry (BDLE). */
typedef HDABDLE *PHDABDLE;
/** @name Object lookup functions.
* @{
*/
#ifdef IN_RING3
PHDAMIXERSINK hdaR3GetDefaultSink(PHDASTATE pThis, uint8_t uSD);
#endif
PDMAUDIODIR hdaGetDirFromSD(uint8_t uSD);
PHDASTREAM hdaGetStreamFromSD(PHDASTATE pThis, uint8_t uSD);
#ifdef IN_RING3
PHDASTREAM hdaR3GetStreamFromSink(PHDASTATE pThis, PHDAMIXERSINK pSink);
#endif
/** @} */
/** @name Interrupt functions.
* @{
*/
#ifdef LOG_ENABLED
int hdaProcessInterrupt(PHDASTATE pThis, const char *pszSource);
#else
int hdaProcessInterrupt(PHDASTATE pThis);
#endif
/** @} */
/** @name Wall clock (WALCLK) functions.
* @{
*/
uint64_t hdaWalClkGetCurrent(PHDASTATE pThis);
#ifdef IN_RING3
bool hdaR3WalClkSet(PHDASTATE pThis, uint64_t u64WalClk, bool fForce);
#endif
/** @} */
/** @name DMA utility functions.
* @{
*/
#ifdef IN_RING3
int hdaR3DMARead(PHDASTATE pThis, PHDASTREAM pStream, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead);
int hdaR3DMAWrite(PHDASTATE pThis, PHDASTREAM pStream, const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten);
#endif
/** @} */
/** @name Register functions.
* @{
*/
uint32_t hdaGetINTSTS(PHDASTATE pThis);
#ifdef IN_RING3
int hdaR3SDFMTToPCMProps(uint16_t u16SDFMT, PPDMAUDIOPCMPROPS pProps);
#endif /* IN_RING3 */
/** @} */
/** @name BDLE (Buffer Descriptor List Entry) functions.
* @{
*/
#ifdef IN_RING3
# ifdef LOG_ENABLED
void hdaR3BDLEDumpAll(PHDASTATE pThis, uint64_t u64BDLBase, uint16_t cBDLE);
# endif
int hdaR3BDLEFetch(PHDASTATE pThis, PHDABDLE pBDLE, uint64_t u64BaseDMA, uint16_t u16Entry);
bool hdaR3BDLEIsComplete(PHDABDLE pBDLE);
bool hdaR3BDLENeedsInterrupt(PHDABDLE pBDLE);
#endif /* IN_RING3 */
/** @} */
/** @name Device timer functions.
* @{
*/
#ifdef IN_RING3
bool hdaR3TimerSet(PHDASTATE pThis, PHDASTREAM pStream, uint64_t u64Expire, bool fForce);
#endif /* IN_RING3 */
/** @} */
#endif /* !VBOX_INCLUDED_SRC_Audio_DevHDACommon_h */
|