xref: /OK3568_Linux_fs/kernel/sound/hda/hdac_i915.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  *  hdac_i915.c - routines for sync between HD-A core and i915 display driver
4*4882a593Smuzhiyun  */
5*4882a593Smuzhiyun 
6*4882a593Smuzhiyun #include <linux/init.h>
7*4882a593Smuzhiyun #include <linux/module.h>
8*4882a593Smuzhiyun #include <linux/pci.h>
9*4882a593Smuzhiyun #include <sound/core.h>
10*4882a593Smuzhiyun #include <sound/hdaudio.h>
11*4882a593Smuzhiyun #include <sound/hda_i915.h>
12*4882a593Smuzhiyun #include <sound/hda_register.h>
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun #define IS_HSW_CONTROLLER(pci) (((pci)->device == 0x0a0c) || \
15*4882a593Smuzhiyun 				((pci)->device == 0x0c0c) || \
16*4882a593Smuzhiyun 				((pci)->device == 0x0d0c) || \
17*4882a593Smuzhiyun 				((pci)->device == 0x160c))
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun /**
20*4882a593Smuzhiyun  * snd_hdac_i915_set_bclk - Reprogram BCLK for HSW/BDW
21*4882a593Smuzhiyun  * @bus: HDA core bus
22*4882a593Smuzhiyun  *
23*4882a593Smuzhiyun  * Intel HSW/BDW display HDA controller is in GPU. Both its power and link BCLK
24*4882a593Smuzhiyun  * depends on GPU. Two Extended Mode registers EM4 (M value) and EM5 (N Value)
25*4882a593Smuzhiyun  * are used to convert CDClk (Core Display Clock) to 24MHz BCLK:
26*4882a593Smuzhiyun  * BCLK = CDCLK * M / N
27*4882a593Smuzhiyun  * The values will be lost when the display power well is disabled and need to
28*4882a593Smuzhiyun  * be restored to avoid abnormal playback speed.
29*4882a593Smuzhiyun  *
30*4882a593Smuzhiyun  * Call this function at initializing and changing power well, as well as
31*4882a593Smuzhiyun  * at ELD notifier for the hotplug.
32*4882a593Smuzhiyun  */
snd_hdac_i915_set_bclk(struct hdac_bus * bus)33*4882a593Smuzhiyun void snd_hdac_i915_set_bclk(struct hdac_bus *bus)
34*4882a593Smuzhiyun {
35*4882a593Smuzhiyun 	struct drm_audio_component *acomp = bus->audio_component;
36*4882a593Smuzhiyun 	struct pci_dev *pci = to_pci_dev(bus->dev);
37*4882a593Smuzhiyun 	int cdclk_freq;
38*4882a593Smuzhiyun 	unsigned int bclk_m, bclk_n;
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun 	if (!acomp || !acomp->ops || !acomp->ops->get_cdclk_freq)
41*4882a593Smuzhiyun 		return; /* only for i915 binding */
42*4882a593Smuzhiyun 	if (!IS_HSW_CONTROLLER(pci))
43*4882a593Smuzhiyun 		return; /* only HSW/BDW */
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun 	cdclk_freq = acomp->ops->get_cdclk_freq(acomp->dev);
46*4882a593Smuzhiyun 	switch (cdclk_freq) {
47*4882a593Smuzhiyun 	case 337500:
48*4882a593Smuzhiyun 		bclk_m = 16;
49*4882a593Smuzhiyun 		bclk_n = 225;
50*4882a593Smuzhiyun 		break;
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun 	case 450000:
53*4882a593Smuzhiyun 	default: /* default CDCLK 450MHz */
54*4882a593Smuzhiyun 		bclk_m = 4;
55*4882a593Smuzhiyun 		bclk_n = 75;
56*4882a593Smuzhiyun 		break;
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun 	case 540000:
59*4882a593Smuzhiyun 		bclk_m = 4;
60*4882a593Smuzhiyun 		bclk_n = 90;
61*4882a593Smuzhiyun 		break;
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 	case 675000:
64*4882a593Smuzhiyun 		bclk_m = 8;
65*4882a593Smuzhiyun 		bclk_n = 225;
66*4882a593Smuzhiyun 		break;
67*4882a593Smuzhiyun 	}
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun 	snd_hdac_chip_writew(bus, HSW_EM4, bclk_m);
70*4882a593Smuzhiyun 	snd_hdac_chip_writew(bus, HSW_EM5, bclk_n);
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(snd_hdac_i915_set_bclk);
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun /* returns true if the devices can be connected for audio */
connectivity_check(struct pci_dev * i915,struct pci_dev * hdac)75*4882a593Smuzhiyun static bool connectivity_check(struct pci_dev *i915, struct pci_dev *hdac)
76*4882a593Smuzhiyun {
77*4882a593Smuzhiyun 	struct pci_bus *bus_a = i915->bus, *bus_b = hdac->bus;
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun 	/* directly connected on the same bus */
80*4882a593Smuzhiyun 	if (bus_a == bus_b)
81*4882a593Smuzhiyun 		return true;
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 	/*
84*4882a593Smuzhiyun 	 * on i915 discrete GPUs with embedded HDA audio, the two
85*4882a593Smuzhiyun 	 * devices are connected via 2nd level PCI bridge
86*4882a593Smuzhiyun 	 */
87*4882a593Smuzhiyun 	bus_a = bus_a->parent;
88*4882a593Smuzhiyun 	bus_b = bus_b->parent;
89*4882a593Smuzhiyun 	if (!bus_a || !bus_b)
90*4882a593Smuzhiyun 		return false;
91*4882a593Smuzhiyun 	bus_a = bus_a->parent;
92*4882a593Smuzhiyun 	bus_b = bus_b->parent;
93*4882a593Smuzhiyun 	if (bus_a && bus_a == bus_b)
94*4882a593Smuzhiyun 		return true;
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun 	return false;
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun 
i915_component_master_match(struct device * dev,int subcomponent,void * data)99*4882a593Smuzhiyun static int i915_component_master_match(struct device *dev, int subcomponent,
100*4882a593Smuzhiyun 				       void *data)
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun 	struct pci_dev *hdac_pci, *i915_pci;
103*4882a593Smuzhiyun 	struct hdac_bus *bus = data;
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 	if (!dev_is_pci(dev))
106*4882a593Smuzhiyun 		return 0;
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun 	hdac_pci = to_pci_dev(bus->dev);
109*4882a593Smuzhiyun 	i915_pci = to_pci_dev(dev);
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	if (!strcmp(dev->driver->name, "i915") &&
112*4882a593Smuzhiyun 	    subcomponent == I915_COMPONENT_AUDIO &&
113*4882a593Smuzhiyun 	    connectivity_check(i915_pci, hdac_pci))
114*4882a593Smuzhiyun 		return 1;
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	return 0;
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun /* check whether intel graphics is present */
i915_gfx_present(void)120*4882a593Smuzhiyun static bool i915_gfx_present(void)
121*4882a593Smuzhiyun {
122*4882a593Smuzhiyun 	static const struct pci_device_id ids[] = {
123*4882a593Smuzhiyun 		{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_ANY_ID),
124*4882a593Smuzhiyun 		  .class = PCI_BASE_CLASS_DISPLAY << 16,
125*4882a593Smuzhiyun 		  .class_mask = 0xff << 16 },
126*4882a593Smuzhiyun 		{}
127*4882a593Smuzhiyun 	};
128*4882a593Smuzhiyun 	return pci_dev_present(ids);
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun /**
132*4882a593Smuzhiyun  * snd_hdac_i915_init - Initialize i915 audio component
133*4882a593Smuzhiyun  * @bus: HDA core bus
134*4882a593Smuzhiyun  *
135*4882a593Smuzhiyun  * This function is supposed to be used only by a HD-audio controller
136*4882a593Smuzhiyun  * driver that needs the interaction with i915 graphics.
137*4882a593Smuzhiyun  *
138*4882a593Smuzhiyun  * This function initializes and sets up the audio component to communicate
139*4882a593Smuzhiyun  * with i915 graphics driver.
140*4882a593Smuzhiyun  *
141*4882a593Smuzhiyun  * Returns zero for success or a negative error code.
142*4882a593Smuzhiyun  */
snd_hdac_i915_init(struct hdac_bus * bus)143*4882a593Smuzhiyun int snd_hdac_i915_init(struct hdac_bus *bus)
144*4882a593Smuzhiyun {
145*4882a593Smuzhiyun 	struct drm_audio_component *acomp;
146*4882a593Smuzhiyun 	int err;
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun 	if (!i915_gfx_present())
149*4882a593Smuzhiyun 		return -ENODEV;
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun 	err = snd_hdac_acomp_init(bus, NULL,
152*4882a593Smuzhiyun 				  i915_component_master_match,
153*4882a593Smuzhiyun 				  sizeof(struct i915_audio_component) - sizeof(*acomp));
154*4882a593Smuzhiyun 	if (err < 0)
155*4882a593Smuzhiyun 		return err;
156*4882a593Smuzhiyun 	acomp = bus->audio_component;
157*4882a593Smuzhiyun 	if (!acomp)
158*4882a593Smuzhiyun 		return -ENODEV;
159*4882a593Smuzhiyun 	if (!acomp->ops) {
160*4882a593Smuzhiyun 		if (!IS_ENABLED(CONFIG_MODULES) ||
161*4882a593Smuzhiyun 		    !request_module("i915")) {
162*4882a593Smuzhiyun 			/* 60s timeout */
163*4882a593Smuzhiyun 			wait_for_completion_timeout(&acomp->master_bind_complete,
164*4882a593Smuzhiyun 						    msecs_to_jiffies(60 * 1000));
165*4882a593Smuzhiyun 		}
166*4882a593Smuzhiyun 	}
167*4882a593Smuzhiyun 	if (!acomp->ops) {
168*4882a593Smuzhiyun 		dev_info(bus->dev, "couldn't bind with audio component\n");
169*4882a593Smuzhiyun 		snd_hdac_acomp_exit(bus);
170*4882a593Smuzhiyun 		return -ENODEV;
171*4882a593Smuzhiyun 	}
172*4882a593Smuzhiyun 	return 0;
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(snd_hdac_i915_init);
175