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 #include "nouveau_vmm.h"
0029
0030 #include <nvif/push206e.h>
0031
0032 #include <nvhw/class/cl502d.h>
0033
0034 int
0035 nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
0036 {
0037 struct nouveau_fbdev *nfbdev = info->par;
0038 struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
0039 struct nouveau_channel *chan = drm->channel;
0040 struct nvif_push *push = chan->chan.push;
0041 u32 colour;
0042 int ret;
0043
0044 if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
0045 info->fix.visual == FB_VISUAL_DIRECTCOLOR)
0046 colour = ((uint32_t *)info->pseudo_palette)[rect->color];
0047 else
0048 colour = rect->color;
0049
0050 ret = PUSH_WAIT(push, rect->rop == ROP_COPY ? 7 : 11);
0051 if (ret)
0052 return ret;
0053
0054 if (rect->rop != ROP_COPY) {
0055 PUSH_MTHD(push, NV502D, SET_OPERATION,
0056 NVDEF(NV502D, SET_OPERATION, V, ROP_AND));
0057 }
0058
0059 PUSH_MTHD(push, NV502D, SET_RENDER_SOLID_PRIM_COLOR, colour);
0060
0061 PUSH_MTHD(push, NV502D, RENDER_SOLID_PRIM_POINT_SET_X(0), rect->dx,
0062 RENDER_SOLID_PRIM_POINT_Y(0), rect->dy,
0063 RENDER_SOLID_PRIM_POINT_SET_X(1), rect->dx + rect->width,
0064 RENDER_SOLID_PRIM_POINT_Y(1), rect->dy + rect->height);
0065
0066 if (rect->rop != ROP_COPY) {
0067 PUSH_MTHD(push, NV502D, SET_OPERATION,
0068 NVDEF(NV502D, SET_OPERATION, V, SRCCOPY));
0069 }
0070
0071 PUSH_KICK(push);
0072 return 0;
0073 }
0074
0075 int
0076 nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
0077 {
0078 struct nouveau_fbdev *nfbdev = info->par;
0079 struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
0080 struct nouveau_channel *chan = drm->channel;
0081 struct nvif_push *push = chan->chan.push;
0082 int ret;
0083
0084 ret = PUSH_WAIT(push, 12);
0085 if (ret)
0086 return ret;
0087
0088 PUSH_MTHD(push, NV502D, WAIT_FOR_IDLE, 0);
0089
0090 PUSH_MTHD(push, NV502D, SET_PIXELS_FROM_MEMORY_DST_X0, region->dx,
0091 SET_PIXELS_FROM_MEMORY_DST_Y0, region->dy,
0092 SET_PIXELS_FROM_MEMORY_DST_WIDTH, region->width,
0093 SET_PIXELS_FROM_MEMORY_DST_HEIGHT, region->height);
0094
0095 PUSH_MTHD(push, NV502D, SET_PIXELS_FROM_MEMORY_SRC_X0_FRAC, 0,
0096 SET_PIXELS_FROM_MEMORY_SRC_X0_INT, region->sx,
0097 SET_PIXELS_FROM_MEMORY_SRC_Y0_FRAC, 0,
0098 PIXELS_FROM_MEMORY_SRC_Y0_INT, region->sy);
0099 PUSH_KICK(push);
0100 return 0;
0101 }
0102
0103 int
0104 nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
0105 {
0106 struct nouveau_fbdev *nfbdev = info->par;
0107 struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
0108 struct nouveau_channel *chan = drm->channel;
0109 struct nvif_push *push = chan->chan.push;
0110 uint32_t dwords, *data = (uint32_t *)image->data;
0111 uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel));
0112 uint32_t *palette = info->pseudo_palette, bg, fg;
0113 int ret;
0114
0115 if (image->depth != 1)
0116 return -ENODEV;
0117
0118 if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
0119 info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
0120 bg = palette[image->bg_color] | mask;
0121 fg = palette[image->fg_color] | mask;
0122 } else {
0123 bg = image->bg_color;
0124 fg = image->fg_color;
0125 }
0126
0127 ret = PUSH_WAIT(push, 11);
0128 if (ret)
0129 return ret;
0130
0131 PUSH_MTHD(push, NV502D, SET_PIXELS_FROM_CPU_COLOR0, bg,
0132 SET_PIXELS_FROM_CPU_COLOR1, fg);
0133
0134 PUSH_MTHD(push, NV502D, SET_PIXELS_FROM_CPU_SRC_WIDTH, image->width,
0135 SET_PIXELS_FROM_CPU_SRC_HEIGHT, image->height);
0136
0137 PUSH_MTHD(push, NV502D, SET_PIXELS_FROM_CPU_DST_X0_FRAC, 0,
0138 SET_PIXELS_FROM_CPU_DST_X0_INT, image->dx,
0139 SET_PIXELS_FROM_CPU_DST_Y0_FRAC, 0,
0140 SET_PIXELS_FROM_CPU_DST_Y0_INT, image->dy);
0141
0142 dwords = ALIGN(ALIGN(image->width, 8) * image->height, 32) >> 5;
0143 while (dwords) {
0144 int count = dwords > 2047 ? 2047 : dwords;
0145
0146 ret = PUSH_WAIT(push, count + 1);
0147 if (ret)
0148 return ret;
0149
0150 dwords -= count;
0151
0152 PUSH_NINC(push, NV502D, PIXELS_FROM_CPU_DATA, data, count);
0153 data += count;
0154 }
0155
0156 PUSH_KICK(push);
0157 return 0;
0158 }
0159
0160 int
0161 nv50_fbcon_accel_init(struct fb_info *info)
0162 {
0163 struct nouveau_fbdev *nfbdev = info->par;
0164 struct drm_device *dev = nfbdev->helper.dev;
0165 struct nouveau_drm *drm = nouveau_drm(dev);
0166 struct nouveau_channel *chan = drm->channel;
0167 struct nvif_push *push = chan->chan.push;
0168 int ret, format;
0169
0170 switch (info->var.bits_per_pixel) {
0171 case 8:
0172 format = NV502D_SET_DST_FORMAT_V_Y8;
0173 break;
0174 case 15:
0175 format = NV502D_SET_DST_FORMAT_V_X1R5G5B5;
0176 break;
0177 case 16:
0178 format = NV502D_SET_DST_FORMAT_V_R5G6B5;
0179 break;
0180 case 32:
0181 switch (info->var.transp.length) {
0182 case 0:
0183 case 8:
0184 format = NV502D_SET_DST_FORMAT_V_X8R8G8B8;
0185 break;
0186 case 2:
0187 format = NV502D_SET_DST_FORMAT_V_A2B10G10R10;
0188 break;
0189 default:
0190 return -EINVAL;
0191 }
0192 break;
0193 default:
0194 return -EINVAL;
0195 }
0196
0197 ret = nvif_object_ctor(&chan->user, "fbconTwoD", 0x502d, 0x502d,
0198 NULL, 0, &nfbdev->twod);
0199 if (ret)
0200 return ret;
0201
0202 ret = PUSH_WAIT(push, 56);
0203 if (ret) {
0204 nouveau_fbcon_gpu_lockup(info);
0205 return ret;
0206 }
0207
0208 PUSH_MTHD(push, NV502D, SET_OBJECT, nfbdev->twod.handle);
0209 PUSH_MTHD(push, NV502D, SET_DST_CONTEXT_DMA, chan->vram.handle,
0210 SET_SRC_CONTEXT_DMA, chan->vram.handle,
0211 SET_SEMAPHORE_CONTEXT_DMA, chan->vram.handle);
0212
0213 PUSH_MTHD(push, NV502D, SET_DST_FORMAT,
0214 NVVAL(NV502D, SET_DST_FORMAT, V, format),
0215
0216 SET_DST_MEMORY_LAYOUT,
0217 NVDEF(NV502D, SET_DST_MEMORY_LAYOUT, V, PITCH));
0218
0219 PUSH_MTHD(push, NV502D, SET_DST_PITCH, info->fix.line_length,
0220 SET_DST_WIDTH, info->var.xres_virtual,
0221 SET_DST_HEIGHT, info->var.yres_virtual,
0222
0223 SET_DST_OFFSET_UPPER,
0224 NVVAL(NV502D, SET_DST_OFFSET_UPPER, V, upper_32_bits(nfbdev->vma->addr)),
0225
0226 SET_DST_OFFSET_LOWER,
0227 NVVAL(NV502D, SET_DST_OFFSET_LOWER, V, lower_32_bits(nfbdev->vma->addr)));
0228
0229 PUSH_MTHD(push, NV502D, SET_SRC_FORMAT,
0230 NVVAL(NV502D, SET_SRC_FORMAT, V, format),
0231
0232 SET_SRC_MEMORY_LAYOUT,
0233 NVDEF(NV502D, SET_SRC_MEMORY_LAYOUT, V, PITCH));
0234
0235 PUSH_MTHD(push, NV502D, SET_SRC_PITCH, info->fix.line_length,
0236 SET_SRC_WIDTH, info->var.xres_virtual,
0237 SET_SRC_HEIGHT, info->var.yres_virtual,
0238
0239 SET_SRC_OFFSET_UPPER,
0240 NVVAL(NV502D, SET_SRC_OFFSET_UPPER, V, upper_32_bits(nfbdev->vma->addr)),
0241
0242 SET_SRC_OFFSET_LOWER,
0243 NVVAL(NV502D, SET_SRC_OFFSET_LOWER, V, lower_32_bits(nfbdev->vma->addr)));
0244
0245 PUSH_MTHD(push, NV502D, SET_CLIP_ENABLE,
0246 NVDEF(NV502D, SET_CLIP_ENABLE, V, FALSE));
0247
0248 PUSH_MTHD(push, NV502D, SET_ROP,
0249 NVVAL(NV502D, SET_ROP, V, 0x55));
0250
0251 PUSH_MTHD(push, NV502D, SET_OPERATION,
0252 NVDEF(NV502D, SET_OPERATION, V, SRCCOPY));
0253
0254 PUSH_MTHD(push, NV502D, SET_MONOCHROME_PATTERN_COLOR_FORMAT,
0255 NVDEF(NV502D, SET_MONOCHROME_PATTERN_COLOR_FORMAT, V, A8R8G8B8),
0256
0257 SET_MONOCHROME_PATTERN_FORMAT,
0258 NVDEF(NV502D, SET_MONOCHROME_PATTERN_FORMAT, V, LE_M1));
0259
0260 PUSH_MTHD(push, NV502D, RENDER_SOLID_PRIM_MODE,
0261 NVDEF(NV502D, RENDER_SOLID_PRIM_MODE, V, RECTS),
0262
0263 SET_RENDER_SOLID_PRIM_COLOR_FORMAT,
0264 NVVAL(NV502D, SET_RENDER_SOLID_PRIM_COLOR_FORMAT, V, format));
0265
0266 PUSH_MTHD(push, NV502D, SET_PIXELS_FROM_CPU_DATA_TYPE,
0267 NVDEF(NV502D, SET_PIXELS_FROM_CPU_DATA_TYPE, V, INDEX),
0268
0269 SET_PIXELS_FROM_CPU_COLOR_FORMAT,
0270 NVVAL(NV502D, SET_PIXELS_FROM_CPU_COLOR_FORMAT, V, format),
0271
0272 SET_PIXELS_FROM_CPU_INDEX_FORMAT,
0273 NVDEF(NV502D, SET_PIXELS_FROM_CPU_INDEX_FORMAT, V, I1),
0274
0275 SET_PIXELS_FROM_CPU_MONO_FORMAT,
0276 NVDEF(NV502D, SET_PIXELS_FROM_CPU_MONO_FORMAT, V, CGA6_M1),
0277
0278 SET_PIXELS_FROM_CPU_WRAP,
0279 NVDEF(NV502D, SET_PIXELS_FROM_CPU_WRAP, V, WRAP_BYTE));
0280
0281 PUSH_MTHD(push, NV502D, SET_PIXELS_FROM_CPU_MONO_OPACITY,
0282 NVDEF(NV502D, SET_PIXELS_FROM_CPU_MONO_OPACITY, V, OPAQUE));
0283
0284 PUSH_MTHD(push, NV502D, SET_PIXELS_FROM_CPU_DX_DU_FRAC, 0,
0285 SET_PIXELS_FROM_CPU_DX_DU_INT, 1,
0286 SET_PIXELS_FROM_CPU_DY_DV_FRAC, 0,
0287 SET_PIXELS_FROM_CPU_DY_DV_INT, 1);
0288
0289 PUSH_MTHD(push, NV502D, SET_PIXELS_FROM_MEMORY_SAFE_OVERLAP,
0290 NVDEF(NV502D, SET_PIXELS_FROM_MEMORY_SAFE_OVERLAP, V, TRUE));
0291
0292 PUSH_MTHD(push, NV502D, SET_PIXELS_FROM_MEMORY_DU_DX_FRAC, 0,
0293 SET_PIXELS_FROM_MEMORY_DU_DX_INT, 1,
0294 SET_PIXELS_FROM_MEMORY_DV_DY_FRAC, 0,
0295 SET_PIXELS_FROM_MEMORY_DV_DY_INT, 1);
0296 PUSH_KICK(push);
0297 return 0;
0298 }
0299