diff options
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_fbcon.c | 137 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_fbcon.h | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv04_fbcon.c | 68 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_fbcon.c | 69 |
4 files changed, 153 insertions, 133 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); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.h b/drivers/gpu/drm/nouveau/nouveau_fbcon.h index e7e12684c37..6b933f2c3a5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.h +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.h | |||
@@ -40,13 +40,13 @@ struct nouveau_fbdev { | |||
40 | 40 | ||
41 | void nouveau_fbcon_restore(void); | 41 | void nouveau_fbcon_restore(void); |
42 | 42 | ||
43 | void nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region); | 43 | int nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region); |
44 | void nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect); | 44 | int nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect); |
45 | void nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image); | 45 | int nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image); |
46 | int nv04_fbcon_accel_init(struct fb_info *info); | 46 | int nv04_fbcon_accel_init(struct fb_info *info); |
47 | void nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect); | 47 | int nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect); |
48 | void nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region); | 48 | int nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region); |
49 | void nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image); | 49 | int nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image); |
50 | int nv50_fbcon_accel_init(struct fb_info *info); | 50 | int nv50_fbcon_accel_init(struct fb_info *info); |
51 | 51 | ||
52 | void nouveau_fbcon_gpu_lockup(struct fb_info *info); | 52 | void nouveau_fbcon_gpu_lockup(struct fb_info *info); |
diff --git a/drivers/gpu/drm/nouveau/nv04_fbcon.c b/drivers/gpu/drm/nouveau/nv04_fbcon.c index 33e4c9388bc..a32804e7d20 100644 --- a/drivers/gpu/drm/nouveau/nv04_fbcon.c +++ b/drivers/gpu/drm/nouveau/nv04_fbcon.c | |||
@@ -28,52 +28,39 @@ | |||
28 | #include "nouveau_ramht.h" | 28 | #include "nouveau_ramht.h" |
29 | #include "nouveau_fbcon.h" | 29 | #include "nouveau_fbcon.h" |
30 | 30 | ||
31 | void | 31 | int |
32 | nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) | 32 | nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) |
33 | { | 33 | { |
34 | struct nouveau_fbdev *nfbdev = info->par; | 34 | struct nouveau_fbdev *nfbdev = info->par; |
35 | struct drm_device *dev = nfbdev->dev; | 35 | struct drm_device *dev = nfbdev->dev; |
36 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 36 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
37 | struct nouveau_channel *chan = dev_priv->channel; | 37 | struct nouveau_channel *chan = dev_priv->channel; |
38 | int ret; | ||
38 | 39 | ||
39 | if (info->state != FBINFO_STATE_RUNNING) | 40 | ret = RING_SPACE(chan, 4); |
40 | return; | 41 | if (ret) |
41 | 42 | return ret; | |
42 | if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 4)) { | ||
43 | nouveau_fbcon_gpu_lockup(info); | ||
44 | } | ||
45 | |||
46 | if (info->flags & FBINFO_HWACCEL_DISABLED) { | ||
47 | cfb_copyarea(info, region); | ||
48 | return; | ||
49 | } | ||
50 | 43 | ||
51 | BEGIN_RING(chan, NvSubImageBlit, 0x0300, 3); | 44 | BEGIN_RING(chan, NvSubImageBlit, 0x0300, 3); |
52 | OUT_RING(chan, (region->sy << 16) | region->sx); | 45 | OUT_RING(chan, (region->sy << 16) | region->sx); |
53 | OUT_RING(chan, (region->dy << 16) | region->dx); | 46 | OUT_RING(chan, (region->dy << 16) | region->dx); |
54 | OUT_RING(chan, (region->height << 16) | region->width); | 47 | OUT_RING(chan, (region->height << 16) | region->width); |
55 | FIRE_RING(chan); | 48 | FIRE_RING(chan); |
49 | return 0; | ||
56 | } | 50 | } |
57 | 51 | ||
58 | void | 52 | int |
59 | nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) | 53 | nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) |
60 | { | 54 | { |
61 | struct nouveau_fbdev *nfbdev = info->par; | 55 | struct nouveau_fbdev *nfbdev = info->par; |
62 | struct drm_device *dev = nfbdev->dev; | 56 | struct drm_device *dev = nfbdev->dev; |
63 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 57 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
64 | struct nouveau_channel *chan = dev_priv->channel; | 58 | struct nouveau_channel *chan = dev_priv->channel; |
59 | int ret; | ||
65 | 60 | ||
66 | if (info->state != FBINFO_STATE_RUNNING) | 61 | ret = RING_SPACE(chan, 7); |
67 | return; | 62 | if (ret) |
68 | 63 | return ret; | |
69 | if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 7)) { | ||
70 | nouveau_fbcon_gpu_lockup(info); | ||
71 | } | ||
72 | |||
73 | if (info->flags & FBINFO_HWACCEL_DISABLED) { | ||
74 | cfb_fillrect(info, rect); | ||
75 | return; | ||
76 | } | ||
77 | 64 | ||
78 | BEGIN_RING(chan, NvSubGdiRect, 0x02fc, 1); | 65 | BEGIN_RING(chan, NvSubGdiRect, 0x02fc, 1); |
79 | OUT_RING(chan, (rect->rop != ROP_COPY) ? 1 : 3); | 66 | OUT_RING(chan, (rect->rop != ROP_COPY) ? 1 : 3); |
@@ -87,9 +74,10 @@ nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) | |||
87 | OUT_RING(chan, (rect->dx << 16) | rect->dy); | 74 | OUT_RING(chan, (rect->dx << 16) | rect->dy); |
88 | OUT_RING(chan, (rect->width << 16) | rect->height); | 75 | OUT_RING(chan, (rect->width << 16) | rect->height); |
89 | FIRE_RING(chan); | 76 | FIRE_RING(chan); |
77 | return 0; | ||
90 | } | 78 | } |
91 | 79 | ||
92 | void | 80 | int |
93 | nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) | 81 | nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) |
94 | { | 82 | { |
95 | struct nouveau_fbdev *nfbdev = info->par; | 83 | struct nouveau_fbdev *nfbdev = info->par; |
@@ -101,23 +89,14 @@ nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) | |||
101 | uint32_t dsize; | 89 | uint32_t dsize; |
102 | uint32_t width; | 90 | uint32_t width; |
103 | uint32_t *data = (uint32_t *)image->data; | 91 | uint32_t *data = (uint32_t *)image->data; |
92 | int ret; | ||
104 | 93 | ||
105 | if (info->state != FBINFO_STATE_RUNNING) | 94 | if (image->depth != 1) |
106 | return; | 95 | return -ENODEV; |
107 | |||
108 | if (image->depth != 1) { | ||
109 | cfb_imageblit(info, image); | ||
110 | return; | ||
111 | } | ||
112 | |||
113 | if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 8)) { | ||
114 | nouveau_fbcon_gpu_lockup(info); | ||
115 | } | ||
116 | 96 | ||
117 | if (info->flags & FBINFO_HWACCEL_DISABLED) { | 97 | ret = RING_SPACE(chan, 8); |
118 | cfb_imageblit(info, image); | 98 | if (ret) |
119 | return; | 99 | return ret; |
120 | } | ||
121 | 100 | ||
122 | width = ALIGN(image->width, 8); | 101 | width = ALIGN(image->width, 8); |
123 | dsize = ALIGN(width * image->height, 32) >> 5; | 102 | dsize = ALIGN(width * image->height, 32) >> 5; |
@@ -144,11 +123,9 @@ nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) | |||
144 | while (dsize) { | 123 | while (dsize) { |
145 | int iter_len = dsize > 128 ? 128 : dsize; | 124 | int iter_len = dsize > 128 ? 128 : dsize; |
146 | 125 | ||
147 | if (RING_SPACE(chan, iter_len + 1)) { | 126 | ret = RING_SPACE(chan, iter_len + 1); |
148 | nouveau_fbcon_gpu_lockup(info); | 127 | if (ret) |
149 | cfb_imageblit(info, image); | 128 | return ret; |
150 | return; | ||
151 | } | ||
152 | 129 | ||
153 | BEGIN_RING(chan, NvSubGdiRect, 0x0c00, iter_len); | 130 | BEGIN_RING(chan, NvSubGdiRect, 0x0c00, iter_len); |
154 | OUT_RINGp(chan, data, iter_len); | 131 | OUT_RINGp(chan, data, iter_len); |
@@ -157,6 +134,7 @@ nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) | |||
157 | } | 134 | } |
158 | 135 | ||
159 | FIRE_RING(chan); | 136 | FIRE_RING(chan); |
137 | return 0; | ||
160 | } | 138 | } |
161 | 139 | ||
162 | static int | 140 | static int |
diff --git a/drivers/gpu/drm/nouveau/nv50_fbcon.c b/drivers/gpu/drm/nouveau/nv50_fbcon.c index 6dcf048eddb..6edf9dca35c 100644 --- a/drivers/gpu/drm/nouveau/nv50_fbcon.c +++ b/drivers/gpu/drm/nouveau/nv50_fbcon.c | |||
@@ -4,26 +4,18 @@ | |||
4 | #include "nouveau_ramht.h" | 4 | #include "nouveau_ramht.h" |
5 | #include "nouveau_fbcon.h" | 5 | #include "nouveau_fbcon.h" |
6 | 6 | ||
7 | void | 7 | int |
8 | nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) | 8 | nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) |
9 | { | 9 | { |
10 | struct nouveau_fbdev *nfbdev = info->par; | 10 | struct nouveau_fbdev *nfbdev = info->par; |
11 | struct drm_device *dev = nfbdev->dev; | 11 | struct drm_device *dev = nfbdev->dev; |
12 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 12 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
13 | struct nouveau_channel *chan = dev_priv->channel; | 13 | struct nouveau_channel *chan = dev_priv->channel; |
14 | int ret; | ||
14 | 15 | ||
15 | if (info->state != FBINFO_STATE_RUNNING) | 16 | ret = RING_SPACE(chan, rect->rop == ROP_COPY ? 7 : 11); |
16 | return; | 17 | if (ret) |
17 | 18 | return ret; | |
18 | if (!(info->flags & FBINFO_HWACCEL_DISABLED) && | ||
19 | RING_SPACE(chan, rect->rop == ROP_COPY ? 7 : 11)) { | ||
20 | nouveau_fbcon_gpu_lockup(info); | ||
21 | } | ||
22 | |||
23 | if (info->flags & FBINFO_HWACCEL_DISABLED) { | ||
24 | cfb_fillrect(info, rect); | ||
25 | return; | ||
26 | } | ||
27 | 19 | ||
28 | if (rect->rop != ROP_COPY) { | 20 | if (rect->rop != ROP_COPY) { |
29 | BEGIN_RING(chan, NvSub2D, 0x02ac, 1); | 21 | BEGIN_RING(chan, NvSub2D, 0x02ac, 1); |
@@ -45,27 +37,21 @@ nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) | |||
45 | OUT_RING(chan, 3); | 37 | OUT_RING(chan, 3); |
46 | } | 38 | } |
47 | FIRE_RING(chan); | 39 | FIRE_RING(chan); |
40 | return 0; | ||
48 | } | 41 | } |
49 | 42 | ||
50 | void | 43 | int |
51 | nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) | 44 | nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) |
52 | { | 45 | { |
53 | struct nouveau_fbdev *nfbdev = info->par; | 46 | struct nouveau_fbdev *nfbdev = info->par; |
54 | struct drm_device *dev = nfbdev->dev; | 47 | struct drm_device *dev = nfbdev->dev; |
55 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 48 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
56 | struct nouveau_channel *chan = dev_priv->channel; | 49 | struct nouveau_channel *chan = dev_priv->channel; |
50 | int ret; | ||
57 | 51 | ||
58 | if (info->state != FBINFO_STATE_RUNNING) | 52 | ret = RING_SPACE(chan, 12); |
59 | return; | 53 | if (ret) |
60 | 54 | return ret; | |
61 | if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 12)) { | ||
62 | nouveau_fbcon_gpu_lockup(info); | ||
63 | } | ||
64 | |||
65 | if (info->flags & FBINFO_HWACCEL_DISABLED) { | ||
66 | cfb_copyarea(info, region); | ||
67 | return; | ||
68 | } | ||
69 | 55 | ||
70 | BEGIN_RING(chan, NvSub2D, 0x0110, 1); | 56 | BEGIN_RING(chan, NvSub2D, 0x0110, 1); |
71 | OUT_RING(chan, 0); | 57 | OUT_RING(chan, 0); |
@@ -80,9 +66,10 @@ nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) | |||
80 | OUT_RING(chan, 0); | 66 | OUT_RING(chan, 0); |
81 | OUT_RING(chan, region->sy); | 67 | OUT_RING(chan, region->sy); |
82 | FIRE_RING(chan); | 68 | FIRE_RING(chan); |
69 | return 0; | ||
83 | } | 70 | } |
84 | 71 | ||
85 | void | 72 | int |
86 | nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) | 73 | nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) |
87 | { | 74 | { |
88 | struct nouveau_fbdev *nfbdev = info->par; | 75 | struct nouveau_fbdev *nfbdev = info->par; |
@@ -92,23 +79,14 @@ nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) | |||
92 | uint32_t width, dwords, *data = (uint32_t *)image->data; | 79 | uint32_t width, dwords, *data = (uint32_t *)image->data; |
93 | uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel)); | 80 | uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel)); |
94 | uint32_t *palette = info->pseudo_palette; | 81 | uint32_t *palette = info->pseudo_palette; |
82 | int ret; | ||
95 | 83 | ||
96 | if (info->state != FBINFO_STATE_RUNNING) | 84 | if (image->depth != 1) |
97 | return; | 85 | return -ENODEV; |
98 | |||
99 | if (image->depth != 1) { | ||
100 | cfb_imageblit(info, image); | ||
101 | return; | ||
102 | } | ||
103 | |||
104 | if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 11)) { | ||
105 | nouveau_fbcon_gpu_lockup(info); | ||
106 | } | ||
107 | 86 | ||
108 | if (info->flags & FBINFO_HWACCEL_DISABLED) { | 87 | ret = RING_SPACE(chan, 11); |
109 | cfb_imageblit(info, image); | 88 | if (ret) |
110 | return; | 89 | return ret; |
111 | } | ||
112 | 90 | ||
113 | width = ALIGN(image->width, 32); | 91 | width = ALIGN(image->width, 32); |
114 | dwords = (width * image->height) >> 5; | 92 | dwords = (width * image->height) >> 5; |
@@ -134,11 +112,9 @@ nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) | |||
134 | while (dwords) { | 112 | while (dwords) { |
135 | int push = dwords > 2047 ? 2047 : dwords; | 113 | int push = dwords > 2047 ? 2047 : dwords; |
136 | 114 | ||
137 | if (RING_SPACE(chan, push + 1)) { | 115 | ret = RING_SPACE(chan, push + 1); |
138 | nouveau_fbcon_gpu_lockup(info); | 116 | if (ret) |
139 | cfb_imageblit(info, image); | 117 | return ret; |
140 | return; | ||
141 | } | ||
142 | 118 | ||
143 | dwords -= push; | 119 | dwords -= push; |
144 | 120 | ||
@@ -148,6 +124,7 @@ nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) | |||
148 | } | 124 | } |
149 | 125 | ||
150 | FIRE_RING(chan); | 126 | FIRE_RING(chan); |
127 | return 0; | ||
151 | } | 128 | } |
152 | 129 | ||
153 | int | 130 | int |