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