blob: 1567319939079a5c21a5dbce47021c790c6895b8 [file] [log] [blame]
Ben Skeggs6ee73862009-12-11 19:24:15 +10001#include "drmP.h"
2#include "nouveau_drv.h"
3#include "nouveau_dma.h"
Ben Skeggsa8eaebc2010-09-01 15:24:31 +10004#include "nouveau_ramht.h"
Ben Skeggs6ee73862009-12-11 19:24:15 +10005#include "nouveau_fbcon.h"
6
Ben Skeggsceed5f32010-10-05 16:41:29 +10007int
Ben Skeggs6ee73862009-12-11 19:24:15 +10008nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
9{
Dave Airlie8be48d92010-03-30 05:34:14 +000010 struct nouveau_fbdev *nfbdev = info->par;
11 struct drm_device *dev = nfbdev->dev;
Ben Skeggs6ee73862009-12-11 19:24:15 +100012 struct drm_nouveau_private *dev_priv = dev->dev_private;
13 struct nouveau_channel *chan = dev_priv->channel;
Ben Skeggsceed5f32010-10-05 16:41:29 +100014 int ret;
Ben Skeggs6ee73862009-12-11 19:24:15 +100015
Ben Skeggsceed5f32010-10-05 16:41:29 +100016 ret = RING_SPACE(chan, rect->rop == ROP_COPY ? 7 : 11);
17 if (ret)
18 return ret;
Ben Skeggs6ee73862009-12-11 19:24:15 +100019
20 if (rect->rop != ROP_COPY) {
21 BEGIN_RING(chan, NvSub2D, 0x02ac, 1);
22 OUT_RING(chan, 1);
23 }
24 BEGIN_RING(chan, NvSub2D, 0x0588, 1);
Ben Skeggsbf5302b2010-01-04 09:10:55 +100025 if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
26 info->fix.visual == FB_VISUAL_DIRECTCOLOR)
27 OUT_RING(chan, ((uint32_t *)info->pseudo_palette)[rect->color]);
28 else
29 OUT_RING(chan, rect->color);
Ben Skeggs6ee73862009-12-11 19:24:15 +100030 BEGIN_RING(chan, NvSub2D, 0x0600, 4);
31 OUT_RING(chan, rect->dx);
32 OUT_RING(chan, rect->dy);
33 OUT_RING(chan, rect->dx + rect->width);
34 OUT_RING(chan, rect->dy + rect->height);
35 if (rect->rop != ROP_COPY) {
36 BEGIN_RING(chan, NvSub2D, 0x02ac, 1);
37 OUT_RING(chan, 3);
38 }
39 FIRE_RING(chan);
Ben Skeggsceed5f32010-10-05 16:41:29 +100040 return 0;
Ben Skeggs6ee73862009-12-11 19:24:15 +100041}
42
Ben Skeggsceed5f32010-10-05 16:41:29 +100043int
Ben Skeggs6ee73862009-12-11 19:24:15 +100044nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
45{
Dave Airlie8be48d92010-03-30 05:34:14 +000046 struct nouveau_fbdev *nfbdev = info->par;
47 struct drm_device *dev = nfbdev->dev;
Ben Skeggs6ee73862009-12-11 19:24:15 +100048 struct drm_nouveau_private *dev_priv = dev->dev_private;
49 struct nouveau_channel *chan = dev_priv->channel;
Ben Skeggsceed5f32010-10-05 16:41:29 +100050 int ret;
Ben Skeggs6ee73862009-12-11 19:24:15 +100051
Ben Skeggsceed5f32010-10-05 16:41:29 +100052 ret = RING_SPACE(chan, 12);
53 if (ret)
54 return ret;
Ben Skeggs6ee73862009-12-11 19:24:15 +100055
56 BEGIN_RING(chan, NvSub2D, 0x0110, 1);
57 OUT_RING(chan, 0);
58 BEGIN_RING(chan, NvSub2D, 0x08b0, 4);
59 OUT_RING(chan, region->dx);
60 OUT_RING(chan, region->dy);
61 OUT_RING(chan, region->width);
62 OUT_RING(chan, region->height);
63 BEGIN_RING(chan, NvSub2D, 0x08d0, 4);
64 OUT_RING(chan, 0);
65 OUT_RING(chan, region->sx);
66 OUT_RING(chan, 0);
67 OUT_RING(chan, region->sy);
68 FIRE_RING(chan);
Ben Skeggsceed5f32010-10-05 16:41:29 +100069 return 0;
Ben Skeggs6ee73862009-12-11 19:24:15 +100070}
71
Ben Skeggsceed5f32010-10-05 16:41:29 +100072int
Ben Skeggs6ee73862009-12-11 19:24:15 +100073nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
74{
Dave Airlie8be48d92010-03-30 05:34:14 +000075 struct nouveau_fbdev *nfbdev = info->par;
76 struct drm_device *dev = nfbdev->dev;
Ben Skeggs6ee73862009-12-11 19:24:15 +100077 struct drm_nouveau_private *dev_priv = dev->dev_private;
78 struct nouveau_channel *chan = dev_priv->channel;
79 uint32_t width, dwords, *data = (uint32_t *)image->data;
80 uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel));
81 uint32_t *palette = info->pseudo_palette;
Ben Skeggsceed5f32010-10-05 16:41:29 +100082 int ret;
Ben Skeggs6ee73862009-12-11 19:24:15 +100083
Ben Skeggsceed5f32010-10-05 16:41:29 +100084 if (image->depth != 1)
85 return -ENODEV;
Ben Skeggs6ee73862009-12-11 19:24:15 +100086
Ben Skeggsceed5f32010-10-05 16:41:29 +100087 ret = RING_SPACE(chan, 11);
88 if (ret)
89 return ret;
Ben Skeggs6ee73862009-12-11 19:24:15 +100090
Matt Turner3bfc7d22010-02-24 23:27:10 -050091 width = ALIGN(image->width, 32);
Ben Skeggs6ee73862009-12-11 19:24:15 +100092 dwords = (width * image->height) >> 5;
93
94 BEGIN_RING(chan, NvSub2D, 0x0814, 2);
95 if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
96 info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
97 OUT_RING(chan, palette[image->bg_color] | mask);
98 OUT_RING(chan, palette[image->fg_color] | mask);
99 } else {
100 OUT_RING(chan, image->bg_color);
101 OUT_RING(chan, image->fg_color);
102 }
103 BEGIN_RING(chan, NvSub2D, 0x0838, 2);
104 OUT_RING(chan, image->width);
105 OUT_RING(chan, image->height);
106 BEGIN_RING(chan, NvSub2D, 0x0850, 4);
107 OUT_RING(chan, 0);
108 OUT_RING(chan, image->dx);
109 OUT_RING(chan, 0);
110 OUT_RING(chan, image->dy);
111
112 while (dwords) {
113 int push = dwords > 2047 ? 2047 : dwords;
114
Ben Skeggsceed5f32010-10-05 16:41:29 +1000115 ret = RING_SPACE(chan, push + 1);
116 if (ret)
117 return ret;
Ben Skeggs6ee73862009-12-11 19:24:15 +1000118
119 dwords -= push;
120
121 BEGIN_RING(chan, NvSub2D, 0x40000860, push);
122 OUT_RINGp(chan, data, push);
123 data += push;
124 }
125
126 FIRE_RING(chan);
Ben Skeggsceed5f32010-10-05 16:41:29 +1000127 return 0;
Ben Skeggs6ee73862009-12-11 19:24:15 +1000128}
129
130int
131nv50_fbcon_accel_init(struct fb_info *info)
132{
Dave Airlie8be48d92010-03-30 05:34:14 +0000133 struct nouveau_fbdev *nfbdev = info->par;
134 struct drm_device *dev = nfbdev->dev;
Ben Skeggs6ee73862009-12-11 19:24:15 +1000135 struct drm_nouveau_private *dev_priv = dev->dev_private;
136 struct nouveau_channel *chan = dev_priv->channel;
Ben Skeggs6ee73862009-12-11 19:24:15 +1000137 int ret, format;
Ben Skeggsceac3092010-11-23 10:10:24 +1000138 uint64_t fb;
Ben Skeggs6ee73862009-12-11 19:24:15 +1000139
Ben Skeggs0c324972010-03-16 13:20:58 +1000140 fb = info->fix.smem_start - dev_priv->fb_phys + dev_priv->vm_vram_base;
141
Ben Skeggs6ee73862009-12-11 19:24:15 +1000142 switch (info->var.bits_per_pixel) {
143 case 8:
144 format = 0xf3;
145 break;
146 case 15:
147 format = 0xf8;
148 break;
149 case 16:
150 format = 0xe8;
151 break;
152 case 32:
153 switch (info->var.transp.length) {
154 case 0: /* depth 24 */
155 case 8: /* depth 32, just use 24.. */
156 format = 0xe6;
157 break;
158 case 2: /* depth 30 */
159 format = 0xd1;
160 break;
161 default:
162 return -EINVAL;
163 }
164 break;
165 default:
166 return -EINVAL;
167 }
168
Ben Skeggsceac3092010-11-23 10:10:24 +1000169 ret = nouveau_gpuobj_gr_new(dev_priv->channel, Nv2D, 0x502d);
Ben Skeggs6ee73862009-12-11 19:24:15 +1000170 if (ret)
171 return ret;
172
173 ret = RING_SPACE(chan, 59);
174 if (ret) {
Marcin Slusarz846975a2010-01-04 19:25:09 +0100175 nouveau_fbcon_gpu_lockup(info);
Ben Skeggs6ee73862009-12-11 19:24:15 +1000176 return ret;
177 }
178
179 BEGIN_RING(chan, NvSub2D, 0x0000, 1);
180 OUT_RING(chan, Nv2D);
181 BEGIN_RING(chan, NvSub2D, 0x0180, 4);
182 OUT_RING(chan, NvNotify0);
183 OUT_RING(chan, chan->vram_handle);
184 OUT_RING(chan, chan->vram_handle);
185 OUT_RING(chan, chan->vram_handle);
186 BEGIN_RING(chan, NvSub2D, 0x0290, 1);
187 OUT_RING(chan, 0);
188 BEGIN_RING(chan, NvSub2D, 0x0888, 1);
189 OUT_RING(chan, 1);
190 BEGIN_RING(chan, NvSub2D, 0x02ac, 1);
191 OUT_RING(chan, 3);
192 BEGIN_RING(chan, NvSub2D, 0x02a0, 1);
193 OUT_RING(chan, 0x55);
194 BEGIN_RING(chan, NvSub2D, 0x08c0, 4);
195 OUT_RING(chan, 0);
196 OUT_RING(chan, 1);
197 OUT_RING(chan, 0);
198 OUT_RING(chan, 1);
199 BEGIN_RING(chan, NvSub2D, 0x0580, 2);
200 OUT_RING(chan, 4);
201 OUT_RING(chan, format);
202 BEGIN_RING(chan, NvSub2D, 0x02e8, 2);
203 OUT_RING(chan, 2);
204 OUT_RING(chan, 1);
205 BEGIN_RING(chan, NvSub2D, 0x0804, 1);
206 OUT_RING(chan, format);
207 BEGIN_RING(chan, NvSub2D, 0x0800, 1);
208 OUT_RING(chan, 1);
209 BEGIN_RING(chan, NvSub2D, 0x0808, 3);
210 OUT_RING(chan, 0);
211 OUT_RING(chan, 0);
Marcin Koƛcielnickic82b88d2010-02-27 18:13:35 +0000212 OUT_RING(chan, 1);
Ben Skeggs6ee73862009-12-11 19:24:15 +1000213 BEGIN_RING(chan, NvSub2D, 0x081c, 1);
214 OUT_RING(chan, 1);
215 BEGIN_RING(chan, NvSub2D, 0x0840, 4);
216 OUT_RING(chan, 0);
217 OUT_RING(chan, 1);
218 OUT_RING(chan, 0);
219 OUT_RING(chan, 1);
220 BEGIN_RING(chan, NvSub2D, 0x0200, 2);
221 OUT_RING(chan, format);
222 OUT_RING(chan, 1);
223 BEGIN_RING(chan, NvSub2D, 0x0214, 5);
224 OUT_RING(chan, info->fix.line_length);
225 OUT_RING(chan, info->var.xres_virtual);
226 OUT_RING(chan, info->var.yres_virtual);
Ben Skeggs0c324972010-03-16 13:20:58 +1000227 OUT_RING(chan, upper_32_bits(fb));
228 OUT_RING(chan, lower_32_bits(fb));
Ben Skeggs6ee73862009-12-11 19:24:15 +1000229 BEGIN_RING(chan, NvSub2D, 0x0230, 2);
230 OUT_RING(chan, format);
231 OUT_RING(chan, 1);
232 BEGIN_RING(chan, NvSub2D, 0x0244, 5);
233 OUT_RING(chan, info->fix.line_length);
234 OUT_RING(chan, info->var.xres_virtual);
235 OUT_RING(chan, info->var.yres_virtual);
Ben Skeggs0c324972010-03-16 13:20:58 +1000236 OUT_RING(chan, upper_32_bits(fb));
237 OUT_RING(chan, lower_32_bits(fb));
Ben Skeggs6ee73862009-12-11 19:24:15 +1000238
Ben Skeggs6ee73862009-12-11 19:24:15 +1000239 return 0;
240}
241