aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nouveau_fbcon.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_fbcon.c')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fbcon.c137
1 files changed, 101 insertions, 36 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
index 02a4d1fd4845..22e83adcc930 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
@@ -49,6 +49,90 @@
49#include "nouveau_fbcon.h" 49#include "nouveau_fbcon.h"
50#include "nouveau_dma.h" 50#include "nouveau_dma.h"
51 51
52static void
53nouveau_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
54{
55 struct nouveau_fbdev *nfbdev = info->par;
56 struct drm_device *dev = nfbdev->dev;
57 struct drm_nouveau_private *dev_priv = dev->dev_private;
58 int ret;
59
60 if (info->state != FBINFO_STATE_RUNNING)
61 return;
62
63 ret = -ENODEV;
64 if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED)) {
65 if (dev_priv->card_type < NV_50)
66 ret = nv04_fbcon_fillrect(info, rect);
67 else
68 if (dev_priv->card_type < NV_C0)
69 ret = nv50_fbcon_fillrect(info, rect);
70 }
71
72 if (ret == 0)
73 return;
74
75 if (ret != -ENODEV)
76 nouveau_fbcon_gpu_lockup(info);
77 cfb_fillrect(info, rect);
78}
79
80static void
81nouveau_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *image)
82{
83 struct nouveau_fbdev *nfbdev = info->par;
84 struct drm_device *dev = nfbdev->dev;
85 struct drm_nouveau_private *dev_priv = dev->dev_private;
86 int ret;
87
88 if (info->state != FBINFO_STATE_RUNNING)
89 return;
90
91 ret = -ENODEV;
92 if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED)) {
93 if (dev_priv->card_type < NV_50)
94 ret = nv04_fbcon_copyarea(info, image);
95 else
96 if (dev_priv->card_type < NV_C0)
97 ret = nv50_fbcon_copyarea(info, image);
98 }
99
100 if (ret == 0)
101 return;
102
103 if (ret != -ENODEV)
104 nouveau_fbcon_gpu_lockup(info);
105 cfb_copyarea(info, image);
106}
107
108static void
109nouveau_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
110{
111 struct nouveau_fbdev *nfbdev = info->par;
112 struct drm_device *dev = nfbdev->dev;
113 struct drm_nouveau_private *dev_priv = dev->dev_private;
114 int ret;
115
116 if (info->state != FBINFO_STATE_RUNNING)
117 return;
118
119 ret = -ENODEV;
120 if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED)) {
121 if (dev_priv->card_type < NV_50)
122 ret = nv04_fbcon_imageblit(info, image);
123 else
124 if (dev_priv->card_type < NV_C0)
125 ret = nv50_fbcon_imageblit(info, image);
126 }
127
128 if (ret == 0)
129 return;
130
131 if (ret != -ENODEV)
132 nouveau_fbcon_gpu_lockup(info);
133 cfb_imageblit(info, image);
134}
135
52static int 136static int
53nouveau_fbcon_sync(struct fb_info *info) 137nouveau_fbcon_sync(struct fb_info *info)
54{ 138{
@@ -97,24 +181,9 @@ static struct fb_ops nouveau_fbcon_ops = {
97 .owner = THIS_MODULE, 181 .owner = THIS_MODULE,
98 .fb_check_var = drm_fb_helper_check_var, 182 .fb_check_var = drm_fb_helper_check_var,
99 .fb_set_par = drm_fb_helper_set_par, 183 .fb_set_par = drm_fb_helper_set_par,
100 .fb_fillrect = cfb_fillrect, 184 .fb_fillrect = nouveau_fbcon_fillrect,
101 .fb_copyarea = cfb_copyarea, 185 .fb_copyarea = nouveau_fbcon_copyarea,
102 .fb_imageblit = cfb_imageblit, 186 .fb_imageblit = nouveau_fbcon_imageblit,
103 .fb_sync = nouveau_fbcon_sync,
104 .fb_pan_display = drm_fb_helper_pan_display,
105 .fb_blank = drm_fb_helper_blank,
106 .fb_setcmap = drm_fb_helper_setcmap,
107 .fb_debug_enter = drm_fb_helper_debug_enter,
108 .fb_debug_leave = drm_fb_helper_debug_leave,
109};
110
111static struct fb_ops nv04_fbcon_ops = {
112 .owner = THIS_MODULE,
113 .fb_check_var = drm_fb_helper_check_var,
114 .fb_set_par = drm_fb_helper_set_par,
115 .fb_fillrect = nv04_fbcon_fillrect,
116 .fb_copyarea = nv04_fbcon_copyarea,
117 .fb_imageblit = nv04_fbcon_imageblit,
118 .fb_sync = nouveau_fbcon_sync, 187 .fb_sync = nouveau_fbcon_sync,
119 .fb_pan_display = drm_fb_helper_pan_display, 188 .fb_pan_display = drm_fb_helper_pan_display,
120 .fb_blank = drm_fb_helper_blank, 189 .fb_blank = drm_fb_helper_blank,
@@ -123,14 +192,13 @@ static struct fb_ops nv04_fbcon_ops = {
123 .fb_debug_leave = drm_fb_helper_debug_leave, 192 .fb_debug_leave = drm_fb_helper_debug_leave,
124}; 193};
125 194
126static struct fb_ops nv50_fbcon_ops = { 195static struct fb_ops nouveau_fbcon_sw_ops = {
127 .owner = THIS_MODULE, 196 .owner = THIS_MODULE,
128 .fb_check_var = drm_fb_helper_check_var, 197 .fb_check_var = drm_fb_helper_check_var,
129 .fb_set_par = drm_fb_helper_set_par, 198 .fb_set_par = drm_fb_helper_set_par,
130 .fb_fillrect = nv50_fbcon_fillrect, 199 .fb_fillrect = cfb_fillrect,
131 .fb_copyarea = nv50_fbcon_copyarea, 200 .fb_copyarea = cfb_copyarea,
132 .fb_imageblit = nv50_fbcon_imageblit, 201 .fb_imageblit = cfb_imageblit,
133 .fb_sync = nouveau_fbcon_sync,
134 .fb_pan_display = drm_fb_helper_pan_display, 202 .fb_pan_display = drm_fb_helper_pan_display,
135 .fb_blank = drm_fb_helper_blank, 203 .fb_blank = drm_fb_helper_blank,
136 .fb_setcmap = drm_fb_helper_setcmap, 204 .fb_setcmap = drm_fb_helper_setcmap,
@@ -257,7 +325,7 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev,
257 FBINFO_HWACCEL_FILLRECT | 325 FBINFO_HWACCEL_FILLRECT |
258 FBINFO_HWACCEL_IMAGEBLIT; 326 FBINFO_HWACCEL_IMAGEBLIT;
259 info->flags |= FBINFO_CAN_FORCE_OUTPUT; 327 info->flags |= FBINFO_CAN_FORCE_OUTPUT;
260 info->fbops = &nouveau_fbcon_ops; 328 info->fbops = &nouveau_fbcon_sw_ops;
261 info->fix.smem_start = dev->mode_config.fb_base + nvbo->bo.offset - 329 info->fix.smem_start = dev->mode_config.fb_base + nvbo->bo.offset -
262 dev_priv->vm_vram_base; 330 dev_priv->vm_vram_base;
263 info->fix.smem_len = size; 331 info->fix.smem_len = size;
@@ -286,18 +354,15 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev,
286 info->pixmap.scan_align = 1; 354 info->pixmap.scan_align = 1;
287 355
288 if (dev_priv->channel && !nouveau_nofbaccel) { 356 if (dev_priv->channel && !nouveau_nofbaccel) {
289 switch (dev_priv->card_type) { 357 ret = -ENODEV;
290 case NV_C0: 358 if (dev_priv->card_type < NV_50)
291 break; 359 ret = nv04_fbcon_accel_init(info);
292 case NV_50: 360 else
293 nv50_fbcon_accel_init(info); 361 if (dev_priv->card_type < NV_C0)
294 info->fbops = &nv50_fbcon_ops; 362 ret = nv50_fbcon_accel_init(info);
295 break; 363
296 default: 364 if (ret == 0)
297 nv04_fbcon_accel_init(info); 365 info->fbops = &nouveau_fbcon_ops;
298 info->fbops = &nv04_fbcon_ops;
299 break;
300 };
301 } 366 }
302 367
303 nouveau_fbcon_zfill(dev, nfbdev); 368 nouveau_fbcon_zfill(dev, nfbdev);