diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_drv.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.c | 299 |
1 files changed, 255 insertions, 44 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 7f436ec075f6..cc03537bb883 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
@@ -33,7 +33,6 @@ | |||
33 | #include "i915_drm.h" | 33 | #include "i915_drm.h" |
34 | #include "i915_drv.h" | 34 | #include "i915_drv.h" |
35 | 35 | ||
36 | #include "drm_pciids.h" | ||
37 | #include <linux/console.h> | 36 | #include <linux/console.h> |
38 | #include "drm_crtc_helper.h" | 37 | #include "drm_crtc_helper.h" |
39 | 38 | ||
@@ -46,36 +45,163 @@ module_param_named(fbpercrtc, i915_fbpercrtc, int, 0400); | |||
46 | unsigned int i915_powersave = 1; | 45 | unsigned int i915_powersave = 1; |
47 | module_param_named(powersave, i915_powersave, int, 0400); | 46 | module_param_named(powersave, i915_powersave, int, 0400); |
48 | 47 | ||
48 | unsigned int i915_lvds_downclock = 0; | ||
49 | module_param_named(lvds_downclock, i915_lvds_downclock, int, 0400); | ||
50 | |||
49 | static struct drm_driver driver; | 51 | static struct drm_driver driver; |
52 | extern int intel_agp_enabled; | ||
53 | |||
54 | #define INTEL_VGA_DEVICE(id, info) { \ | ||
55 | .class = PCI_CLASS_DISPLAY_VGA << 8, \ | ||
56 | .class_mask = 0xffff00, \ | ||
57 | .vendor = 0x8086, \ | ||
58 | .device = id, \ | ||
59 | .subvendor = PCI_ANY_ID, \ | ||
60 | .subdevice = PCI_ANY_ID, \ | ||
61 | .driver_data = (unsigned long) info } | ||
62 | |||
63 | const static struct intel_device_info intel_i830_info = { | ||
64 | .is_i8xx = 1, .is_mobile = 1, .cursor_needs_physical = 1, | ||
65 | }; | ||
66 | |||
67 | const static struct intel_device_info intel_845g_info = { | ||
68 | .is_i8xx = 1, | ||
69 | }; | ||
70 | |||
71 | const static struct intel_device_info intel_i85x_info = { | ||
72 | .is_i8xx = 1, .is_i85x = 1, .is_mobile = 1, | ||
73 | .cursor_needs_physical = 1, | ||
74 | }; | ||
75 | |||
76 | const static struct intel_device_info intel_i865g_info = { | ||
77 | .is_i8xx = 1, | ||
78 | }; | ||
79 | |||
80 | const static struct intel_device_info intel_i915g_info = { | ||
81 | .is_i915g = 1, .is_i9xx = 1, .cursor_needs_physical = 1, | ||
82 | }; | ||
83 | const static struct intel_device_info intel_i915gm_info = { | ||
84 | .is_i9xx = 1, .is_mobile = 1, | ||
85 | .cursor_needs_physical = 1, | ||
86 | }; | ||
87 | const static struct intel_device_info intel_i945g_info = { | ||
88 | .is_i9xx = 1, .has_hotplug = 1, .cursor_needs_physical = 1, | ||
89 | }; | ||
90 | const static struct intel_device_info intel_i945gm_info = { | ||
91 | .is_i945gm = 1, .is_i9xx = 1, .is_mobile = 1, | ||
92 | .has_hotplug = 1, .cursor_needs_physical = 1, | ||
93 | }; | ||
94 | |||
95 | const static struct intel_device_info intel_i965g_info = { | ||
96 | .is_i965g = 1, .is_i9xx = 1, .has_hotplug = 1, | ||
97 | }; | ||
98 | |||
99 | const static struct intel_device_info intel_i965gm_info = { | ||
100 | .is_i965g = 1, .is_mobile = 1, .is_i965gm = 1, .is_i9xx = 1, | ||
101 | .is_mobile = 1, .has_fbc = 1, .has_rc6 = 1, | ||
102 | .has_hotplug = 1, | ||
103 | }; | ||
104 | |||
105 | const static struct intel_device_info intel_g33_info = { | ||
106 | .is_g33 = 1, .is_i9xx = 1, .need_gfx_hws = 1, | ||
107 | .has_hotplug = 1, | ||
108 | }; | ||
109 | |||
110 | const static struct intel_device_info intel_g45_info = { | ||
111 | .is_i965g = 1, .is_g4x = 1, .is_i9xx = 1, .need_gfx_hws = 1, | ||
112 | .has_pipe_cxsr = 1, | ||
113 | .has_hotplug = 1, | ||
114 | }; | ||
115 | |||
116 | const static struct intel_device_info intel_gm45_info = { | ||
117 | .is_i965g = 1, .is_mobile = 1, .is_g4x = 1, .is_i9xx = 1, | ||
118 | .is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1, | ||
119 | .has_pipe_cxsr = 1, | ||
120 | .has_hotplug = 1, | ||
121 | }; | ||
122 | |||
123 | const static struct intel_device_info intel_pineview_info = { | ||
124 | .is_g33 = 1, .is_pineview = 1, .is_mobile = 1, .is_i9xx = 1, | ||
125 | .need_gfx_hws = 1, | ||
126 | .has_hotplug = 1, | ||
127 | }; | ||
128 | |||
129 | const static struct intel_device_info intel_ironlake_d_info = { | ||
130 | .is_ironlake = 1, .is_i965g = 1, .is_i9xx = 1, .need_gfx_hws = 1, | ||
131 | .has_pipe_cxsr = 1, | ||
132 | .has_hotplug = 1, | ||
133 | }; | ||
50 | 134 | ||
51 | static struct pci_device_id pciidlist[] = { | 135 | const static struct intel_device_info intel_ironlake_m_info = { |
52 | i915_PCI_IDS | 136 | .is_ironlake = 1, .is_mobile = 1, .is_i965g = 1, .is_i9xx = 1, |
137 | .need_gfx_hws = 1, .has_rc6 = 1, | ||
138 | .has_hotplug = 1, | ||
139 | }; | ||
140 | |||
141 | const static struct intel_device_info intel_sandybridge_d_info = { | ||
142 | .is_i965g = 1, .is_i9xx = 1, .need_gfx_hws = 1, | ||
143 | .has_hotplug = 1, .is_gen6 = 1, | ||
144 | }; | ||
145 | |||
146 | const static struct intel_device_info intel_sandybridge_m_info = { | ||
147 | .is_i965g = 1, .is_mobile = 1, .is_i9xx = 1, .need_gfx_hws = 1, | ||
148 | .has_hotplug = 1, .is_gen6 = 1, | ||
149 | }; | ||
150 | |||
151 | const static struct pci_device_id pciidlist[] = { | ||
152 | INTEL_VGA_DEVICE(0x3577, &intel_i830_info), | ||
153 | INTEL_VGA_DEVICE(0x2562, &intel_845g_info), | ||
154 | INTEL_VGA_DEVICE(0x3582, &intel_i85x_info), | ||
155 | INTEL_VGA_DEVICE(0x358e, &intel_i85x_info), | ||
156 | INTEL_VGA_DEVICE(0x2572, &intel_i865g_info), | ||
157 | INTEL_VGA_DEVICE(0x2582, &intel_i915g_info), | ||
158 | INTEL_VGA_DEVICE(0x258a, &intel_i915g_info), | ||
159 | INTEL_VGA_DEVICE(0x2592, &intel_i915gm_info), | ||
160 | INTEL_VGA_DEVICE(0x2772, &intel_i945g_info), | ||
161 | INTEL_VGA_DEVICE(0x27a2, &intel_i945gm_info), | ||
162 | INTEL_VGA_DEVICE(0x27ae, &intel_i945gm_info), | ||
163 | INTEL_VGA_DEVICE(0x2972, &intel_i965g_info), | ||
164 | INTEL_VGA_DEVICE(0x2982, &intel_i965g_info), | ||
165 | INTEL_VGA_DEVICE(0x2992, &intel_i965g_info), | ||
166 | INTEL_VGA_DEVICE(0x29a2, &intel_i965g_info), | ||
167 | INTEL_VGA_DEVICE(0x29b2, &intel_g33_info), | ||
168 | INTEL_VGA_DEVICE(0x29c2, &intel_g33_info), | ||
169 | INTEL_VGA_DEVICE(0x29d2, &intel_g33_info), | ||
170 | INTEL_VGA_DEVICE(0x2a02, &intel_i965gm_info), | ||
171 | INTEL_VGA_DEVICE(0x2a12, &intel_i965gm_info), | ||
172 | INTEL_VGA_DEVICE(0x2a42, &intel_gm45_info), | ||
173 | INTEL_VGA_DEVICE(0x2e02, &intel_g45_info), | ||
174 | INTEL_VGA_DEVICE(0x2e12, &intel_g45_info), | ||
175 | INTEL_VGA_DEVICE(0x2e22, &intel_g45_info), | ||
176 | INTEL_VGA_DEVICE(0x2e32, &intel_g45_info), | ||
177 | INTEL_VGA_DEVICE(0x2e42, &intel_g45_info), | ||
178 | INTEL_VGA_DEVICE(0xa001, &intel_pineview_info), | ||
179 | INTEL_VGA_DEVICE(0xa011, &intel_pineview_info), | ||
180 | INTEL_VGA_DEVICE(0x0042, &intel_ironlake_d_info), | ||
181 | INTEL_VGA_DEVICE(0x0046, &intel_ironlake_m_info), | ||
182 | INTEL_VGA_DEVICE(0x0102, &intel_sandybridge_d_info), | ||
183 | INTEL_VGA_DEVICE(0x0106, &intel_sandybridge_m_info), | ||
184 | {0, 0, 0} | ||
53 | }; | 185 | }; |
54 | 186 | ||
55 | #if defined(CONFIG_DRM_I915_KMS) | 187 | #if defined(CONFIG_DRM_I915_KMS) |
56 | MODULE_DEVICE_TABLE(pci, pciidlist); | 188 | MODULE_DEVICE_TABLE(pci, pciidlist); |
57 | #endif | 189 | #endif |
58 | 190 | ||
59 | static int i915_suspend(struct drm_device *dev, pm_message_t state) | 191 | static int i915_drm_freeze(struct drm_device *dev) |
60 | { | 192 | { |
61 | struct drm_i915_private *dev_priv = dev->dev_private; | 193 | struct drm_i915_private *dev_priv = dev->dev_private; |
62 | 194 | ||
63 | if (!dev || !dev_priv) { | ||
64 | DRM_ERROR("dev: %p, dev_priv: %p\n", dev, dev_priv); | ||
65 | DRM_ERROR("DRM not initialized, aborting suspend.\n"); | ||
66 | return -ENODEV; | ||
67 | } | ||
68 | |||
69 | if (state.event == PM_EVENT_PRETHAW) | ||
70 | return 0; | ||
71 | |||
72 | pci_save_state(dev->pdev); | 195 | pci_save_state(dev->pdev); |
73 | 196 | ||
74 | /* If KMS is active, we do the leavevt stuff here */ | 197 | /* If KMS is active, we do the leavevt stuff here */ |
75 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | 198 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { |
76 | if (i915_gem_idle(dev)) | 199 | int error = i915_gem_idle(dev); |
200 | if (error) { | ||
77 | dev_err(&dev->pdev->dev, | 201 | dev_err(&dev->pdev->dev, |
78 | "GEM idle failed, resume may fail\n"); | 202 | "GEM idle failed, resume might fail\n"); |
203 | return error; | ||
204 | } | ||
79 | drm_irq_uninstall(dev); | 205 | drm_irq_uninstall(dev); |
80 | } | 206 | } |
81 | 207 | ||
@@ -83,26 +209,42 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state) | |||
83 | 209 | ||
84 | intel_opregion_free(dev, 1); | 210 | intel_opregion_free(dev, 1); |
85 | 211 | ||
212 | /* Modeset on resume, not lid events */ | ||
213 | dev_priv->modeset_on_lid = 0; | ||
214 | |||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | int i915_suspend(struct drm_device *dev, pm_message_t state) | ||
219 | { | ||
220 | int error; | ||
221 | |||
222 | if (!dev || !dev->dev_private) { | ||
223 | DRM_ERROR("dev: %p\n", dev); | ||
224 | DRM_ERROR("DRM not initialized, aborting suspend.\n"); | ||
225 | return -ENODEV; | ||
226 | } | ||
227 | |||
228 | if (state.event == PM_EVENT_PRETHAW) | ||
229 | return 0; | ||
230 | |||
231 | error = i915_drm_freeze(dev); | ||
232 | if (error) | ||
233 | return error; | ||
234 | |||
86 | if (state.event == PM_EVENT_SUSPEND) { | 235 | if (state.event == PM_EVENT_SUSPEND) { |
87 | /* Shut down the device */ | 236 | /* Shut down the device */ |
88 | pci_disable_device(dev->pdev); | 237 | pci_disable_device(dev->pdev); |
89 | pci_set_power_state(dev->pdev, PCI_D3hot); | 238 | pci_set_power_state(dev->pdev, PCI_D3hot); |
90 | } | 239 | } |
91 | 240 | ||
92 | /* Modeset on resume, not lid events */ | ||
93 | dev_priv->modeset_on_lid = 0; | ||
94 | |||
95 | return 0; | 241 | return 0; |
96 | } | 242 | } |
97 | 243 | ||
98 | static int i915_resume(struct drm_device *dev) | 244 | static int i915_drm_thaw(struct drm_device *dev) |
99 | { | 245 | { |
100 | struct drm_i915_private *dev_priv = dev->dev_private; | 246 | struct drm_i915_private *dev_priv = dev->dev_private; |
101 | int ret = 0; | 247 | int error = 0; |
102 | |||
103 | if (pci_enable_device(dev->pdev)) | ||
104 | return -1; | ||
105 | pci_set_master(dev->pdev); | ||
106 | 248 | ||
107 | i915_restore_state(dev); | 249 | i915_restore_state(dev); |
108 | 250 | ||
@@ -113,21 +255,28 @@ static int i915_resume(struct drm_device *dev) | |||
113 | mutex_lock(&dev->struct_mutex); | 255 | mutex_lock(&dev->struct_mutex); |
114 | dev_priv->mm.suspended = 0; | 256 | dev_priv->mm.suspended = 0; |
115 | 257 | ||
116 | ret = i915_gem_init_ringbuffer(dev); | 258 | error = i915_gem_init_ringbuffer(dev); |
117 | if (ret != 0) | ||
118 | ret = -1; | ||
119 | mutex_unlock(&dev->struct_mutex); | 259 | mutex_unlock(&dev->struct_mutex); |
120 | 260 | ||
121 | drm_irq_install(dev); | 261 | drm_irq_install(dev); |
122 | } | 262 | |
123 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | ||
124 | /* Resume the modeset for every activated CRTC */ | 263 | /* Resume the modeset for every activated CRTC */ |
125 | drm_helper_resume_force_mode(dev); | 264 | drm_helper_resume_force_mode(dev); |
126 | } | 265 | } |
127 | 266 | ||
128 | dev_priv->modeset_on_lid = 0; | 267 | dev_priv->modeset_on_lid = 0; |
129 | 268 | ||
130 | return ret; | 269 | return error; |
270 | } | ||
271 | |||
272 | int i915_resume(struct drm_device *dev) | ||
273 | { | ||
274 | if (pci_enable_device(dev->pdev)) | ||
275 | return -EIO; | ||
276 | |||
277 | pci_set_master(dev->pdev); | ||
278 | |||
279 | return i915_drm_thaw(dev); | ||
131 | } | 280 | } |
132 | 281 | ||
133 | /** | 282 | /** |
@@ -213,7 +362,7 @@ int i965_reset(struct drm_device *dev, u8 flags) | |||
213 | !dev_priv->mm.suspended) { | 362 | !dev_priv->mm.suspended) { |
214 | drm_i915_ring_buffer_t *ring = &dev_priv->ring; | 363 | drm_i915_ring_buffer_t *ring = &dev_priv->ring; |
215 | struct drm_gem_object *obj = ring->ring_obj; | 364 | struct drm_gem_object *obj = ring->ring_obj; |
216 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | 365 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); |
217 | dev_priv->mm.suspended = 0; | 366 | dev_priv->mm.suspended = 0; |
218 | 367 | ||
219 | /* Stop the ring if it's running. */ | 368 | /* Stop the ring if it's running. */ |
@@ -268,22 +417,73 @@ i915_pci_remove(struct pci_dev *pdev) | |||
268 | drm_put_dev(dev); | 417 | drm_put_dev(dev); |
269 | } | 418 | } |
270 | 419 | ||
271 | static int | 420 | static int i915_pm_suspend(struct device *dev) |
272 | i915_pci_suspend(struct pci_dev *pdev, pm_message_t state) | ||
273 | { | 421 | { |
274 | struct drm_device *dev = pci_get_drvdata(pdev); | 422 | struct pci_dev *pdev = to_pci_dev(dev); |
423 | struct drm_device *drm_dev = pci_get_drvdata(pdev); | ||
424 | int error; | ||
275 | 425 | ||
276 | return i915_suspend(dev, state); | 426 | if (!drm_dev || !drm_dev->dev_private) { |
427 | dev_err(dev, "DRM not initialized, aborting suspend.\n"); | ||
428 | return -ENODEV; | ||
429 | } | ||
430 | |||
431 | error = i915_drm_freeze(drm_dev); | ||
432 | if (error) | ||
433 | return error; | ||
434 | |||
435 | pci_disable_device(pdev); | ||
436 | pci_set_power_state(pdev, PCI_D3hot); | ||
437 | |||
438 | return 0; | ||
277 | } | 439 | } |
278 | 440 | ||
279 | static int | 441 | static int i915_pm_resume(struct device *dev) |
280 | i915_pci_resume(struct pci_dev *pdev) | ||
281 | { | 442 | { |
282 | struct drm_device *dev = pci_get_drvdata(pdev); | 443 | struct pci_dev *pdev = to_pci_dev(dev); |
444 | struct drm_device *drm_dev = pci_get_drvdata(pdev); | ||
445 | |||
446 | return i915_resume(drm_dev); | ||
447 | } | ||
448 | |||
449 | static int i915_pm_freeze(struct device *dev) | ||
450 | { | ||
451 | struct pci_dev *pdev = to_pci_dev(dev); | ||
452 | struct drm_device *drm_dev = pci_get_drvdata(pdev); | ||
453 | |||
454 | if (!drm_dev || !drm_dev->dev_private) { | ||
455 | dev_err(dev, "DRM not initialized, aborting suspend.\n"); | ||
456 | return -ENODEV; | ||
457 | } | ||
458 | |||
459 | return i915_drm_freeze(drm_dev); | ||
460 | } | ||
461 | |||
462 | static int i915_pm_thaw(struct device *dev) | ||
463 | { | ||
464 | struct pci_dev *pdev = to_pci_dev(dev); | ||
465 | struct drm_device *drm_dev = pci_get_drvdata(pdev); | ||
466 | |||
467 | return i915_drm_thaw(drm_dev); | ||
468 | } | ||
469 | |||
470 | static int i915_pm_poweroff(struct device *dev) | ||
471 | { | ||
472 | struct pci_dev *pdev = to_pci_dev(dev); | ||
473 | struct drm_device *drm_dev = pci_get_drvdata(pdev); | ||
283 | 474 | ||
284 | return i915_resume(dev); | 475 | return i915_drm_freeze(drm_dev); |
285 | } | 476 | } |
286 | 477 | ||
478 | const struct dev_pm_ops i915_pm_ops = { | ||
479 | .suspend = i915_pm_suspend, | ||
480 | .resume = i915_pm_resume, | ||
481 | .freeze = i915_pm_freeze, | ||
482 | .thaw = i915_pm_thaw, | ||
483 | .poweroff = i915_pm_poweroff, | ||
484 | .restore = i915_pm_resume, | ||
485 | }; | ||
486 | |||
287 | static struct vm_operations_struct i915_gem_vm_ops = { | 487 | static struct vm_operations_struct i915_gem_vm_ops = { |
288 | .fault = i915_gem_fault, | 488 | .fault = i915_gem_fault, |
289 | .open = drm_gem_vm_open, | 489 | .open = drm_gem_vm_open, |
@@ -303,8 +503,11 @@ static struct drm_driver driver = { | |||
303 | .lastclose = i915_driver_lastclose, | 503 | .lastclose = i915_driver_lastclose, |
304 | .preclose = i915_driver_preclose, | 504 | .preclose = i915_driver_preclose, |
305 | .postclose = i915_driver_postclose, | 505 | .postclose = i915_driver_postclose, |
506 | |||
507 | /* Used in place of i915_pm_ops for non-DRIVER_MODESET */ | ||
306 | .suspend = i915_suspend, | 508 | .suspend = i915_suspend, |
307 | .resume = i915_resume, | 509 | .resume = i915_resume, |
510 | |||
308 | .device_is_agp = i915_driver_device_is_agp, | 511 | .device_is_agp = i915_driver_device_is_agp, |
309 | .enable_vblank = i915_enable_vblank, | 512 | .enable_vblank = i915_enable_vblank, |
310 | .disable_vblank = i915_disable_vblank, | 513 | .disable_vblank = i915_disable_vblank, |
@@ -329,10 +532,11 @@ static struct drm_driver driver = { | |||
329 | .owner = THIS_MODULE, | 532 | .owner = THIS_MODULE, |
330 | .open = drm_open, | 533 | .open = drm_open, |
331 | .release = drm_release, | 534 | .release = drm_release, |
332 | .ioctl = drm_ioctl, | 535 | .unlocked_ioctl = drm_ioctl, |
333 | .mmap = drm_gem_mmap, | 536 | .mmap = drm_gem_mmap, |
334 | .poll = drm_poll, | 537 | .poll = drm_poll, |
335 | .fasync = drm_fasync, | 538 | .fasync = drm_fasync, |
539 | .read = drm_read, | ||
336 | #ifdef CONFIG_COMPAT | 540 | #ifdef CONFIG_COMPAT |
337 | .compat_ioctl = i915_compat_ioctl, | 541 | .compat_ioctl = i915_compat_ioctl, |
338 | #endif | 542 | #endif |
@@ -343,10 +547,7 @@ static struct drm_driver driver = { | |||
343 | .id_table = pciidlist, | 547 | .id_table = pciidlist, |
344 | .probe = i915_pci_probe, | 548 | .probe = i915_pci_probe, |
345 | .remove = i915_pci_remove, | 549 | .remove = i915_pci_remove, |
346 | #ifdef CONFIG_PM | 550 | .driver.pm = &i915_pm_ops, |
347 | .resume = i915_pci_resume, | ||
348 | .suspend = i915_pci_suspend, | ||
349 | #endif | ||
350 | }, | 551 | }, |
351 | 552 | ||
352 | .name = DRIVER_NAME, | 553 | .name = DRIVER_NAME, |
@@ -359,6 +560,11 @@ static struct drm_driver driver = { | |||
359 | 560 | ||
360 | static int __init i915_init(void) | 561 | static int __init i915_init(void) |
361 | { | 562 | { |
563 | if (!intel_agp_enabled) { | ||
564 | DRM_ERROR("drm/i915 can't work without intel_agp module!\n"); | ||
565 | return -ENODEV; | ||
566 | } | ||
567 | |||
362 | driver.num_ioctls = i915_max_ioctl; | 568 | driver.num_ioctls = i915_max_ioctl; |
363 | 569 | ||
364 | i915_gem_shrinker_init(); | 570 | i915_gem_shrinker_init(); |
@@ -384,6 +590,11 @@ static int __init i915_init(void) | |||
384 | driver.driver_features &= ~DRIVER_MODESET; | 590 | driver.driver_features &= ~DRIVER_MODESET; |
385 | #endif | 591 | #endif |
386 | 592 | ||
593 | if (!(driver.driver_features & DRIVER_MODESET)) { | ||
594 | driver.suspend = i915_suspend; | ||
595 | driver.resume = i915_resume; | ||
596 | } | ||
597 | |||
387 | return drm_init(&driver); | 598 | return drm_init(&driver); |
388 | } | 599 | } |
389 | 600 | ||