Linux Audio

Check our new training course

Loading...
v4.6
 
  1/*
  2 * This program is free software; you can redistribute it and/or modify
  3 * it under the terms of the GNU General Public License as published by
  4 * the Free Software Foundation; either version 2 of the License, or
  5 * (at your option) any later version.
  6 */
  7
  8#include <linux/mm.h>
  9#include <linux/module.h>
 10#include <linux/slab.h>
 
 
 
 11
 12#include "bochs.h"
 13
 14static bool enable_fbdev = true;
 15module_param_named(fbdev, enable_fbdev, bool, 0444);
 16MODULE_PARM_DESC(fbdev, "register fbdev device");
 17
 18/* ---------------------------------------------------------------------- */
 19/* drm interface                                                          */
 20
 21static int bochs_unload(struct drm_device *dev)
 22{
 23	struct bochs_device *bochs = dev->dev_private;
 24
 25	bochs_fbdev_fini(bochs);
 26	bochs_kms_fini(bochs);
 27	bochs_mm_fini(bochs);
 28	bochs_hw_fini(dev);
 29	kfree(bochs);
 30	dev->dev_private = NULL;
 31	return 0;
 32}
 33
 34static int bochs_load(struct drm_device *dev, unsigned long flags)
 35{
 36	struct bochs_device *bochs;
 37	int ret;
 38
 39	bochs = kzalloc(sizeof(*bochs), GFP_KERNEL);
 40	if (bochs == NULL)
 41		return -ENOMEM;
 42	dev->dev_private = bochs;
 43	bochs->dev = dev;
 44
 45	ret = bochs_hw_init(dev, flags);
 46	if (ret)
 47		goto err;
 48
 49	ret = bochs_mm_init(bochs);
 50	if (ret)
 51		goto err;
 52
 53	ret = bochs_kms_init(bochs);
 54	if (ret)
 55		goto err;
 56
 57	if (enable_fbdev)
 58		bochs_fbdev_init(bochs);
 59
 60	return 0;
 61
 62err:
 63	bochs_unload(dev);
 64	return ret;
 65}
 66
 67static const struct file_operations bochs_fops = {
 68	.owner		= THIS_MODULE,
 69	.open		= drm_open,
 70	.release	= drm_release,
 71	.unlocked_ioctl	= drm_ioctl,
 72#ifdef CONFIG_COMPAT
 73	.compat_ioctl	= drm_compat_ioctl,
 74#endif
 75	.poll		= drm_poll,
 76	.read		= drm_read,
 77	.llseek		= no_llseek,
 78	.mmap           = bochs_mmap,
 79};
 80
 81static struct drm_driver bochs_driver = {
 82	.driver_features	= DRIVER_GEM | DRIVER_MODESET,
 83	.load			= bochs_load,
 84	.unload			= bochs_unload,
 85	.set_busid		= drm_pci_set_busid,
 86	.fops			= &bochs_fops,
 87	.name			= "bochs-drm",
 88	.desc			= "bochs dispi vga interface (qemu stdvga)",
 89	.date			= "20130925",
 90	.major			= 1,
 91	.minor			= 0,
 92	.gem_free_object        = bochs_gem_free_object,
 93	.dumb_create            = bochs_dumb_create,
 94	.dumb_map_offset        = bochs_dumb_mmap_offset,
 95	.dumb_destroy           = drm_gem_dumb_destroy,
 96};
 97
 98/* ---------------------------------------------------------------------- */
 99/* pm interface                                                           */
100
101#ifdef CONFIG_PM_SLEEP
102static int bochs_pm_suspend(struct device *dev)
103{
104	struct pci_dev *pdev = to_pci_dev(dev);
105	struct drm_device *drm_dev = pci_get_drvdata(pdev);
106	struct bochs_device *bochs = drm_dev->dev_private;
107
108	drm_kms_helper_poll_disable(drm_dev);
109
110	if (bochs->fb.initialized) {
111		console_lock();
112		drm_fb_helper_set_suspend(&bochs->fb.helper, 1);
113		console_unlock();
114	}
115
116	return 0;
117}
118
119static int bochs_pm_resume(struct device *dev)
120{
121	struct pci_dev *pdev = to_pci_dev(dev);
122	struct drm_device *drm_dev = pci_get_drvdata(pdev);
123	struct bochs_device *bochs = drm_dev->dev_private;
124
125	drm_helper_resume_force_mode(drm_dev);
126
127	if (bochs->fb.initialized) {
128		console_lock();
129		drm_fb_helper_set_suspend(&bochs->fb.helper, 0);
130		console_unlock();
131	}
132
133	drm_kms_helper_poll_enable(drm_dev);
134	return 0;
135}
136#endif
137
138static const struct dev_pm_ops bochs_pm_ops = {
139	SET_SYSTEM_SLEEP_PM_OPS(bochs_pm_suspend,
140				bochs_pm_resume)
141};
142
143/* ---------------------------------------------------------------------- */
144/* pci interface                                                          */
145
146static int bochs_kick_out_firmware_fb(struct pci_dev *pdev)
 
147{
148	struct apertures_struct *ap;
 
 
149
150	ap = alloc_apertures(1);
151	if (!ap)
 
152		return -ENOMEM;
 
153
154	ap->ranges[0].base = pci_resource_start(pdev, 0);
155	ap->ranges[0].size = pci_resource_len(pdev, 0);
156	remove_conflicting_framebuffers(ap, "bochsdrmfb", false);
157	kfree(ap);
158
159	return 0;
160}
 
161
162static int bochs_pci_probe(struct pci_dev *pdev,
163			   const struct pci_device_id *ent)
164{
165	int ret;
 
 
166
167	ret = bochs_kick_out_firmware_fb(pdev);
168	if (ret)
169		return ret;
 
 
 
 
 
 
 
170
171	return drm_get_pci_dev(pdev, ent, &bochs_driver);
 
 
 
 
172}
173
174static void bochs_pci_remove(struct pci_dev *pdev)
175{
176	struct drm_device *dev = pci_get_drvdata(pdev);
177
178	drm_put_dev(dev);
 
 
 
179}
180
181static const struct pci_device_id bochs_pci_tbl[] = {
182	{
183		.vendor      = 0x1234,
184		.device      = 0x1111,
185		.subvendor   = PCI_SUBVENDOR_ID_REDHAT_QUMRANET,
186		.subdevice   = PCI_SUBDEVICE_ID_QEMU,
187		.driver_data = BOCHS_QEMU_STDVGA,
188	},
189	{
190		.vendor      = 0x1234,
191		.device      = 0x1111,
192		.subvendor   = PCI_ANY_ID,
193		.subdevice   = PCI_ANY_ID,
194		.driver_data = BOCHS_UNKNOWN,
195	},
196	{ /* end of list */ }
197};
198
199static struct pci_driver bochs_pci_driver = {
200	.name =		"bochs-drm",
201	.id_table =	bochs_pci_tbl,
202	.probe =	bochs_pci_probe,
203	.remove =	bochs_pci_remove,
204	.driver.pm =    &bochs_pm_ops,
205};
206
207/* ---------------------------------------------------------------------- */
208/* module init/exit                                                       */
209
210static int __init bochs_init(void)
211{
212	return drm_pci_init(&bochs_driver, &bochs_pci_driver);
 
 
 
 
 
 
213}
214
215static void __exit bochs_exit(void)
216{
217	drm_pci_exit(&bochs_driver, &bochs_pci_driver);
218}
219
220module_init(bochs_init);
221module_exit(bochs_exit);
222
223MODULE_DEVICE_TABLE(pci, bochs_pci_tbl);
224MODULE_AUTHOR("Gerd Hoffmann <kraxel@redhat.com>");
225MODULE_LICENSE("GPL");
v5.4
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
 
 
 
 
  3 */
  4
 
  5#include <linux/module.h>
  6#include <linux/pci.h>
  7
  8#include <drm/drm_drv.h>
  9#include <drm/drm_atomic_helper.h>
 10
 11#include "bochs.h"
 12
 13static int bochs_modeset = -1;
 14module_param_named(modeset, bochs_modeset, int, 0444);
 15MODULE_PARM_DESC(modeset, "enable/disable kernel modesetting");
 16
 17/* ---------------------------------------------------------------------- */
 18/* drm interface                                                          */
 19
 20static void bochs_unload(struct drm_device *dev)
 21{
 22	struct bochs_device *bochs = dev->dev_private;
 23
 
 24	bochs_kms_fini(bochs);
 25	bochs_mm_fini(bochs);
 26	bochs_hw_fini(dev);
 27	kfree(bochs);
 28	dev->dev_private = NULL;
 
 29}
 30
 31static int bochs_load(struct drm_device *dev)
 32{
 33	struct bochs_device *bochs;
 34	int ret;
 35
 36	bochs = kzalloc(sizeof(*bochs), GFP_KERNEL);
 37	if (bochs == NULL)
 38		return -ENOMEM;
 39	dev->dev_private = bochs;
 40	bochs->dev = dev;
 41
 42	ret = bochs_hw_init(dev);
 43	if (ret)
 44		goto err;
 45
 46	ret = bochs_mm_init(bochs);
 47	if (ret)
 48		goto err;
 49
 50	ret = bochs_kms_init(bochs);
 51	if (ret)
 52		goto err;
 53
 
 
 
 54	return 0;
 55
 56err:
 57	bochs_unload(dev);
 58	return ret;
 59}
 60
 61static const struct file_operations bochs_fops = {
 62	.owner		= THIS_MODULE,
 63	DRM_VRAM_MM_FILE_OPERATIONS
 
 
 
 
 
 
 
 
 
 64};
 65
 66static struct drm_driver bochs_driver = {
 67	.driver_features	= DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
 
 
 
 68	.fops			= &bochs_fops,
 69	.name			= "bochs-drm",
 70	.desc			= "bochs dispi vga interface (qemu stdvga)",
 71	.date			= "20130925",
 72	.major			= 1,
 73	.minor			= 0,
 74	DRM_GEM_VRAM_DRIVER,
 
 
 
 75};
 76
 77/* ---------------------------------------------------------------------- */
 78/* pm interface                                                           */
 79
 80#ifdef CONFIG_PM_SLEEP
 81static int bochs_pm_suspend(struct device *dev)
 82{
 83	struct drm_device *drm_dev = dev_get_drvdata(dev);
 
 
 
 
 
 
 
 
 
 
 84
 85	return drm_mode_config_helper_suspend(drm_dev);
 86}
 87
 88static int bochs_pm_resume(struct device *dev)
 89{
 90	struct drm_device *drm_dev = dev_get_drvdata(dev);
 
 
 
 
 
 
 
 
 
 
 91
 92	return drm_mode_config_helper_resume(drm_dev);
 
 93}
 94#endif
 95
 96static const struct dev_pm_ops bochs_pm_ops = {
 97	SET_SYSTEM_SLEEP_PM_OPS(bochs_pm_suspend,
 98				bochs_pm_resume)
 99};
100
101/* ---------------------------------------------------------------------- */
102/* pci interface                                                          */
103
104static int bochs_pci_probe(struct pci_dev *pdev,
105			   const struct pci_device_id *ent)
106{
107	struct drm_device *dev;
108	unsigned long fbsize;
109	int ret;
110
111	fbsize = pci_resource_len(pdev, 0);
112	if (fbsize < 4 * 1024 * 1024) {
113		DRM_ERROR("less than 4 MB video memory, ignoring device\n");
114		return -ENOMEM;
115	}
116
117	ret = drm_fb_helper_remove_conflicting_pci_framebuffers(pdev, 0, "bochsdrmfb");
118	if (ret)
119		return ret;
 
120
121	dev = drm_dev_alloc(&bochs_driver, &pdev->dev);
122	if (IS_ERR(dev))
123		return PTR_ERR(dev);
124
125	ret = pci_enable_device(pdev);
126	if (ret)
127		goto err_free_dev;
128
129	dev->pdev = pdev;
130	pci_set_drvdata(pdev, dev);
131
132	ret = bochs_load(dev);
133	if (ret)
134		goto err_free_dev;
135
136	ret = drm_dev_register(dev, 0);
137	if (ret)
138		goto err_unload;
139
140	drm_fbdev_generic_setup(dev, 32);
141	return ret;
142
143err_unload:
144	bochs_unload(dev);
145err_free_dev:
146	drm_dev_put(dev);
147	return ret;
148}
149
150static void bochs_pci_remove(struct pci_dev *pdev)
151{
152	struct drm_device *dev = pci_get_drvdata(pdev);
153
154	drm_atomic_helper_shutdown(dev);
155	drm_dev_unregister(dev);
156	bochs_unload(dev);
157	drm_dev_put(dev);
158}
159
160static const struct pci_device_id bochs_pci_tbl[] = {
161	{
162		.vendor      = 0x1234,
163		.device      = 0x1111,
164		.subvendor   = PCI_SUBVENDOR_ID_REDHAT_QUMRANET,
165		.subdevice   = PCI_SUBDEVICE_ID_QEMU,
166		.driver_data = BOCHS_QEMU_STDVGA,
167	},
168	{
169		.vendor      = 0x1234,
170		.device      = 0x1111,
171		.subvendor   = PCI_ANY_ID,
172		.subdevice   = PCI_ANY_ID,
173		.driver_data = BOCHS_UNKNOWN,
174	},
175	{ /* end of list */ }
176};
177
178static struct pci_driver bochs_pci_driver = {
179	.name =		"bochs-drm",
180	.id_table =	bochs_pci_tbl,
181	.probe =	bochs_pci_probe,
182	.remove =	bochs_pci_remove,
183	.driver.pm =    &bochs_pm_ops,
184};
185
186/* ---------------------------------------------------------------------- */
187/* module init/exit                                                       */
188
189static int __init bochs_init(void)
190{
191	if (vgacon_text_force() && bochs_modeset == -1)
192		return -EINVAL;
193
194	if (bochs_modeset == 0)
195		return -EINVAL;
196
197	return pci_register_driver(&bochs_pci_driver);
198}
199
200static void __exit bochs_exit(void)
201{
202	pci_unregister_driver(&bochs_pci_driver);
203}
204
205module_init(bochs_init);
206module_exit(bochs_exit);
207
208MODULE_DEVICE_TABLE(pci, bochs_pci_tbl);
209MODULE_AUTHOR("Gerd Hoffmann <kraxel@redhat.com>");
210MODULE_LICENSE("GPL");