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.
24 #define NVIF_DEBUG_PRINT_DISABLE
25 #include "nouveau_drv.h"
26 #include "nouveau_dma.h"
27 #include "nouveau_fbcon.h"
29 #include <nvif/push006c.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
->helper
.dev
);
36 struct nouveau_channel
*chan
= drm
->channel
;
37 struct nvif_push
*push
= chan
->chan
.push
;
40 ret
= PUSH_WAIT(push
, 4);
44 PUSH_NVSQ(push
, NV05F
, 0x0300, (region
->sy
<< 16) | region
->sx
,
45 0x0304, (region
->dy
<< 16) | region
->dx
,
46 0x0308, (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
->helper
.dev
);
56 struct nouveau_channel
*chan
= drm
->channel
;
57 struct nvif_push
*push
= chan
->chan
.push
;
60 ret
= PUSH_WAIT(push
, 7);
64 PUSH_NVSQ(push
, NV04A
, 0x02fc, (rect
->rop
!= ROP_COPY
) ? 1 : 3);
65 if (info
->fix
.visual
== FB_VISUAL_TRUECOLOR
||
66 info
->fix
.visual
== FB_VISUAL_DIRECTCOLOR
)
67 PUSH_NVSQ(push
, NV04A
, 0x03fc, ((uint32_t *)info
->pseudo_palette
)[rect
->color
]);
69 PUSH_NVSQ(push
, NV04A
, 0x03fc, rect
->color
);
70 PUSH_NVSQ(push
, NV04A
, 0x0400, (rect
->dx
<< 16) | rect
->dy
,
71 0x0404, (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
;
82 struct nvif_push
*push
= chan
->chan
.push
;
86 uint32_t *data
= (uint32_t *)image
->data
;
89 if (image
->depth
!= 1)
92 ret
= PUSH_WAIT(push
, 8);
96 if (info
->fix
.visual
== FB_VISUAL_TRUECOLOR
||
97 info
->fix
.visual
== FB_VISUAL_DIRECTCOLOR
) {
98 fg
= ((uint32_t *) info
->pseudo_palette
)[image
->fg_color
];
99 bg
= ((uint32_t *) info
->pseudo_palette
)[image
->bg_color
];
101 fg
= image
->fg_color
;
102 bg
= image
->bg_color
;
105 PUSH_NVSQ(push
, NV04A
, 0x0be4, (image
->dy
<< 16) | (image
->dx
& 0xffff),
106 0x0be8, ((image
->dy
+ image
->height
) << 16) |
107 ((image
->dx
+ image
->width
) & 0xffff),
110 0x0bf4, (image
->height
<< 16) | ALIGN(image
->width
, 8),
111 0x0bf8, (image
->height
<< 16) | image
->width
,
112 0x0bfc, (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
= PUSH_WAIT(push
, iter_len
+ 1);
122 PUSH_NVSQ(push
, NV04A
, 0x0c00, data
, iter_len
);
132 nv04_fbcon_accel_init(struct fb_info
*info
)
134 struct nouveau_fbdev
*nfbdev
= info
->par
;
135 struct drm_device
*dev
= nfbdev
->helper
.dev
;
136 struct nouveau_drm
*drm
= nouveau_drm(dev
);
137 struct nouveau_channel
*chan
= drm
->channel
;
138 struct nvif_device
*device
= &drm
->client
.device
;
139 struct nvif_push
*push
= chan
->chan
.push
;
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_ctor(&chan
->user
, "fbconCtxSurf2d", 0x0062,
172 device
->info
.family
>= NV_DEVICE_INFO_V0_CELSIUS
?
173 0x0062 : 0x0042, NULL
, 0, &nfbdev
->surf2d
);
177 ret
= nvif_object_ctor(&chan
->user
, "fbconCtxClip", 0x0019, 0x0019,
178 NULL
, 0, &nfbdev
->clip
);
182 ret
= nvif_object_ctor(&chan
->user
, "fbconCtxRop", 0x0043, 0x0043,
183 NULL
, 0, &nfbdev
->rop
);
187 ret
= nvif_object_ctor(&chan
->user
, "fbconCtxPatt", 0x0044, 0x0044,
188 NULL
, 0, &nfbdev
->patt
);
192 ret
= nvif_object_ctor(&chan
->user
, "fbconGdiRectText", 0x004a, 0x004a,
193 NULL
, 0, &nfbdev
->gdi
);
197 ret
= nvif_object_ctor(&chan
->user
, "fbconImageBlit", 0x005f,
198 device
->info
.chipset
>= 0x11 ? 0x009f : 0x005f,
199 NULL
, 0, &nfbdev
->blit
);
203 if (PUSH_WAIT(push
, 49 + (device
->info
.chipset
>= 0x11 ? 4 : 0))) {
204 nouveau_fbcon_gpu_lockup(info
);
208 PUSH_NVSQ(push
, NV042
, 0x0000, nfbdev
->surf2d
.handle
);
209 PUSH_NVSQ(push
, NV042
, 0x0184, chan
->vram
.handle
,
210 0x0188, chan
->vram
.handle
);
211 PUSH_NVSQ(push
, NV042
, 0x0300, surface_fmt
,
212 0x0304, info
->fix
.line_length
| (info
->fix
.line_length
<< 16),
213 0x0308, info
->fix
.smem_start
- dev
->mode_config
.fb_base
,
214 0x030c, info
->fix
.smem_start
- dev
->mode_config
.fb_base
);
216 PUSH_NVSQ(push
, NV043
, 0x0000, nfbdev
->rop
.handle
);
217 PUSH_NVSQ(push
, NV043
, 0x0300, 0x55);
219 PUSH_NVSQ(push
, NV044
, 0x0000, nfbdev
->patt
.handle
);
220 PUSH_NVSQ(push
, NV044
, 0x0300, pattern_fmt
,
233 PUSH_NVSQ(push
, NV019
, 0x0000, nfbdev
->clip
.handle
);
234 PUSH_NVSQ(push
, NV019
, 0x0300, 0,
235 0x0304, (info
->var
.yres_virtual
<< 16) | info
->var
.xres_virtual
);
237 PUSH_NVSQ(push
, NV05F
, 0x0000, nfbdev
->blit
.handle
);
238 PUSH_NVSQ(push
, NV05F
, 0x019c, nfbdev
->surf2d
.handle
);
239 PUSH_NVSQ(push
, NV05F
, 0x02fc, 3);
240 if (nfbdev
->blit
.oclass
== 0x009f) {
241 PUSH_NVSQ(push
, NV09F
, 0x0120, 0,
246 PUSH_NVSQ(push
, NV04A
, 0x0000, nfbdev
->gdi
.handle
);
247 PUSH_NVSQ(push
, NV04A
, 0x0198, nfbdev
->surf2d
.handle
);
248 PUSH_NVSQ(push
, NV04A
, 0x0188, nfbdev
->patt
.handle
,
249 0x018c, nfbdev
->rop
.handle
);
250 PUSH_NVSQ(push
, NV04A
, 0x0304, 1);
251 PUSH_NVSQ(push
, NV04A
, 0x0300, rect_fmt
);
252 PUSH_NVSQ(push
, NV04A
, 0x02fc, 3);