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