]> git.karo-electronics.de Git - mv-sheeva.git/blob - drivers/gpu/drm/nouveau/nv50_fbcon.c
drm/nouveau: implicitly insert non-DMA objects into RAMHT
[mv-sheeva.git] / drivers / gpu / drm / nouveau / nv50_fbcon.c
1 #include "drmP.h"
2 #include "nouveau_drv.h"
3 #include "nouveau_dma.h"
4 #include "nouveau_ramht.h"
5 #include "nouveau_fbcon.h"
6
7 int
8 nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
9 {
10         struct nouveau_fbdev *nfbdev = info->par;
11         struct drm_device *dev = nfbdev->dev;
12         struct drm_nouveau_private *dev_priv = dev->dev_private;
13         struct nouveau_channel *chan = dev_priv->channel;
14         int ret;
15
16         ret = RING_SPACE(chan, rect->rop == ROP_COPY ? 7 : 11);
17         if (ret)
18                 return ret;
19
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);
25         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);
30         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);
40         return 0;
41 }
42
43 int
44 nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
45 {
46         struct nouveau_fbdev *nfbdev = info->par;
47         struct drm_device *dev = nfbdev->dev;
48         struct drm_nouveau_private *dev_priv = dev->dev_private;
49         struct nouveau_channel *chan = dev_priv->channel;
50         int ret;
51
52         ret = RING_SPACE(chan, 12);
53         if (ret)
54                 return ret;
55
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);
69         return 0;
70 }
71
72 int
73 nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
74 {
75         struct nouveau_fbdev *nfbdev = info->par;
76         struct drm_device *dev = nfbdev->dev;
77         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;
82         int ret;
83
84         if (image->depth != 1)
85                 return -ENODEV;
86
87         ret = RING_SPACE(chan, 11);
88         if (ret)
89                 return ret;
90
91         width = ALIGN(image->width, 32);
92         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
115                 ret = RING_SPACE(chan, push + 1);
116                 if (ret)
117                         return ret;
118
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);
127         return 0;
128 }
129
130 int
131 nv50_fbcon_accel_init(struct fb_info *info)
132 {
133         struct nouveau_fbdev *nfbdev = info->par;
134         struct drm_device *dev = nfbdev->dev;
135         struct drm_nouveau_private *dev_priv = dev->dev_private;
136         struct nouveau_channel *chan = dev_priv->channel;
137         int ret, format;
138         uint64_t fb;
139
140         fb = info->fix.smem_start - dev_priv->fb_phys + dev_priv->vm_vram_base;
141
142         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
169         ret = nouveau_gpuobj_gr_new(dev_priv->channel, Nv2D, 0x502d);
170         if (ret)
171                 return ret;
172
173         ret = RING_SPACE(chan, 59);
174         if (ret) {
175                 nouveau_fbcon_gpu_lockup(info);
176                 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);
212         OUT_RING(chan, 1);
213         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);
227         OUT_RING(chan, upper_32_bits(fb));
228         OUT_RING(chan, lower_32_bits(fb));
229         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);
236         OUT_RING(chan, upper_32_bits(fb));
237         OUT_RING(chan, lower_32_bits(fb));
238
239         return 0;
240 }
241