ReactOS 0.4.16-dev-2293-g4d8327b
hdac_controller.cpp File Reference
#include "driver.h"
Include dependency graph for hdac_controller.cpp:

Go to the source code of this file.

Macros

#define HDA_RIRB_EX_UNSOL_EV   (1<<4)
 

Functions

NTSTATUS ResetHDAController (PFDO_CONTEXT fdoCtx, BOOLEAN wakeup)
 
NTSTATUS GetHDACapabilities (PFDO_CONTEXT fdoCtx)
 
void HDAInitCorb (PFDO_CONTEXT fdoCtx)
 
void HDAInitRirb (PFDO_CONTEXT fdoCtx)
 
void HDAStartCorb (PFDO_CONTEXT fdoCtx)
 
void HDAStartRirb (PFDO_CONTEXT fdoCtx)
 
NTSTATUS StartHDAController (PFDO_CONTEXT fdoCtx)
 
NTSTATUS StopHDAController (PFDO_CONTEXT fdoCtx)
 
static UINT16 HDACommandAddr (UINT32 cmd)
 
NTSTATUS SendHDACmds (PFDO_CONTEXT fdoCtx, ULONG count, PHDAUDIO_CODEC_TRANSFER CodecTransfer)
 
NTSTATUS RunSingleHDACmd (PFDO_CONTEXT fdoCtx, ULONG val, ULONG *res)
 
static void HDAFlushRIRB (PFDO_CONTEXT fdoCtx)
 
int hda_stream_interrupt (PFDO_CONTEXT fdoCtx, unsigned int status)
 
BOOLEAN NTAPI hda_interrupt (WDFINTERRUPT Interrupt, ULONG MessageID)
 
void NTAPI hda_dpc (WDFINTERRUPT Interrupt, WDFOBJECT AssociatedObject)
 

Macro Definition Documentation

◆ HDA_RIRB_EX_UNSOL_EV

#define HDA_RIRB_EX_UNSOL_EV   (1<<4)

Definition at line 269 of file hdac_controller.cpp.

Function Documentation

◆ GetHDACapabilities()

NTSTATUS GetHDACapabilities ( PFDO_CONTEXT  fdoCtx)

Definition at line 72 of file hdac_controller.cpp.

72 {
73 UINT16 gcap = hda_read16(fdoCtx, GCAP);
74 SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT,
75 "chipset global capabilities = 0x%x\n", gcap);
76
77 fdoCtx->is64BitOK = !!(gcap & 0x1);
78 SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT,
79 "64 bit OK? %d\n", fdoCtx->is64BitOK);
80
81 fdoCtx->hwVersion = (hda_read8(fdoCtx, VMAJ) << 8) | hda_read8(fdoCtx, VMIN);
82
83 fdoCtx->captureStreams = (gcap >> 8) & 0x0f;
84 fdoCtx->playbackStreams = (gcap >> 12) & 0x0f;
85
86 SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT,
87 "streams (cap %d, playback %d)\n", fdoCtx->captureStreams, fdoCtx->playbackStreams);
88
89 fdoCtx->captureIndexOff = 0;
90 fdoCtx->playbackIndexOff = fdoCtx->captureStreams;
91 fdoCtx->numStreams = fdoCtx->captureStreams + fdoCtx->playbackStreams;
92
93 UINT8 corbSize = hda_read8(fdoCtx, CORBSIZE);
94 if (!(corbSize & 0x40)) {
95 return STATUS_DEVICE_FEATURE_NOT_SUPPORTED; //CORB must support 256
96 }
97
98 UINT8 rirbSize = hda_read8(fdoCtx, RIRBSIZE);
99 if (!(rirbSize & 0x40)) {
100 return STATUS_DEVICE_FEATURE_NOT_SUPPORTED; //RIRB must support 256
101 }
102
103 return STATUS_SUCCESS;
104}
unsigned short UINT16
Definition: actypes.h:129
unsigned char UINT8
Definition: actypes.h:128
#define SklHdAudBusPrint(dbglevel, fmt,...)
Definition: driver.h:111
#define STATUS_DEVICE_FEATURE_NOT_SUPPORTED
Definition: ntstatus.h:1137
#define hda_read8(ctx, reg)
Definition: regfuncs.h:53
#define hda_read16(ctx, reg)
Definition: regfuncs.h:56
#define STATUS_SUCCESS
Definition: shellext.h:65
UINT32 playbackStreams
Definition: fdo.h:146
UINT32 captureIndexOff
Definition: fdo.h:143
BOOLEAN is64BitOK
Definition: fdo.h:140
UINT32 numStreams
Definition: fdo.h:147
UINT32 playbackIndexOff
Definition: fdo.h:144
UINT16 hwVersion
Definition: fdo.h:141
UINT32 captureStreams
Definition: fdo.h:145

Referenced by Fdo_EvtDevicePrepareHardware().

◆ hda_dpc()

void NTAPI hda_dpc ( WDFINTERRUPT  Interrupt,
WDFOBJECT  AssociatedObject 
)

Definition at line 415 of file hdac_controller.cpp.

418 {
420
422 PFDO_CONTEXT fdoCtx = Fdo_GetContext(Device);
423
424 for (UINT32 i = 0; i < fdoCtx->numStreams; i++) {
425 PHDAC_STREAM stream = &fdoCtx->streams[i];
426 if (stream->irqReceived) {
427 stream->irqReceived = FALSE;
428
429 for (int j = 0; j < MAX_NOTIF_EVENTS; j++) {
430 if (stream->registeredCallbacks[j].InUse) {
431 LARGE_INTEGER unknownVal = { 0 };
432 KeQuerySystemTime(&unknownVal);
433 stream->registeredCallbacks[j].NotificationCallback(stream->registeredCallbacks[j].CallbackContext, unknownVal);
434 }
435 }
436
437 for (int j = 0; j < MAX_NOTIF_EVENTS; j++) {
438 if (stream->registeredEvents[j]) {
439 KeSetEvent(stream->registeredEvents[j], IO_NO_INCREMENT, FALSE);
440 }
441 }
442 }
443 }
444
445 if (fdoCtx->processRirb) {
446 fdoCtx->processRirb = FALSE;
447 HDAFlushRIRB(fdoCtx);
448 }
449}
#define FALSE
Definition: types.h:117
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
#define MAX_NOTIF_EVENTS
Definition: fdo.h:17
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
static void HDAFlushRIRB(PFDO_CONTEXT fdoCtx)
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
BOOL processRirb
Definition: fdo.h:165
PHDAC_STREAM streams
Definition: fdo.h:149
Definition: parse.h:23
uint32_t UINT32
Definition: typedefs.h:59
_Must_inspect_result_ _In_ WDFDEVICE Device
Definition: wdfchildlist.h:474
FORCEINLINE WDFDEVICE WdfInterruptGetDevice(_In_ WDFINTERRUPT Interrupt)
Definition: wdfinterrupt.h:721
_In_ WDFOBJECT AssociatedObject
Definition: wdfinterrupt.h:132
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_INTERRUPT_CONFIG _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFINTERRUPT * Interrupt
Definition: wdfinterrupt.h:379
#define IO_NO_INCREMENT
Definition: iotypes.h:598

Referenced by Fdo_Initialize().

◆ hda_interrupt()

BOOLEAN NTAPI hda_interrupt ( WDFINTERRUPT  Interrupt,
ULONG  MessageID 
)

Definition at line 374 of file hdac_controller.cpp.

376 {
378
380 PFDO_CONTEXT fdoCtx = Fdo_GetContext(Device);
381
382 BOOLEAN handled = FALSE;
383
384 if (fdoCtx->dspInterruptCallback) {
385 handled = (BOOLEAN)fdoCtx->dspInterruptCallback(fdoCtx->dspInterruptContext);
386 }
387
388 if (!fdoCtx->ControllerEnabled)
389 return handled;
390
391 UINT32 status = hda_read32(fdoCtx, INTSTS);
392 if (status == 0 || status == 0xffffffff)
393 return handled;
394
395 handled = TRUE;
396
397 if (hda_stream_interrupt(fdoCtx, status)) {
399 }
400
401 status = hda_read8(fdoCtx, RIRBSTS);
402 if (status & RIRB_INT_MASK) {
403 hda_write8(fdoCtx, RIRBSTS, RIRB_INT_MASK);
405 fdoCtx->processRirb = TRUE;
407 }
408 }
409
410 return handled;
411}
unsigned char BOOLEAN
Definition: actypes.h:127
#define TRUE
Definition: types.h:120
#define RIRB_INT_MASK
#define RIRB_INT_RESPONSE
int hda_stream_interrupt(PFDO_CONTEXT fdoCtx, unsigned int status)
#define BOOLEAN
Definition: pedump.c:73
#define hda_read32(ctx, reg)
Definition: regfuncs.h:59
#define hda_write8(ctx, reg, data)
Definition: regfuncs.h:54
PVOID dspInterruptContext
Definition: fdo.h:153
BOOLEAN ControllerEnabled
Definition: fdo.h:138
PADSP_INTERRUPT_CALLBACK dspInterruptCallback
Definition: fdo.h:152
Definition: ps.c:97
_In_ ULONG MessageID
Definition: wdfinterrupt.h:92
FORCEINLINE BOOLEAN WdfInterruptQueueDpcForIsr(_In_ WDFINTERRUPT Interrupt)
Definition: wdfinterrupt.h:414

Referenced by Fdo_Initialize().

◆ hda_stream_interrupt()

int hda_stream_interrupt ( PFDO_CONTEXT  fdoCtx,
unsigned int  status 
)

Definition at line 348 of file hdac_controller.cpp.

348 {
349 int handled = 0;
350 UINT8 sd_status;
351
352 for (UINT32 i = 0; i < fdoCtx->numStreams; i++) {
353 PHDAC_STREAM stream = &fdoCtx->streams[i];
354 if (status & stream->int_sta_mask) {
355 sd_status = stream_read8(stream, SD_STS);
357 handled |= 1 << stream->idx;
358
359 if (sd_status & SD_INT_COMPLETE) {
360 if (stream->isr.IOC && stream->isr.IsrCallback) {
361 stream->isr.IsrCallback(
362 stream->isr.CallbackContext,
363 sd_status);
364 }
365 stream->irqReceived = TRUE;
366 }
367 }
368 }
369 return handled;
370}
#define SD_INT_COMPLETE
#define SD_INT_MASK
#define stream_read8(ctx, reg)
Definition: regfuncs.h:63
#define stream_write8(ctx, reg, data)
Definition: regfuncs.h:64

Referenced by hda_interrupt().

◆ HDACommandAddr()

static UINT16 HDACommandAddr ( UINT32  cmd)
static

Definition at line 203 of file hdac_controller.cpp.

203 {
204 return (cmd >> 28) & 0xF;
205}
Definition: ftp_var.h:139

Referenced by RunSingleHDACmd(), and SendHDACmds().

◆ HDAFlushRIRB()

static void HDAFlushRIRB ( PFDO_CONTEXT  fdoCtx)
static

Definition at line 271 of file hdac_controller.cpp.

271 {
272 UINT16 wp, addr;
273
274 wp = hda_read16(fdoCtx, RIRBWP);
275 if (wp == 0xffff) {
276 //Invalid WP
277 return;
278 }
279
280 if (wp == fdoCtx->rirb.wp)
281 return;
282 fdoCtx->rirb.wp = wp;
283
284 while (fdoCtx->rirb.rp != wp) {
285 fdoCtx->rirb.rp++;
286 fdoCtx->rirb.rp %= HDA_MAX_RIRB_ENTRIES;
287
288 HDAC_RIRB rirb = fdoCtx->rirb.rirbbuf[fdoCtx->rirb.rp];
289
290 addr = rirb.response_ex & 0xf;
291 if (addr >= HDA_MAX_CODECS) {
292 SklHdAudBusPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL,
293 "Unexpected unsolicited response %x: %x\n",
294 rirb.response, rirb.response_ex);
295 }
296 else if (rirb.response_ex & HDA_RIRB_EX_UNSOL_EV) {
297 HDAUDIO_CODEC_RESPONSE response;
298 RtlZeroMemory(&response, sizeof(HDAUDIO_CODEC_RESPONSE));
299
300 response.SDataIn = addr;
301 response.Response = rirb.response;
302 response.IsUnsolicitedResponse = 1;
303 response.IsValid = 1;
304
305 SklHdAudBusPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL,
306 "Unsol response on 0x%x: 0x%x\n", addr, response.Response);
307
308 PPDO_DEVICE_DATA codec = fdoCtx->codecs[addr];
309 if (!codec || codec->FdoContext != fdoCtx)
310 continue;
311
312 UINT Tag = response.Unsolicited.Tag;
314 if (callback.inUse && callback.Routine) {
315 callback.Routine(response, callback.Context);
316 }
317 }
318 else if (InterlockedAdd(&fdoCtx->rirb.cmds[addr], 0)) {
319 PHDAC_CODEC_XFER codecXfer = &fdoCtx->rirb.xfer[addr];
320 if (codecXfer->xfer[0]) {
321 codecXfer->xfer[0]->Input.SDataIn = addr;
322 codecXfer->xfer[0]->Input.Response = rirb.response;
323 codecXfer->xfer[0]->Input.IsValid = 1;
324
325 SklHdAudBusPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL,
326 "Got response on 0x%x for 0x%x: 0x%x\n", addr, codecXfer->xfer[0]->Output.Command, rirb.response);
327 }
328 else {
329 SklHdAudBusPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL,
330 "Got response 0x%x but no xfer!\n", rirb.response);
331 }
332
333 RtlMoveMemory(&codecXfer->xfer[0], &codecXfer->xfer[1], sizeof(PHDAUDIO_CODEC_TRANSFER) * (HDA_MAX_CORB_ENTRIES - 1));
334 codecXfer->xfer[HDA_MAX_CORB_ENTRIES - 1] = NULL;
335 if (!InterlockedDecrement(&fdoCtx->rirb.cmds[addr])) {
336 SklHdAudBusPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, "Empty queue for 0x%x\n", addr);
338 }
339 }
340 else {
341 SklHdAudBusPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL,
342 "Unexpected unsolicited response from address %d %x\n", addr,
343 rirb.response);
344 }
345 }
346}
#define InterlockedDecrement
Definition: armddk.h:52
#define NULL
Definition: types.h:112
#define HDA_MAX_CODECS
Definition: driver.h:41
GLenum const GLvoid * addr
Definition: glext.h:9621
#define HDA_MAX_RIRB_ENTRIES
#define HDA_MAX_CORB_ENTRIES
#define HDA_RIRB_EX_UNSOL_EV
#define InterlockedAdd
Definition: interlocked.h:66
static IPrintDialogCallback callback
Definition: printdlg.c:326
unsigned int UINT
Definition: ndis.h:50
struct _PDO_DEVICE_DATA * codecs[HDA_MAX_CODECS]
Definition: fdo.h:150
HDAC_RB rirb
Definition: fdo.h:164
PHDAUDIO_CODEC_TRANSFER xfer[HDA_MAX_CORB_ENTRIES]
Definition: fdo.h:85
UINT16 wp
Definition: fdo.h:94
PHDAC_RIRB rirbbuf
Definition: fdo.h:91
UINT16 rp
Definition: fdo.h:94
HDAC_CODEC_XFER xfer[HDA_MAX_CODECS]
Definition: fdo.h:97
LONG cmds[HDA_MAX_CODECS]
Definition: fdo.h:95
KEVENT xferEvent[HDA_MAX_CODECS]
Definition: fdo.h:96
Definition: fdo.h:79
UINT32 response_ex
Definition: fdo.h:81
UINT32 response
Definition: fdo.h:80
ULONG IsUnsolicitedResponse
Definition: hdaudio.h:47
struct _HDAUDIO_CODEC_RESPONSE::@2194::@2196::@2198::@2200 Unsolicited
HDAUDIO_CODEC_RESPONSE Input
Definition: hdaudio.h:58
HDAUDIO_CODEC_COMMAND Output
Definition: hdaudio.h:57
PFDO_CONTEXT FdoContext
Definition: buspdo.h:49
CODEC_UNSOLICITED_CALLBACK unsolitCallbacks[MAX_UNSOLICIT_CALLBACKS]
Definition: buspdo.h:53
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
_Must_inspect_result_ _In_ WDFDEVICE _In_ BOOLEAN _In_opt_ PVOID Tag
Definition: wdfdevice.h:4071

Referenced by hda_dpc().

◆ HDAInitCorb()

void HDAInitCorb ( PFDO_CONTEXT  fdoCtx)

Definition at line 106 of file hdac_controller.cpp.

106 {
107 //Set the corb size to 256 entries
108 hda_write8(fdoCtx, CORBSIZE, 0x02);
109
110 //Setup CORB address
111 fdoCtx->corb.buf = (UINT32*)fdoCtx->rb;
112 fdoCtx->corb.addr = MmGetPhysicalAddress(fdoCtx->corb.buf);
113 hda_write32(fdoCtx, CORBLBASE, fdoCtx->corb.addr.LowPart);
114 hda_write32(fdoCtx, CORBUBASE, fdoCtx->corb.addr.HighPart);
115
116 //Set WP and RP
117 fdoCtx->corb.wp = 0;
118 hda_write16(fdoCtx, CORBWP, fdoCtx->corb.wp);
119 hda_write16(fdoCtx, CORBRP, HDA_CORBRP_RST);
120
121 udelay(10); //Delay for 10 us to reset
122
123 hda_write16(fdoCtx, CORBRP, 0);
124}
static void udelay(LONG usec)
Definition: driver.h:80
#define HDA_CORBRP_RST
Definition: hda_registers.h:33
PHYSICAL_ADDRESS NTAPI MmGetPhysicalAddress(IN PVOID Address)
Definition: stubs.c:685
#define hda_write16(ctx, reg, data)
Definition: regfuncs.h:57
#define hda_write32(ctx, reg, data)
Definition: regfuncs.h:60
HDAC_RB corb
Definition: fdo.h:163
UINT8 * rb
Definition: fdo.h:167
PHYSICAL_ADDRESS addr
Definition: fdo.h:93
UINT32 * buf
Definition: fdo.h:90
ULONG LowPart
Definition: typedefs.h:106

Referenced by StartHDAController().

◆ HDAInitRirb()

void HDAInitRirb ( PFDO_CONTEXT  fdoCtx)

Definition at line 126 of file hdac_controller.cpp.

126 {
127 //Set the rirb size to 256 entries
128 hda_write8(fdoCtx, RIRBSIZE, 0x02);
129
130 //Setup RIRB address
131 fdoCtx->rirb.buf = (UINT32*)(fdoCtx->rb + 0x800);
132 fdoCtx->rirb.addr = MmGetPhysicalAddress(fdoCtx->rirb.buf);
133 RtlZeroMemory(fdoCtx->rirb.cmds, sizeof(fdoCtx->rirb.cmds));
134 hda_write32(fdoCtx, RIRBLBASE, fdoCtx->rirb.addr.LowPart);
135 hda_write32(fdoCtx, RIRBUBASE, fdoCtx->rirb.addr.HighPart);
136
137 //Set WP and RP
138 fdoCtx->rirb.rp = 0;
139 hda_write16(fdoCtx, RIRBWP, HDA_RIRBWP_RST);
140
141 //Set interrupt threshold
142 hda_write16(fdoCtx, RINTCNT, 1);
143
144 //Enable Received response reporting
145 hda_write8(fdoCtx, RIRBCTL, HDA_RBCTL_IRQ_EN);
146}
#define HDA_RIRBWP_RST
Definition: hda_registers.h:44
#define HDA_RBCTL_IRQ_EN
Definition: hda_registers.h:47

Referenced by StartHDAController().

◆ HDAStartCorb()

void HDAStartCorb ( PFDO_CONTEXT  fdoCtx)

Definition at line 148 of file hdac_controller.cpp.

148 {
149 UINT8 corbCTL;
150 corbCTL = hda_read8(fdoCtx, CORBCTL);
151 corbCTL |= HDA_CORBCTL_RUN;
152 hda_write8(fdoCtx, CORBCTL, corbCTL);
153}
#define HDA_CORBCTL_RUN
Definition: hda_registers.h:35

Referenced by StartHDAController().

◆ HDAStartRirb()

void HDAStartRirb ( PFDO_CONTEXT  fdoCtx)

Definition at line 155 of file hdac_controller.cpp.

155 {
156 UINT8 rirbCTL;
157 rirbCTL = hda_read8(fdoCtx, RIRBCTL);
158 rirbCTL |= HDA_RBCTL_DMA_EN;
159 hda_write8(fdoCtx, RIRBCTL, rirbCTL);
160}
#define HDA_RBCTL_DMA_EN
Definition: hda_registers.h:48

Referenced by StartHDAController().

◆ ResetHDAController()

NTSTATUS ResetHDAController ( PFDO_CONTEXT  fdoCtx,
BOOLEAN  wakeup 
)

Definition at line 4 of file hdac_controller.cpp.

4 {
5 UINT32 gctl;
6
7 //Clear STATESTS
8 hda_write16(fdoCtx, STATESTS, STATESTS_INT_MASK);
9
10 //Stop all Streams DMA Engine
11 for (UINT32 i = 0; i < fdoCtx->numStreams; i++) {
12 hdac_stream_stop(&fdoCtx->streams[i]);
13 }
14
15 //Stop CORB and RIRB
16 hda_write8(fdoCtx, CORBCTL, 0);
17 hda_write8(fdoCtx, RIRBCTL, 0);
18
19 //Reset DMA position buffer
20 hda_write32(fdoCtx, DPLBASE, 0);
21 hda_write32(fdoCtx, DPUBASE, 0);
22
23 //Reset the controller for at least 100 us
24 gctl = hda_read32(fdoCtx, GCTL);
25 hda_write32(fdoCtx, GCTL, gctl & ~HDA_GCTL_RESET);
26
27 for (int count = 0; count < 1000; count++) {
28 gctl = hda_read32(fdoCtx, GCTL);
29 if (!(gctl & HDA_GCTL_RESET)) {
30 break;
31 }
32 udelay(10);
33 }
34
35 if (gctl & HDA_GCTL_RESET) {
36 SklHdAudBusPrint(DEBUG_LEVEL_ERROR, DBG_INIT, "%s Error: unable to put controller in reset\n", __func__);
38 }
39
40 //If wakeup not requested, leave in reset state
41 if (!wakeup)
42 return STATUS_SUCCESS;
43
44 udelay(100);
45 gctl = hda_read32(fdoCtx, GCTL);
46 hda_write32(fdoCtx, GCTL, gctl | HDA_GCTL_RESET);
47
48 for (int count = 0; count < 1000; count++) {
49 gctl = hda_read32(fdoCtx, GCTL);
50 if (gctl & HDA_GCTL_RESET) {
51 break;
52 }
53 udelay(10);
54 }
55 if (!(gctl & HDA_GCTL_RESET)) {
56 SklHdAudBusPrint(DEBUG_LEVEL_ERROR, DBG_INIT, "%s Error: controller stuck in reset\n", __func__);
58 }
59
60 //Wait for codecs to finish their own reset sequence. Delay from VoodooHDA so it resets properly
61 udelay(1000);
62
63 if (!fdoCtx->codecMask) {
64 fdoCtx->codecMask = hda_read16(fdoCtx, STATESTS);
65 SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT,
66 "codec mask = 0x%lx\n", fdoCtx->codecMask);
67 }
68
69 return STATUS_SUCCESS;
70}
GLuint GLuint GLsizei count
Definition: gl.h:1545
#define STATESTS_INT_MASK
#define HDA_GCTL_RESET
Definition: hda_registers.h:12
void hdac_stream_stop(PHDAC_STREAM stream)
Definition: hdac_stream.cpp:30
#define STATUS_DEVICE_POWER_FAILURE
Definition: ntstatus.h:488
UINT16 codecMask
Definition: fdo.h:160

Referenced by StartHDAController(), and StopHDAController().

◆ RunSingleHDACmd()

NTSTATUS RunSingleHDACmd ( PFDO_CONTEXT  fdoCtx,
ULONG  val,
ULONG res 
)

Definition at line 249 of file hdac_controller.cpp.

249 {
250 HDAUDIO_CODEC_TRANSFER transfer = { 0 };
251 transfer.Output.Command = val;
252
253 SklHdAudBusPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL,
254 "%s: Called. Command: 0x%x\n", __func__, val);
255
256 NTSTATUS status = SendHDACmds(fdoCtx, 1, &transfer);
257 if (!NT_SUCCESS(status)) {
258 return status;
259 }
260
262 status = HDA_WaitForTransfer(fdoCtx, addr, 1, &transfer);
263 if (transfer.Input.IsValid && res) {
264 *res = transfer.Input.Response;
265 }
266 return status;
267}
LONG NTSTATUS
Definition: precomp.h:26
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
NTSTATUS HDA_WaitForTransfer(PFDO_CONTEXT fdoCtx, UINT16 codecAddr, _In_ ULONG Count, _Inout_updates_(Count) PHDAUDIO_CODEC_TRANSFER CodecTransfer)
Definition: hdaudio.cpp:3
GLuint res
Definition: glext.h:9613
GLuint GLfloat * val
Definition: glext.h:7180
NTSTATUS SendHDACmds(PFDO_CONTEXT fdoCtx, ULONG count, PHDAUDIO_CODEC_TRANSFER CodecTransfer)
static UINT16 HDACommandAddr(UINT32 cmd)

Referenced by Fdo_EnumerateCodec(), and Fdo_EvtDeviceD0EntryPostInterrupts().

◆ SendHDACmds()

NTSTATUS SendHDACmds ( PFDO_CONTEXT  fdoCtx,
ULONG  count,
PHDAUDIO_CODEC_TRANSFER  CodecTransfer 
)

Definition at line 207 of file hdac_controller.cpp.

207 {
208 WdfInterruptAcquireLock(fdoCtx->Interrupt);
209 for (ULONG i = 0; i < count; i++) {
210 PHDAUDIO_CODEC_TRANSFER transfer = &CodecTransfer[i];
211 RtlZeroMemory(&transfer->Input, sizeof(transfer->Input));
212
214
215 //Add command to corb
216 UINT16 wp = hda_read16(fdoCtx, CORBWP);
217 if (wp == 0xffff) {
218 //Something wrong, controller likely went to sleep
219 SklHdAudBusPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL,
220 "%s: device not found\n", __func__);
221 WdfInterruptReleaseLock(fdoCtx->Interrupt);
223 }
224
225 wp++;
227
228 UINT16 rp = hda_read16(fdoCtx, CORBRP);
229 if (wp == rp) {
230 //Oops it's full
231 SklHdAudBusPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL,
232 "%s: device busy\n", __func__);
233 WdfInterruptReleaseLock(fdoCtx->Interrupt);
234 return STATUS_RETRY;
235 }
236
237 LONG oldVal = InterlockedIncrement(&fdoCtx->rirb.cmds[addr]);
238 fdoCtx->rirb.xfer[addr].xfer[oldVal - 1] = transfer;
239
240 fdoCtx->corb.buf[wp] = transfer->Output.Command;
241
242 hda_write16(fdoCtx, CORBWP, wp);
243 }
244
245 WdfInterruptReleaseLock(fdoCtx->Interrupt);
246 return STATUS_SUCCESS;
247}
#define InterlockedIncrement
Definition: armddk.h:53
#define STATUS_DEVICE_DOES_NOT_EXIST
Definition: ntstatus.h:522
long LONG
Definition: pedump.c:60
WDFINTERRUPT Interrupt
Definition: fdo.h:124
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_RETRY
Definition: udferr_usr.h:182

Referenced by HDA_TransferCodecVerbs(), and RunSingleHDACmd().

◆ StartHDAController()

NTSTATUS StartHDAController ( PFDO_CONTEXT  fdoCtx)

Definition at line 162 of file hdac_controller.cpp.

162 {
164 status = ResetHDAController(fdoCtx, TRUE);
165 if (!NT_SUCCESS(status)) {
166 goto exit;
167 }
168
169 //Clear STATESTS
170 hda_write16(fdoCtx, STATESTS, STATESTS_INT_MASK);
171
172 HDAInitCorb(fdoCtx);
173 HDAInitRirb(fdoCtx);
174
175 HDAStartCorb(fdoCtx);
176 HDAStartRirb(fdoCtx);
177
178 //Enabling Controller Interrupt
179 hda_write32(fdoCtx, GCTL, hda_read32(fdoCtx, GCTL) | HDA_GCTL_UNSOL);
180 hda_write32(fdoCtx, INTCTL, hda_read32(fdoCtx, INTCTL) | HDA_INT_CTRL_EN | HDA_INT_GLOBAL_EN);
181
182 {
183 //Program position buffer
184 PHYSICAL_ADDRESS posbufAddr = MmGetPhysicalAddress(fdoCtx->posbuf);
185 hda_write32(fdoCtx, DPLBASE, posbufAddr.LowPart);
186 hda_write32(fdoCtx, DPUBASE, posbufAddr.HighPart);
187 }
188
189 udelay(1000);
190
191 fdoCtx->ControllerEnabled = TRUE;
192
193exit:
194 return status;
195}
#define HDA_GCTL_UNSOL
Definition: hda_registers.h:14
#define HDA_INT_GLOBAL_EN
#define HDA_INT_CTRL_EN
void HDAInitRirb(PFDO_CONTEXT fdoCtx)
void HDAStartRirb(PFDO_CONTEXT fdoCtx)
void HDAStartCorb(PFDO_CONTEXT fdoCtx)
NTSTATUS ResetHDAController(PFDO_CONTEXT fdoCtx, BOOLEAN wakeup)
void HDAInitCorb(PFDO_CONTEXT fdoCtx)
#define exit(n)
Definition: config.h:202
PVOID posbuf
Definition: fdo.h:168

Referenced by Fdo_EvtDeviceD0Entry().

◆ StopHDAController()

NTSTATUS StopHDAController ( PFDO_CONTEXT  fdoCtx)

Definition at line 197 of file hdac_controller.cpp.

197 {
199 fdoCtx->ControllerEnabled = FALSE;
200 return status;
201}

Referenced by Fdo_EvtDeviceD0Exit().