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/push906f.h>
0031
0032 #include <nvhw/class/cl902d.h>
0033
0034 int
0035 nvc0_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 : 9);
0051 if (ret)
0052 return ret;
0053
0054 if (rect->rop != ROP_COPY) {
0055 PUSH_IMMD(push, NV902D, SET_OPERATION,
0056 NVDEF(NV902D, SET_OPERATION, V, ROP_AND));
0057 }
0058
0059 PUSH_MTHD(push, NV902D, SET_RENDER_SOLID_PRIM_COLOR, colour);
0060
0061 PUSH_MTHD(push, NV902D, 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_IMMD(push, NV902D, SET_OPERATION,
0068 NVDEF(NV902D, SET_OPERATION, V, SRCCOPY));
0069 }
0070
0071 PUSH_KICK(push);
0072 return 0;
0073 }
0074
0075 int
0076 nvc0_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, 11);
0085 if (ret)
0086 return ret;
0087
0088 PUSH_IMMD(push, NV902D, WAIT_FOR_IDLE, 0);
0089
0090 PUSH_MTHD(push, NV902D, 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, NV902D, 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 nvc0_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, NV902D, SET_PIXELS_FROM_CPU_COLOR0, bg,
0132 SET_PIXELS_FROM_CPU_COLOR1, fg);
0133
0134 PUSH_MTHD(push, NV902D, SET_PIXELS_FROM_CPU_SRC_WIDTH, image->width,
0135 SET_PIXELS_FROM_CPU_SRC_HEIGHT, image->height);
0136
0137 PUSH_MTHD(push, NV902D, 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, NV902D, PIXELS_FROM_CPU_DATA, data, count);
0153 data += count;
0154 }
0155
0156 PUSH_KICK(push);
0157 return 0;
0158 }
0159
0160 int
0161 nvc0_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 ret = nvif_object_ctor(&chan->user, "fbconTwoD", 0x902d, 0x902d,
0171 NULL, 0, &nfbdev->twod);
0172 if (ret)
0173 return ret;
0174
0175 switch (info->var.bits_per_pixel) {
0176 case 8:
0177 format = NV902D_SET_DST_FORMAT_V_Y8;
0178 break;
0179 case 15:
0180 format = NV902D_SET_DST_FORMAT_V_X1R5G5B5;
0181 break;
0182 case 16:
0183 format = NV902D_SET_DST_FORMAT_V_R5G6B5;
0184 break;
0185 case 32:
0186 switch (info->var.transp.length) {
0187 case 0:
0188 case 8:
0189 format = NV902D_SET_DST_FORMAT_V_X8R8G8B8;
0190 break;
0191 case 2:
0192 format = NV902D_SET_DST_FORMAT_V_A2B10G10R10;
0193 break;
0194 default:
0195 return -EINVAL;
0196 }
0197 break;
0198 default:
0199 return -EINVAL;
0200 }
0201
0202 ret = PUSH_WAIT(push, 52);
0203 if (ret) {
0204 WARN_ON(1);
0205 nouveau_fbcon_gpu_lockup(info);
0206 return ret;
0207 }
0208
0209 PUSH_MTHD(push, NV902D, SET_OBJECT, nfbdev->twod.handle);
0210
0211 PUSH_MTHD(push, NV902D, SET_DST_FORMAT,
0212 NVVAL(NV902D, SET_DST_FORMAT, V, format),
0213
0214 SET_DST_MEMORY_LAYOUT,
0215 NVDEF(NV902D, SET_DST_MEMORY_LAYOUT, V, PITCH));
0216
0217 PUSH_MTHD(push, NV902D, SET_DST_PITCH, info->fix.line_length,
0218 SET_DST_WIDTH, info->var.xres_virtual,
0219 SET_DST_HEIGHT, info->var.yres_virtual,
0220
0221 SET_DST_OFFSET_UPPER,
0222 NVVAL(NV902D, SET_DST_OFFSET_UPPER, V, upper_32_bits(nfbdev->vma->addr)),
0223
0224 SET_DST_OFFSET_LOWER,
0225 NVVAL(NV902D, SET_DST_OFFSET_LOWER, V, lower_32_bits(nfbdev->vma->addr)));
0226
0227 PUSH_MTHD(push, NV902D, SET_SRC_FORMAT,
0228 NVVAL(NV902D, SET_SRC_FORMAT, V, format),
0229
0230 SET_SRC_MEMORY_LAYOUT,
0231 NVDEF(NV902D, SET_SRC_MEMORY_LAYOUT, V, PITCH));
0232
0233 PUSH_MTHD(push, NV902D, SET_SRC_PITCH, info->fix.line_length,
0234 SET_SRC_WIDTH, info->var.xres_virtual,
0235 SET_SRC_HEIGHT, info->var.yres_virtual,
0236
0237 SET_SRC_OFFSET_UPPER,
0238 NVVAL(NV902D, SET_SRC_OFFSET_UPPER, V, upper_32_bits(nfbdev->vma->addr)),
0239
0240 SET_SRC_OFFSET_LOWER,
0241 NVVAL(NV902D, SET_SRC_OFFSET_LOWER, V, lower_32_bits(nfbdev->vma->addr)));
0242
0243 PUSH_IMMD(push, NV902D, SET_CLIP_ENABLE,
0244 NVDEF(NV902D, SET_CLIP_ENABLE, V, FALSE));
0245
0246 PUSH_IMMD(push, NV902D, SET_ROP,
0247 NVVAL(NV902D, SET_ROP, V, 0x55));
0248
0249 PUSH_IMMD(push, NV902D, SET_OPERATION,
0250 NVDEF(NV902D, SET_OPERATION, V, SRCCOPY));
0251
0252 PUSH_MTHD(push, NV902D, SET_MONOCHROME_PATTERN_COLOR_FORMAT,
0253 NVDEF(NV902D, SET_MONOCHROME_PATTERN_COLOR_FORMAT, V, A8R8G8B8),
0254
0255 SET_MONOCHROME_PATTERN_FORMAT,
0256 NVDEF(NV902D, SET_MONOCHROME_PATTERN_FORMAT, V, LE_M1));
0257
0258 PUSH_MTHD(push, NV902D, RENDER_SOLID_PRIM_MODE,
0259 NVDEF(NV902D, RENDER_SOLID_PRIM_MODE, V, RECTS),
0260
0261 SET_RENDER_SOLID_PRIM_COLOR_FORMAT,
0262 NVVAL(NV902D, SET_RENDER_SOLID_PRIM_COLOR_FORMAT, V, format));
0263
0264 PUSH_MTHD(push, NV902D, SET_PIXELS_FROM_CPU_DATA_TYPE,
0265 NVDEF(NV902D, SET_PIXELS_FROM_CPU_DATA_TYPE, V, INDEX),
0266
0267 SET_PIXELS_FROM_CPU_COLOR_FORMAT,
0268 NVVAL(NV902D, SET_PIXELS_FROM_CPU_COLOR_FORMAT, V, format),
0269
0270 SET_PIXELS_FROM_CPU_INDEX_FORMAT,
0271 NVDEF(NV902D, SET_PIXELS_FROM_CPU_INDEX_FORMAT, V, I1),
0272
0273 SET_PIXELS_FROM_CPU_MONO_FORMAT,
0274 NVDEF(NV902D, SET_PIXELS_FROM_CPU_MONO_FORMAT, V, CGA6_M1),
0275
0276 SET_PIXELS_FROM_CPU_WRAP,
0277 NVDEF(NV902D, SET_PIXELS_FROM_CPU_WRAP, V, WRAP_BYTE));
0278
0279 PUSH_IMMD(push, NV902D, SET_PIXELS_FROM_CPU_MONO_OPACITY,
0280 NVDEF(NV902D, SET_PIXELS_FROM_CPU_MONO_OPACITY, V, OPAQUE));
0281
0282 PUSH_MTHD(push, NV902D, SET_PIXELS_FROM_CPU_DX_DU_FRAC, 0,
0283 SET_PIXELS_FROM_CPU_DX_DU_INT, 1,
0284 SET_PIXELS_FROM_CPU_DY_DV_FRAC, 0,
0285 SET_PIXELS_FROM_CPU_DY_DV_INT, 1);
0286
0287 PUSH_IMMD(push, NV902D, SET_PIXELS_FROM_MEMORY_SAFE_OVERLAP,
0288 NVDEF(NV902D, SET_PIXELS_FROM_MEMORY_SAFE_OVERLAP, V, TRUE));
0289
0290 PUSH_MTHD(push, NV902D, SET_PIXELS_FROM_MEMORY_DU_DX_FRAC, 0,
0291 SET_PIXELS_FROM_MEMORY_DU_DX_INT, 1,
0292 SET_PIXELS_FROM_MEMORY_DV_DY_FRAC, 0,
0293 SET_PIXELS_FROM_MEMORY_DV_DY_INT, 1);
0294 PUSH_KICK(push);
0295 return 0;
0296 }
0297