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.
25 #include "nouveau_drv.h"
26 #include "nouveau_dma.h"
27 #include "nouveau_fbcon.h"
30 nv04_fbcon_copyarea(struct fb_info
*info
, const struct fb_copyarea
*region
)
32 struct nouveau_fbdev
*nfbdev
= info
->par
;
33 struct nouveau_drm
*drm
= nouveau_drm(nfbdev
->helper
.dev
);
34 struct nouveau_channel
*chan
= drm
->channel
;
37 ret
= RING_SPACE(chan
, 4);
41 BEGIN_NV04(chan
, NvSubImageBlit
, 0x0300, 3);
42 OUT_RING(chan
, (region
->sy
<< 16) | region
->sx
);
43 OUT_RING(chan
, (region
->dy
<< 16) | region
->dx
);
44 OUT_RING(chan
, (region
->height
<< 16) | region
->width
);
50 nv04_fbcon_fillrect(struct fb_info
*info
, const struct fb_fillrect
*rect
)
52 struct nouveau_fbdev
*nfbdev
= info
->par
;
53 struct nouveau_drm
*drm
= nouveau_drm(nfbdev
->helper
.dev
);
54 struct nouveau_channel
*chan
= drm
->channel
;
57 ret
= RING_SPACE(chan
, 7);
61 BEGIN_NV04(chan
, NvSubGdiRect
, 0x02fc, 1);
62 OUT_RING(chan
, (rect
->rop
!= ROP_COPY
) ? 1 : 3);
63 BEGIN_NV04(chan
, NvSubGdiRect
, 0x03fc, 1);
64 if (info
->fix
.visual
== FB_VISUAL_TRUECOLOR
||
65 info
->fix
.visual
== FB_VISUAL_DIRECTCOLOR
)
66 OUT_RING(chan
, ((uint32_t *)info
->pseudo_palette
)[rect
->color
]);
68 OUT_RING(chan
, rect
->color
);
69 BEGIN_NV04(chan
, NvSubGdiRect
, 0x0400, 2);
70 OUT_RING(chan
, (rect
->dx
<< 16) | rect
->dy
);
71 OUT_RING(chan
, (rect
->width
<< 16) | rect
->height
);
77 nv04_fbcon_imageblit(struct fb_info
*info
, const struct fb_image
*image
)
79 struct nouveau_fbdev
*nfbdev
= info
->par
;
80 struct nouveau_drm
*drm
= nouveau_drm(nfbdev
->helper
.dev
);
81 struct nouveau_channel
*chan
= drm
->channel
;
85 uint32_t *data
= (uint32_t *)image
->data
;
88 if (image
->depth
!= 1)
91 ret
= RING_SPACE(chan
, 8);
95 if (info
->fix
.visual
== FB_VISUAL_TRUECOLOR
||
96 info
->fix
.visual
== FB_VISUAL_DIRECTCOLOR
) {
97 fg
= ((uint32_t *) info
->pseudo_palette
)[image
->fg_color
];
98 bg
= ((uint32_t *) info
->pseudo_palette
)[image
->bg_color
];
100 fg
= image
->fg_color
;
101 bg
= image
->bg_color
;
104 BEGIN_NV04(chan
, NvSubGdiRect
, 0x0be4, 7);
105 OUT_RING(chan
, (image
->dy
<< 16) | (image
->dx
& 0xffff));
106 OUT_RING(chan
, ((image
->dy
+ image
->height
) << 16) |
107 ((image
->dx
+ image
->width
) & 0xffff));
110 OUT_RING(chan
, (image
->height
<< 16) | ALIGN(image
->width
, 8));
111 OUT_RING(chan
, (image
->height
<< 16) | image
->width
);
112 OUT_RING(chan
, (image
->dy
<< 16) | (image
->dx
& 0xffff));
114 dsize
= ALIGN(ALIGN(image
->width
, 8) * image
->height
, 32) >> 5;
116 int iter_len
= dsize
> 128 ? 128 : dsize
;
118 ret
= RING_SPACE(chan
, iter_len
+ 1);
122 BEGIN_NV04(chan
, NvSubGdiRect
, 0x0c00, iter_len
);
123 OUT_RINGp(chan
, data
, iter_len
);
133 nv04_fbcon_accel_init(struct fb_info
*info
)
135 struct nouveau_fbdev
*nfbdev
= info
->par
;
136 struct drm_device
*dev
= nfbdev
->helper
.dev
;
137 struct nouveau_drm
*drm
= nouveau_drm(dev
);
138 struct nouveau_channel
*chan
= drm
->channel
;
139 struct nvif_device
*device
= &drm
->client
.device
;
140 int surface_fmt
, pattern_fmt
, rect_fmt
;
143 switch (info
->var
.bits_per_pixel
) {
155 switch (info
->var
.transp
.length
) {
156 case 0: /* depth 24 */
157 case 8: /* depth 32 */
171 ret
= nvif_object_init(&chan
->user
, 0x0062,
172 device
->info
.family
>= NV_DEVICE_INFO_V0_CELSIUS
?
173 0x0062 : 0x0042, NULL
, 0, &nfbdev
->surf2d
);
177 ret
= nvif_object_init(&chan
->user
, 0x0019, 0x0019, NULL
, 0,
182 ret
= nvif_object_init(&chan
->user
, 0x0043, 0x0043, NULL
, 0,
187 ret
= nvif_object_init(&chan
->user
, 0x0044, 0x0044, NULL
, 0,
192 ret
= nvif_object_init(&chan
->user
, 0x004a, 0x004a, NULL
, 0,
197 ret
= nvif_object_init(&chan
->user
, 0x005f,
198 device
->info
.chipset
>= 0x11 ? 0x009f : 0x005f,
199 NULL
, 0, &nfbdev
->blit
);
203 if (RING_SPACE(chan
, 49 + (device
->info
.chipset
>= 0x11 ? 4 : 0))) {
204 nouveau_fbcon_gpu_lockup(info
);
208 BEGIN_NV04(chan
, NvSubCtxSurf2D
, 0x0000, 1);
209 OUT_RING(chan
, nfbdev
->surf2d
.handle
);
210 BEGIN_NV04(chan
, NvSubCtxSurf2D
, 0x0184, 2);
211 OUT_RING(chan
, chan
->vram
.handle
);
212 OUT_RING(chan
, chan
->vram
.handle
);
213 BEGIN_NV04(chan
, NvSubCtxSurf2D
, 0x0300, 4);
214 OUT_RING(chan
, surface_fmt
);
215 OUT_RING(chan
, info
->fix
.line_length
| (info
->fix
.line_length
<< 16));
216 OUT_RING(chan
, info
->fix
.smem_start
- dev
->mode_config
.fb_base
);
217 OUT_RING(chan
, info
->fix
.smem_start
- dev
->mode_config
.fb_base
);
219 BEGIN_NV04(chan
, NvSubCtxSurf2D
, 0x0000, 1);
220 OUT_RING(chan
, nfbdev
->rop
.handle
);
221 BEGIN_NV04(chan
, NvSubCtxSurf2D
, 0x0300, 1);
222 OUT_RING(chan
, 0x55);
224 BEGIN_NV04(chan
, NvSubCtxSurf2D
, 0x0000, 1);
225 OUT_RING(chan
, nfbdev
->patt
.handle
);
226 BEGIN_NV04(chan
, NvSubCtxSurf2D
, 0x0300, 8);
227 OUT_RING(chan
, pattern_fmt
);
240 BEGIN_NV04(chan
, NvSubCtxSurf2D
, 0x0000, 1);
241 OUT_RING(chan
, nfbdev
->clip
.handle
);
242 BEGIN_NV04(chan
, NvSubCtxSurf2D
, 0x0300, 2);
244 OUT_RING(chan
, (info
->var
.yres_virtual
<< 16) | info
->var
.xres_virtual
);
246 BEGIN_NV04(chan
, NvSubImageBlit
, 0x0000, 1);
247 OUT_RING(chan
, nfbdev
->blit
.handle
);
248 BEGIN_NV04(chan
, NvSubImageBlit
, 0x019c, 1);
249 OUT_RING(chan
, nfbdev
->surf2d
.handle
);
250 BEGIN_NV04(chan
, NvSubImageBlit
, 0x02fc, 1);
252 if (device
->info
.chipset
>= 0x11 /*XXX: oclass == 0x009f*/) {
253 BEGIN_NV04(chan
, NvSubImageBlit
, 0x0120, 3);
259 BEGIN_NV04(chan
, NvSubGdiRect
, 0x0000, 1);
260 OUT_RING(chan
, nfbdev
->gdi
.handle
);
261 BEGIN_NV04(chan
, NvSubGdiRect
, 0x0198, 1);
262 OUT_RING(chan
, nfbdev
->surf2d
.handle
);
263 BEGIN_NV04(chan
, NvSubGdiRect
, 0x0188, 2);
264 OUT_RING(chan
, nfbdev
->patt
.handle
);
265 OUT_RING(chan
, nfbdev
->rop
.handle
);
266 BEGIN_NV04(chan
, NvSubGdiRect
, 0x0304, 1);
268 BEGIN_NV04(chan
, NvSubGdiRect
, 0x0300, 1);
269 OUT_RING(chan
, rect_fmt
);
270 BEGIN_NV04(chan
, NvSubGdiRect
, 0x02fc, 1);