aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/nouveau/nv04_fbcon.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nv04_fbcon.c')
-rw-r--r--drivers/gpu/drm/nouveau/nv04_fbcon.c206
1 files changed, 87 insertions, 119 deletions
diff --git a/drivers/gpu/drm/nouveau/nv04_fbcon.c b/drivers/gpu/drm/nouveau/nv04_fbcon.c
index d910873c136..8fe32bbed99 100644
--- a/drivers/gpu/drm/nouveau/nv04_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nv04_fbcon.c
@@ -22,104 +22,81 @@
* DEALINGS IN THE SOFTWARE.
*/
-#include "drmP.h"
-#include "nouveau_drv.h"
+#include <core/object.h>
+
+#include "nouveau_drm.h"
#include "nouveau_dma.h"
#include "nouveau_fbcon.h"
-static void
+int
nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
{
- struct nouveau_fbcon_par *par = info->par;
- struct drm_device *dev = par->dev;
- struct drm_nouveau_private *dev_priv = dev->dev_private;
- struct nouveau_channel *chan = dev_priv->channel;
-
- if (info->state != FBINFO_STATE_RUNNING)
- return;
-
- if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 4)) {
- nouveau_fbcon_gpu_lockup(info);
- }
+ struct nouveau_fbdev *nfbdev = info->par;
+ struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
+ struct nouveau_channel *chan = drm->channel;
+ int ret;
- if (info->flags & FBINFO_HWACCEL_DISABLED) {
- cfb_copyarea(info, region);
- return;
- }
+ ret = RING_SPACE(chan, 4);
+ if (ret)
+ return ret;
- BEGIN_RING(chan, NvSubImageBlit, 0x0300, 3);
+ BEGIN_NV04(chan, NvSubImageBlit, 0x0300, 3);
OUT_RING(chan, (region->sy << 16) | region->sx);
OUT_RING(chan, (region->dy << 16) | region->dx);
OUT_RING(chan, (region->height << 16) | region->width);
FIRE_RING(chan);
+ return 0;
}
-static void
+int
nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
- struct nouveau_fbcon_par *par = info->par;
- struct drm_device *dev = par->dev;
- struct drm_nouveau_private *dev_priv = dev->dev_private;
- struct nouveau_channel *chan = dev_priv->channel;
-
- if (info->state != FBINFO_STATE_RUNNING)
- return;
-
- if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 7)) {
- nouveau_fbcon_gpu_lockup(info);
- }
+ struct nouveau_fbdev *nfbdev = info->par;
+ struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
+ struct nouveau_channel *chan = drm->channel;
+ int ret;
- if (info->flags & FBINFO_HWACCEL_DISABLED) {
- cfb_fillrect(info, rect);
- return;
- }
+ ret = RING_SPACE(chan, 7);
+ if (ret)
+ return ret;
- BEGIN_RING(chan, NvSubGdiRect, 0x02fc, 1);
+ BEGIN_NV04(chan, NvSubGdiRect, 0x02fc, 1);
OUT_RING(chan, (rect->rop != ROP_COPY) ? 1 : 3);
- BEGIN_RING(chan, NvSubGdiRect, 0x03fc, 1);
+ BEGIN_NV04(chan, NvSubGdiRect, 0x03fc, 1);
if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
info->fix.visual == FB_VISUAL_DIRECTCOLOR)
OUT_RING(chan, ((uint32_t *)info->pseudo_palette)[rect->color]);
else
OUT_RING(chan, rect->color);
- BEGIN_RING(chan, NvSubGdiRect, 0x0400, 2);
+ BEGIN_NV04(chan, NvSubGdiRect, 0x0400, 2);
OUT_RING(chan, (rect->dx << 16) | rect->dy);
OUT_RING(chan, (rect->width << 16) | rect->height);
FIRE_RING(chan);
+ return 0;
}
-static void
+int
nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
{
- struct nouveau_fbcon_par *par = info->par;
- struct drm_device *dev = par->dev;
- struct drm_nouveau_private *dev_priv = dev->dev_private;
- struct nouveau_channel *chan = dev_priv->channel;
+ struct nouveau_fbdev *nfbdev = info->par;
+ struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
+ struct nouveau_channel *chan = drm->channel;
uint32_t fg;
uint32_t bg;
uint32_t dsize;
uint32_t width;
uint32_t *data = (uint32_t *)image->data;
+ int ret;
- if (info->state != FBINFO_STATE_RUNNING)
- return;
-
- if (image->depth != 1) {
- cfb_imageblit(info, image);
- return;
- }
-
- if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 8)) {
- nouveau_fbcon_gpu_lockup(info);
- }
+ if (image->depth != 1)
+ return -ENODEV;
- if (info->flags & FBINFO_HWACCEL_DISABLED) {
- cfb_imageblit(info, image);
- return;
- }
+ ret = RING_SPACE(chan, 8);
+ if (ret)
+ return ret;
- width = (image->width + 31) & ~31;
- dsize = (width * image->height) >> 5;
+ width = ALIGN(image->width, 8);
+ dsize = ALIGN(width * image->height, 32) >> 5;
if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
@@ -130,60 +107,42 @@ nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
bg = image->bg_color;
}
- BEGIN_RING(chan, NvSubGdiRect, 0x0be4, 7);
+ BEGIN_NV04(chan, NvSubGdiRect, 0x0be4, 7);
OUT_RING(chan, (image->dy << 16) | (image->dx & 0xffff));
OUT_RING(chan, ((image->dy + image->height) << 16) |
((image->dx + image->width) & 0xffff));
OUT_RING(chan, bg);
OUT_RING(chan, fg);
- OUT_RING(chan, (image->height << 16) | image->width);
OUT_RING(chan, (image->height << 16) | width);
+ OUT_RING(chan, (image->height << 16) | image->width);
OUT_RING(chan, (image->dy << 16) | (image->dx & 0xffff));
while (dsize) {
int iter_len = dsize > 128 ? 128 : dsize;
- if (RING_SPACE(chan, iter_len + 1)) {
- nouveau_fbcon_gpu_lockup(info);
- cfb_imageblit(info, image);
- return;
- }
+ ret = RING_SPACE(chan, iter_len + 1);
+ if (ret)
+ return ret;
- BEGIN_RING(chan, NvSubGdiRect, 0x0c00, iter_len);
+ BEGIN_NV04(chan, NvSubGdiRect, 0x0c00, iter_len);
OUT_RINGp(chan, data, iter_len);
data += iter_len;
dsize -= iter_len;
}
FIRE_RING(chan);
-}
-
-static int
-nv04_fbcon_grobj_new(struct drm_device *dev, int class, uint32_t handle)
-{
- struct drm_nouveau_private *dev_priv = dev->dev_private;
- struct nouveau_gpuobj *obj = NULL;
- int ret;
-
- ret = nouveau_gpuobj_gr_new(dev_priv->channel, class, &obj);
- if (ret)
- return ret;
-
- ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, handle, obj, NULL);
- if (ret)
- return ret;
-
return 0;
}
int
nv04_fbcon_accel_init(struct fb_info *info)
{
- struct nouveau_fbcon_par *par = info->par;
- struct drm_device *dev = par->dev;
- struct drm_nouveau_private *dev_priv = dev->dev_private;
- struct nouveau_channel *chan = dev_priv->channel;
- const int sub = NvSubCtxSurf2D;
+ struct nouveau_fbdev *nfbdev = info->par;
+ struct drm_device *dev = nfbdev->dev;
+ struct nouveau_drm *drm = nouveau_drm(dev);
+ struct nouveau_channel *chan = drm->channel;
+ struct nouveau_device *device = nv_device(drm->device);
+ struct nouveau_object *object;
int surface_fmt, pattern_fmt, rect_fmt;
int ret;
@@ -215,29 +174,35 @@ nv04_fbcon_accel_init(struct fb_info *info)
return -EINVAL;
}
- ret = nv04_fbcon_grobj_new(dev, dev_priv->card_type >= NV_10 ?
- 0x0062 : 0x0042, NvCtxSurf2D);
+ ret = nouveau_object_new(nv_object(chan->cli), NVDRM_CHAN, NvCtxSurf2D,
+ device->card_type >= NV_10 ? 0x0062 : 0x0042,
+ NULL, 0, &object);
if (ret)
return ret;
- ret = nv04_fbcon_grobj_new(dev, 0x0019, NvClipRect);
+ ret = nouveau_object_new(nv_object(chan->cli), NVDRM_CHAN, NvClipRect,
+ 0x0019, NULL, 0, &object);
if (ret)
return ret;
- ret = nv04_fbcon_grobj_new(dev, 0x0043, NvRop);
+ ret = nouveau_object_new(nv_object(chan->cli), NVDRM_CHAN, NvRop,
+ 0x0043, NULL, 0, &object);
if (ret)
return ret;
- ret = nv04_fbcon_grobj_new(dev, 0x0044, NvImagePatt);
+ ret = nouveau_object_new(nv_object(chan->cli), NVDRM_CHAN, NvImagePatt,
+ 0x0044, NULL, 0, &object);
if (ret)
return ret;
- ret = nv04_fbcon_grobj_new(dev, 0x004a, NvGdiRect);
+ ret = nouveau_object_new(nv_object(chan->cli), NVDRM_CHAN, NvGdiRect,
+ 0x004a, NULL, 0, &object);
if (ret)
return ret;
- ret = nv04_fbcon_grobj_new(dev, dev_priv->card_type >= NV_10 ?
- 0x009f : 0x005f, NvImageBlit);
+ ret = nouveau_object_new(nv_object(chan->cli), NVDRM_CHAN, NvImageBlit,
+ device->chipset >= 0x11 ? 0x009f : 0x005f,
+ NULL, 0, &object);
if (ret)
return ret;
@@ -246,25 +211,25 @@ nv04_fbcon_accel_init(struct fb_info *info)
return 0;
}
- BEGIN_RING(chan, sub, 0x0000, 1);
+ BEGIN_NV04(chan, NvSubCtxSurf2D, 0x0000, 1);
OUT_RING(chan, NvCtxSurf2D);
- BEGIN_RING(chan, sub, 0x0184, 2);
+ BEGIN_NV04(chan, NvSubCtxSurf2D, 0x0184, 2);
OUT_RING(chan, NvDmaFB);
OUT_RING(chan, NvDmaFB);
- BEGIN_RING(chan, sub, 0x0300, 4);
+ BEGIN_NV04(chan, NvSubCtxSurf2D, 0x0300, 4);
OUT_RING(chan, surface_fmt);
OUT_RING(chan, info->fix.line_length | (info->fix.line_length << 16));
OUT_RING(chan, info->fix.smem_start - dev->mode_config.fb_base);
OUT_RING(chan, info->fix.smem_start - dev->mode_config.fb_base);
- BEGIN_RING(chan, sub, 0x0000, 1);
+ BEGIN_NV04(chan, NvSubCtxSurf2D, 0x0000, 1);
OUT_RING(chan, NvRop);
- BEGIN_RING(chan, sub, 0x0300, 1);
+ BEGIN_NV04(chan, NvSubCtxSurf2D, 0x0300, 1);
OUT_RING(chan, 0x55);
- BEGIN_RING(chan, sub, 0x0000, 1);
+ BEGIN_NV04(chan, NvSubCtxSurf2D, 0x0000, 1);
OUT_RING(chan, NvImagePatt);
- BEGIN_RING(chan, sub, 0x0300, 8);
+ BEGIN_NV04(chan, NvSubCtxSurf2D, 0x0300, 8);
OUT_RING(chan, pattern_fmt);
#ifdef __BIG_ENDIAN
OUT_RING(chan, 2);
@@ -278,38 +243,41 @@ nv04_fbcon_accel_init(struct fb_info *info)
OUT_RING(chan, ~0);
OUT_RING(chan, ~0);
- BEGIN_RING(chan, sub, 0x0000, 1);
+ BEGIN_NV04(chan, NvSubCtxSurf2D, 0x0000, 1);
OUT_RING(chan, NvClipRect);
- BEGIN_RING(chan, sub, 0x0300, 2);
+ BEGIN_NV04(chan, NvSubCtxSurf2D, 0x0300, 2);
OUT_RING(chan, 0);
OUT_RING(chan, (info->var.yres_virtual << 16) | info->var.xres_virtual);
- BEGIN_RING(chan, NvSubImageBlit, 0x0000, 1);
+ BEGIN_NV04(chan, NvSubImageBlit, 0x0000, 1);
OUT_RING(chan, NvImageBlit);
- BEGIN_RING(chan, NvSubImageBlit, 0x019c, 1);
+ BEGIN_NV04(chan, NvSubImageBlit, 0x019c, 1);
OUT_RING(chan, NvCtxSurf2D);
- BEGIN_RING(chan, NvSubImageBlit, 0x02fc, 1);
+ BEGIN_NV04(chan, NvSubImageBlit, 0x02fc, 1);
OUT_RING(chan, 3);
+ if (device->chipset >= 0x11 /*XXX: oclass == 0x009f*/) {
+ BEGIN_NV04(chan, NvSubImageBlit, 0x0120, 3);
+ OUT_RING(chan, 0);
+ OUT_RING(chan, 1);
+ OUT_RING(chan, 2);
+ }
- BEGIN_RING(chan, NvSubGdiRect, 0x0000, 1);
+ BEGIN_NV04(chan, NvSubGdiRect, 0x0000, 1);
OUT_RING(chan, NvGdiRect);
- BEGIN_RING(chan, NvSubGdiRect, 0x0198, 1);
+ BEGIN_NV04(chan, NvSubGdiRect, 0x0198, 1);
OUT_RING(chan, NvCtxSurf2D);
- BEGIN_RING(chan, NvSubGdiRect, 0x0188, 2);
+ BEGIN_NV04(chan, NvSubGdiRect, 0x0188, 2);
OUT_RING(chan, NvImagePatt);
OUT_RING(chan, NvRop);
- BEGIN_RING(chan, NvSubGdiRect, 0x0304, 1);
+ BEGIN_NV04(chan, NvSubGdiRect, 0x0304, 1);
OUT_RING(chan, 1);
- BEGIN_RING(chan, NvSubGdiRect, 0x0300, 1);
+ BEGIN_NV04(chan, NvSubGdiRect, 0x0300, 1);
OUT_RING(chan, rect_fmt);
- BEGIN_RING(chan, NvSubGdiRect, 0x02fc, 1);
+ BEGIN_NV04(chan, NvSubGdiRect, 0x02fc, 1);
OUT_RING(chan, 3);
FIRE_RING(chan);
- info->fbops->fb_fillrect = nv04_fbcon_fillrect;
- info->fbops->fb_copyarea = nv04_fbcon_copyarea;
- info->fbops->fb_imageblit = nv04_fbcon_imageblit;
return 0;
}