0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024 #define NVIF_DEBUG_PRINT_DISABLE
0025 #include "nouveau_drv.h"
0026 #include "nouveau_dma.h"
0027 #include "nouveau_fbcon.h"
0028
0029 #include <nvif/push006c.h>
0030
0031 int
0032 nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
0033 {
0034 struct nouveau_fbdev *nfbdev = info->par;
0035 struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
0036 struct nouveau_channel *chan = drm->channel;
0037 struct nvif_push *push = chan->chan.push;
0038 int ret;
0039
0040 ret = PUSH_WAIT(push, 4);
0041 if (ret)
0042 return ret;
0043
0044 PUSH_NVSQ(push, NV05F, 0x0300, (region->sy << 16) | region->sx,
0045 0x0304, (region->dy << 16) | region->dx,
0046 0x0308, (region->height << 16) | region->width);
0047 PUSH_KICK(push);
0048 return 0;
0049 }
0050
0051 int
0052 nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
0053 {
0054 struct nouveau_fbdev *nfbdev = info->par;
0055 struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
0056 struct nouveau_channel *chan = drm->channel;
0057 struct nvif_push *push = chan->chan.push;
0058 int ret;
0059
0060 ret = PUSH_WAIT(push, 7);
0061 if (ret)
0062 return ret;
0063
0064 PUSH_NVSQ(push, NV04A, 0x02fc, (rect->rop != ROP_COPY) ? 1 : 3);
0065 if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
0066 info->fix.visual == FB_VISUAL_DIRECTCOLOR)
0067 PUSH_NVSQ(push, NV04A, 0x03fc, ((uint32_t *)info->pseudo_palette)[rect->color]);
0068 else
0069 PUSH_NVSQ(push, NV04A, 0x03fc, rect->color);
0070 PUSH_NVSQ(push, NV04A, 0x0400, (rect->dx << 16) | rect->dy,
0071 0x0404, (rect->width << 16) | rect->height);
0072 PUSH_KICK(push);
0073 return 0;
0074 }
0075
0076 int
0077 nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
0078 {
0079 struct nouveau_fbdev *nfbdev = info->par;
0080 struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
0081 struct nouveau_channel *chan = drm->channel;
0082 struct nvif_push *push = chan->chan.push;
0083 uint32_t fg;
0084 uint32_t bg;
0085 uint32_t dsize;
0086 uint32_t *data = (uint32_t *)image->data;
0087 int ret;
0088
0089 if (image->depth != 1)
0090 return -ENODEV;
0091
0092 ret = PUSH_WAIT(push, 8);
0093 if (ret)
0094 return ret;
0095
0096 if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
0097 info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
0098 fg = ((uint32_t *) info->pseudo_palette)[image->fg_color];
0099 bg = ((uint32_t *) info->pseudo_palette)[image->bg_color];
0100 } else {
0101 fg = image->fg_color;
0102 bg = image->bg_color;
0103 }
0104
0105 PUSH_NVSQ(push, NV04A, 0x0be4, (image->dy << 16) | (image->dx & 0xffff),
0106 0x0be8, ((image->dy + image->height) << 16) |
0107 ((image->dx + image->width) & 0xffff),
0108 0x0bec, bg,
0109 0x0bf0, fg,
0110 0x0bf4, (image->height << 16) | ALIGN(image->width, 8),
0111 0x0bf8, (image->height << 16) | image->width,
0112 0x0bfc, (image->dy << 16) | (image->dx & 0xffff));
0113
0114 dsize = ALIGN(ALIGN(image->width, 8) * image->height, 32) >> 5;
0115 while (dsize) {
0116 int iter_len = dsize > 128 ? 128 : dsize;
0117
0118 ret = PUSH_WAIT(push, iter_len + 1);
0119 if (ret)
0120 return ret;
0121
0122 PUSH_NVSQ(push, NV04A, 0x0c00, data, iter_len);
0123 data += iter_len;
0124 dsize -= iter_len;
0125 }
0126
0127 PUSH_KICK(push);
0128 return 0;
0129 }
0130
0131 int
0132 nv04_fbcon_accel_init(struct fb_info *info)
0133 {
0134 struct nouveau_fbdev *nfbdev = info->par;
0135 struct drm_device *dev = nfbdev->helper.dev;
0136 struct nouveau_drm *drm = nouveau_drm(dev);
0137 struct nouveau_channel *chan = drm->channel;
0138 struct nvif_device *device = &drm->client.device;
0139 struct nvif_push *push = chan->chan.push;
0140 int surface_fmt, pattern_fmt, rect_fmt;
0141 int ret;
0142
0143 switch (info->var.bits_per_pixel) {
0144 case 8:
0145 surface_fmt = 1;
0146 pattern_fmt = 3;
0147 rect_fmt = 3;
0148 break;
0149 case 16:
0150 surface_fmt = 4;
0151 pattern_fmt = 1;
0152 rect_fmt = 1;
0153 break;
0154 case 32:
0155 switch (info->var.transp.length) {
0156 case 0:
0157 case 8:
0158 break;
0159 default:
0160 return -EINVAL;
0161 }
0162
0163 surface_fmt = 6;
0164 pattern_fmt = 3;
0165 rect_fmt = 3;
0166 break;
0167 default:
0168 return -EINVAL;
0169 }
0170
0171 ret = nvif_object_ctor(&chan->user, "fbconCtxSurf2d", 0x0062,
0172 device->info.family >= NV_DEVICE_INFO_V0_CELSIUS ?
0173 0x0062 : 0x0042, NULL, 0, &nfbdev->surf2d);
0174 if (ret)
0175 return ret;
0176
0177 ret = nvif_object_ctor(&chan->user, "fbconCtxClip", 0x0019, 0x0019,
0178 NULL, 0, &nfbdev->clip);
0179 if (ret)
0180 return ret;
0181
0182 ret = nvif_object_ctor(&chan->user, "fbconCtxRop", 0x0043, 0x0043,
0183 NULL, 0, &nfbdev->rop);
0184 if (ret)
0185 return ret;
0186
0187 ret = nvif_object_ctor(&chan->user, "fbconCtxPatt", 0x0044, 0x0044,
0188 NULL, 0, &nfbdev->patt);
0189 if (ret)
0190 return ret;
0191
0192 ret = nvif_object_ctor(&chan->user, "fbconGdiRectText", 0x004a, 0x004a,
0193 NULL, 0, &nfbdev->gdi);
0194 if (ret)
0195 return ret;
0196
0197 ret = nvif_object_ctor(&chan->user, "fbconImageBlit", 0x005f,
0198 device->info.chipset >= 0x11 ? 0x009f : 0x005f,
0199 NULL, 0, &nfbdev->blit);
0200 if (ret)
0201 return ret;
0202
0203 if (PUSH_WAIT(push, 49 + (device->info.chipset >= 0x11 ? 4 : 0))) {
0204 nouveau_fbcon_gpu_lockup(info);
0205 return 0;
0206 }
0207
0208 PUSH_NVSQ(push, NV042, 0x0000, nfbdev->surf2d.handle);
0209 PUSH_NVSQ(push, NV042, 0x0184, chan->vram.handle,
0210 0x0188, chan->vram.handle);
0211 PUSH_NVSQ(push, NV042, 0x0300, surface_fmt,
0212 0x0304, info->fix.line_length | (info->fix.line_length << 16),
0213 0x0308, info->fix.smem_start - dev->mode_config.fb_base,
0214 0x030c, info->fix.smem_start - dev->mode_config.fb_base);
0215
0216 PUSH_NVSQ(push, NV043, 0x0000, nfbdev->rop.handle);
0217 PUSH_NVSQ(push, NV043, 0x0300, 0x55);
0218
0219 PUSH_NVSQ(push, NV044, 0x0000, nfbdev->patt.handle);
0220 PUSH_NVSQ(push, NV044, 0x0300, pattern_fmt,
0221 #ifdef __BIG_ENDIAN
0222 0x0304, 2,
0223 #else
0224 0x0304, 1,
0225 #endif
0226 0x0308, 0,
0227 0x030c, 1,
0228 0x0310, ~0,
0229 0x0314, ~0,
0230 0x0318, ~0,
0231 0x031c, ~0);
0232
0233 PUSH_NVSQ(push, NV019, 0x0000, nfbdev->clip.handle);
0234 PUSH_NVSQ(push, NV019, 0x0300, 0,
0235 0x0304, (info->var.yres_virtual << 16) | info->var.xres_virtual);
0236
0237 PUSH_NVSQ(push, NV05F, 0x0000, nfbdev->blit.handle);
0238 PUSH_NVSQ(push, NV05F, 0x019c, nfbdev->surf2d.handle);
0239 PUSH_NVSQ(push, NV05F, 0x02fc, 3);
0240 if (nfbdev->blit.oclass == 0x009f) {
0241 PUSH_NVSQ(push, NV09F, 0x0120, 0,
0242 0x0124, 1,
0243 0x0128, 2);
0244 }
0245
0246 PUSH_NVSQ(push, NV04A, 0x0000, nfbdev->gdi.handle);
0247 PUSH_NVSQ(push, NV04A, 0x0198, nfbdev->surf2d.handle);
0248 PUSH_NVSQ(push, NV04A, 0x0188, nfbdev->patt.handle,
0249 0x018c, nfbdev->rop.handle);
0250 PUSH_NVSQ(push, NV04A, 0x0304, 1);
0251 PUSH_NVSQ(push, NV04A, 0x0300, rect_fmt);
0252 PUSH_NVSQ(push, NV04A, 0x02fc, 3);
0253
0254 PUSH_KICK(push);
0255 return 0;
0256 }
0257