Back to home page

OSCL-LXR

 
 

    


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