diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_fbcon.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_fbcon.c | 225 |
1 files changed, 118 insertions, 107 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index f3f0b4c362c..8b8bc8314d9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c | |||
@@ -43,19 +43,31 @@ | |||
43 | #include "drm_crtc.h" | 43 | #include "drm_crtc.h" |
44 | #include "drm_crtc_helper.h" | 44 | #include "drm_crtc_helper.h" |
45 | #include "drm_fb_helper.h" | 45 | #include "drm_fb_helper.h" |
46 | #include "nouveau_drv.h" | 46 | |
47 | #include <nouveau_drm.h> | 47 | #include "nouveau_drm.h" |
48 | #include "nouveau_crtc.h" | 48 | #include "nouveau_gem.h" |
49 | #include "nouveau_bo.h" | ||
49 | #include "nouveau_fb.h" | 50 | #include "nouveau_fb.h" |
50 | #include "nouveau_fbcon.h" | 51 | #include "nouveau_fbcon.h" |
51 | #include "nouveau_dma.h" | 52 | #include "nouveau_chan.h" |
53 | |||
54 | #include "nouveau_crtc.h" | ||
55 | |||
56 | #include <core/client.h> | ||
57 | #include <core/device.h> | ||
58 | |||
59 | #include <subdev/fb.h> | ||
60 | |||
61 | MODULE_PARM_DESC(nofbaccel, "Disable fbcon acceleration"); | ||
62 | static int nouveau_nofbaccel = 0; | ||
63 | module_param_named(nofbaccel, nouveau_nofbaccel, int, 0400); | ||
52 | 64 | ||
53 | static void | 65 | static void |
54 | nouveau_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) | 66 | nouveau_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) |
55 | { | 67 | { |
56 | struct nouveau_fbdev *nfbdev = info->par; | 68 | struct nouveau_fbdev *fbcon = info->par; |
57 | struct drm_device *dev = nfbdev->dev; | 69 | struct nouveau_drm *drm = nouveau_newpriv(fbcon->dev); |
58 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 70 | struct nouveau_device *device = nv_device(drm->device); |
59 | int ret; | 71 | int ret; |
60 | 72 | ||
61 | if (info->state != FBINFO_STATE_RUNNING) | 73 | if (info->state != FBINFO_STATE_RUNNING) |
@@ -63,15 +75,15 @@ nouveau_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) | |||
63 | 75 | ||
64 | ret = -ENODEV; | 76 | ret = -ENODEV; |
65 | if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED) && | 77 | if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED) && |
66 | mutex_trylock(&dev_priv->channel->mutex)) { | 78 | mutex_trylock(&drm->client.mutex)) { |
67 | if (dev_priv->card_type < NV_50) | 79 | if (device->card_type < NV_50) |
68 | ret = nv04_fbcon_fillrect(info, rect); | 80 | ret = nv04_fbcon_fillrect(info, rect); |
69 | else | 81 | else |
70 | if (dev_priv->card_type < NV_C0) | 82 | if (device->card_type < NV_C0) |
71 | ret = nv50_fbcon_fillrect(info, rect); | 83 | ret = nv50_fbcon_fillrect(info, rect); |
72 | else | 84 | else |
73 | ret = nvc0_fbcon_fillrect(info, rect); | 85 | ret = nvc0_fbcon_fillrect(info, rect); |
74 | mutex_unlock(&dev_priv->channel->mutex); | 86 | mutex_unlock(&drm->client.mutex); |
75 | } | 87 | } |
76 | 88 | ||
77 | if (ret == 0) | 89 | if (ret == 0) |
@@ -85,9 +97,9 @@ nouveau_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) | |||
85 | static void | 97 | static void |
86 | nouveau_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *image) | 98 | nouveau_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *image) |
87 | { | 99 | { |
88 | struct nouveau_fbdev *nfbdev = info->par; | 100 | struct nouveau_fbdev *fbcon = info->par; |
89 | struct drm_device *dev = nfbdev->dev; | 101 | struct nouveau_drm *drm = nouveau_newpriv(fbcon->dev); |
90 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 102 | struct nouveau_device *device = nv_device(drm->device); |
91 | int ret; | 103 | int ret; |
92 | 104 | ||
93 | if (info->state != FBINFO_STATE_RUNNING) | 105 | if (info->state != FBINFO_STATE_RUNNING) |
@@ -95,15 +107,15 @@ nouveau_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *image) | |||
95 | 107 | ||
96 | ret = -ENODEV; | 108 | ret = -ENODEV; |
97 | if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED) && | 109 | if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED) && |
98 | mutex_trylock(&dev_priv->channel->mutex)) { | 110 | mutex_trylock(&drm->client.mutex)) { |
99 | if (dev_priv->card_type < NV_50) | 111 | if (device->card_type < NV_50) |
100 | ret = nv04_fbcon_copyarea(info, image); | 112 | ret = nv04_fbcon_copyarea(info, image); |
101 | else | 113 | else |
102 | if (dev_priv->card_type < NV_C0) | 114 | if (device->card_type < NV_C0) |
103 | ret = nv50_fbcon_copyarea(info, image); | 115 | ret = nv50_fbcon_copyarea(info, image); |
104 | else | 116 | else |
105 | ret = nvc0_fbcon_copyarea(info, image); | 117 | ret = nvc0_fbcon_copyarea(info, image); |
106 | mutex_unlock(&dev_priv->channel->mutex); | 118 | mutex_unlock(&drm->client.mutex); |
107 | } | 119 | } |
108 | 120 | ||
109 | if (ret == 0) | 121 | if (ret == 0) |
@@ -117,9 +129,9 @@ nouveau_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *image) | |||
117 | static void | 129 | static void |
118 | nouveau_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) | 130 | nouveau_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) |
119 | { | 131 | { |
120 | struct nouveau_fbdev *nfbdev = info->par; | 132 | struct nouveau_fbdev *fbcon = info->par; |
121 | struct drm_device *dev = nfbdev->dev; | 133 | struct nouveau_drm *drm = nouveau_newpriv(fbcon->dev); |
122 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 134 | struct nouveau_device *device = nv_device(drm->device); |
123 | int ret; | 135 | int ret; |
124 | 136 | ||
125 | if (info->state != FBINFO_STATE_RUNNING) | 137 | if (info->state != FBINFO_STATE_RUNNING) |
@@ -127,15 +139,15 @@ nouveau_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) | |||
127 | 139 | ||
128 | ret = -ENODEV; | 140 | ret = -ENODEV; |
129 | if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED) && | 141 | if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED) && |
130 | mutex_trylock(&dev_priv->channel->mutex)) { | 142 | mutex_trylock(&drm->client.mutex)) { |
131 | if (dev_priv->card_type < NV_50) | 143 | if (device->card_type < NV_50) |
132 | ret = nv04_fbcon_imageblit(info, image); | 144 | ret = nv04_fbcon_imageblit(info, image); |
133 | else | 145 | else |
134 | if (dev_priv->card_type < NV_C0) | 146 | if (device->card_type < NV_C0) |
135 | ret = nv50_fbcon_imageblit(info, image); | 147 | ret = nv50_fbcon_imageblit(info, image); |
136 | else | 148 | else |
137 | ret = nvc0_fbcon_imageblit(info, image); | 149 | ret = nvc0_fbcon_imageblit(info, image); |
138 | mutex_unlock(&dev_priv->channel->mutex); | 150 | mutex_unlock(&drm->client.mutex); |
139 | } | 151 | } |
140 | 152 | ||
141 | if (ret == 0) | 153 | if (ret == 0) |
@@ -149,10 +161,9 @@ nouveau_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) | |||
149 | static int | 161 | static int |
150 | nouveau_fbcon_sync(struct fb_info *info) | 162 | nouveau_fbcon_sync(struct fb_info *info) |
151 | { | 163 | { |
152 | struct nouveau_fbdev *nfbdev = info->par; | 164 | struct nouveau_fbdev *fbcon = info->par; |
153 | struct drm_device *dev = nfbdev->dev; | 165 | struct nouveau_drm *drm = nouveau_newpriv(fbcon->dev); |
154 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 166 | struct nouveau_channel *chan = drm->channel; |
155 | struct nouveau_channel *chan = dev_priv->channel; | ||
156 | int ret; | 167 | int ret; |
157 | 168 | ||
158 | if (!chan || !chan->accel_done || in_interrupt() || | 169 | if (!chan || !chan->accel_done || in_interrupt() || |
@@ -160,11 +171,11 @@ nouveau_fbcon_sync(struct fb_info *info) | |||
160 | info->flags & FBINFO_HWACCEL_DISABLED) | 171 | info->flags & FBINFO_HWACCEL_DISABLED) |
161 | return 0; | 172 | return 0; |
162 | 173 | ||
163 | if (!mutex_trylock(&chan->mutex)) | 174 | if (!mutex_trylock(&drm->client.mutex)) |
164 | return 0; | 175 | return 0; |
165 | 176 | ||
166 | ret = nouveau_channel_idle(chan); | 177 | ret = nouveau_channel_idle(chan); |
167 | mutex_unlock(&chan->mutex); | 178 | mutex_unlock(&drm->client.mutex); |
168 | if (ret) { | 179 | if (ret) { |
169 | nouveau_fbcon_gpu_lockup(info); | 180 | nouveau_fbcon_gpu_lockup(info); |
170 | return 0; | 181 | return 0; |
@@ -224,9 +235,9 @@ static void nouveau_fbcon_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, | |||
224 | } | 235 | } |
225 | 236 | ||
226 | static void | 237 | static void |
227 | nouveau_fbcon_zfill(struct drm_device *dev, struct nouveau_fbdev *nfbdev) | 238 | nouveau_fbcon_zfill(struct drm_device *dev, struct nouveau_fbdev *fbcon) |
228 | { | 239 | { |
229 | struct fb_info *info = nfbdev->helper.fbdev; | 240 | struct fb_info *info = fbcon->helper.fbdev; |
230 | struct fb_fillrect rect; | 241 | struct fb_fillrect rect; |
231 | 242 | ||
232 | /* Clear the entire fbcon. The drm will program every connector | 243 | /* Clear the entire fbcon. The drm will program every connector |
@@ -242,11 +253,12 @@ nouveau_fbcon_zfill(struct drm_device *dev, struct nouveau_fbdev *nfbdev) | |||
242 | } | 253 | } |
243 | 254 | ||
244 | static int | 255 | static int |
245 | nouveau_fbcon_create(struct nouveau_fbdev *nfbdev, | 256 | nouveau_fbcon_create(struct nouveau_fbdev *fbcon, |
246 | struct drm_fb_helper_surface_size *sizes) | 257 | struct drm_fb_helper_surface_size *sizes) |
247 | { | 258 | { |
248 | struct drm_device *dev = nfbdev->dev; | 259 | struct drm_device *dev = fbcon->dev; |
249 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 260 | struct nouveau_drm *drm = nouveau_newpriv(dev); |
261 | struct nouveau_device *device = nv_device(drm->device); | ||
250 | struct fb_info *info; | 262 | struct fb_info *info; |
251 | struct drm_framebuffer *fb; | 263 | struct drm_framebuffer *fb; |
252 | struct nouveau_framebuffer *nouveau_fb; | 264 | struct nouveau_framebuffer *nouveau_fb; |
@@ -254,7 +266,6 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev, | |||
254 | struct nouveau_bo *nvbo; | 266 | struct nouveau_bo *nvbo; |
255 | struct drm_mode_fb_cmd2 mode_cmd; | 267 | struct drm_mode_fb_cmd2 mode_cmd; |
256 | struct pci_dev *pdev = dev->pdev; | 268 | struct pci_dev *pdev = dev->pdev; |
257 | struct device *device = &pdev->dev; | ||
258 | int size, ret; | 269 | int size, ret; |
259 | 270 | ||
260 | mode_cmd.width = sizes->surface_width; | 271 | mode_cmd.width = sizes->surface_width; |
@@ -272,37 +283,38 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev, | |||
272 | ret = nouveau_gem_new(dev, size, 0, NOUVEAU_GEM_DOMAIN_VRAM, | 283 | ret = nouveau_gem_new(dev, size, 0, NOUVEAU_GEM_DOMAIN_VRAM, |
273 | 0, 0x0000, &nvbo); | 284 | 0, 0x0000, &nvbo); |
274 | if (ret) { | 285 | if (ret) { |
275 | NV_ERROR(dev, "failed to allocate framebuffer\n"); | 286 | NV_ERROR(drm, "failed to allocate framebuffer\n"); |
276 | goto out; | 287 | goto out; |
277 | } | 288 | } |
278 | 289 | ||
279 | ret = nouveau_bo_pin(nvbo, TTM_PL_FLAG_VRAM); | 290 | ret = nouveau_bo_pin(nvbo, TTM_PL_FLAG_VRAM); |
280 | if (ret) { | 291 | if (ret) { |
281 | NV_ERROR(dev, "failed to pin fb: %d\n", ret); | 292 | NV_ERROR(drm, "failed to pin fb: %d\n", ret); |
282 | nouveau_bo_ref(NULL, &nvbo); | 293 | nouveau_bo_ref(NULL, &nvbo); |
283 | goto out; | 294 | goto out; |
284 | } | 295 | } |
285 | 296 | ||
286 | ret = nouveau_bo_map(nvbo); | 297 | ret = nouveau_bo_map(nvbo); |
287 | if (ret) { | 298 | if (ret) { |
288 | NV_ERROR(dev, "failed to map fb: %d\n", ret); | 299 | NV_ERROR(drm, "failed to map fb: %d\n", ret); |
289 | nouveau_bo_unpin(nvbo); | 300 | nouveau_bo_unpin(nvbo); |
290 | nouveau_bo_ref(NULL, &nvbo); | 301 | nouveau_bo_ref(NULL, &nvbo); |
291 | goto out; | 302 | goto out; |
292 | } | 303 | } |
293 | 304 | ||
294 | chan = nouveau_nofbaccel ? NULL : dev_priv->channel; | 305 | chan = nouveau_nofbaccel ? NULL : drm->channel; |
295 | if (chan && dev_priv->card_type >= NV_50) { | 306 | if (chan && device->card_type >= NV_50) { |
296 | ret = nouveau_bo_vma_add(nvbo, chan->vm, &nfbdev->nouveau_fb.vma); | 307 | ret = nouveau_bo_vma_add(nvbo, nv_client(chan->cli)->vm, |
308 | &fbcon->nouveau_fb.vma); | ||
297 | if (ret) { | 309 | if (ret) { |
298 | NV_ERROR(dev, "failed to map fb into chan: %d\n", ret); | 310 | NV_ERROR(drm, "failed to map fb into chan: %d\n", ret); |
299 | chan = NULL; | 311 | chan = NULL; |
300 | } | 312 | } |
301 | } | 313 | } |
302 | 314 | ||
303 | mutex_lock(&dev->struct_mutex); | 315 | mutex_lock(&dev->struct_mutex); |
304 | 316 | ||
305 | info = framebuffer_alloc(0, device); | 317 | info = framebuffer_alloc(0, &pdev->dev); |
306 | if (!info) { | 318 | if (!info) { |
307 | ret = -ENOMEM; | 319 | ret = -ENOMEM; |
308 | goto out_unref; | 320 | goto out_unref; |
@@ -314,16 +326,16 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev, | |||
314 | goto out_unref; | 326 | goto out_unref; |
315 | } | 327 | } |
316 | 328 | ||
317 | info->par = nfbdev; | 329 | info->par = fbcon; |
318 | 330 | ||
319 | nouveau_framebuffer_init(dev, &nfbdev->nouveau_fb, &mode_cmd, nvbo); | 331 | nouveau_framebuffer_init(dev, &fbcon->nouveau_fb, &mode_cmd, nvbo); |
320 | 332 | ||
321 | nouveau_fb = &nfbdev->nouveau_fb; | 333 | nouveau_fb = &fbcon->nouveau_fb; |
322 | fb = &nouveau_fb->base; | 334 | fb = &nouveau_fb->base; |
323 | 335 | ||
324 | /* setup helper */ | 336 | /* setup helper */ |
325 | nfbdev->helper.fb = fb; | 337 | fbcon->helper.fb = fb; |
326 | nfbdev->helper.fbdev = info; | 338 | fbcon->helper.fbdev = info; |
327 | 339 | ||
328 | strcpy(info->fix.id, "nouveaufb"); | 340 | strcpy(info->fix.id, "nouveaufb"); |
329 | if (nouveau_nofbaccel) | 341 | if (nouveau_nofbaccel) |
@@ -342,25 +354,18 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev, | |||
342 | info->screen_size = size; | 354 | info->screen_size = size; |
343 | 355 | ||
344 | drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); | 356 | drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); |
345 | drm_fb_helper_fill_var(info, &nfbdev->helper, sizes->fb_width, sizes->fb_height); | 357 | drm_fb_helper_fill_var(info, &fbcon->helper, sizes->fb_width, sizes->fb_height); |
346 | |||
347 | /* Set aperture base/size for vesafb takeover */ | ||
348 | info->apertures = dev_priv->apertures; | ||
349 | if (!info->apertures) { | ||
350 | ret = -ENOMEM; | ||
351 | goto out_unref; | ||
352 | } | ||
353 | 358 | ||
354 | /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ | 359 | /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ |
355 | 360 | ||
356 | mutex_unlock(&dev->struct_mutex); | 361 | mutex_unlock(&dev->struct_mutex); |
357 | 362 | ||
358 | if (dev_priv->channel && !nouveau_nofbaccel) { | 363 | if (chan) { |
359 | ret = -ENODEV; | 364 | ret = -ENODEV; |
360 | if (dev_priv->card_type < NV_50) | 365 | if (device->card_type < NV_50) |
361 | ret = nv04_fbcon_accel_init(info); | 366 | ret = nv04_fbcon_accel_init(info); |
362 | else | 367 | else |
363 | if (dev_priv->card_type < NV_C0) | 368 | if (device->card_type < NV_C0) |
364 | ret = nv50_fbcon_accel_init(info); | 369 | ret = nv50_fbcon_accel_init(info); |
365 | else | 370 | else |
366 | ret = nvc0_fbcon_accel_init(info); | 371 | ret = nvc0_fbcon_accel_init(info); |
@@ -369,13 +374,12 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev, | |||
369 | info->fbops = &nouveau_fbcon_ops; | 374 | info->fbops = &nouveau_fbcon_ops; |
370 | } | 375 | } |
371 | 376 | ||
372 | nouveau_fbcon_zfill(dev, nfbdev); | 377 | nouveau_fbcon_zfill(dev, fbcon); |
373 | 378 | ||
374 | /* To allow resizeing without swapping buffers */ | 379 | /* To allow resizeing without swapping buffers */ |
375 | NV_INFO(dev, "allocated %dx%d fb: 0x%lx, bo %p\n", | 380 | NV_INFO(drm, "allocated %dx%d fb: 0x%lx, bo %p\n", |
376 | nouveau_fb->base.width, | 381 | nouveau_fb->base.width, nouveau_fb->base.height, |
377 | nouveau_fb->base.height, | 382 | nvbo->bo.offset, nvbo); |
378 | nvbo->bo.offset, nvbo); | ||
379 | 383 | ||
380 | vga_switcheroo_client_fb_set(dev->pdev, info); | 384 | vga_switcheroo_client_fb_set(dev->pdev, info); |
381 | return 0; | 385 | return 0; |
@@ -390,12 +394,12 @@ static int | |||
390 | nouveau_fbcon_find_or_create_single(struct drm_fb_helper *helper, | 394 | nouveau_fbcon_find_or_create_single(struct drm_fb_helper *helper, |
391 | struct drm_fb_helper_surface_size *sizes) | 395 | struct drm_fb_helper_surface_size *sizes) |
392 | { | 396 | { |
393 | struct nouveau_fbdev *nfbdev = (struct nouveau_fbdev *)helper; | 397 | struct nouveau_fbdev *fbcon = (struct nouveau_fbdev *)helper; |
394 | int new_fb = 0; | 398 | int new_fb = 0; |
395 | int ret; | 399 | int ret; |
396 | 400 | ||
397 | if (!helper->fb) { | 401 | if (!helper->fb) { |
398 | ret = nouveau_fbcon_create(nfbdev, sizes); | 402 | ret = nouveau_fbcon_create(fbcon, sizes); |
399 | if (ret) | 403 | if (ret) |
400 | return ret; | 404 | return ret; |
401 | new_fb = 1; | 405 | new_fb = 1; |
@@ -406,18 +410,18 @@ nouveau_fbcon_find_or_create_single(struct drm_fb_helper *helper, | |||
406 | void | 410 | void |
407 | nouveau_fbcon_output_poll_changed(struct drm_device *dev) | 411 | nouveau_fbcon_output_poll_changed(struct drm_device *dev) |
408 | { | 412 | { |
409 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 413 | struct nouveau_drm *drm = nouveau_newpriv(dev); |
410 | drm_fb_helper_hotplug_event(&dev_priv->nfbdev->helper); | 414 | drm_fb_helper_hotplug_event(&drm->fbcon->helper); |
411 | } | 415 | } |
412 | 416 | ||
413 | static int | 417 | static int |
414 | nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *nfbdev) | 418 | nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *fbcon) |
415 | { | 419 | { |
416 | struct nouveau_framebuffer *nouveau_fb = &nfbdev->nouveau_fb; | 420 | struct nouveau_framebuffer *nouveau_fb = &fbcon->nouveau_fb; |
417 | struct fb_info *info; | 421 | struct fb_info *info; |
418 | 422 | ||
419 | if (nfbdev->helper.fbdev) { | 423 | if (fbcon->helper.fbdev) { |
420 | info = nfbdev->helper.fbdev; | 424 | info = fbcon->helper.fbdev; |
421 | unregister_framebuffer(info); | 425 | unregister_framebuffer(info); |
422 | if (info->cmap.len) | 426 | if (info->cmap.len) |
423 | fb_dealloc_cmap(&info->cmap); | 427 | fb_dealloc_cmap(&info->cmap); |
@@ -430,17 +434,17 @@ nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *nfbdev) | |||
430 | drm_gem_object_unreference_unlocked(nouveau_fb->nvbo->gem); | 434 | drm_gem_object_unreference_unlocked(nouveau_fb->nvbo->gem); |
431 | nouveau_fb->nvbo = NULL; | 435 | nouveau_fb->nvbo = NULL; |
432 | } | 436 | } |
433 | drm_fb_helper_fini(&nfbdev->helper); | 437 | drm_fb_helper_fini(&fbcon->helper); |
434 | drm_framebuffer_cleanup(&nouveau_fb->base); | 438 | drm_framebuffer_cleanup(&nouveau_fb->base); |
435 | return 0; | 439 | return 0; |
436 | } | 440 | } |
437 | 441 | ||
438 | void nouveau_fbcon_gpu_lockup(struct fb_info *info) | 442 | void nouveau_fbcon_gpu_lockup(struct fb_info *info) |
439 | { | 443 | { |
440 | struct nouveau_fbdev *nfbdev = info->par; | 444 | struct nouveau_fbdev *fbcon = info->par; |
441 | struct drm_device *dev = nfbdev->dev; | 445 | struct nouveau_drm *drm = nouveau_newpriv(fbcon->dev); |
442 | 446 | ||
443 | NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); | 447 | NV_ERROR(drm, "GPU lockup - switching to software fbcon\n"); |
444 | info->flags |= FBINFO_HWACCEL_DISABLED; | 448 | info->flags |= FBINFO_HWACCEL_DISABLED; |
445 | } | 449 | } |
446 | 450 | ||
@@ -451,74 +455,81 @@ static struct drm_fb_helper_funcs nouveau_fbcon_helper_funcs = { | |||
451 | }; | 455 | }; |
452 | 456 | ||
453 | 457 | ||
454 | int nouveau_fbcon_init(struct drm_device *dev) | 458 | int |
459 | nouveau_fbcon_init(struct drm_device *dev) | ||
455 | { | 460 | { |
456 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 461 | struct nouveau_drm *drm = nouveau_newpriv(dev); |
457 | struct nouveau_fbdev *nfbdev; | 462 | struct nouveau_fb *pfb = nouveau_fb(drm->device); |
463 | struct nouveau_fbdev *fbcon; | ||
458 | int preferred_bpp; | 464 | int preferred_bpp; |
459 | int ret; | 465 | int ret; |
460 | 466 | ||
461 | nfbdev = kzalloc(sizeof(struct nouveau_fbdev), GFP_KERNEL); | 467 | if (!dev->mode_config.num_crtc) |
462 | if (!nfbdev) | 468 | return 0; |
469 | |||
470 | fbcon = kzalloc(sizeof(struct nouveau_fbdev), GFP_KERNEL); | ||
471 | if (!fbcon) | ||
463 | return -ENOMEM; | 472 | return -ENOMEM; |
464 | 473 | ||
465 | nfbdev->dev = dev; | 474 | fbcon->dev = dev; |
466 | dev_priv->nfbdev = nfbdev; | 475 | drm->fbcon = fbcon; |
467 | nfbdev->helper.funcs = &nouveau_fbcon_helper_funcs; | 476 | fbcon->helper.funcs = &nouveau_fbcon_helper_funcs; |
468 | 477 | ||
469 | ret = drm_fb_helper_init(dev, &nfbdev->helper, | 478 | ret = drm_fb_helper_init(dev, &fbcon->helper, |
470 | dev->mode_config.num_crtc, 4); | 479 | dev->mode_config.num_crtc, 4); |
471 | if (ret) { | 480 | if (ret) { |
472 | kfree(nfbdev); | 481 | kfree(fbcon); |
473 | return ret; | 482 | return ret; |
474 | } | 483 | } |
475 | 484 | ||
476 | drm_fb_helper_single_add_all_connectors(&nfbdev->helper); | 485 | drm_fb_helper_single_add_all_connectors(&fbcon->helper); |
477 | 486 | ||
478 | if (nvfb_vram_size(dev) <= 32 * 1024 * 1024) | 487 | if (pfb->ram.size <= 32 * 1024 * 1024) |
479 | preferred_bpp = 8; | 488 | preferred_bpp = 8; |
480 | else if (nvfb_vram_size(dev) <= 64 * 1024 * 1024) | 489 | else |
490 | if (pfb->ram.size <= 64 * 1024 * 1024) | ||
481 | preferred_bpp = 16; | 491 | preferred_bpp = 16; |
482 | else | 492 | else |
483 | preferred_bpp = 32; | 493 | preferred_bpp = 32; |
484 | 494 | ||
485 | drm_fb_helper_initial_config(&nfbdev->helper, preferred_bpp); | 495 | drm_fb_helper_initial_config(&fbcon->helper, preferred_bpp); |
486 | return 0; | 496 | return 0; |
487 | } | 497 | } |
488 | 498 | ||
489 | void nouveau_fbcon_fini(struct drm_device *dev) | 499 | void |
500 | nouveau_fbcon_fini(struct drm_device *dev) | ||
490 | { | 501 | { |
491 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 502 | struct nouveau_drm *drm = nouveau_newpriv(dev); |
492 | 503 | ||
493 | if (!dev_priv->nfbdev) | 504 | if (!drm->fbcon) |
494 | return; | 505 | return; |
495 | 506 | ||
496 | nouveau_fbcon_destroy(dev, dev_priv->nfbdev); | 507 | nouveau_fbcon_destroy(dev, drm->fbcon); |
497 | kfree(dev_priv->nfbdev); | 508 | kfree(drm->fbcon); |
498 | dev_priv->nfbdev = NULL; | 509 | drm->fbcon = NULL; |
499 | } | 510 | } |
500 | 511 | ||
501 | void nouveau_fbcon_save_disable_accel(struct drm_device *dev) | 512 | void nouveau_fbcon_save_disable_accel(struct drm_device *dev) |
502 | { | 513 | { |
503 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 514 | struct nouveau_drm *drm = nouveau_newpriv(dev); |
504 | 515 | ||
505 | dev_priv->nfbdev->saved_flags = dev_priv->nfbdev->helper.fbdev->flags; | 516 | drm->fbcon->saved_flags = drm->fbcon->helper.fbdev->flags; |
506 | dev_priv->nfbdev->helper.fbdev->flags |= FBINFO_HWACCEL_DISABLED; | 517 | drm->fbcon->helper.fbdev->flags |= FBINFO_HWACCEL_DISABLED; |
507 | } | 518 | } |
508 | 519 | ||
509 | void nouveau_fbcon_restore_accel(struct drm_device *dev) | 520 | void nouveau_fbcon_restore_accel(struct drm_device *dev) |
510 | { | 521 | { |
511 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 522 | struct nouveau_drm *drm = nouveau_newpriv(dev); |
512 | dev_priv->nfbdev->helper.fbdev->flags = dev_priv->nfbdev->saved_flags; | 523 | drm->fbcon->helper.fbdev->flags = drm->fbcon->saved_flags; |
513 | } | 524 | } |
514 | 525 | ||
515 | void nouveau_fbcon_set_suspend(struct drm_device *dev, int state) | 526 | void nouveau_fbcon_set_suspend(struct drm_device *dev, int state) |
516 | { | 527 | { |
517 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 528 | struct nouveau_drm *drm = nouveau_newpriv(dev); |
518 | console_lock(); | 529 | console_lock(); |
519 | if (state == 0) | 530 | if (state == 0) |
520 | nouveau_fbcon_save_disable_accel(dev); | 531 | nouveau_fbcon_save_disable_accel(dev); |
521 | fb_set_suspend(dev_priv->nfbdev->helper.fbdev, state); | 532 | fb_set_suspend(drm->fbcon->helper.fbdev, state); |
522 | if (state == 1) | 533 | if (state == 1) |
523 | nouveau_fbcon_restore_accel(dev); | 534 | nouveau_fbcon_restore_accel(dev); |
524 | console_unlock(); | 535 | console_unlock(); |
@@ -526,6 +537,6 @@ void nouveau_fbcon_set_suspend(struct drm_device *dev, int state) | |||
526 | 537 | ||
527 | void nouveau_fbcon_zfill_all(struct drm_device *dev) | 538 | void nouveau_fbcon_zfill_all(struct drm_device *dev) |
528 | { | 539 | { |
529 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 540 | struct nouveau_drm *drm = nouveau_newpriv(dev); |
530 | nouveau_fbcon_zfill(dev, dev_priv->nfbdev); | 541 | nouveau_fbcon_zfill(dev, drm->fbcon); |
531 | } | 542 | } |