ivybridge_sound.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Intel HDA audio (Azalia) for ivybridge
  4. *
  5. * Originally from coreboot file bd82x6x/azalia.c
  6. *
  7. * Copyright (C) 2008 Advanced Micro Devices, Inc.
  8. * Copyright (C) 2008-2009 coresystems GmbH
  9. * Copyright (C) 2011 The ChromiumOS Authors.
  10. * Copyright 2018 Google LLC
  11. */
  12. #define LOG_CATEGORY UCLASS_SOUND
  13. #include <common.h>
  14. #include <dm.h>
  15. #include <hda_codec.h>
  16. #include <log.h>
  17. #include <pch.h>
  18. #include <sound.h>
  19. #include <linux/bitops.h>
  20. static int bd82x6x_azalia_probe(struct udevice *dev)
  21. {
  22. struct pci_child_platdata *plat;
  23. struct hda_codec_priv *priv;
  24. struct udevice *pch;
  25. u32 codec_mask;
  26. int conf;
  27. int ret;
  28. /* Only init after relocation */
  29. if (!(gd->flags & GD_FLG_RELOC))
  30. return 0;
  31. ret = hda_codec_init(dev);
  32. if (ret) {
  33. log_debug("Cannot set up HDA codec (err=%d)\n", ret);
  34. return ret;
  35. }
  36. priv = dev_get_priv(dev);
  37. ret = uclass_first_device_err(UCLASS_PCH, &pch);
  38. log_debug("PCH %p %s\n", pch, pch->name);
  39. if (ret)
  40. return ret;
  41. conf = pch_ioctl(pch, PCH_REQ_HDA_CONFIG, NULL, 0);
  42. log_debug("conf = %x\n", conf);
  43. if (conf >= 0) {
  44. dm_pci_clrset_config32(dev, 0x120, 7 << 24 | 0xfe,
  45. 1 << 24 | /* 2 << 24 for server */
  46. conf);
  47. dm_pci_clrset_config16(dev, 0x78, 0, 1 << 1);
  48. } else {
  49. log_debug("V1CTL disabled\n");
  50. }
  51. dm_pci_clrset_config32(dev, 0x114, 0xfe, 0);
  52. /* Set VCi enable bit */
  53. dm_pci_clrset_config32(dev, 0x120, 0, 1U << 31);
  54. /* Enable HDMI codec */
  55. dm_pci_clrset_config32(dev, 0xc4, 0, 1 << 1);
  56. dm_pci_clrset_config8(dev, 0x43, 0, 1 << 6);
  57. /* Additional programming steps */
  58. dm_pci_clrset_config32(dev, 0xc4, 0, 1 << 13);
  59. dm_pci_clrset_config32(dev, 0xc4, 0, 1 << 10);
  60. dm_pci_clrset_config32(dev, 0xd0, 1U << 31, 0);
  61. /* Additional step on Panther Point */
  62. plat = dev_get_parent_platdata(dev);
  63. if (plat->device == PCI_DEVICE_ID_INTEL_PANTHERPOINT_HDA)
  64. dm_pci_clrset_config32(dev, 0xc4, 0, 1 << 17);
  65. dm_pci_write_config8(dev, 0x3c, 0xa); /* unused? */
  66. /* Audio Control: Select Azalia mode */
  67. dm_pci_clrset_config8(dev, 0x40, 0, 1);
  68. dm_pci_clrset_config8(dev, 0x4d, 1 << 7, 0); /* Docking not supported */
  69. codec_mask = hda_codec_detect(priv->regs);
  70. log_debug("codec_mask = %02x\n", codec_mask);
  71. if (codec_mask) {
  72. ret = hda_codecs_init(dev, priv->regs, codec_mask);
  73. if (ret) {
  74. log_err("Codec init failed (err=%d)\n", ret);
  75. return ret;
  76. }
  77. }
  78. /* Enable dynamic clock gating */
  79. dm_pci_clrset_config8(dev, 0x43, 7, BIT(2) | BIT(0));
  80. ret = hda_codec_finish_init(dev);
  81. if (ret) {
  82. log_debug("Cannot set up HDA codec (err=%d)\n", ret);
  83. return ret;
  84. }
  85. return 0;
  86. }
  87. static int bd82x6x_azalia_setup(struct udevice *dev)
  88. {
  89. return 0;
  90. }
  91. int bd82x6x_azalia_start_beep(struct udevice *dev, int frequency_hz)
  92. {
  93. return hda_codec_start_beep(dev, frequency_hz);
  94. }
  95. int bd82x6x_azalia_stop_beep(struct udevice *dev)
  96. {
  97. return hda_codec_stop_beep(dev);
  98. }
  99. static const struct sound_ops bd82x6x_azalia_ops = {
  100. .setup = bd82x6x_azalia_setup,
  101. .start_beep = bd82x6x_azalia_start_beep,
  102. .stop_beep = bd82x6x_azalia_stop_beep,
  103. };
  104. static const struct udevice_id bd82x6x_azalia_ids[] = {
  105. { .compatible = "intel,hd-audio" },
  106. { }
  107. };
  108. U_BOOT_DRIVER(bd82x6x_azalia_drv) = {
  109. .name = "bd82x6x-hda",
  110. .id = UCLASS_SOUND,
  111. .of_match = bd82x6x_azalia_ids,
  112. .probe = bd82x6x_azalia_probe,
  113. .ops = &bd82x6x_azalia_ops,
  114. .priv_auto_alloc_size = sizeof(struct hda_codec_priv),
  115. };