1/* Public domain. */
2
3#include <linux/types.h>
4#include <linux/ioport.h>
5#include <linux/pci.h>
6#include <drm/i915_drm.h>
7#include "i915_drv.h"
8
9struct resource intel_graphics_stolen_res = DEFINE_RES_MEM(0, 0);
10
11bus_addr_t
12gen3_stolen_base(struct inteldrm_softc *dev_priv)
13{
14	uint32_t bsm = pci_conf_read(dev_priv->pc, dev_priv->tag,
15	    INTEL_BSM);
16	return bsm & INTEL_BSM_MASK;
17}
18
19bus_addr_t
20gen11_stolen_base(struct inteldrm_softc *dev_priv)
21{
22	uint64_t bsm = pci_conf_read(dev_priv->pc, dev_priv->tag,
23	    INTEL_GEN11_BSM_DW0);
24	bsm &= INTEL_BSM_MASK;
25	bsm |= (uint64_t)pci_conf_read(dev_priv->pc, dev_priv->tag,
26	    INTEL_GEN11_BSM_DW1) << 32;
27	return bsm;
28}
29
30bus_size_t
31i830_stolen_size(struct inteldrm_softc *dev_priv)
32{
33	uint16_t gmch_ctl, gms;
34
35	pci_read_config_word(dev_priv->gmch.pdev, I830_GMCH_CTRL,
36	    &gmch_ctl);
37	gms = gmch_ctl & I830_GMCH_GMS_MASK;
38
39	switch (gms) {
40	case I830_GMCH_GMS_STOLEN_512:
41		return 512 * 1024;
42	case I830_GMCH_GMS_STOLEN_1024:
43		return 1 * 1024 * 1024;
44	case I830_GMCH_GMS_STOLEN_8192:
45		return 8 * 1024 * 1024;
46	}
47
48	return 0;
49}
50
51bus_size_t
52gen3_stolen_size(struct inteldrm_softc *dev_priv)
53{
54	uint16_t gmch_ctl, gms;
55
56	pci_read_config_word(dev_priv->gmch.pdev, I830_GMCH_CTRL,
57	    &gmch_ctl);
58	gms = gmch_ctl & I855_GMCH_GMS_MASK;
59
60	switch (gms) {
61	case I855_GMCH_GMS_STOLEN_1M:
62		return 1 * 1024 * 1024;
63	case I855_GMCH_GMS_STOLEN_4M:
64		return 4 * 1024 * 1024;
65	case I855_GMCH_GMS_STOLEN_8M:
66		return 8 * 1024 * 1024;
67	case I855_GMCH_GMS_STOLEN_16M:
68		return 16 * 1024 * 1024;
69	case I855_GMCH_GMS_STOLEN_32M:
70		return 32 * 1024 * 1024;
71	case I915_GMCH_GMS_STOLEN_48M:
72		return 48 * 1024 * 1024;
73	case I915_GMCH_GMS_STOLEN_64M:
74		return 64 * 1024 * 1024;
75	case G33_GMCH_GMS_STOLEN_128M:
76		return 128 * 1024 * 1024;
77	case G33_GMCH_GMS_STOLEN_256M:
78		return 256 * 1024 * 1024;
79	case INTEL_GMCH_GMS_STOLEN_96M:
80		return 96 * 1024 * 1024;
81	case INTEL_GMCH_GMS_STOLEN_160M:
82		return 160 * 1024 * 1024;
83	case INTEL_GMCH_GMS_STOLEN_224M:
84		return 224 * 1024 * 1024;
85	case INTEL_GMCH_GMS_STOLEN_352M:
86		return 352 * 1024 * 1024;
87	}
88
89	return 0;
90}
91
92bus_size_t
93gen6_stolen_size(struct inteldrm_softc *dev_priv)
94{
95	struct pci_dev *pdev = dev_priv->drm.pdev;
96	uint16_t gmch_ctl, gms;
97
98	pci_read_config_word(pdev, SNB_GMCH_CTRL, &gmch_ctl);
99	gms = (gmch_ctl >> SNB_GMCH_GMS_SHIFT) & SNB_GMCH_GMS_MASK;
100
101	return gms * (32 * 1024 * 1024);
102}
103
104bus_size_t
105chv_stolen_size(struct inteldrm_softc *dev_priv)
106{
107	struct pci_dev *pdev = dev_priv->drm.pdev;
108	uint16_t gmch_ctl, gms;
109
110	pci_read_config_word(pdev, SNB_GMCH_CTRL, &gmch_ctl);
111	gms = (gmch_ctl >> SNB_GMCH_GMS_SHIFT) & SNB_GMCH_GMS_MASK;
112
113	if (gms < 0x11)
114		return gms * (32 * 1024 * 1024);
115	else if (gms < 0x17)
116		return (gms - 0x11) * (4 * 1024 * 1024) + (8 * 1024 * 1024);
117	else
118		return (gms - 0x17) + (4 * 1024 * 1024) + (36 * 1024 * 1024);
119}
120
121bus_size_t
122gen8_stolen_size(struct inteldrm_softc *dev_priv)
123{
124	struct pci_dev *pdev = dev_priv->drm.pdev;
125	uint16_t gmch_ctl, gms;
126
127	pci_read_config_word(pdev, SNB_GMCH_CTRL, &gmch_ctl);
128	gms = (gmch_ctl >> BDW_GMCH_GMS_SHIFT) & BDW_GMCH_GMS_MASK;
129
130	return gms * (32 * 1024 * 1024);
131}
132
133bus_size_t
134gen9_stolen_size(struct inteldrm_softc *dev_priv)
135{
136	struct pci_dev *pdev = dev_priv->drm.pdev;
137	uint16_t gmch_ctl, gms;
138
139	pci_read_config_word(pdev, SNB_GMCH_CTRL, &gmch_ctl);
140	gms = (gmch_ctl >> BDW_GMCH_GMS_SHIFT) & BDW_GMCH_GMS_MASK;
141	if (gms < 0xf0)
142		return gms * (32 * 1024 * 1024);
143	else
144		return (gms - 0xf0) * (4 * 1024 * 1024) + (4 * 1024 * 1024);
145}
146
147void
148intel_init_stolen_res(struct inteldrm_softc *dev_priv)
149{
150	bus_addr_t stolen_base = 0;
151	bus_size_t stolen_size = 0;
152
153#ifdef notyet
154	if (IS_I830(dev_priv))
155		stolen_base  = i830_stolen_base(dev_priv);
156	else if (IS_I845G(dev_priv))
157		stolen_base  = i845_stolen_base(dev_priv);
158	else if (IS_I85X(dev_priv))
159		stolen_base  = i85x_stolen_base(dev_priv);
160	else if (IS_I865G(dev_priv))
161		stolen_base  = i865_stolen_base(dev_priv);
162#endif
163
164	if (GRAPHICS_VER(dev_priv) >= 3 && GRAPHICS_VER(dev_priv) < 11)
165		stolen_base  = gen3_stolen_base(dev_priv);
166	else if (GRAPHICS_VER(dev_priv) == 11 || GRAPHICS_VER(dev_priv) == 12)
167		stolen_base = gen11_stolen_base(dev_priv);
168
169	if (IS_I830(dev_priv) || IS_I845G(dev_priv))
170		stolen_size = i830_stolen_size(dev_priv);
171	else if (IS_I85X(dev_priv) || IS_I865G(dev_priv) ||
172	    (GRAPHICS_VER(dev_priv) >= 3 && GRAPHICS_VER(dev_priv) <= 5))
173		stolen_size = gen3_stolen_size(dev_priv);
174	else if (IS_CHERRYVIEW(dev_priv))
175		stolen_size = chv_stolen_size(dev_priv);
176	else if (GRAPHICS_VER(dev_priv) >= 6 && GRAPHICS_VER(dev_priv) < 8)
177		stolen_size = gen6_stolen_size(dev_priv);
178	else if (GRAPHICS_VER(dev_priv) == 8)
179		stolen_size = gen8_stolen_size(dev_priv);
180	else if (GRAPHICS_VER(dev_priv) >= 9 && GRAPHICS_VER(dev_priv) <= 12)
181		stolen_size = gen9_stolen_size(dev_priv);
182
183	if (stolen_base == 0 || stolen_size == 0)
184		return;
185
186	intel_graphics_stolen_res.start = stolen_base;
187	intel_graphics_stolen_res.end = stolen_base + stolen_size - 1;
188}
189