blob: 953ee1a501a54a1ea862f4ed61fd653153439852 [file] [log] [blame]
Emily Dengc6e14f42016-08-08 11:30:50 +08001/*
2 * Copyright 2014 Advanced Micro Devices, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 */
23#include "drmP.h"
24#include "amdgpu.h"
25#include "amdgpu_pm.h"
26#include "amdgpu_i2c.h"
27#include "atom.h"
28#include "amdgpu_atombios.h"
29#include "atombios_crtc.h"
30#include "atombios_encoders.h"
31#include "amdgpu_pll.h"
32#include "amdgpu_connectors.h"
33
34static void dce_virtual_set_display_funcs(struct amdgpu_device *adev);
35static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev);
36
37static const struct drm_crtc_funcs dce_virtual_crtc_funcs = {
38 .cursor_set2 = NULL,
39 .cursor_move = NULL,
40 .gamma_set = NULL,
41 .set_config = NULL,
42 .destroy = NULL,
43 .page_flip = NULL,
44};
45
46static const struct drm_crtc_helper_funcs dce_virtual_crtc_helper_funcs = {
47 .dpms = NULL,
48 .mode_fixup = NULL,
49 .mode_set = NULL,
50 .mode_set_base = NULL,
51 .mode_set_base_atomic = NULL,
52 .prepare = NULL,
53 .commit = NULL,
54 .load_lut = NULL,
55 .disable = NULL,
56};
57
58static int dce_virtual_crtc_init(struct amdgpu_device *adev, int index)
59{
60 struct amdgpu_crtc *amdgpu_crtc;
61 int i;
62
63 amdgpu_crtc = kzalloc(sizeof(struct amdgpu_crtc) +
64 (AMDGPUFB_CONN_LIMIT * sizeof(struct drm_connector *)), GFP_KERNEL);
65 if (amdgpu_crtc == NULL)
66 return -ENOMEM;
67
68 drm_crtc_init(adev->ddev, &amdgpu_crtc->base, &dce_virtual_crtc_funcs);
69
70 drm_mode_crtc_set_gamma_size(&amdgpu_crtc->base, 256);
71 amdgpu_crtc->crtc_id = index;
72 adev->mode_info.crtcs[index] = amdgpu_crtc;
73
74 for (i = 0; i < 256; i++) {
75 amdgpu_crtc->lut_r[i] = i << 2;
76 amdgpu_crtc->lut_g[i] = i << 2;
77 amdgpu_crtc->lut_b[i] = i << 2;
78 }
79
80 amdgpu_crtc->pll_id = ATOM_PPLL_INVALID;
81 amdgpu_crtc->encoder = NULL;
82 amdgpu_crtc->connector = NULL;
83 drm_crtc_helper_add(&amdgpu_crtc->base, &dce_virtual_crtc_helper_funcs);
84
85 return 0;
86}
87
88static int dce_virtual_early_init(void *handle)
89{
90 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
91
92 dce_virtual_set_display_funcs(adev);
93 dce_virtual_set_irq_funcs(adev);
94
95 adev->mode_info.num_crtc = 1;
96 adev->mode_info.num_hpd = 1;
97 adev->mode_info.num_dig = 1;
98 return 0;
99}
100
101static bool dce_virtual_get_connector_info(struct amdgpu_device *adev)
102{
103 struct amdgpu_i2c_bus_rec ddc_bus;
104 struct amdgpu_router router;
105 struct amdgpu_hpd hpd;
106
107 /* look up gpio for ddc, hpd */
108 ddc_bus.valid = false;
109 hpd.hpd = AMDGPU_HPD_NONE;
110 /* needed for aux chan transactions */
111 ddc_bus.hpd = hpd.hpd;
112
113 memset(&router, 0, sizeof(router));
114 router.ddc_valid = false;
115 router.cd_valid = false;
116 amdgpu_display_add_connector(adev,
117 0,
118 ATOM_DEVICE_CRT1_SUPPORT,
119 DRM_MODE_CONNECTOR_VIRTUAL, &ddc_bus,
120 CONNECTOR_OBJECT_ID_VIRTUAL,
121 &hpd,
122 &router);
123
124 amdgpu_display_add_encoder(adev, ENCODER_VIRTUAL_ENUM_VIRTUAL,
125 ATOM_DEVICE_CRT1_SUPPORT,
126 0);
127
128 amdgpu_link_encoder_connector(adev->ddev);
129
130 return true;
131}
132
133static int dce_virtual_sw_init(void *handle)
134{
135 int r, i;
136 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
137
138 r = amdgpu_irq_add_id(adev, 229, &adev->crtc_irq);
139 if (r)
140 return r;
141
142 adev->ddev->mode_config.funcs = &amdgpu_mode_funcs;
143
144 adev->ddev->mode_config.max_width = 16384;
145 adev->ddev->mode_config.max_height = 16384;
146
147 adev->ddev->mode_config.preferred_depth = 24;
148 adev->ddev->mode_config.prefer_shadow = 1;
149
150 adev->ddev->mode_config.fb_base = adev->mc.aper_base;
151
152 r = amdgpu_modeset_create_props(adev);
153 if (r)
154 return r;
155
156 adev->ddev->mode_config.max_width = 16384;
157 adev->ddev->mode_config.max_height = 16384;
158
159 /* allocate crtcs */
160 for (i = 0; i < adev->mode_info.num_crtc; i++) {
161 r = dce_virtual_crtc_init(adev, i);
162 if (r)
163 return r;
164 }
165
166 dce_virtual_get_connector_info(adev);
167 amdgpu_print_display_setup(adev->ddev);
168
169 drm_kms_helper_poll_init(adev->ddev);
170
171 adev->mode_info.mode_config_initialized = true;
172 return 0;
173}
174
175static int dce_virtual_sw_fini(void *handle)
176{
177 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
178
179 kfree(adev->mode_info.bios_hardcoded_edid);
180
181 drm_kms_helper_poll_fini(adev->ddev);
182
183 drm_mode_config_cleanup(adev->ddev);
184 adev->mode_info.mode_config_initialized = false;
185 return 0;
186}
187
188static int dce_virtual_hw_init(void *handle)
189{
190 return 0;
191}
192
193static int dce_virtual_hw_fini(void *handle)
194{
195 return 0;
196}
197
198static int dce_virtual_suspend(void *handle)
199{
200 return dce_virtual_hw_fini(handle);
201}
202
203static int dce_virtual_resume(void *handle)
204{
205 int ret;
206
207 ret = dce_virtual_hw_init(handle);
208
209 return ret;
210}
211
212static bool dce_virtual_is_idle(void *handle)
213{
214 return true;
215}
216
217static int dce_virtual_wait_for_idle(void *handle)
218{
219 return 0;
220}
221
222static int dce_virtual_soft_reset(void *handle)
223{
224 return 0;
225}
226
227static int dce_virtual_set_clockgating_state(void *handle,
228 enum amd_clockgating_state state)
229{
230 return 0;
231}
232
233static int dce_virtual_set_powergating_state(void *handle,
234 enum amd_powergating_state state)
235{
236 return 0;
237}
238
239const struct amd_ip_funcs dce_virtual_ip_funcs = {
240 .name = "dce_virtual",
241 .early_init = dce_virtual_early_init,
242 .late_init = NULL,
243 .sw_init = dce_virtual_sw_init,
244 .sw_fini = dce_virtual_sw_fini,
245 .hw_init = dce_virtual_hw_init,
246 .hw_fini = dce_virtual_hw_fini,
247 .suspend = dce_virtual_suspend,
248 .resume = dce_virtual_resume,
249 .is_idle = dce_virtual_is_idle,
250 .wait_for_idle = dce_virtual_wait_for_idle,
251 .soft_reset = dce_virtual_soft_reset,
252 .set_clockgating_state = dce_virtual_set_clockgating_state,
253 .set_powergating_state = dce_virtual_set_powergating_state,
254};
255
256static const struct amdgpu_display_funcs dce_virtual_display_funcs = {
257 .set_vga_render_state = NULL,
258 .bandwidth_update = NULL,
259 .vblank_get_counter = NULL,
260 .vblank_wait = NULL,
261 .is_display_hung = NULL,
262 .backlight_set_level = NULL,
263 .backlight_get_level = NULL,
264 .hpd_sense = NULL,
265 .hpd_set_polarity = NULL,
266 .hpd_get_gpio_reg = NULL,
267 .page_flip = NULL,
268 .page_flip_get_scanoutpos = NULL,
269 .add_encoder = NULL,
270 .add_connector = &amdgpu_connector_add,
271 .stop_mc_access = NULL,
272 .resume_mc_access = NULL,
273};
274
275static void dce_virtual_set_display_funcs(struct amdgpu_device *adev)
276{
277 if (adev->mode_info.funcs == NULL)
278 adev->mode_info.funcs = &dce_virtual_display_funcs;
279}
280
281static const struct amdgpu_irq_src_funcs dce_virtual_crtc_irq_funcs = {
282 .set = NULL,
283 .process = NULL,
284};
285
286static const struct amdgpu_irq_src_funcs dce_virtual_pageflip_irq_funcs = {
287 .set = NULL,
288 .process = NULL,
289};
290
291static const struct amdgpu_irq_src_funcs dce_virtual_hpd_irq_funcs = {
292 .set = NULL,
293 .process = NULL,
294};
295
296static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev)
297{
298 adev->crtc_irq.num_types = AMDGPU_CRTC_IRQ_LAST;
299 adev->crtc_irq.funcs = &dce_virtual_crtc_irq_funcs;
300
301 adev->pageflip_irq.num_types = AMDGPU_PAGEFLIP_IRQ_LAST;
302 adev->pageflip_irq.funcs = &dce_virtual_pageflip_irq_funcs;
303
304 adev->hpd_irq.num_types = AMDGPU_HPD_LAST;
305 adev->hpd_irq.funcs = &dce_virtual_hpd_irq_funcs;
306}
307
308