OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
HdaCodecAudioIo.c
Go to the documentation of this file.
1
7
8#include "HdaCodec.h"
9#include <Protocol/AudioIo.h>
10#include <Library/OcMiscLib.h>
11#include <Library/PcdLib.h>
12
13//
14// Cache playback setup.
15//
16STATIC UINT64 mOutputIndexMask = 0;
20STATIC UINT8 mChannels = 0xFFU;
21
22// HDA I/O Stream callback.
23VOID
24EFIAPI
27 IN VOID *Context1,
28 IN VOID *Context2,
29 IN VOID *Context3
30 )
31{
32 DEBUG ((DEBUG_VERBOSE, "HdaCodecHdaIoStreamCallback(): start\n"));
33
34 // Create variables.
35 EFI_AUDIO_IO_PROTOCOL *AudioIo = (EFI_AUDIO_IO_PROTOCOL *)Context1;
36 EFI_AUDIO_IO_CALLBACK AudioIoCallback = (EFI_AUDIO_IO_CALLBACK)Context2;
37
38 // Ensure required parameters are valid.
39 if ((AudioIo == NULL) || (AudioIoCallback == NULL)) {
40 return;
41 }
42
43 // Invoke callback.
44 AudioIoCallback (AudioIo, Context3);
45}
46
57EFI_STATUS
58EFIAPI
60 IN EFI_AUDIO_IO_PROTOCOL *This,
61 OUT EFI_AUDIO_IO_PROTOCOL_PORT **OutputPorts,
62 OUT UINTN *OutputPortsCount
63 )
64{
65 DEBUG ((DEBUG_VERBOSE, "HdaCodecAudioIoGetOutputs(): start\n"));
66
67 // Create variables.
68 EFI_STATUS Status;
69 AUDIO_IO_PRIVATE_DATA *AudioIoPrivateData;
70 HDA_CODEC_DEV *HdaCodecDev;
71 EFI_AUDIO_IO_PROTOCOL_PORT *HdaOutputPorts;
72 UINT32 SupportedRates;
73
74 // If a parameter is invalid, return error.
75 if ((This == NULL) || (OutputPorts == NULL) ||
76 (OutputPortsCount == NULL))
77 {
78 return EFI_INVALID_PARAMETER;
79 }
80
81 // Get private data.
82 AudioIoPrivateData = AUDIO_IO_PRIVATE_DATA_FROM_THIS (This);
83 HdaCodecDev = AudioIoPrivateData->HdaCodecDev;
84
85 // Allocate buffer.
86 HdaOutputPorts = AllocateZeroPool (sizeof (EFI_AUDIO_IO_PROTOCOL_PORT) * HdaCodecDev->OutputPortsCount);
87 if (HdaOutputPorts == NULL) {
88 return EFI_OUT_OF_RESOURCES;
89 }
90
91 // Get output ports.
92 for (UINTN i = 0; i < HdaCodecDev->OutputPortsCount; i++) {
93 // Port is an output.
94 HdaOutputPorts[i].Type = EfiAudioIoTypeOutput;
95
96 // Get device type.
100 HdaOutputPorts[i].Device = EfiAudioIoDeviceLine;
101 break;
102
104 HdaOutputPorts[i].Device = EfiAudioIoDeviceSpeaker;
105 break;
106
108 HdaOutputPorts[i].Device = EfiAudioIoDeviceHeadphones;
109 break;
110
113 HdaOutputPorts[i].Device = EfiAudioIoDeviceSpdif;
114 break;
115
117 HdaOutputPorts[i].Device = EfiAudioIoDeviceMic;
118 break;
119
120 default:
122 HdaOutputPorts[i].Device = EfiAudioIoDeviceHdmi;
123 } else {
124 HdaOutputPorts[i].Device = EfiAudioIoDeviceOther;
125 }
126 }
127
128 // Get location.
131 HdaOutputPorts[i].Location = EfiAudioIoLocationNone;
132 break;
133
135 HdaOutputPorts[i].Location = EfiAudioIoLocationRear;
136 break;
137
139 HdaOutputPorts[i].Location = EfiAudioIoLocationFront;
140 break;
141
143 HdaOutputPorts[i].Location = EfiAudioIoLocationLeft;
144 break;
145
147 HdaOutputPorts[i].Location = EfiAudioIoLocationRight;
148 break;
149
151 HdaOutputPorts[i].Location = EfiAudioIoLocationTop;
152 break;
153
155 HdaOutputPorts[i].Location = EfiAudioIoLocationBottom;
156 break;
157
158 default:
159 HdaOutputPorts[i].Location = EfiAudioIoLocationOther;
160 }
161
162 // Get surface.
165 HdaOutputPorts[i].Surface = EfiAudioIoSurfaceExternal;
166 break;
167
169 HdaOutputPorts[i].Surface = EfiAudioIoSurfaceInternal;
170 break;
171
172 default:
173 HdaOutputPorts[i].Surface = EfiAudioIoSurfaceOther;
174 }
175
176 // Get supported stream formats.
177 Status = HdaCodecGetSupportedPcmRates (HdaCodecDev->OutputPorts[i], &SupportedRates);
178 if (EFI_ERROR (Status)) {
179 return Status;
180 }
181
182 // Get supported bit depths.
183 HdaOutputPorts[i].SupportedBits = 0;
184 if (SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_8BIT) {
185 HdaOutputPorts[i].SupportedBits |= EfiAudioIoBits8;
186 }
187
189 HdaOutputPorts[i].SupportedBits |= EfiAudioIoBits16;
190 }
191
193 HdaOutputPorts[i].SupportedBits |= EfiAudioIoBits20;
194 }
195
197 HdaOutputPorts[i].SupportedBits |= EfiAudioIoBits24;
198 }
199
201 HdaOutputPorts[i].SupportedBits |= EfiAudioIoBits32;
202 }
203
204 // Get supported sample rates.
205 HdaOutputPorts[i].SupportedFreqs = 0;
206 if (SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_8KHZ) {
207 HdaOutputPorts[i].SupportedFreqs |= EfiAudioIoFreq8kHz;
208 }
209
211 HdaOutputPorts[i].SupportedFreqs |= EfiAudioIoFreq11kHz;
212 }
213
215 HdaOutputPorts[i].SupportedFreqs |= EfiAudioIoFreq16kHz;
216 }
217
219 HdaOutputPorts[i].SupportedFreqs |= EfiAudioIoFreq22kHz;
220 }
221
223 HdaOutputPorts[i].SupportedFreqs |= EfiAudioIoFreq32kHz;
224 }
225
227 HdaOutputPorts[i].SupportedFreqs |= EfiAudioIoFreq44kHz;
228 }
229
231 HdaOutputPorts[i].SupportedFreqs |= EfiAudioIoFreq48kHz;
232 }
233
235 HdaOutputPorts[i].SupportedFreqs |= EfiAudioIoFreq88kHz;
236 }
237
239 HdaOutputPorts[i].SupportedFreqs |= EfiAudioIoFreq96kHz;
240 }
241
243 HdaOutputPorts[i].SupportedFreqs |= EfiAudioIoFreq192kHz;
244 }
245 }
246
247 // Ports gotten successfully.
248 *OutputPorts = HdaOutputPorts;
249 *OutputPortsCount = HdaCodecDev->OutputPortsCount;
250 return EFI_SUCCESS;
251}
252
268EFI_STATUS
269EFIAPI
271 IN EFI_AUDIO_IO_PROTOCOL *This,
272 IN UINT64 OutputIndexMask,
273 IN UINT8 GainParam,
274 OUT INT8 *Gain
275 )
276{
277 EFI_STATUS Status;
278 AUDIO_IO_PRIVATE_DATA *AudioIoPrivateData;
279 HDA_CODEC_DEV *HdaCodecDev;
280 UINTN Index;
281 UINT64 IndexMask;
282
283 // If a parameter is invalid, return error.
284 if ((This == NULL) || (Gain == NULL)) {
285 return EFI_INVALID_PARAMETER;
286 }
287
288 // Get private data.
289 AudioIoPrivateData = AUDIO_IO_PRIVATE_DATA_FROM_THIS (This);
290 HdaCodecDev = AudioIoPrivateData->HdaCodecDev;
291
292 Status = EFI_NOT_FOUND;
293
294 // Try to convert on requested outputs.
295 for (Index = 0, IndexMask = 1; Index < HdaCodecDev->OutputPortsCount; Index++, IndexMask <<= 1) {
296 if ((OutputIndexMask & IndexMask) == 0) {
297 continue;
298 }
299
300 Status = HdaCodecWidgetRawGainToDecibels (HdaCodecDev->OutputPorts[Index], GainParam, Gain);
301 if (!EFI_ERROR (Status) || (Status != EFI_NOT_FOUND)) {
302 return Status;
303 }
304 }
305
306 return Status;
307}
308
325EFI_STATUS
326EFIAPI
328 IN EFI_AUDIO_IO_PROTOCOL *This,
329 IN UINT64 OutputIndexMask,
330 IN INT8 Gain,
333 IN UINT8 Channels,
334 IN UINTN PlaybackDelay
335 )
336{
337 EFI_STATUS Status;
338 AUDIO_IO_PRIVATE_DATA *AudioIoPrivateData;
339 HDA_CODEC_DEV *HdaCodecDev;
340 EFI_HDA_IO_PROTOCOL *HdaIo;
341 UINTN Index;
342 UINT64 IndexMask;
343 UINT32 Response;
344 UINT8 NumGpios;
345 UINT8 ChannelPayload;
346
347 // Widgets.
348 HDA_WIDGET_DEV *PinWidget;
349 HDA_WIDGET_DEV *OutputWidget;
350 UINT32 SupportedRates;
351 UINT8 HdaStreamId;
352
353 // Stream.
354 UINT8 StreamBits;
355 UINT8 StreamDiv;
356 UINT8 StreamMult;
357 BOOLEAN StreamBase44kHz;
358 UINT16 StreamFmt;
359
360 DEBUG ((DEBUG_VERBOSE, "HdaCodecAudioIoSetupPlayback(): start\n"));
361
362 // Basic settings caching.
363 if ( (mOutputIndexMask == OutputIndexMask)
364 && (mGain == Gain)
365 && (mFreq == Freq)
366 && (mBits == Bits)
367 && (mChannels == Channels))
368 {
369 return EFI_SUCCESS;
370 }
371
372 mOutputIndexMask = OutputIndexMask;
373 mGain = Gain;
374 mFreq = Freq;
375 mBits = Bits;
376 mChannels = Channels;
377
378 // If a parameter is invalid, return error.
379 if (This == NULL) {
380 return EFI_INVALID_PARAMETER;
381 }
382
383 // Get private data.
384 AudioIoPrivateData = AUDIO_IO_PRIVATE_DATA_FROM_THIS (This);
385 HdaCodecDev = AudioIoPrivateData->HdaCodecDev;
386 HdaIo = HdaCodecDev->HdaIo;
387
388 // Mask to only outputs which are within bounds.
389 if (HdaCodecDev->OutputPortsCount > sizeof (UINT64) * OC_CHAR_BIT) {
390 return EFI_UNSUPPORTED;
391 }
392
393 OutputIndexMask &= ~LShiftU64(MAX_UINT64, HdaCodecDev->OutputPortsCount);
394
395 // Fail visibily if nothing is requested.
396 if (PcdGetBool (PcdAudioCodecErrorOnNoOutputs) && (OutputIndexMask == 0)) {
397 return EFI_INVALID_PARAMETER;
398 }
399
400 // Avoid Coverity warnings (the bit mask checks actually ensure that these cannot be used uninitialised).
401 StreamBits = 0;
402 StreamDiv = 0;
403 StreamMult = 0;
404 StreamBase44kHz = FALSE;
405
406 // Expand the requested stream frequency and sample size params,
407 // and check that every requested channel can support them.
408 for (Index = 0, IndexMask = 1; Index < HdaCodecDev->OutputPortsCount; Index++, IndexMask <<= 1) {
409 if ((OutputIndexMask & IndexMask) == 0) {
410 continue;
411 }
412
413 PinWidget = HdaCodecDev->OutputPorts[Index];
414
415 // Get the output DAC for the path.
416 Status = HdaCodecGetOutputDac (PinWidget, &OutputWidget);
417 if (EFI_ERROR (Status)) {
418 return Status;
419 }
420
421 // Get supported stream formats.
422 Status = HdaCodecGetSupportedPcmRates (OutputWidget, &SupportedRates);
423 if (EFI_ERROR (Status)) {
424 DEBUG ((DEBUG_INFO, "HdaCodecGetSupportedPcmRates(): failure - %r\n", Status));
425 return Status;
426 }
427
428 // Determine bitness of samples, ensuring desired bitness is supported.
429 switch (Bits) {
430 // 8-bit.
431 case EfiAudioIoBits8:
432 if (!(SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_8BIT)) {
433 return EFI_UNSUPPORTED;
434 }
435
436 StreamBits = HDA_CONVERTER_FORMAT_BITS_8;
437 break;
438
439 // 16-bit.
440 case EfiAudioIoBits16:
441 if (!(SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_16BIT)) {
442 return EFI_UNSUPPORTED;
443 }
444
445 StreamBits = HDA_CONVERTER_FORMAT_BITS_16;
446 break;
447
448 // 20-bit.
449 case EfiAudioIoBits20:
450 if (!(SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_20BIT)) {
451 return EFI_UNSUPPORTED;
452 }
453
454 StreamBits = HDA_CONVERTER_FORMAT_BITS_20;
455 break;
456
457 // 24-bit.
458 case EfiAudioIoBits24:
459 if (!(SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_24BIT)) {
460 return EFI_UNSUPPORTED;
461 }
462
463 StreamBits = HDA_CONVERTER_FORMAT_BITS_24;
464 break;
465
466 // 32-bit.
467 case EfiAudioIoBits32:
468 if (!(SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_32BIT)) {
469 return EFI_UNSUPPORTED;
470 }
471
472 StreamBits = HDA_CONVERTER_FORMAT_BITS_32;
473 break;
474
475 // Others.
476 default:
477 return EFI_INVALID_PARAMETER;
478 }
479
480 // Determine base, divisor, and multipler.
481 switch (Freq) {
482 // 8 kHz.
484 if (!(SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_8KHZ)) {
485 return EFI_UNSUPPORTED;
486 }
487
488 StreamBase44kHz = FALSE;
489 StreamDiv = 6;
490 StreamMult = 1;
491 break;
492
493 // 11.025 kHz.
495 if (!(SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_11KHZ)) {
496 return EFI_UNSUPPORTED;
497 }
498
499 StreamBase44kHz = FALSE;
500 StreamDiv = 4;
501 StreamMult = 1;
502 break;
503
504 // 16 kHz.
506 if (!(SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_16KHZ)) {
507 return EFI_UNSUPPORTED;
508 }
509
510 StreamBase44kHz = FALSE;
511 StreamDiv = 3;
512 StreamMult = 1;
513 break;
514
515 // 22.05 kHz.
517 if (!(SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_22KHZ)) {
518 return EFI_UNSUPPORTED;
519 }
520
521 StreamBase44kHz = FALSE;
522 StreamDiv = 2;
523 StreamMult = 1;
524 break;
525
526 // 32 kHz.
528 if (!(SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_32KHZ)) {
529 return EFI_UNSUPPORTED;
530 }
531
532 StreamBase44kHz = FALSE;
533 StreamDiv = 3;
534 StreamMult = 2;
535 break;
536
537 // 44.1 kHz.
539 if (!(SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_44KHZ)) {
540 return EFI_UNSUPPORTED;
541 }
542
543 StreamBase44kHz = TRUE;
544 StreamDiv = 1;
545 StreamMult = 1;
546 break;
547
548 // 48 kHz.
550 if (!(SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_48KHZ)) {
551 return EFI_UNSUPPORTED;
552 }
553
554 StreamBase44kHz = FALSE;
555 StreamDiv = 1;
556 StreamMult = 1;
557 break;
558
559 // 88 kHz.
561 if (!(SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_88KHZ)) {
562 return EFI_UNSUPPORTED;
563 }
564
565 StreamBase44kHz = TRUE;
566 StreamDiv = 1;
567 StreamMult = 2;
568 break;
569
570 // 96 kHz.
572 if (!(SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_96KHZ)) {
573 return EFI_UNSUPPORTED;
574 }
575
576 StreamBase44kHz = FALSE;
577 StreamDiv = 1;
578 StreamMult = 2;
579 break;
580
581 // 192 kHz.
583 if (!(SupportedRates & HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_192KHZ)) {
584 return EFI_UNSUPPORTED;
585 }
586
587 StreamBase44kHz = FALSE;
588 StreamDiv = 1;
589 StreamMult = 4;
590 break;
591
592 // Others.
593 default:
594 return EFI_INVALID_PARAMETER;
595 }
596 }
597
598 // Disable all non-selected widget paths.
599 for (Index = 0, IndexMask = 1; Index < HdaCodecDev->OutputPortsCount; Index++, IndexMask <<= 1) {
600 if ((OutputIndexMask & IndexMask) != 0) {
601 continue;
602 }
603
604 Status = HdaCodecDisableWidgetPath (HdaCodecDev->OutputPorts[Index]);
605 if (EFI_ERROR (Status)) {
606 return Status;
607 }
608 }
609
610 // Close stream first.
611 Status = HdaIo->CloseStream (HdaIo, EfiHdaIoTypeOutput);
612 if (EFI_ERROR (Status)) {
613 return Status;
614 }
615
616 // Save requested outputs.
617 AudioIoPrivateData->SelectedOutputIndexMask = OutputIndexMask;
618
619 // Nothing to play.
620 if (OutputIndexMask == 0) {
621 return EFI_SUCCESS;
622 }
623
624 // Calculate stream format and setup stream.
625 StreamFmt = HDA_CONVERTER_FORMAT_SET (
626 Channels - 1,
627 StreamBits,
628 StreamDiv - 1,
629 StreamMult - 1,
630 StreamBase44kHz
631 );
632 DEBUG ((DEBUG_VERBOSE, "HdaCodecAudioIoPlay(): Stream format 0x%X\n", StreamFmt));
633 Status = HdaIo->SetupStream (HdaIo, EfiHdaIoTypeOutput, StreamFmt, &HdaStreamId);
634 if (EFI_ERROR (Status)) {
635 return Status;
636 }
637
638 // Setup widget path for desired outputs.
639 for (Index = 0, IndexMask = 1; Index < HdaCodecDev->OutputPortsCount; Index++, IndexMask <<= 1) {
640 if ((OutputIndexMask & IndexMask) == 0) {
641 continue;
642 }
643
644 Status = HdaCodecEnableWidgetPath (HdaCodecDev->OutputPorts[Index], Gain, HdaStreamId, StreamFmt);
645 if (EFI_ERROR (Status)) {
646 goto CLOSE_STREAM;
647 }
648 }
649
650 //
651 // Enable GPIO pins. This is similar to how Linux drivers enable audio on e.g. Cirrus Logic and
652 // Realtek devices on Mac, by enabling specific GPIO pins as required.
653 // REF:
654 // - https://github.com/torvalds/linux/blob/6f513529296fd4f696afb4354c46508abe646541/sound/pci/hda/patch_cirrus.c#L43-L57
655 // - https://github.com/torvalds/linux/blob/6f513529296fd4f696afb4354c46508abe646541/sound/pci/hda/patch_cirrus.c#L493-L517
656 // - https://github.com/torvalds/linux/blob/6f513529296fd4f696afb4354c46508abe646541/sound/pci/hda/patch_realtek.c#L244-L258
657 //
658 // Note 1: On at least one WWHC system, waiting for current sound to finish playing stopped working when this was
659 // applied automatically, whereas everything already worked fine without this, so we now need to require users to
660 // specify at least `-gpio-setup` (which means: all stages, automatic pins') in the driver params, to use this.
661 //
662 // Note 2: So far we have found no need to specify anything other than 'all stages, automatic (i.e. all) pins', although
663 // we do know that not all systems require all stages (e.g. MBP10,2 only requires DATA stage; but based on Linux
664 // drivers, it is likely that some do), and almost certainly no systems require all pins.
665 //
666 if (gGpioSetupStageMask != 0) {
667 if (gGpioPinMask != 0) {
668 //
669 // Enable user-specified pins.
670 //
671 ChannelPayload = (UINT8)gGpioPinMask;
672 } else {
674 //
675 // According to Intel HDA spec this can be from 0 to 7, however we
676 // have seen 8 in the wild, and values up to 8 are perfectly usable.
677 // REF: https://github.com/acidanthera/bugtracker/issues/740#issuecomment-1005279476
678 //
679 if (NumGpios > 8) {
680 Status = EFI_INVALID_PARAMETER;
681 goto CLOSE_STREAM;
682 }
683
684 ChannelPayload = (1 << NumGpios) - 1;
685 }
686
687 if (ChannelPayload != 0) {
688 Status = EFI_SUCCESS;
689
691 Status = HdaIo->SendCommand (
692 HdaIo,
693 HdaCodecDev->AudioFuncGroup->NodeId,
695 &Response
696 );
697 }
698
699 if ( !EFI_ERROR (Status)
701 {
702 Status = HdaIo->SendCommand (
703 HdaIo,
704 HdaCodecDev->AudioFuncGroup->NodeId,
706 &Response
707 );
708 }
709
710 if ( !EFI_ERROR (Status)
712 {
713 gBS->Stall (MS_TO_MICROSECONDS (1));
714 Status = HdaIo->SendCommand (
715 HdaIo,
716 HdaCodecDev->AudioFuncGroup->NodeId,
717 HDA_CODEC_VERB (HDA_VERB_SET_GPIO_DATA, ChannelPayload),
718 &Response
719 );
720 }
721
722 DEBUG ((
723 EFI_ERROR (Status) ? DEBUG_WARN : DEBUG_INFO,
724 "HDA: GPIO setup on pins 0x%02X - %r\n",
725 ChannelPayload,
726 Status
727 ));
728
729 if (EFI_ERROR (Status)) {
730 goto CLOSE_STREAM;
731 }
732 }
733 }
734
735 //
736 // We are required to wait for some time after codec setup on some systems.
737 // REF: https://github.com/acidanthera/bugtracker/issues/971
738 //
739 if (PlaybackDelay > 0) {
740 gBS->Stall (MS_TO_MICROSECONDS (PlaybackDelay));
741 }
742
743 return EFI_SUCCESS;
744
745CLOSE_STREAM:
746 // Close stream.
747 HdaIo->CloseStream (HdaIo, EfiHdaIoTypeOutput);
748 return Status;
749}
750
762EFI_STATUS
763EFIAPI
765 IN EFI_AUDIO_IO_PROTOCOL *This,
766 IN VOID *Data,
767 IN UINTN DataLength,
768 IN UINTN Position OPTIONAL
769 )
770{
771 DEBUG ((DEBUG_VERBOSE, "HdaCodecAudioIoStartPlayback(): start\n"));
772
773 // Create variables.
774 EFI_STATUS Status;
775 AUDIO_IO_PRIVATE_DATA *AudioIoPrivateData;
776 EFI_HDA_IO_PROTOCOL *HdaIo;
777 BOOLEAN StreamRunning;
778
779 // If a parameter is invalid, return error.
780 if ((This == NULL) || (Data == NULL) || (DataLength == 0)) {
781 return EFI_INVALID_PARAMETER;
782 }
783
784 // Get private data.
785 AudioIoPrivateData = AUDIO_IO_PRIVATE_DATA_FROM_THIS (This);
786 HdaIo = AudioIoPrivateData->HdaCodecDev->HdaIo;
787
788 // Nothing to play.
789 if (AudioIoPrivateData->SelectedOutputIndexMask == 0) {
790 return EFI_SUCCESS;
791 }
792
793 // Start stream.
794 Status = HdaIo->StartStream (
795 HdaIo,
797 Data,
798 DataLength,
799 Position,
800 NULL,
801 NULL,
802 NULL,
803 NULL
804 );
805 if (EFI_ERROR (Status)) {
806 return Status;
807 }
808
809 // Wait for stream to stop.
810 StreamRunning = TRUE;
811 while (StreamRunning) {
812 Status = HdaIo->GetStream (HdaIo, EfiHdaIoTypeOutput, &StreamRunning);
813 if (EFI_ERROR (Status)) {
814 HdaIo->StopStream (HdaIo, EfiHdaIoTypeOutput);
815 return Status;
816 }
817
818 // Wait 100ms.
819 // gBS->Stall (MS_TO_MICROSECONDS (100));
820 }
821
822 return EFI_SUCCESS;
823}
824
838EFI_STATUS
839EFIAPI
841 IN EFI_AUDIO_IO_PROTOCOL *This,
842 IN VOID *Data,
843 IN UINTN DataLength,
844 IN UINTN Position OPTIONAL,
845 IN EFI_AUDIO_IO_CALLBACK Callback OPTIONAL,
846 IN VOID *Context OPTIONAL
847 )
848{
849 DEBUG ((DEBUG_VERBOSE, "HdaCodecAudioIoStartPlaybackAsync(): start\n"));
850
851 // Create variables.
852 EFI_STATUS Status;
853 AUDIO_IO_PRIVATE_DATA *AudioIoPrivateData;
854 EFI_HDA_IO_PROTOCOL *HdaIo;
855
856 // If a parameter is invalid, return error.
857 if ((This == NULL) || (Data == NULL) || (DataLength == 0)) {
858 return EFI_INVALID_PARAMETER;
859 }
860
861 // Get private data.
862 AudioIoPrivateData = AUDIO_IO_PRIVATE_DATA_FROM_THIS (This);
863 HdaIo = AudioIoPrivateData->HdaCodecDev->HdaIo;
864
865 // Start stream.
866 Status = HdaIo->StartStream (
867 HdaIo,
869 Data,
870 DataLength,
871 Position,
873 (VOID *)This,
874 (VOID *)Callback,
875 Context
876 );
877 return Status;
878}
879
888EFI_STATUS
889EFIAPI
891 IN EFI_AUDIO_IO_PROTOCOL *This
892 )
893{
894 DEBUG ((DEBUG_VERBOSE, "HdaCodecAudioIoStopPlayback(): start\n"));
895
896 // Create variables.
897 AUDIO_IO_PRIVATE_DATA *AudioIoPrivateData;
898 EFI_HDA_IO_PROTOCOL *HdaIo;
899
900 // If a parameter is invalid, return error.
901 if (This == NULL) {
902 return EFI_INVALID_PARAMETER;
903 }
904
905 // Get private data.
906 AudioIoPrivateData = AUDIO_IO_PRIVATE_DATA_FROM_THIS (This);
907 HdaIo = AudioIoPrivateData->HdaCodecDev->HdaIo;
908
909 // Stop stream.
910 return HdaIo->StopStream (HdaIo, EfiHdaIoTypeOutput);
911}
#define APPLE_SYSTEM_AUDIO_VOLUME_DB_MIN
@ EfiAudioIoDeviceMic
Definition AudioIo.h:59
@ EfiAudioIoDeviceSpdif
Definition AudioIo.h:58
@ EfiAudioIoDeviceOther
Definition AudioIo.h:61
@ EfiAudioIoDeviceHdmi
Definition AudioIo.h:60
@ EfiAudioIoDeviceSpeaker
Definition AudioIo.h:56
@ EfiAudioIoDeviceLine
Definition AudioIo.h:55
@ EfiAudioIoDeviceHeadphones
Definition AudioIo.h:57
@ EfiAudioIoSurfaceOther
Definition AudioIo.h:86
@ EfiAudioIoSurfaceExternal
Definition AudioIo.h:84
@ EfiAudioIoSurfaceInternal
Definition AudioIo.h:85
@ EfiAudioIoLocationNone
Definition AudioIo.h:69
@ EfiAudioIoLocationOther
Definition AudioIo.h:76
@ EfiAudioIoLocationRear
Definition AudioIo.h:70
@ EfiAudioIoLocationRight
Definition AudioIo.h:73
@ EfiAudioIoLocationBottom
Definition AudioIo.h:75
@ EfiAudioIoLocationTop
Definition AudioIo.h:74
@ EfiAudioIoLocationFront
Definition AudioIo.h:71
@ EfiAudioIoLocationLeft
Definition AudioIo.h:72
EFI_AUDIO_IO_PROTOCOL_FREQ
Definition AudioIo.h:104
@ EfiAudioIoFreq11kHz
Definition AudioIo.h:106
@ EfiAudioIoFreq96kHz
Definition AudioIo.h:113
@ EfiAudioIoFreq22kHz
Definition AudioIo.h:108
@ EfiAudioIoFreq44kHz
Definition AudioIo.h:110
@ EfiAudioIoFreq88kHz
Definition AudioIo.h:112
@ EfiAudioIoFreq192kHz
Definition AudioIo.h:114
@ EfiAudioIoFreq16kHz
Definition AudioIo.h:107
@ EfiAudioIoFreq48kHz
Definition AudioIo.h:111
@ EfiAudioIoFreq32kHz
Definition AudioIo.h:109
@ EfiAudioIoFreq8kHz
Definition AudioIo.h:105
VOID(EFIAPI * EFI_AUDIO_IO_CALLBACK)(IN EFI_AUDIO_IO_PROTOCOL *AudioIo, IN VOID *Context)
Definition AudioIo.h:140
@ EfiAudioIoTypeOutput
Definition AudioIo.h:46
EFI_AUDIO_IO_PROTOCOL_BITS
Definition AudioIo.h:93
@ EfiAudioIoBits24
Definition AudioIo.h:97
@ EfiAudioIoBits20
Definition AudioIo.h:96
@ EfiAudioIoBits16
Definition AudioIo.h:95
@ EfiAudioIoBits8
Definition AudioIo.h:94
@ EfiAudioIoBits32
Definition AudioIo.h:98
EFI_STATUS EFIAPI HdaCodecGetSupportedPcmRates(IN HDA_WIDGET_DEV *HdaPinWidget, OUT UINT32 *SupportedRates)
Definition HdaCodec.c:1183
EFI_STATUS EFIAPI HdaCodecDisableWidgetPath(IN HDA_WIDGET_DEV *HdaWidget)
Definition HdaCodec.c:1228
EFI_STATUS EFIAPI HdaCodecGetOutputDac(IN HDA_WIDGET_DEV *HdaWidget, OUT HDA_WIDGET_DEV **HdaOutputWidget)
Definition HdaCodec.c:1153
EFI_STATUS EFIAPI HdaCodecEnableWidgetPath(IN HDA_WIDGET_DEV *HdaWidget, IN INT8 Gain, IN UINT8 StreamId, IN UINT16 StreamFormat)
Definition HdaCodec.c:1344
UINTN gGpioSetupStageMask
Definition HdaCodec.c:34
EFI_STATUS EFIAPI HdaCodecWidgetRawGainToDecibels(IN HDA_WIDGET_DEV *HdaWidget, IN UINT8 GainParam, OUT INT8 *Gain)
Definition HdaCodec.c:1288
UINTN gGpioPinMask
Definition HdaCodec.c:37
#define GPIO_SETUP_STAGE_ENABLE
Definition HdaCodec.h:372
#define GPIO_SETUP_STAGE_DIRECTION
Definition HdaCodec.h:371
#define GPIO_SETUP_STAGE_DATA
Definition HdaCodec.h:370
#define AUDIO_IO_PRIVATE_DATA_FROM_THIS(This)
Definition HdaCodec.h:159
STATIC EFI_AUDIO_IO_PROTOCOL_BITS mBits
VOID EFIAPI HdaCodecHdaIoStreamCallback(IN EFI_HDA_IO_PROTOCOL_TYPE Type, IN VOID *Context1, IN VOID *Context2, IN VOID *Context3)
EFI_STATUS EFIAPI HdaCodecAudioIoSetupPlayback(IN EFI_AUDIO_IO_PROTOCOL *This, IN UINT64 OutputIndexMask, IN INT8 Gain, IN EFI_AUDIO_IO_PROTOCOL_FREQ Freq, IN EFI_AUDIO_IO_PROTOCOL_BITS Bits, IN UINT8 Channels, IN UINTN PlaybackDelay)
STATIC EFI_AUDIO_IO_PROTOCOL_FREQ mFreq
STATIC INT8 mGain
EFI_STATUS EFIAPI HdaCodecAudioIoStartPlaybackAsync(IN EFI_AUDIO_IO_PROTOCOL *This, IN VOID *Data, IN UINTN DataLength, IN UINTN Position OPTIONAL, IN EFI_AUDIO_IO_CALLBACK Callback OPTIONAL, IN VOID *Context OPTIONAL)
STATIC UINT64 mOutputIndexMask
EFI_STATUS EFIAPI HdaCodecAudioIoStartPlayback(IN EFI_AUDIO_IO_PROTOCOL *This, IN VOID *Data, IN UINTN DataLength, IN UINTN Position OPTIONAL)
EFI_STATUS EFIAPI HdaCodecAudioIoGetOutputs(IN EFI_AUDIO_IO_PROTOCOL *This, OUT EFI_AUDIO_IO_PROTOCOL_PORT **OutputPorts, OUT UINTN *OutputPortsCount)
STATIC UINT8 mChannels
EFI_STATUS EFIAPI HdaCodecAudioIoRawGainToDecibels(IN EFI_AUDIO_IO_PROTOCOL *This, IN UINT64 OutputIndexMask, IN UINT8 GainParam, OUT INT8 *Gain)
EFI_STATUS EFIAPI HdaCodecAudioIoStopPlayback(IN EFI_AUDIO_IO_PROTOCOL *This)
EFI_HDA_IO_PROTOCOL_TYPE
Definition HdaIo.h:47
@ EfiHdaIoTypeOutput
Definition HdaIo.h:49
#define HDA_VERB_GET_CONFIGURATION_DEFAULT_DEVICE(a)
Definition HdaVerbs.h:275
#define HDA_CONFIG_DEFAULT_DEVICE_SPEAKER
Definition HdaVerbs.h:278
#define HDA_CONFIG_DEFAULT_DEVICE_SPDIF_IN
Definition HdaVerbs.h:289
#define HDA_VERB_SET_GPIO_DIRECTION
Definition HdaVerbs.h:200
#define HDA_CONFIG_DEFAULT_LOC_SPEC_BOTTOM
Definition HdaVerbs.h:302
#define HDA_CONFIG_DEFAULT_DEVICE_LINE_OUT
Definition HdaVerbs.h:277
#define HDA_CONFIG_DEFAULT_LOC_SPEC_TOP
Definition HdaVerbs.h:301
#define HDA_CONFIG_DEFAULT_LOC_SPEC_RIGHT
Definition HdaVerbs.h:300
#define HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_24BIT
Definition HdaVerbs.h:446
#define HDA_CONFIG_DEFAULT_DEVICE_MIC_IN
Definition HdaVerbs.h:287
#define HDA_CODEC_VERB(Verb, Payload)
Definition HdaVerbs.h:32
#define HDA_CONVERTER_FORMAT_BITS_16
Definition HdaVerbs.h:42
#define HDA_VERB_SET_GPIO_DATA
Definition HdaVerbs.h:192
#define HDA_CONFIG_DEFAULT_LOC_SURF_INTERNAL
Definition HdaVerbs.h:307
#define HDA_CONFIG_DEFAULT_LOC_SPEC_REAR
Definition HdaVerbs.h:297
#define HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_16KHZ
Definition HdaVerbs.h:433
#define HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_88KHZ
Definition HdaVerbs.h:438
#define HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_192KHZ
Definition HdaVerbs.h:441
#define HDA_CONFIG_DEFAULT_DEVICE_SPDIF_OUT
Definition HdaVerbs.h:281
#define HDA_VERB_GET_CONFIGURATION_DEFAULT_LOC(a)
Definition HdaVerbs.h:294
#define HDA_PARAMETER_GPIO_COUNT_NUM_GPIOS(a)
Definition HdaVerbs.h:506
#define HDA_CONVERTER_FORMAT_BITS_8
Definition HdaVerbs.h:41
#define HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_16BIT
Definition HdaVerbs.h:444
#define HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_8BIT
Definition HdaVerbs.h:443
#define HDA_VERB_SET_GPIO_ENABLE_MASK
Definition HdaVerbs.h:196
#define HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_44KHZ
Definition HdaVerbs.h:436
#define HDA_CONVERTER_FORMAT_BITS_20
Definition HdaVerbs.h:43
#define HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_32BIT
Definition HdaVerbs.h:447
#define HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_8KHZ
Definition HdaVerbs.h:431
#define HDA_CONVERTER_FORMAT_SET(chan, bits, div, mult, base)
Definition HdaVerbs.h:49
#define HDA_CONFIG_DEFAULT_DEVICE_LINE_IN
Definition HdaVerbs.h:285
#define HDA_CONFIG_DEFAULT_LOC_SPEC_LEFT
Definition HdaVerbs.h:299
#define HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_11KHZ
Definition HdaVerbs.h:432
#define HDA_CONFIG_DEFAULT_LOC_SPEC_FRONT
Definition HdaVerbs.h:298
#define HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_32KHZ
Definition HdaVerbs.h:435
#define HDA_PARAMETER_PIN_CAPS_HDMI
Definition HdaVerbs.h:464
#define HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_48KHZ
Definition HdaVerbs.h:437
#define HDA_CONFIG_DEFAULT_LOC_SPEC_NA
Definition HdaVerbs.h:296
#define HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_22KHZ
Definition HdaVerbs.h:434
#define HDA_CONVERTER_FORMAT_BITS_24
Definition HdaVerbs.h:44
#define HDA_CONFIG_DEFAULT_DEVICE_HEADPHONE_OUT
Definition HdaVerbs.h:279
#define HDA_CONVERTER_FORMAT_BITS_32
Definition HdaVerbs.h:45
#define HDA_CONFIG_DEFAULT_LOC_SURF_EXTERNAL
Definition HdaVerbs.h:306
#define HDA_VERB_GET_CONFIGURATION_DEFAULT_SURF(a)
Definition HdaVerbs.h:304
#define HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_20BIT
Definition HdaVerbs.h:445
#define HDA_PARAMETER_SUPPORTED_PCM_SIZE_RATES_96KHZ
Definition HdaVerbs.h:439
EFI_BOOT_SERVICES * gBS
#define OC_CHAR_BIT
Definition OcMiscLib.h:25
#define MS_TO_MICROSECONDS(x)
Definition OcMiscLib.h:31
#define Freq
Definition deflate.h:79
UINT64 SelectedOutputIndexMask
Definition HdaCodec.h:152
HDA_CODEC_DEV * HdaCodecDev
Definition HdaCodec.h:156
HDA_WIDGET_DEV ** OutputPorts
Definition HdaCodec.h:127
EFI_HDA_IO_PROTOCOL * HdaIo
Definition HdaCodec.h:109
HDA_FUNC_GROUP * AudioFuncGroup
Definition HdaCodec.h:124
UINTN OutputPortsCount
Definition HdaCodec.h:129
UINT32 GpioCapabilities
Definition HdaCodec.h:98
UINT32 DefaultConfiguration
Definition HdaCodec.h:78
UINT32 PinCapabilities
Definition HdaCodec.h:75
EFI_AUDIO_IO_PROTOCOL_BITS SupportedBits
Definition AudioIo.h:122
EFI_AUDIO_IO_PROTOCOL_SURFACE Surface
Definition AudioIo.h:126
EFI_AUDIO_IO_PROTOCOL_FREQ SupportedFreqs
Definition AudioIo.h:123
EFI_AUDIO_IO_PROTOCOL_LOCATION Location
Definition AudioIo.h:125
EFI_AUDIO_IO_PROTOCOL_TYPE Type
Definition AudioIo.h:121
EFI_AUDIO_IO_PROTOCOL_DEVICE Device
Definition AudioIo.h:124
EFI_HDA_IO_CLOSE_STREAM CloseStream
Definition HdaIo.h:181
EFI_HDA_IO_START_STREAM StartStream
Definition HdaIo.h:183
EFI_HDA_IO_SETUP_STREAM SetupStream
Definition HdaIo.h:180
EFI_HDA_IO_SEND_COMMAND SendCommand
Definition HdaIo.h:178
EFI_HDA_IO_GET_STREAM GetStream
Definition HdaIo.h:182
EFI_HDA_IO_STOP_STREAM StopStream
Definition HdaIo.h:184