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_drm.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
->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
->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
->dev
);
81 struct nouveau_channel
*chan
= drm
->channel
;
86 uint32_t *data
= (uint32_t *)image
->data
;
89 if (image
->depth
!= 1)
92 ret
= RING_SPACE(chan
, 8);
96 width
= ALIGN(image
->width
, 8);
97 dsize
= ALIGN(width
* image
->height
, 32) >> 5;
99 if (info
->fix
.visual
== FB_VISUAL_TRUECOLOR
||
100 info
->fix
.visual
== FB_VISUAL_DIRECTCOLOR
) {
101 fg
= ((uint32_t *) info
->pseudo_palette
)[image
->fg_color
];
102 bg
= ((uint32_t *) info
->pseudo_palette
)[image
->bg_color
];
104 fg
= image
->fg_color
;
105 bg
= image
->bg_color
;
108 BEGIN_NV04(chan
, NvSubGdiRect
, 0x0be4, 7);
109 OUT_RING(chan
, (image
->dy
<< 16) | (image
->dx
& 0xffff));
110 OUT_RING(chan
, ((image
->dy
+ image
->height
) << 16) |
111 ((image
->dx
+ image
->width
) & 0xffff));
114 OUT_RING(chan
, (image
->height
<< 16) | width
);
115 OUT_RING(chan
, (image
->height
<< 16) | image
->width
);
116 OUT_RING(chan
, (image
->dy
<< 16) | (image
->dx
& 0xffff));
119 int iter_len
= dsize
> 128 ? 128 : dsize
;
121 ret
= RING_SPACE(chan
, iter_len
+ 1);
125 BEGIN_NV04(chan
, NvSubGdiRect
, 0x0c00, iter_len
);
126 OUT_RINGp(chan
, data
, iter_len
);
136 nv04_fbcon_accel_init(struct fb_info
*info
)
138 struct nouveau_fbdev
*nfbdev
= info
->par
;
139 struct drm_device
*dev
= nfbdev
->dev
;
140 struct nouveau_drm
*drm
= nouveau_drm(dev
);
141 struct nouveau_channel
*chan
= drm
->channel
;
142 struct nvif_device
*device
= &drm
->device
;
143 int surface_fmt
, pattern_fmt
, rect_fmt
;
146 switch (info
->var
.bits_per_pixel
) {
158 switch (info
->var
.transp
.length
) {
159 case 0: /* depth 24 */
160 case 8: /* depth 32 */
174 ret
= nvif_object_init(chan
->object
, NULL
, 0x0062,
175 device
->info
.family
>= NV_DEVICE_INFO_V0_CELSIUS
?
176 0x0062 : 0x0042, NULL
, 0, &nfbdev
->surf2d
);
180 ret
= nvif_object_init(chan
->object
, NULL
, 0x0019, 0x0019, NULL
, 0,
185 ret
= nvif_object_init(chan
->object
, NULL
, 0x0043, 0x0043, NULL
, 0,
190 ret
= nvif_object_init(chan
->object
, NULL
, 0x0044, 0x0044, NULL
, 0,
195 ret
= nvif_object_init(chan
->object
, NULL
, 0x004a, 0x004a, NULL
, 0,
200 ret
= nvif_object_init(chan
->object
, NULL
, 0x005f,
201 device
->info
.chipset
>= 0x11 ? 0x009f : 0x005f,
202 NULL
, 0, &nfbdev
->blit
);
206 if (RING_SPACE(chan
, 49 + (device
->info
.chipset
>= 0x11 ? 4 : 0))) {
207 nouveau_fbcon_gpu_lockup(info
);
211 BEGIN_NV04(chan
, NvSubCtxSurf2D
, 0x0000, 1);
212 OUT_RING(chan
, nfbdev
->surf2d
.handle
);
213 BEGIN_NV04(chan
, NvSubCtxSurf2D
, 0x0184, 2);
214 OUT_RING(chan
, chan
->vram
.handle
);
215 OUT_RING(chan
, chan
->vram
.handle
);
216 BEGIN_NV04(chan
, NvSubCtxSurf2D
, 0x0300, 4);
217 OUT_RING(chan
, surface_fmt
);
218 OUT_RING(chan
, info
->fix
.line_length
| (info
->fix
.line_length
<< 16));
219 OUT_RING(chan
, info
->fix
.smem_start
- dev
->mode_config
.fb_base
);
220 OUT_RING(chan
, info
->fix
.smem_start
- dev
->mode_config
.fb_base
);
222 BEGIN_NV04(chan
, NvSubCtxSurf2D
, 0x0000, 1);
223 OUT_RING(chan
, nfbdev
->rop
.handle
);
224 BEGIN_NV04(chan
, NvSubCtxSurf2D
, 0x0300, 1);
225 OUT_RING(chan
, 0x55);
227 BEGIN_NV04(chan
, NvSubCtxSurf2D
, 0x0000, 1);
228 OUT_RING(chan
, nfbdev
->patt
.handle
);
229 BEGIN_NV04(chan
, NvSubCtxSurf2D
, 0x0300, 8);
230 OUT_RING(chan
, pattern_fmt
);
243 BEGIN_NV04(chan
, NvSubCtxSurf2D
, 0x0000, 1);
244 OUT_RING(chan
, nfbdev
->clip
.handle
);
245 BEGIN_NV04(chan
, NvSubCtxSurf2D
, 0x0300, 2);
247 OUT_RING(chan
, (info
->var
.yres_virtual
<< 16) | info
->var
.xres_virtual
);
249 BEGIN_NV04(chan
, NvSubImageBlit
, 0x0000, 1);
250 OUT_RING(chan
, nfbdev
->blit
.handle
);
251 BEGIN_NV04(chan
, NvSubImageBlit
, 0x019c, 1);
252 OUT_RING(chan
, nfbdev
->surf2d
.handle
);
253 BEGIN_NV04(chan
, NvSubImageBlit
, 0x02fc, 1);
255 if (device
->info
.chipset
>= 0x11 /*XXX: oclass == 0x009f*/) {
256 BEGIN_NV04(chan
, NvSubImageBlit
, 0x0120, 3);
262 BEGIN_NV04(chan
, NvSubGdiRect
, 0x0000, 1);
263 OUT_RING(chan
, nfbdev
->gdi
.handle
);
264 BEGIN_NV04(chan
, NvSubGdiRect
, 0x0198, 1);
265 OUT_RING(chan
, nfbdev
->surf2d
.handle
);
266 BEGIN_NV04(chan
, NvSubGdiRect
, 0x0188, 2);
267 OUT_RING(chan
, nfbdev
->patt
.handle
);
268 OUT_RING(chan
, nfbdev
->rop
.handle
);
269 BEGIN_NV04(chan
, NvSubGdiRect
, 0x0304, 1);
271 BEGIN_NV04(chan
, NvSubGdiRect
, 0x0300, 1);
272 OUT_RING(chan
, rect_fmt
);
273 BEGIN_NV04(chan
, NvSubGdiRect
, 0x02fc, 1);