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 <core/object.h>
27 #include "nouveau_drm.h"
28 #include "nouveau_dma.h"
29 #include "nouveau_fbcon.h"
32 nv04_fbcon_copyarea(struct fb_info
*info
, const struct fb_copyarea
*region
)
34 struct nouveau_fbdev
*nfbdev
= info
->par
;
35 struct nouveau_drm
*drm
= nouveau_drm(nfbdev
->dev
);
36 struct nouveau_channel
*chan
= drm
->channel
;
39 ret
= RING_SPACE(chan
, 4);
43 BEGIN_NV04(chan
, NvSubImageBlit
, 0x0300, 3);
44 OUT_RING(chan
, (region
->sy
<< 16) | region
->sx
);
45 OUT_RING(chan
, (region
->dy
<< 16) | region
->dx
);
46 OUT_RING(chan
, (region
->height
<< 16) | region
->width
);
52 nv04_fbcon_fillrect(struct fb_info
*info
, const struct fb_fillrect
*rect
)
54 struct nouveau_fbdev
*nfbdev
= info
->par
;
55 struct nouveau_drm
*drm
= nouveau_drm(nfbdev
->dev
);
56 struct nouveau_channel
*chan
= drm
->channel
;
59 ret
= RING_SPACE(chan
, 7);
63 BEGIN_NV04(chan
, NvSubGdiRect
, 0x02fc, 1);
64 OUT_RING(chan
, (rect
->rop
!= ROP_COPY
) ? 1 : 3);
65 BEGIN_NV04(chan
, NvSubGdiRect
, 0x03fc, 1);
66 if (info
->fix
.visual
== FB_VISUAL_TRUECOLOR
||
67 info
->fix
.visual
== FB_VISUAL_DIRECTCOLOR
)
68 OUT_RING(chan
, ((uint32_t *)info
->pseudo_palette
)[rect
->color
]);
70 OUT_RING(chan
, rect
->color
);
71 BEGIN_NV04(chan
, NvSubGdiRect
, 0x0400, 2);
72 OUT_RING(chan
, (rect
->dx
<< 16) | rect
->dy
);
73 OUT_RING(chan
, (rect
->width
<< 16) | rect
->height
);
79 nv04_fbcon_imageblit(struct fb_info
*info
, const struct fb_image
*image
)
81 struct nouveau_fbdev
*nfbdev
= info
->par
;
82 struct nouveau_drm
*drm
= nouveau_drm(nfbdev
->dev
);
83 struct nouveau_channel
*chan
= drm
->channel
;
88 uint32_t *data
= (uint32_t *)image
->data
;
91 if (image
->depth
!= 1)
94 ret
= RING_SPACE(chan
, 8);
98 width
= ALIGN(image
->width
, 8);
99 dsize
= ALIGN(width
* image
->height
, 32) >> 5;
101 if (info
->fix
.visual
== FB_VISUAL_TRUECOLOR
||
102 info
->fix
.visual
== FB_VISUAL_DIRECTCOLOR
) {
103 fg
= ((uint32_t *) info
->pseudo_palette
)[image
->fg_color
];
104 bg
= ((uint32_t *) info
->pseudo_palette
)[image
->bg_color
];
106 fg
= image
->fg_color
;
107 bg
= image
->bg_color
;
110 BEGIN_NV04(chan
, NvSubGdiRect
, 0x0be4, 7);
111 OUT_RING(chan
, (image
->dy
<< 16) | (image
->dx
& 0xffff));
112 OUT_RING(chan
, ((image
->dy
+ image
->height
) << 16) |
113 ((image
->dx
+ image
->width
) & 0xffff));
116 OUT_RING(chan
, (image
->height
<< 16) | width
);
117 OUT_RING(chan
, (image
->height
<< 16) | image
->width
);
118 OUT_RING(chan
, (image
->dy
<< 16) | (image
->dx
& 0xffff));
121 int iter_len
= dsize
> 128 ? 128 : dsize
;
123 ret
= RING_SPACE(chan
, iter_len
+ 1);
127 BEGIN_NV04(chan
, NvSubGdiRect
, 0x0c00, iter_len
);
128 OUT_RINGp(chan
, data
, iter_len
);
138 nv04_fbcon_accel_init(struct fb_info
*info
)
140 struct nouveau_fbdev
*nfbdev
= info
->par
;
141 struct drm_device
*dev
= nfbdev
->dev
;
142 struct nouveau_drm
*drm
= nouveau_drm(dev
);
143 struct nouveau_channel
*chan
= drm
->channel
;
144 struct nouveau_device
*device
= nv_device(drm
->device
);
145 struct nouveau_object
*object
;
146 int surface_fmt
, pattern_fmt
, rect_fmt
;
149 switch (info
->var
.bits_per_pixel
) {
161 switch (info
->var
.transp
.length
) {
162 case 0: /* depth 24 */
163 case 8: /* depth 32 */
177 ret
= nouveau_object_new(nv_object(chan
->cli
), NVDRM_CHAN
, NvCtxSurf2D
,
178 device
->card_type
>= NV_10
? 0x0062 : 0x0042,
183 ret
= nouveau_object_new(nv_object(chan
->cli
), NVDRM_CHAN
, NvClipRect
,
184 0x0019, NULL
, 0, &object
);
188 ret
= nouveau_object_new(nv_object(chan
->cli
), NVDRM_CHAN
, NvRop
,
189 0x0043, NULL
, 0, &object
);
193 ret
= nouveau_object_new(nv_object(chan
->cli
), NVDRM_CHAN
, NvImagePatt
,
194 0x0044, NULL
, 0, &object
);
198 ret
= nouveau_object_new(nv_object(chan
->cli
), NVDRM_CHAN
, NvGdiRect
,
199 0x004a, NULL
, 0, &object
);
203 ret
= nouveau_object_new(nv_object(chan
->cli
), NVDRM_CHAN
, NvImageBlit
,
204 device
->chipset
>= 0x11 ? 0x009f : 0x005f,
209 if (RING_SPACE(chan
, 49)) {
210 nouveau_fbcon_gpu_lockup(info
);
214 BEGIN_NV04(chan
, NvSubCtxSurf2D
, 0x0000, 1);
215 OUT_RING(chan
, NvCtxSurf2D
);
216 BEGIN_NV04(chan
, NvSubCtxSurf2D
, 0x0184, 2);
217 OUT_RING(chan
, NvDmaFB
);
218 OUT_RING(chan
, NvDmaFB
);
219 BEGIN_NV04(chan
, NvSubCtxSurf2D
, 0x0300, 4);
220 OUT_RING(chan
, surface_fmt
);
221 OUT_RING(chan
, info
->fix
.line_length
| (info
->fix
.line_length
<< 16));
222 OUT_RING(chan
, info
->fix
.smem_start
- dev
->mode_config
.fb_base
);
223 OUT_RING(chan
, info
->fix
.smem_start
- dev
->mode_config
.fb_base
);
225 BEGIN_NV04(chan
, NvSubCtxSurf2D
, 0x0000, 1);
226 OUT_RING(chan
, NvRop
);
227 BEGIN_NV04(chan
, NvSubCtxSurf2D
, 0x0300, 1);
228 OUT_RING(chan
, 0x55);
230 BEGIN_NV04(chan
, NvSubCtxSurf2D
, 0x0000, 1);
231 OUT_RING(chan
, NvImagePatt
);
232 BEGIN_NV04(chan
, NvSubCtxSurf2D
, 0x0300, 8);
233 OUT_RING(chan
, pattern_fmt
);
246 BEGIN_NV04(chan
, NvSubCtxSurf2D
, 0x0000, 1);
247 OUT_RING(chan
, NvClipRect
);
248 BEGIN_NV04(chan
, NvSubCtxSurf2D
, 0x0300, 2);
250 OUT_RING(chan
, (info
->var
.yres_virtual
<< 16) | info
->var
.xres_virtual
);
252 BEGIN_NV04(chan
, NvSubImageBlit
, 0x0000, 1);
253 OUT_RING(chan
, NvImageBlit
);
254 BEGIN_NV04(chan
, NvSubImageBlit
, 0x019c, 1);
255 OUT_RING(chan
, NvCtxSurf2D
);
256 BEGIN_NV04(chan
, NvSubImageBlit
, 0x02fc, 1);
259 BEGIN_NV04(chan
, NvSubGdiRect
, 0x0000, 1);
260 OUT_RING(chan
, NvGdiRect
);
261 BEGIN_NV04(chan
, NvSubGdiRect
, 0x0198, 1);
262 OUT_RING(chan
, NvCtxSurf2D
);
263 BEGIN_NV04(chan
, NvSubGdiRect
, 0x0188, 2);
264 OUT_RING(chan
, NvImagePatt
);
265 OUT_RING(chan
, NvRop
);
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);