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