2 * Copyright 2009 Ben Skeggs
3 * Copyright 2008 Stuart Bennett
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
26 #include "nouveau_drv.h"
27 #include "nouveau_dma.h"
28 #include "nouveau_fbcon.h"
31 nv04_fbcon_copyarea(struct fb_info
*info
, const struct fb_copyarea
*region
)
33 struct nouveau_fbcon_par
*par
= info
->par
;
34 struct drm_device
*dev
= par
->dev
;
35 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
36 struct nouveau_channel
*chan
= dev_priv
->channel
;
38 if (info
->state
!= FBINFO_STATE_RUNNING
)
41 if (!(info
->flags
& FBINFO_HWACCEL_DISABLED
) && RING_SPACE(chan
, 4)) {
42 nouveau_fbcon_gpu_lockup(info
);
45 if (info
->flags
& FBINFO_HWACCEL_DISABLED
) {
46 cfb_copyarea(info
, region
);
50 BEGIN_RING(chan
, NvSubImageBlit
, 0x0300, 3);
51 OUT_RING(chan
, (region
->sy
<< 16) | region
->sx
);
52 OUT_RING(chan
, (region
->dy
<< 16) | region
->dx
);
53 OUT_RING(chan
, (region
->height
<< 16) | region
->width
);
58 nv04_fbcon_fillrect(struct fb_info
*info
, const struct fb_fillrect
*rect
)
60 struct nouveau_fbcon_par
*par
= info
->par
;
61 struct drm_device
*dev
= par
->dev
;
62 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
63 struct nouveau_channel
*chan
= dev_priv
->channel
;
65 if (info
->state
!= FBINFO_STATE_RUNNING
)
68 if (!(info
->flags
& FBINFO_HWACCEL_DISABLED
) && RING_SPACE(chan
, 7)) {
69 nouveau_fbcon_gpu_lockup(info
);
72 if (info
->flags
& FBINFO_HWACCEL_DISABLED
) {
73 cfb_fillrect(info
, rect
);
77 BEGIN_RING(chan
, NvSubGdiRect
, 0x02fc, 1);
78 OUT_RING(chan
, (rect
->rop
!= ROP_COPY
) ? 1 : 3);
79 BEGIN_RING(chan
, NvSubGdiRect
, 0x03fc, 1);
80 if (info
->fix
.visual
== FB_VISUAL_TRUECOLOR
||
81 info
->fix
.visual
== FB_VISUAL_DIRECTCOLOR
)
82 OUT_RING(chan
, ((uint32_t *)info
->pseudo_palette
)[rect
->color
]);
84 OUT_RING(chan
, rect
->color
);
85 BEGIN_RING(chan
, NvSubGdiRect
, 0x0400, 2);
86 OUT_RING(chan
, (rect
->dx
<< 16) | rect
->dy
);
87 OUT_RING(chan
, (rect
->width
<< 16) | rect
->height
);
92 nv04_fbcon_imageblit(struct fb_info
*info
, const struct fb_image
*image
)
94 struct nouveau_fbcon_par
*par
= info
->par
;
95 struct drm_device
*dev
= par
->dev
;
96 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
97 struct nouveau_channel
*chan
= dev_priv
->channel
;
102 uint32_t *data
= (uint32_t *)image
->data
;
104 if (info
->state
!= FBINFO_STATE_RUNNING
)
107 if (image
->depth
!= 1) {
108 cfb_imageblit(info
, image
);
112 if (!(info
->flags
& FBINFO_HWACCEL_DISABLED
) && RING_SPACE(chan
, 8)) {
113 nouveau_fbcon_gpu_lockup(info
);
116 if (info
->flags
& FBINFO_HWACCEL_DISABLED
) {
117 cfb_imageblit(info
, image
);
121 width
= (image
->width
+ 31) & ~31;
122 dsize
= (width
* image
->height
) >> 5;
124 if (info
->fix
.visual
== FB_VISUAL_TRUECOLOR
||
125 info
->fix
.visual
== FB_VISUAL_DIRECTCOLOR
) {
126 fg
= ((uint32_t *) info
->pseudo_palette
)[image
->fg_color
];
127 bg
= ((uint32_t *) info
->pseudo_palette
)[image
->bg_color
];
129 fg
= image
->fg_color
;
130 bg
= image
->bg_color
;
133 BEGIN_RING(chan
, NvSubGdiRect
, 0x0be4, 7);
134 OUT_RING(chan
, (image
->dy
<< 16) | (image
->dx
& 0xffff));
135 OUT_RING(chan
, ((image
->dy
+ image
->height
) << 16) |
136 ((image
->dx
+ image
->width
) & 0xffff));
139 OUT_RING(chan
, (image
->height
<< 16) | image
->width
);
140 OUT_RING(chan
, (image
->height
<< 16) | width
);
141 OUT_RING(chan
, (image
->dy
<< 16) | (image
->dx
& 0xffff));
144 int iter_len
= dsize
> 128 ? 128 : dsize
;
146 if (RING_SPACE(chan
, iter_len
+ 1)) {
147 nouveau_fbcon_gpu_lockup(info
);
148 cfb_imageblit(info
, image
);
152 BEGIN_RING(chan
, NvSubGdiRect
, 0x0c00, iter_len
);
153 OUT_RINGp(chan
, data
, iter_len
);
162 nv04_fbcon_grobj_new(struct drm_device
*dev
, int class, uint32_t handle
)
164 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
165 struct nouveau_gpuobj
*obj
= NULL
;
168 ret
= nouveau_gpuobj_gr_new(dev_priv
->channel
, class, &obj
);
172 ret
= nouveau_gpuobj_ref_add(dev
, dev_priv
->channel
, handle
, obj
, NULL
);
180 nv04_fbcon_accel_init(struct fb_info
*info
)
182 struct nouveau_fbcon_par
*par
= info
->par
;
183 struct drm_device
*dev
= par
->dev
;
184 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
185 struct nouveau_channel
*chan
= dev_priv
->channel
;
186 const int sub
= NvSubCtxSurf2D
;
187 int surface_fmt
, pattern_fmt
, rect_fmt
;
190 switch (info
->var
.bits_per_pixel
) {
202 switch (info
->var
.transp
.length
) {
203 case 0: /* depth 24 */
204 case 8: /* depth 32 */
218 ret
= nv04_fbcon_grobj_new(dev
, dev_priv
->card_type
>= NV_10
?
219 0x0062 : 0x0042, NvCtxSurf2D
);
223 ret
= nv04_fbcon_grobj_new(dev
, 0x0019, NvClipRect
);
227 ret
= nv04_fbcon_grobj_new(dev
, 0x0043, NvRop
);
231 ret
= nv04_fbcon_grobj_new(dev
, 0x0044, NvImagePatt
);
235 ret
= nv04_fbcon_grobj_new(dev
, 0x004a, NvGdiRect
);
239 ret
= nv04_fbcon_grobj_new(dev
, dev_priv
->card_type
>= NV_10
?
240 0x009f : 0x005f, NvImageBlit
);
244 if (RING_SPACE(chan
, 49)) {
245 nouveau_fbcon_gpu_lockup(info
);
249 BEGIN_RING(chan
, sub
, 0x0000, 1);
250 OUT_RING(chan
, NvCtxSurf2D
);
251 BEGIN_RING(chan
, sub
, 0x0184, 2);
252 OUT_RING(chan
, NvDmaFB
);
253 OUT_RING(chan
, NvDmaFB
);
254 BEGIN_RING(chan
, sub
, 0x0300, 4);
255 OUT_RING(chan
, surface_fmt
);
256 OUT_RING(chan
, info
->fix
.line_length
| (info
->fix
.line_length
<< 16));
257 OUT_RING(chan
, info
->fix
.smem_start
- dev
->mode_config
.fb_base
);
258 OUT_RING(chan
, info
->fix
.smem_start
- dev
->mode_config
.fb_base
);
260 BEGIN_RING(chan
, sub
, 0x0000, 1);
261 OUT_RING(chan
, NvRop
);
262 BEGIN_RING(chan
, sub
, 0x0300, 1);
263 OUT_RING(chan
, 0x55);
265 BEGIN_RING(chan
, sub
, 0x0000, 1);
266 OUT_RING(chan
, NvImagePatt
);
267 BEGIN_RING(chan
, sub
, 0x0300, 8);
268 OUT_RING(chan
, pattern_fmt
);
281 BEGIN_RING(chan
, sub
, 0x0000, 1);
282 OUT_RING(chan
, NvClipRect
);
283 BEGIN_RING(chan
, sub
, 0x0300, 2);
285 OUT_RING(chan
, (info
->var
.yres_virtual
<< 16) | info
->var
.xres_virtual
);
287 BEGIN_RING(chan
, NvSubImageBlit
, 0x0000, 1);
288 OUT_RING(chan
, NvImageBlit
);
289 BEGIN_RING(chan
, NvSubImageBlit
, 0x019c, 1);
290 OUT_RING(chan
, NvCtxSurf2D
);
291 BEGIN_RING(chan
, NvSubImageBlit
, 0x02fc, 1);
294 BEGIN_RING(chan
, NvSubGdiRect
, 0x0000, 1);
295 OUT_RING(chan
, NvGdiRect
);
296 BEGIN_RING(chan
, NvSubGdiRect
, 0x0198, 1);
297 OUT_RING(chan
, NvCtxSurf2D
);
298 BEGIN_RING(chan
, NvSubGdiRect
, 0x0188, 2);
299 OUT_RING(chan
, NvImagePatt
);
300 OUT_RING(chan
, NvRop
);
301 BEGIN_RING(chan
, NvSubGdiRect
, 0x0304, 1);
303 BEGIN_RING(chan
, NvSubGdiRect
, 0x0300, 1);
304 OUT_RING(chan
, rect_fmt
);
305 BEGIN_RING(chan
, NvSubGdiRect
, 0x02fc, 1);
310 info
->fbops
->fb_fillrect
= nv04_fbcon_fillrect
;
311 info
->fbops
->fb_copyarea
= nv04_fbcon_copyarea
;
312 info
->fbops
->fb_imageblit
= nv04_fbcon_imageblit
;