xref: /linux/drivers/gpu/drm/loongson/lsdc_drv.c (revision 7f71507851fc7764b36a3221839607d3a45c2025)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2023 Loongson Technology Corporation Limited
4  */
5 
6 #include <linux/aperture.h>
7 #include <linux/pci.h>
8 #include <linux/vgaarb.h>
9 
10 #include <drm/drm_atomic.h>
11 #include <drm/drm_atomic_helper.h>
12 #include <drm/drm_client_setup.h>
13 #include <drm/drm_drv.h>
14 #include <drm/drm_fbdev_ttm.h>
15 #include <drm/drm_gem_framebuffer_helper.h>
16 #include <drm/drm_ioctl.h>
17 #include <drm/drm_modeset_helper.h>
18 #include <drm/drm_probe_helper.h>
19 #include <drm/drm_vblank.h>
20 
21 #include "loongson_module.h"
22 #include "lsdc_drv.h"
23 #include "lsdc_gem.h"
24 #include "lsdc_ttm.h"
25 
26 #define DRIVER_AUTHOR               "Sui Jingfeng <suijingfeng@loongson.cn>"
27 #define DRIVER_NAME                 "loongson"
28 #define DRIVER_DESC                 "drm driver for loongson graphics"
29 #define DRIVER_DATE                 "20220701"
30 #define DRIVER_MAJOR                1
31 #define DRIVER_MINOR                0
32 #define DRIVER_PATCHLEVEL           0
33 
34 DEFINE_DRM_GEM_FOPS(lsdc_gem_fops);
35 
36 static const struct drm_driver lsdc_drm_driver = {
37 	.driver_features = DRIVER_MODESET | DRIVER_RENDER | DRIVER_GEM | DRIVER_ATOMIC,
38 	.fops = &lsdc_gem_fops,
39 
40 	.name = DRIVER_NAME,
41 	.desc = DRIVER_DESC,
42 	.date = DRIVER_DATE,
43 	.major = DRIVER_MAJOR,
44 	.minor = DRIVER_MINOR,
45 	.patchlevel = DRIVER_PATCHLEVEL,
46 
47 	.debugfs_init = lsdc_debugfs_init,
48 	.dumb_create = lsdc_dumb_create,
49 	.dumb_map_offset = lsdc_dumb_map_offset,
50 	.gem_prime_import_sg_table = lsdc_prime_import_sg_table,
51 	DRM_FBDEV_TTM_DRIVER_OPS,
52 };
53 
54 static const struct drm_mode_config_funcs lsdc_mode_config_funcs = {
55 	.fb_create = drm_gem_fb_create,
56 	.atomic_check = drm_atomic_helper_check,
57 	.atomic_commit = drm_atomic_helper_commit,
58 };
59 
60 /* Display related */
61 
62 static int lsdc_modeset_init(struct lsdc_device *ldev,
63 			     unsigned int num_crtc,
64 			     const struct lsdc_kms_funcs *funcs,
65 			     bool has_vblank)
66 {
67 	struct drm_device *ddev = &ldev->base;
68 	struct lsdc_display_pipe *dispipe;
69 	unsigned int i;
70 	int ret;
71 
72 	for (i = 0; i < num_crtc; i++) {
73 		dispipe = &ldev->dispipe[i];
74 
75 		/* We need an index before crtc is initialized */
76 		dispipe->index = i;
77 
78 		ret = funcs->create_i2c(ddev, dispipe, i);
79 		if (ret)
80 			return ret;
81 	}
82 
83 	for (i = 0; i < num_crtc; i++) {
84 		struct i2c_adapter *ddc = NULL;
85 
86 		dispipe = &ldev->dispipe[i];
87 		if (dispipe->li2c)
88 			ddc = &dispipe->li2c->adapter;
89 
90 		ret = funcs->output_init(ddev, dispipe, ddc, i);
91 		if (ret)
92 			return ret;
93 
94 		ldev->num_output++;
95 	}
96 
97 	for (i = 0; i < num_crtc; i++) {
98 		dispipe = &ldev->dispipe[i];
99 
100 		ret = funcs->primary_plane_init(ddev, &dispipe->primary.base, i);
101 		if (ret)
102 			return ret;
103 
104 		ret = funcs->cursor_plane_init(ddev, &dispipe->cursor.base, i);
105 		if (ret)
106 			return ret;
107 
108 		ret = funcs->crtc_init(ddev, &dispipe->crtc.base,
109 				       &dispipe->primary.base,
110 				       &dispipe->cursor.base,
111 				       i, has_vblank);
112 		if (ret)
113 			return ret;
114 	}
115 
116 	drm_info(ddev, "Total %u outputs\n", ldev->num_output);
117 
118 	return 0;
119 }
120 
121 static const struct drm_mode_config_helper_funcs lsdc_mode_config_helper_funcs = {
122 	.atomic_commit_tail = drm_atomic_helper_commit_tail,
123 };
124 
125 static int lsdc_mode_config_init(struct drm_device *ddev,
126 				 const struct lsdc_desc *descp)
127 {
128 	int ret;
129 
130 	ret = drmm_mode_config_init(ddev);
131 	if (ret)
132 		return ret;
133 
134 	ddev->mode_config.funcs = &lsdc_mode_config_funcs;
135 	ddev->mode_config.min_width = 1;
136 	ddev->mode_config.min_height = 1;
137 	ddev->mode_config.max_width = descp->max_width * LSDC_NUM_CRTC;
138 	ddev->mode_config.max_height = descp->max_height * LSDC_NUM_CRTC;
139 	ddev->mode_config.preferred_depth = 24;
140 	ddev->mode_config.prefer_shadow = 1;
141 
142 	ddev->mode_config.cursor_width = descp->hw_cursor_h;
143 	ddev->mode_config.cursor_height = descp->hw_cursor_h;
144 
145 	ddev->mode_config.helper_private = &lsdc_mode_config_helper_funcs;
146 
147 	if (descp->has_vblank_counter)
148 		ddev->max_vblank_count = 0xffffffff;
149 
150 	return ret;
151 }
152 
153 /*
154  * The GPU and display controller in the LS7A1000/LS7A2000/LS2K2000 are
155  * separated PCIE devices. They are two devices, not one. Bar 2 of the GPU
156  * device contains the base address and size of the VRAM, both the GPU and
157  * the DC could access the on-board VRAM.
158  */
159 static int lsdc_get_dedicated_vram(struct lsdc_device *ldev,
160 				   struct pci_dev *pdev_dc,
161 				   const struct lsdc_desc *descp)
162 {
163 	struct drm_device *ddev = &ldev->base;
164 	struct pci_dev *pdev_gpu;
165 	resource_size_t base, size;
166 
167 	/*
168 	 * The GPU has 00:06.0 as its BDF, while the DC has 00:06.1
169 	 * This is true for the LS7A1000, LS7A2000 and LS2K2000.
170 	 */
171 	pdev_gpu = pci_get_domain_bus_and_slot(pci_domain_nr(pdev_dc->bus),
172 					       pdev_dc->bus->number,
173 					       PCI_DEVFN(6, 0));
174 	if (!pdev_gpu) {
175 		drm_err(ddev, "No GPU device, then no VRAM\n");
176 		return -ENODEV;
177 	}
178 
179 	base = pci_resource_start(pdev_gpu, 2);
180 	size = pci_resource_len(pdev_gpu, 2);
181 
182 	ldev->vram_base = base;
183 	ldev->vram_size = size;
184 	ldev->gpu = pdev_gpu;
185 
186 	drm_info(ddev, "Dedicated vram start: 0x%llx, size: %uMiB\n",
187 		 (u64)base, (u32)(size >> 20));
188 
189 	return (size > SZ_1M) ? 0 : -ENODEV;
190 }
191 
192 static struct lsdc_device *
193 lsdc_create_device(struct pci_dev *pdev,
194 		   const struct lsdc_desc *descp,
195 		   const struct drm_driver *driver)
196 {
197 	struct lsdc_device *ldev;
198 	struct drm_device *ddev;
199 	int ret;
200 
201 	ldev = devm_drm_dev_alloc(&pdev->dev, driver, struct lsdc_device, base);
202 	if (IS_ERR(ldev))
203 		return ldev;
204 
205 	ldev->dc = pdev;
206 	ldev->descp = descp;
207 
208 	ddev = &ldev->base;
209 
210 	loongson_gfxpll_create(ddev, &ldev->gfxpll);
211 
212 	ret = lsdc_get_dedicated_vram(ldev, pdev, descp);
213 	if (ret) {
214 		drm_err(ddev, "Init VRAM failed: %d\n", ret);
215 		return ERR_PTR(ret);
216 	}
217 
218 	ret = aperture_remove_conflicting_devices(ldev->vram_base,
219 						  ldev->vram_size,
220 						  driver->name);
221 	if (ret) {
222 		drm_err(ddev, "Remove firmware framebuffers failed: %d\n", ret);
223 		return ERR_PTR(ret);
224 	}
225 
226 	ret = lsdc_ttm_init(ldev);
227 	if (ret) {
228 		drm_err(ddev, "Memory manager init failed: %d\n", ret);
229 		return ERR_PTR(ret);
230 	}
231 
232 	lsdc_gem_init(ddev);
233 
234 	/* Bar 0 of the DC device contains the MMIO register's base address */
235 	ldev->reg_base = pcim_iomap(pdev, 0, 0);
236 	if (!ldev->reg_base)
237 		return ERR_PTR(-ENODEV);
238 
239 	spin_lock_init(&ldev->reglock);
240 
241 	ret = lsdc_mode_config_init(ddev, descp);
242 	if (ret)
243 		return ERR_PTR(ret);
244 
245 	ret = lsdc_modeset_init(ldev, descp->num_of_crtc, descp->funcs,
246 				loongson_vblank);
247 	if (ret)
248 		return ERR_PTR(ret);
249 
250 	drm_mode_config_reset(ddev);
251 
252 	return ldev;
253 }
254 
255 /* For multiple GPU driver instance co-exixt in the system */
256 
257 static unsigned int lsdc_vga_set_decode(struct pci_dev *pdev, bool state)
258 {
259 	return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
260 }
261 
262 static int lsdc_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
263 {
264 	const struct lsdc_desc *descp;
265 	struct drm_device *ddev;
266 	struct lsdc_device *ldev;
267 	int ret;
268 
269 	descp = lsdc_device_probe(pdev, ent->driver_data);
270 	if (IS_ERR_OR_NULL(descp))
271 		return -ENODEV;
272 
273 	pci_set_master(pdev);
274 
275 	ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(40));
276 	if (ret)
277 		return ret;
278 
279 	ret = pcim_enable_device(pdev);
280 	if (ret)
281 		return ret;
282 
283 	dev_info(&pdev->dev, "Found %s, revision: %u",
284 		 to_loongson_gfx(descp)->model, pdev->revision);
285 
286 	ldev = lsdc_create_device(pdev, descp, &lsdc_drm_driver);
287 	if (IS_ERR(ldev))
288 		return PTR_ERR(ldev);
289 
290 	ddev = &ldev->base;
291 
292 	pci_set_drvdata(pdev, ddev);
293 
294 	vga_client_register(pdev, lsdc_vga_set_decode);
295 
296 	drm_kms_helper_poll_init(ddev);
297 
298 	if (loongson_vblank) {
299 		ret = drm_vblank_init(ddev, descp->num_of_crtc);
300 		if (ret)
301 			return ret;
302 
303 		ret = devm_request_irq(&pdev->dev, pdev->irq,
304 				       descp->funcs->irq_handler,
305 				       IRQF_SHARED,
306 				       dev_name(&pdev->dev), ddev);
307 		if (ret) {
308 			drm_err(ddev, "Failed to register interrupt: %d\n", ret);
309 			return ret;
310 		}
311 
312 		drm_info(ddev, "registered irq: %u\n", pdev->irq);
313 	}
314 
315 	ret = drm_dev_register(ddev, 0);
316 	if (ret)
317 		return ret;
318 
319 	drm_client_setup(ddev, NULL);
320 
321 	return 0;
322 }
323 
324 static void lsdc_pci_remove(struct pci_dev *pdev)
325 {
326 	struct drm_device *ddev = pci_get_drvdata(pdev);
327 
328 	drm_dev_unregister(ddev);
329 	drm_atomic_helper_shutdown(ddev);
330 }
331 
332 static void lsdc_pci_shutdown(struct pci_dev *pdev)
333 {
334 	drm_atomic_helper_shutdown(pci_get_drvdata(pdev));
335 }
336 
337 static int lsdc_drm_freeze(struct drm_device *ddev)
338 {
339 	struct lsdc_device *ldev = to_lsdc(ddev);
340 	struct lsdc_bo *lbo;
341 	int ret;
342 
343 	/* unpin all of buffers in the VRAM */
344 	mutex_lock(&ldev->gem.mutex);
345 	list_for_each_entry(lbo, &ldev->gem.objects, list) {
346 		struct ttm_buffer_object *tbo = &lbo->tbo;
347 		struct ttm_resource *resource = tbo->resource;
348 		unsigned int pin_count = tbo->pin_count;
349 
350 		drm_dbg(ddev, "bo[%p], size: %zuKiB, type: %s, pin count: %u\n",
351 			lbo, lsdc_bo_size(lbo) >> 10,
352 			lsdc_mem_type_to_str(resource->mem_type), pin_count);
353 
354 		if (!pin_count)
355 			continue;
356 
357 		if (resource->mem_type == TTM_PL_VRAM) {
358 			ret = lsdc_bo_reserve(lbo);
359 			if (unlikely(ret)) {
360 				drm_err(ddev, "bo reserve failed: %d\n", ret);
361 				continue;
362 			}
363 
364 			do {
365 				lsdc_bo_unpin(lbo);
366 				--pin_count;
367 			} while (pin_count);
368 
369 			lsdc_bo_unreserve(lbo);
370 		}
371 	}
372 	mutex_unlock(&ldev->gem.mutex);
373 
374 	lsdc_bo_evict_vram(ddev);
375 
376 	ret = drm_mode_config_helper_suspend(ddev);
377 	if (unlikely(ret)) {
378 		drm_err(ddev, "Freeze error: %d", ret);
379 		return ret;
380 	}
381 
382 	return 0;
383 }
384 
385 static int lsdc_drm_resume(struct device *dev)
386 {
387 	struct pci_dev *pdev = to_pci_dev(dev);
388 	struct drm_device *ddev = pci_get_drvdata(pdev);
389 
390 	return drm_mode_config_helper_resume(ddev);
391 }
392 
393 static int lsdc_pm_freeze(struct device *dev)
394 {
395 	struct pci_dev *pdev = to_pci_dev(dev);
396 	struct drm_device *ddev = pci_get_drvdata(pdev);
397 
398 	return lsdc_drm_freeze(ddev);
399 }
400 
401 static int lsdc_pm_thaw(struct device *dev)
402 {
403 	return lsdc_drm_resume(dev);
404 }
405 
406 static int lsdc_pm_suspend(struct device *dev)
407 {
408 	struct pci_dev *pdev = to_pci_dev(dev);
409 	int error;
410 
411 	error = lsdc_pm_freeze(dev);
412 	if (error)
413 		return error;
414 
415 	pci_save_state(pdev);
416 	/* Shut down the device */
417 	pci_disable_device(pdev);
418 	pci_set_power_state(pdev, PCI_D3hot);
419 
420 	return 0;
421 }
422 
423 static int lsdc_pm_resume(struct device *dev)
424 {
425 	struct pci_dev *pdev = to_pci_dev(dev);
426 
427 	pci_set_power_state(pdev, PCI_D0);
428 
429 	pci_restore_state(pdev);
430 
431 	if (pcim_enable_device(pdev))
432 		return -EIO;
433 
434 	return lsdc_pm_thaw(dev);
435 }
436 
437 static const struct dev_pm_ops lsdc_pm_ops = {
438 	.suspend = lsdc_pm_suspend,
439 	.resume = lsdc_pm_resume,
440 	.freeze = lsdc_pm_freeze,
441 	.thaw = lsdc_pm_thaw,
442 	.poweroff = lsdc_pm_freeze,
443 	.restore = lsdc_pm_resume,
444 };
445 
446 static const struct pci_device_id lsdc_pciid_list[] = {
447 	{PCI_VDEVICE(LOONGSON, 0x7a06), CHIP_LS7A1000},
448 	{PCI_VDEVICE(LOONGSON, 0x7a36), CHIP_LS7A2000},
449 	{ }
450 };
451 
452 struct pci_driver lsdc_pci_driver = {
453 	.name = DRIVER_NAME,
454 	.id_table = lsdc_pciid_list,
455 	.probe = lsdc_pci_probe,
456 	.remove = lsdc_pci_remove,
457 	.shutdown = lsdc_pci_shutdown,
458 	.driver.pm = &lsdc_pm_ops,
459 };
460 
461 MODULE_DEVICE_TABLE(pci, lsdc_pciid_list);
462 MODULE_AUTHOR(DRIVER_AUTHOR);
463 MODULE_DESCRIPTION(DRIVER_DESC);
464 MODULE_LICENSE("GPL");
465