Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2010 Red Hat Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  * Authors: Ben Skeggs
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: /* depth 24 */
0183         case 8: /* depth 32, just use 24.. */
0184             format = NV502D_SET_DST_FORMAT_V_X8R8G8B8;
0185             break;
0186         case 2: /* depth 30 */
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