xref: /linux/drivers/gpu/drm/tiny/bochs.c (revision fcc79e1714e8c2b8e216dc3149812edd37884eef)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 #include <linux/bug.h>
4 #include <linux/module.h>
5 #include <linux/pci.h>
6 
7 #include <drm/drm_aperture.h>
8 #include <drm/drm_atomic_helper.h>
9 #include <drm/drm_drv.h>
10 #include <drm/drm_edid.h>
11 #include <drm/drm_fbdev_ttm.h>
12 #include <drm/drm_fourcc.h>
13 #include <drm/drm_framebuffer.h>
14 #include <drm/drm_gem_framebuffer_helper.h>
15 #include <drm/drm_gem_vram_helper.h>
16 #include <drm/drm_managed.h>
17 #include <drm/drm_module.h>
18 #include <drm/drm_probe_helper.h>
19 #include <drm/drm_simple_kms_helper.h>
20 
21 #include <video/vga.h>
22 
23 /* ---------------------------------------------------------------------- */
24 
25 #define VBE_DISPI_IOPORT_INDEX           0x01CE
26 #define VBE_DISPI_IOPORT_DATA            0x01CF
27 
28 #define VBE_DISPI_INDEX_ID               0x0
29 #define VBE_DISPI_INDEX_XRES             0x1
30 #define VBE_DISPI_INDEX_YRES             0x2
31 #define VBE_DISPI_INDEX_BPP              0x3
32 #define VBE_DISPI_INDEX_ENABLE           0x4
33 #define VBE_DISPI_INDEX_BANK             0x5
34 #define VBE_DISPI_INDEX_VIRT_WIDTH       0x6
35 #define VBE_DISPI_INDEX_VIRT_HEIGHT      0x7
36 #define VBE_DISPI_INDEX_X_OFFSET         0x8
37 #define VBE_DISPI_INDEX_Y_OFFSET         0x9
38 #define VBE_DISPI_INDEX_VIDEO_MEMORY_64K 0xa
39 
40 #define VBE_DISPI_ID0                    0xB0C0
41 #define VBE_DISPI_ID1                    0xB0C1
42 #define VBE_DISPI_ID2                    0xB0C2
43 #define VBE_DISPI_ID3                    0xB0C3
44 #define VBE_DISPI_ID4                    0xB0C4
45 #define VBE_DISPI_ID5                    0xB0C5
46 
47 #define VBE_DISPI_DISABLED               0x00
48 #define VBE_DISPI_ENABLED                0x01
49 #define VBE_DISPI_GETCAPS                0x02
50 #define VBE_DISPI_8BIT_DAC               0x20
51 #define VBE_DISPI_LFB_ENABLED            0x40
52 #define VBE_DISPI_NOCLEARMEM             0x80
53 
54 static int bochs_modeset = -1;
55 static int defx = 1024;
56 static int defy = 768;
57 
58 module_param_named(modeset, bochs_modeset, int, 0444);
59 MODULE_PARM_DESC(modeset, "enable/disable kernel modesetting");
60 
61 module_param(defx, int, 0444);
62 module_param(defy, int, 0444);
63 MODULE_PARM_DESC(defx, "default x resolution");
64 MODULE_PARM_DESC(defy, "default y resolution");
65 
66 /* ---------------------------------------------------------------------- */
67 
68 enum bochs_types {
69 	BOCHS_QEMU_STDVGA,
70 	BOCHS_SIMICS,
71 	BOCHS_UNKNOWN,
72 };
73 
74 struct bochs_device {
75 	/* hw */
76 	void __iomem   *mmio;
77 	int            ioports;
78 	void __iomem   *fb_map;
79 	unsigned long  fb_base;
80 	unsigned long  fb_size;
81 	unsigned long  qext_size;
82 
83 	/* mode */
84 	u16 xres;
85 	u16 yres;
86 	u16 yres_virtual;
87 	u32 stride;
88 	u32 bpp;
89 	const struct drm_edid *drm_edid;
90 
91 	/* drm */
92 	struct drm_device *dev;
93 	struct drm_simple_display_pipe pipe;
94 	struct drm_connector connector;
95 };
96 
97 /* ---------------------------------------------------------------------- */
98 
99 static __always_inline bool bochs_uses_mmio(struct bochs_device *bochs)
100 {
101 	return !IS_ENABLED(CONFIG_HAS_IOPORT) || bochs->mmio;
102 }
103 
104 static void bochs_vga_writeb(struct bochs_device *bochs, u16 ioport, u8 val)
105 {
106 	if (WARN_ON(ioport < 0x3c0 || ioport > 0x3df))
107 		return;
108 
109 	if (bochs_uses_mmio(bochs)) {
110 		int offset = ioport - 0x3c0 + 0x400;
111 
112 		writeb(val, bochs->mmio + offset);
113 	} else {
114 		outb(val, ioport);
115 	}
116 }
117 
118 static u8 bochs_vga_readb(struct bochs_device *bochs, u16 ioport)
119 {
120 	if (WARN_ON(ioport < 0x3c0 || ioport > 0x3df))
121 		return 0xff;
122 
123 	if (bochs_uses_mmio(bochs)) {
124 		int offset = ioport - 0x3c0 + 0x400;
125 
126 		return readb(bochs->mmio + offset);
127 	} else {
128 		return inb(ioport);
129 	}
130 }
131 
132 static u16 bochs_dispi_read(struct bochs_device *bochs, u16 reg)
133 {
134 	u16 ret = 0;
135 
136 	if (bochs_uses_mmio(bochs)) {
137 		int offset = 0x500 + (reg << 1);
138 
139 		ret = readw(bochs->mmio + offset);
140 	} else {
141 		outw(reg, VBE_DISPI_IOPORT_INDEX);
142 		ret = inw(VBE_DISPI_IOPORT_DATA);
143 	}
144 	return ret;
145 }
146 
147 static void bochs_dispi_write(struct bochs_device *bochs, u16 reg, u16 val)
148 {
149 	if (bochs_uses_mmio(bochs)) {
150 		int offset = 0x500 + (reg << 1);
151 
152 		writew(val, bochs->mmio + offset);
153 	} else {
154 		outw(reg, VBE_DISPI_IOPORT_INDEX);
155 		outw(val, VBE_DISPI_IOPORT_DATA);
156 	}
157 }
158 
159 static void bochs_hw_set_big_endian(struct bochs_device *bochs)
160 {
161 	if (bochs->qext_size < 8)
162 		return;
163 
164 	writel(0xbebebebe, bochs->mmio + 0x604);
165 }
166 
167 static void bochs_hw_set_little_endian(struct bochs_device *bochs)
168 {
169 	if (bochs->qext_size < 8)
170 		return;
171 
172 	writel(0x1e1e1e1e, bochs->mmio + 0x604);
173 }
174 
175 #ifdef __BIG_ENDIAN
176 #define bochs_hw_set_native_endian(_b) bochs_hw_set_big_endian(_b)
177 #else
178 #define bochs_hw_set_native_endian(_b) bochs_hw_set_little_endian(_b)
179 #endif
180 
181 static int bochs_get_edid_block(void *data, u8 *buf,
182 				unsigned int block, size_t len)
183 {
184 	struct bochs_device *bochs = data;
185 	size_t i, start = block * EDID_LENGTH;
186 
187 	if (start + len > 0x400 /* vga register offset */)
188 		return -1;
189 
190 	for (i = 0; i < len; i++)
191 		buf[i] = readb(bochs->mmio + start + i);
192 
193 	return 0;
194 }
195 
196 static int bochs_hw_load_edid(struct bochs_device *bochs)
197 {
198 	u8 header[8];
199 
200 	if (!bochs->mmio)
201 		return -1;
202 
203 	/* check header to detect whenever edid support is enabled in qemu */
204 	bochs_get_edid_block(bochs, header, 0, ARRAY_SIZE(header));
205 	if (drm_edid_header_is_valid(header) != 8)
206 		return -1;
207 
208 	drm_edid_free(bochs->drm_edid);
209 	bochs->drm_edid = drm_edid_read_custom(&bochs->connector,
210 					       bochs_get_edid_block, bochs);
211 	if (!bochs->drm_edid)
212 		return -1;
213 
214 	return 0;
215 }
216 
217 static int bochs_hw_init(struct drm_device *dev)
218 {
219 	struct bochs_device *bochs = dev->dev_private;
220 	struct pci_dev *pdev = to_pci_dev(dev->dev);
221 	unsigned long addr, size, mem, ioaddr, iosize;
222 	u16 id;
223 
224 	if (pdev->resource[2].flags & IORESOURCE_MEM) {
225 		/* mmio bar with vga and bochs registers present */
226 		if (pci_request_region(pdev, 2, "bochs-drm") != 0) {
227 			DRM_ERROR("Cannot request mmio region\n");
228 			return -EBUSY;
229 		}
230 		ioaddr = pci_resource_start(pdev, 2);
231 		iosize = pci_resource_len(pdev, 2);
232 		bochs->mmio = ioremap(ioaddr, iosize);
233 		if (bochs->mmio == NULL) {
234 			DRM_ERROR("Cannot map mmio region\n");
235 			return -ENOMEM;
236 		}
237 	} else if (IS_ENABLED(CONFIG_HAS_IOPORT)) {
238 		ioaddr = VBE_DISPI_IOPORT_INDEX;
239 		iosize = 2;
240 		if (!request_region(ioaddr, iosize, "bochs-drm")) {
241 			DRM_ERROR("Cannot request ioports\n");
242 			return -EBUSY;
243 		}
244 		bochs->ioports = 1;
245 	} else {
246 		dev_err(dev->dev, "I/O ports are not supported\n");
247 		return -EIO;
248 	}
249 
250 	id = bochs_dispi_read(bochs, VBE_DISPI_INDEX_ID);
251 	mem = bochs_dispi_read(bochs, VBE_DISPI_INDEX_VIDEO_MEMORY_64K)
252 		* 64 * 1024;
253 	if ((id & 0xfff0) != VBE_DISPI_ID0) {
254 		DRM_ERROR("ID mismatch\n");
255 		return -ENODEV;
256 	}
257 
258 	if ((pdev->resource[0].flags & IORESOURCE_MEM) == 0)
259 		return -ENODEV;
260 	addr = pci_resource_start(pdev, 0);
261 	size = pci_resource_len(pdev, 0);
262 	if (addr == 0)
263 		return -ENODEV;
264 	if (size != mem) {
265 		DRM_ERROR("Size mismatch: pci=%ld, bochs=%ld\n",
266 			size, mem);
267 		size = min(size, mem);
268 	}
269 
270 	if (pci_request_region(pdev, 0, "bochs-drm") != 0)
271 		DRM_WARN("Cannot request framebuffer, boot fb still active?\n");
272 
273 	bochs->fb_map = ioremap(addr, size);
274 	if (bochs->fb_map == NULL) {
275 		DRM_ERROR("Cannot map framebuffer\n");
276 		return -ENOMEM;
277 	}
278 	bochs->fb_base = addr;
279 	bochs->fb_size = size;
280 
281 	DRM_INFO("Found bochs VGA, ID 0x%x.\n", id);
282 	DRM_INFO("Framebuffer size %ld kB @ 0x%lx, %s @ 0x%lx.\n",
283 		 size / 1024, addr,
284 		 bochs->ioports ? "ioports" : "mmio",
285 		 ioaddr);
286 
287 	if (bochs->mmio && pdev->revision >= 2) {
288 		bochs->qext_size = readl(bochs->mmio + 0x600);
289 		if (bochs->qext_size < 4 || bochs->qext_size > iosize) {
290 			bochs->qext_size = 0;
291 			goto noext;
292 		}
293 		DRM_DEBUG("Found qemu ext regs, size %ld\n",
294 			  bochs->qext_size);
295 		bochs_hw_set_native_endian(bochs);
296 	}
297 
298 noext:
299 	return 0;
300 }
301 
302 static void bochs_hw_fini(struct drm_device *dev)
303 {
304 	struct bochs_device *bochs = dev->dev_private;
305 
306 	/* TODO: shot down existing vram mappings */
307 
308 	if (bochs->mmio)
309 		iounmap(bochs->mmio);
310 	if (bochs->ioports)
311 		release_region(VBE_DISPI_IOPORT_INDEX, 2);
312 	if (bochs->fb_map)
313 		iounmap(bochs->fb_map);
314 	pci_release_regions(to_pci_dev(dev->dev));
315 	drm_edid_free(bochs->drm_edid);
316 }
317 
318 static void bochs_hw_blank(struct bochs_device *bochs, bool blank)
319 {
320 	DRM_DEBUG_DRIVER("hw_blank %d\n", blank);
321 	/* enable color bit (so VGA_IS1_RC access works) */
322 	bochs_vga_writeb(bochs, VGA_MIS_W, VGA_MIS_COLOR);
323 	/* discard ar_flip_flop */
324 	(void)bochs_vga_readb(bochs, VGA_IS1_RC);
325 	/* blank or unblank; we need only update index and set 0x20 */
326 	bochs_vga_writeb(bochs, VGA_ATT_W, blank ? 0 : 0x20);
327 }
328 
329 static void bochs_hw_setmode(struct bochs_device *bochs, struct drm_display_mode *mode)
330 {
331 	int idx;
332 
333 	if (!drm_dev_enter(bochs->dev, &idx))
334 		return;
335 
336 	bochs->xres = mode->hdisplay;
337 	bochs->yres = mode->vdisplay;
338 	bochs->bpp = 32;
339 	bochs->stride = mode->hdisplay * (bochs->bpp / 8);
340 	bochs->yres_virtual = bochs->fb_size / bochs->stride;
341 
342 	DRM_DEBUG_DRIVER("%dx%d @ %d bpp, vy %d\n",
343 			 bochs->xres, bochs->yres, bochs->bpp,
344 			 bochs->yres_virtual);
345 
346 	bochs_hw_blank(bochs, false);
347 
348 	bochs_dispi_write(bochs, VBE_DISPI_INDEX_ENABLE,      0);
349 	bochs_dispi_write(bochs, VBE_DISPI_INDEX_BPP,         bochs->bpp);
350 	bochs_dispi_write(bochs, VBE_DISPI_INDEX_XRES,        bochs->xres);
351 	bochs_dispi_write(bochs, VBE_DISPI_INDEX_YRES,        bochs->yres);
352 	bochs_dispi_write(bochs, VBE_DISPI_INDEX_BANK,        0);
353 	bochs_dispi_write(bochs, VBE_DISPI_INDEX_VIRT_WIDTH,  bochs->xres);
354 	bochs_dispi_write(bochs, VBE_DISPI_INDEX_VIRT_HEIGHT,
355 			  bochs->yres_virtual);
356 	bochs_dispi_write(bochs, VBE_DISPI_INDEX_X_OFFSET,    0);
357 	bochs_dispi_write(bochs, VBE_DISPI_INDEX_Y_OFFSET,    0);
358 
359 	bochs_dispi_write(bochs, VBE_DISPI_INDEX_ENABLE,
360 			  VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
361 
362 	drm_dev_exit(idx);
363 }
364 
365 static void bochs_hw_setformat(struct bochs_device *bochs, const struct drm_format_info *format)
366 {
367 	int idx;
368 
369 	if (!drm_dev_enter(bochs->dev, &idx))
370 		return;
371 
372 	DRM_DEBUG_DRIVER("format %c%c%c%c\n",
373 			 (format->format >>  0) & 0xff,
374 			 (format->format >>  8) & 0xff,
375 			 (format->format >> 16) & 0xff,
376 			 (format->format >> 24) & 0xff);
377 
378 	switch (format->format) {
379 	case DRM_FORMAT_XRGB8888:
380 		bochs_hw_set_little_endian(bochs);
381 		break;
382 	case DRM_FORMAT_BGRX8888:
383 		bochs_hw_set_big_endian(bochs);
384 		break;
385 	default:
386 		/* should not happen */
387 		DRM_ERROR("%s: Huh? Got framebuffer format 0x%x",
388 			  __func__, format->format);
389 		break;
390 	}
391 
392 	drm_dev_exit(idx);
393 }
394 
395 static void bochs_hw_setbase(struct bochs_device *bochs, int x, int y, int stride, u64 addr)
396 {
397 	unsigned long offset;
398 	unsigned int vx, vy, vwidth, idx;
399 
400 	if (!drm_dev_enter(bochs->dev, &idx))
401 		return;
402 
403 	bochs->stride = stride;
404 	offset = (unsigned long)addr +
405 		y * bochs->stride +
406 		x * (bochs->bpp / 8);
407 	vy = offset / bochs->stride;
408 	vx = (offset % bochs->stride) * 8 / bochs->bpp;
409 	vwidth = stride * 8 / bochs->bpp;
410 
411 	DRM_DEBUG_DRIVER("x %d, y %d, addr %llx -> offset %lx, vx %d, vy %d\n",
412 			 x, y, addr, offset, vx, vy);
413 	bochs_dispi_write(bochs, VBE_DISPI_INDEX_VIRT_WIDTH, vwidth);
414 	bochs_dispi_write(bochs, VBE_DISPI_INDEX_X_OFFSET, vx);
415 	bochs_dispi_write(bochs, VBE_DISPI_INDEX_Y_OFFSET, vy);
416 
417 	drm_dev_exit(idx);
418 }
419 
420 /* ---------------------------------------------------------------------- */
421 
422 static const uint32_t bochs_formats[] = {
423 	DRM_FORMAT_XRGB8888,
424 	DRM_FORMAT_BGRX8888,
425 };
426 
427 static void bochs_plane_update(struct bochs_device *bochs, struct drm_plane_state *state)
428 {
429 	struct drm_gem_vram_object *gbo;
430 	s64 gpu_addr;
431 
432 	if (!state->fb || !bochs->stride)
433 		return;
434 
435 	gbo = drm_gem_vram_of_gem(state->fb->obj[0]);
436 	gpu_addr = drm_gem_vram_offset(gbo);
437 	if (WARN_ON_ONCE(gpu_addr < 0))
438 		return; /* Bug: we didn't pin the BO to VRAM in prepare_fb. */
439 
440 	bochs_hw_setbase(bochs,
441 			 state->crtc_x,
442 			 state->crtc_y,
443 			 state->fb->pitches[0],
444 			 state->fb->offsets[0] + gpu_addr);
445 	bochs_hw_setformat(bochs, state->fb->format);
446 }
447 
448 static void bochs_pipe_enable(struct drm_simple_display_pipe *pipe,
449 			      struct drm_crtc_state *crtc_state,
450 			      struct drm_plane_state *plane_state)
451 {
452 	struct bochs_device *bochs = pipe->crtc.dev->dev_private;
453 
454 	bochs_hw_setmode(bochs, &crtc_state->mode);
455 	bochs_plane_update(bochs, plane_state);
456 }
457 
458 static void bochs_pipe_disable(struct drm_simple_display_pipe *pipe)
459 {
460 	struct bochs_device *bochs = pipe->crtc.dev->dev_private;
461 
462 	bochs_hw_blank(bochs, true);
463 }
464 
465 static void bochs_pipe_update(struct drm_simple_display_pipe *pipe,
466 			      struct drm_plane_state *old_state)
467 {
468 	struct bochs_device *bochs = pipe->crtc.dev->dev_private;
469 
470 	bochs_plane_update(bochs, pipe->plane.state);
471 }
472 
473 static const struct drm_simple_display_pipe_funcs bochs_pipe_funcs = {
474 	.enable	    = bochs_pipe_enable,
475 	.disable    = bochs_pipe_disable,
476 	.update	    = bochs_pipe_update,
477 	.prepare_fb = drm_gem_vram_simple_display_pipe_prepare_fb,
478 	.cleanup_fb = drm_gem_vram_simple_display_pipe_cleanup_fb,
479 };
480 
481 static int bochs_connector_get_modes(struct drm_connector *connector)
482 {
483 	int count;
484 
485 	count = drm_edid_connector_add_modes(connector);
486 
487 	if (!count) {
488 		count = drm_add_modes_noedid(connector, 8192, 8192);
489 		drm_set_preferred_mode(connector, defx, defy);
490 	}
491 	return count;
492 }
493 
494 static const struct drm_connector_helper_funcs bochs_connector_connector_helper_funcs = {
495 	.get_modes = bochs_connector_get_modes,
496 };
497 
498 static const struct drm_connector_funcs bochs_connector_connector_funcs = {
499 	.fill_modes = drm_helper_probe_single_connector_modes,
500 	.destroy = drm_connector_cleanup,
501 	.reset = drm_atomic_helper_connector_reset,
502 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
503 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
504 };
505 
506 static void bochs_connector_init(struct drm_device *dev)
507 {
508 	struct bochs_device *bochs = dev->dev_private;
509 	struct drm_connector *connector = &bochs->connector;
510 
511 	drm_connector_init(dev, connector, &bochs_connector_connector_funcs,
512 			   DRM_MODE_CONNECTOR_VIRTUAL);
513 	drm_connector_helper_add(connector, &bochs_connector_connector_helper_funcs);
514 
515 	bochs_hw_load_edid(bochs);
516 	if (bochs->drm_edid) {
517 		DRM_INFO("Found EDID data blob.\n");
518 		drm_connector_attach_edid_property(connector);
519 		drm_edid_connector_update(&bochs->connector, bochs->drm_edid);
520 	}
521 }
522 
523 static struct drm_framebuffer *
524 bochs_gem_fb_create(struct drm_device *dev, struct drm_file *file,
525 		    const struct drm_mode_fb_cmd2 *mode_cmd)
526 {
527 	if (mode_cmd->pixel_format != DRM_FORMAT_XRGB8888 &&
528 	    mode_cmd->pixel_format != DRM_FORMAT_BGRX8888)
529 		return ERR_PTR(-EINVAL);
530 
531 	return drm_gem_fb_create(dev, file, mode_cmd);
532 }
533 
534 static const struct drm_mode_config_funcs bochs_mode_funcs = {
535 	.fb_create = bochs_gem_fb_create,
536 	.mode_valid = drm_vram_helper_mode_valid,
537 	.atomic_check = drm_atomic_helper_check,
538 	.atomic_commit = drm_atomic_helper_commit,
539 };
540 
541 static int bochs_kms_init(struct bochs_device *bochs)
542 {
543 	int ret;
544 
545 	ret = drmm_mode_config_init(bochs->dev);
546 	if (ret)
547 		return ret;
548 
549 	bochs->dev->mode_config.max_width = 8192;
550 	bochs->dev->mode_config.max_height = 8192;
551 
552 	bochs->dev->mode_config.preferred_depth = 24;
553 	bochs->dev->mode_config.prefer_shadow = 0;
554 	bochs->dev->mode_config.quirk_addfb_prefer_host_byte_order = true;
555 
556 	bochs->dev->mode_config.funcs = &bochs_mode_funcs;
557 
558 	bochs_connector_init(bochs->dev);
559 	drm_simple_display_pipe_init(bochs->dev,
560 				     &bochs->pipe,
561 				     &bochs_pipe_funcs,
562 				     bochs_formats,
563 				     ARRAY_SIZE(bochs_formats),
564 				     NULL,
565 				     &bochs->connector);
566 
567 	drm_mode_config_reset(bochs->dev);
568 
569 	return 0;
570 }
571 
572 /* ---------------------------------------------------------------------- */
573 /* drm interface                                                          */
574 
575 static int bochs_load(struct drm_device *dev)
576 {
577 	struct bochs_device *bochs;
578 	int ret;
579 
580 	bochs = drmm_kzalloc(dev, sizeof(*bochs), GFP_KERNEL);
581 	if (bochs == NULL)
582 		return -ENOMEM;
583 	dev->dev_private = bochs;
584 	bochs->dev = dev;
585 
586 	ret = bochs_hw_init(dev);
587 	if (ret)
588 		return ret;
589 
590 	ret = drmm_vram_helper_init(dev, bochs->fb_base, bochs->fb_size);
591 	if (ret)
592 		goto err_hw_fini;
593 
594 	ret = bochs_kms_init(bochs);
595 	if (ret)
596 		goto err_hw_fini;
597 
598 	return 0;
599 
600 err_hw_fini:
601 	bochs_hw_fini(dev);
602 	return ret;
603 }
604 
605 DEFINE_DRM_GEM_FOPS(bochs_fops);
606 
607 static const struct drm_driver bochs_driver = {
608 	.driver_features	= DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
609 	.fops			= &bochs_fops,
610 	.name			= "bochs-drm",
611 	.desc			= "bochs dispi vga interface (qemu stdvga)",
612 	.date			= "20130925",
613 	.major			= 1,
614 	.minor			= 0,
615 	DRM_GEM_VRAM_DRIVER,
616 };
617 
618 /* ---------------------------------------------------------------------- */
619 /* pm interface                                                           */
620 
621 #ifdef CONFIG_PM_SLEEP
622 static int bochs_pm_suspend(struct device *dev)
623 {
624 	struct drm_device *drm_dev = dev_get_drvdata(dev);
625 
626 	return drm_mode_config_helper_suspend(drm_dev);
627 }
628 
629 static int bochs_pm_resume(struct device *dev)
630 {
631 	struct drm_device *drm_dev = dev_get_drvdata(dev);
632 
633 	return drm_mode_config_helper_resume(drm_dev);
634 }
635 #endif
636 
637 static const struct dev_pm_ops bochs_pm_ops = {
638 	SET_SYSTEM_SLEEP_PM_OPS(bochs_pm_suspend,
639 				bochs_pm_resume)
640 };
641 
642 /* ---------------------------------------------------------------------- */
643 /* pci interface                                                          */
644 
645 static int bochs_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
646 {
647 	struct drm_device *dev;
648 	unsigned long fbsize;
649 	int ret;
650 
651 	fbsize = pci_resource_len(pdev, 0);
652 	if (fbsize < 4 * 1024 * 1024) {
653 		DRM_ERROR("less than 4 MB video memory, ignoring device\n");
654 		return -ENOMEM;
655 	}
656 
657 	ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, &bochs_driver);
658 	if (ret)
659 		return ret;
660 
661 	dev = drm_dev_alloc(&bochs_driver, &pdev->dev);
662 	if (IS_ERR(dev))
663 		return PTR_ERR(dev);
664 
665 	ret = pcim_enable_device(pdev);
666 	if (ret)
667 		goto err_free_dev;
668 
669 	pci_set_drvdata(pdev, dev);
670 
671 	ret = bochs_load(dev);
672 	if (ret)
673 		goto err_free_dev;
674 
675 	ret = drm_dev_register(dev, 0);
676 	if (ret)
677 		goto err_hw_fini;
678 
679 	drm_fbdev_ttm_setup(dev, 32);
680 	return ret;
681 
682 err_hw_fini:
683 	bochs_hw_fini(dev);
684 err_free_dev:
685 	drm_dev_put(dev);
686 	return ret;
687 }
688 
689 static void bochs_pci_remove(struct pci_dev *pdev)
690 {
691 	struct drm_device *dev = pci_get_drvdata(pdev);
692 
693 	drm_dev_unplug(dev);
694 	drm_atomic_helper_shutdown(dev);
695 	bochs_hw_fini(dev);
696 	drm_dev_put(dev);
697 }
698 
699 static void bochs_pci_shutdown(struct pci_dev *pdev)
700 {
701 	drm_atomic_helper_shutdown(pci_get_drvdata(pdev));
702 }
703 
704 static const struct pci_device_id bochs_pci_tbl[] = {
705 	{
706 		.vendor      = 0x1234,
707 		.device      = 0x1111,
708 		.subvendor   = PCI_SUBVENDOR_ID_REDHAT_QUMRANET,
709 		.subdevice   = PCI_SUBDEVICE_ID_QEMU,
710 		.driver_data = BOCHS_QEMU_STDVGA,
711 	},
712 	{
713 		.vendor      = 0x1234,
714 		.device      = 0x1111,
715 		.subvendor   = PCI_ANY_ID,
716 		.subdevice   = PCI_ANY_ID,
717 		.driver_data = BOCHS_UNKNOWN,
718 	},
719 	{
720 		.vendor      = 0x4321,
721 		.device      = 0x1111,
722 		.subvendor   = PCI_ANY_ID,
723 		.subdevice   = PCI_ANY_ID,
724 		.driver_data = BOCHS_SIMICS,
725 	},
726 	{ /* end of list */ }
727 };
728 
729 static struct pci_driver bochs_pci_driver = {
730 	.name =		"bochs-drm",
731 	.id_table =	bochs_pci_tbl,
732 	.probe =	bochs_pci_probe,
733 	.remove =	bochs_pci_remove,
734 	.shutdown =	bochs_pci_shutdown,
735 	.driver.pm =    &bochs_pm_ops,
736 };
737 
738 /* ---------------------------------------------------------------------- */
739 /* module init/exit                                                       */
740 
741 drm_module_pci_driver_if_modeset(bochs_pci_driver, bochs_modeset);
742 
743 MODULE_DEVICE_TABLE(pci, bochs_pci_tbl);
744 MODULE_AUTHOR("Gerd Hoffmann <kraxel@redhat.com>");
745 MODULE_DESCRIPTION("DRM Support for bochs dispi vga interface (qemu stdvga)");
746 MODULE_LICENSE("GPL");
747