diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_fbcon.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_fbcon.c | 137 |
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 02a4d1fd484..22e83adcc93 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 | ||
52 | static void | ||
53 | nouveau_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 | |||
80 | static void | ||
81 | nouveau_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 | |||
108 | static void | ||
109 | nouveau_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 | |||
52 | static int | 136 | static int |
53 | nouveau_fbcon_sync(struct fb_info *info) | 137 | nouveau_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 | |||
111 | static 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 | ||
126 | static struct fb_ops nv50_fbcon_ops = { | 195 | static 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); |