ivybridge_sound.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  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. #include <asm/global_data.h>
  21. static int bd82x6x_azalia_probe(struct udevice *dev)
  22. {
  23. struct pci_child_plat *plat;
  24. struct hda_codec_priv *priv;
  25. struct udevice *pch;
  26. u32 codec_mask;
  27. int conf;
  28. int ret;
  29. /* Only init after relocation */
  30. if (!(gd->flags & GD_FLG_RELOC))
  31. return 0;
  32. ret = hda_codec_init(dev);
  33. if (ret) {
  34. log_debug("Cannot set up HDA codec (err=%d)\n", ret);
  35. return ret;
  36. }
  37. priv = dev_get_priv(dev);
  38. ret = uclass_first_device_err(UCLASS_PCH, &pch);
  39. log_debug("PCH %p %s\n", pch, pch->name);
  40. if (ret)
  41. return ret;
  42. conf = pch_ioctl(pch, PCH_REQ_HDA_CONFIG, NULL, 0);
  43. log_debug("conf = %x\n", conf);
  44. if (conf >= 0) {
  45. dm_pci_clrset_config32(dev, 0x120, 7 << 24 | 0xfe,
  46. 1 << 24 | /* 2 << 24 for server */
  47. conf);
  48. dm_pci_clrset_config16(dev, 0x78, 0, 1 << 1);
  49. } else {
  50. log_debug("V1CTL disabled\n");
  51. }
  52. dm_pci_clrset_config32(dev, 0x114, 0xfe, 0);
  53. /* Set VCi enable bit */
  54. dm_pci_clrset_config32(dev, 0x120, 0, 1U << 31);
  55. /* Enable HDMI codec */
  56. dm_pci_clrset_config32(dev, 0xc4, 0, 1 << 1);
  57. dm_pci_clrset_config8(dev, 0x43, 0, 1 << 6);
  58. /* Additional programming steps */
  59. dm_pci_clrset_config32(dev, 0xc4, 0, 1 << 13);
  60. dm_pci_clrset_config32(dev, 0xc4, 0, 1 << 10);
  61. dm_pci_clrset_config32(dev, 0xd0, 1U << 31, 0);
  62. /* Additional step on Panther Point */
  63. plat = dev_get_parent_plat(dev);
  64. if (plat->device == PCI_DEVICE_ID_INTEL_PANTHERPOINT_HDA)
  65. dm_pci_clrset_config32(dev, 0xc4, 0, 1 << 17);
  66. dm_pci_write_config8(dev, 0x3c, 0xa); /* unused? */
  67. /* Audio Control: Select Azalia mode */
  68. dm_pci_clrset_config8(dev, 0x40, 0, 1);
  69. dm_pci_clrset_config8(dev, 0x4d, 1 << 7, 0); /* Docking not supported */
  70. codec_mask = hda_codec_detect(priv->regs);
  71. log_debug("codec_mask = %02x\n", codec_mask);
  72. if (codec_mask) {
  73. ret = hda_codecs_init(dev, priv->regs, codec_mask);
  74. if (ret) {
  75. log_err("Codec init failed (err=%d)\n", ret);
  76. return ret;
  77. }
  78. }
  79. /* Enable dynamic clock gating */
  80. dm_pci_clrset_config8(dev, 0x43, 7, BIT(2) | BIT(0));
  81. ret = hda_codec_finish_init(dev);
  82. if (ret) {
  83. log_debug("Cannot set up HDA codec (err=%d)\n", ret);
  84. return ret;
  85. }
  86. return 0;
  87. }
  88. static int bd82x6x_azalia_setup(struct udevice *dev)
  89. {
  90. return 0;
  91. }
  92. int bd82x6x_azalia_start_beep(struct udevice *dev, int frequency_hz)
  93. {
  94. return hda_codec_start_beep(dev, frequency_hz);
  95. }
  96. int bd82x6x_azalia_stop_beep(struct udevice *dev)
  97. {
  98. return hda_codec_stop_beep(dev);
  99. }
  100. static const struct sound_ops bd82x6x_azalia_ops = {
  101. .setup = bd82x6x_azalia_setup,
  102. .start_beep = bd82x6x_azalia_start_beep,
  103. .stop_beep = bd82x6x_azalia_stop_beep,
  104. };
  105. static const struct udevice_id bd82x6x_azalia_ids[] = {
  106. { .compatible = "intel,hd-audio" },
  107. { }
  108. };
  109. U_BOOT_DRIVER(bd82x6x_azalia_drv) = {
  110. .name = "bd82x6x-hda",
  111. .id = UCLASS_SOUND,
  112. .of_match = bd82x6x_azalia_ids,
  113. .probe = bd82x6x_azalia_probe,
  114. .ops = &bd82x6x_azalia_ops,
  115. .priv_auto = sizeof(struct hda_codec_priv),
  116. };