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/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: /* depth 24 */
0188         case 8: /* depth 32, just use 24.. */
0189             format = NV902D_SET_DST_FORMAT_V_X8R8G8B8;
0190             break;
0191         case 2: /* depth 30 */
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