~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/video/mb862xx/mb862xxfb_accel.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * drivers/mb862xx/mb862xxfb_accel.c
 
3
 *
 
4
 * Fujitsu Carmine/Coral-P(A)/Lime framebuffer driver acceleration support
 
5
 *
 
6
 * (C) 2007 Alexander Shishkin <virtuoso@slind.org>
 
7
 * (C) 2009 Valentin Sitdikov <v.sitdikov@gmail.com>
 
8
 * (C) 2009 Siemens AG
 
9
 *
 
10
 * This program is free software; you can redistribute it and/or modify
 
11
 * it under the terms of the GNU General Public License version 2 as
 
12
 * published by the Free Software Foundation.
 
13
 *
 
14
 */
 
15
#include <linux/fb.h>
 
16
#include <linux/delay.h>
 
17
#include <linux/init.h>
 
18
#include <linux/interrupt.h>
 
19
#include <linux/module.h>
 
20
#include <linux/pci.h>
 
21
#include <linux/slab.h>
 
22
#if defined(CONFIG_OF)
 
23
#include <linux/of_platform.h>
 
24
#endif
 
25
#include "mb862xxfb.h"
 
26
#include "mb862xx_reg.h"
 
27
#include "mb862xxfb_accel.h"
 
28
 
 
29
static void mb862xxfb_write_fifo(u32 count, u32 *data, struct fb_info *info)
 
30
{
 
31
        struct mb862xxfb_par *par = info->par;
 
32
        static u32 free;
 
33
 
 
34
        u32 total = 0;
 
35
        while (total < count) {
 
36
                if (free) {
 
37
                        outreg(geo, GDC_GEO_REG_INPUT_FIFO, data[total]);
 
38
                        total++;
 
39
                        free--;
 
40
                } else {
 
41
                        free = (u32) inreg(draw, GDC_REG_FIFO_COUNT);
 
42
                }
 
43
        }
 
44
}
 
45
 
 
46
static void mb86290fb_copyarea(struct fb_info *info,
 
47
                               const struct fb_copyarea *area)
 
48
{
 
49
        __u32 cmd[6];
 
50
 
 
51
        cmd[0] = (GDC_TYPE_SETREGISTER << 24) | (1 << 16) | GDC_REG_MODE_BITMAP;
 
52
        /* Set raster operation */
 
53
        cmd[1] = (2 << 7) | (GDC_ROP_COPY << 9);
 
54
        cmd[2] = GDC_TYPE_BLTCOPYP << 24;
 
55
 
 
56
        if (area->sx >= area->dx && area->sy >= area->dy)
 
57
                cmd[2] |= GDC_CMD_BLTCOPY_TOP_LEFT << 16;
 
58
        else if (area->sx >= area->dx && area->sy <= area->dy)
 
59
                cmd[2] |= GDC_CMD_BLTCOPY_BOTTOM_LEFT << 16;
 
60
        else if (area->sx <= area->dx && area->sy >= area->dy)
 
61
                cmd[2] |= GDC_CMD_BLTCOPY_TOP_RIGHT << 16;
 
62
        else
 
63
                cmd[2] |= GDC_CMD_BLTCOPY_BOTTOM_RIGHT << 16;
 
64
 
 
65
        cmd[3] = (area->sy << 16) | area->sx;
 
66
        cmd[4] = (area->dy << 16) | area->dx;
 
67
        cmd[5] = (area->height << 16) | area->width;
 
68
        mb862xxfb_write_fifo(6, cmd, info);
 
69
}
 
70
 
 
71
/*
 
72
 * Fill in the cmd array /GDC FIFO commands/ to draw a 1bit image.
 
73
 * Make sure cmd has enough room!
 
74
 */
 
75
static void mb86290fb_imageblit1(u32 *cmd, u16 step, u16 dx, u16 dy,
 
76
                                 u16 width, u16 height, u32 fgcolor,
 
77
                                 u32 bgcolor, const struct fb_image *image,
 
78
                                 struct fb_info *info)
 
79
{
 
80
        int i;
 
81
        unsigned const char *line;
 
82
        u16 bytes;
 
83
 
 
84
        /* set colors and raster operation regs */
 
85
        cmd[0] = (GDC_TYPE_SETREGISTER << 24) | (1 << 16) | GDC_REG_MODE_BITMAP;
 
86
        /* Set raster operation */
 
87
        cmd[1] = (2 << 7) | (GDC_ROP_COPY << 9);
 
88
        cmd[2] =
 
89
            (GDC_TYPE_SETCOLORREGISTER << 24) | (GDC_CMD_BODY_FORE_COLOR << 16);
 
90
        cmd[3] = fgcolor;
 
91
        cmd[4] =
 
92
            (GDC_TYPE_SETCOLORREGISTER << 24) | (GDC_CMD_BODY_BACK_COLOR << 16);
 
93
        cmd[5] = bgcolor;
 
94
 
 
95
        i = 0;
 
96
        line = image->data;
 
97
        bytes = (image->width + 7) >> 3;
 
98
 
 
99
        /* and the image */
 
100
        cmd[6] = (GDC_TYPE_DRAWBITMAPP << 24) |
 
101
            (GDC_CMD_BITMAP << 16) | (2 + (step * height));
 
102
        cmd[7] = (dy << 16) | dx;
 
103
        cmd[8] = (height << 16) | width;
 
104
 
 
105
        while (i < height) {
 
106
                memcpy(&cmd[9 + i * step], line, step << 2);
 
107
#ifdef __LITTLE_ENDIAN
 
108
                {
 
109
                        int k = 0;
 
110
                        for (k = 0; k < step; k++)
 
111
                                cmd[9 + i * step + k] =
 
112
                                    cpu_to_be32(cmd[9 + i * step + k]);
 
113
                }
 
114
#endif
 
115
                line += bytes;
 
116
                i++;
 
117
        }
 
118
}
 
119
 
 
120
/*
 
121
 * Fill in the cmd array /GDC FIFO commands/ to draw a 8bit image.
 
122
 * Make sure cmd has enough room!
 
123
 */
 
124
static void mb86290fb_imageblit8(u32 *cmd, u16 step, u16 dx, u16 dy,
 
125
                                 u16 width, u16 height, u32 fgcolor,
 
126
                                 u32 bgcolor, const struct fb_image *image,
 
127
                                 struct fb_info *info)
 
128
{
 
129
        int i, j;
 
130
        unsigned const char *line, *ptr;
 
131
        u16 bytes;
 
132
 
 
133
        cmd[0] = (GDC_TYPE_DRAWBITMAPP << 24) |
 
134
            (GDC_CMD_BLT_DRAW << 16) | (2 + (height * step));
 
135
        cmd[1] = (dy << 16) | dx;
 
136
        cmd[2] = (height << 16) | width;
 
137
 
 
138
        i = 0;
 
139
        line = ptr = image->data;
 
140
        bytes = image->width;
 
141
 
 
142
        while (i < height) {
 
143
                ptr = line;
 
144
                for (j = 0; j < step; j++) {
 
145
                        cmd[3 + i * step + j] =
 
146
                            (((u32 *) (info->pseudo_palette))[*ptr]) & 0xffff;
 
147
                        ptr++;
 
148
                        cmd[3 + i * step + j] |=
 
149
                            ((((u32 *) (info->
 
150
                                        pseudo_palette))[*ptr]) & 0xffff) << 16;
 
151
                        ptr++;
 
152
                }
 
153
 
 
154
                line += bytes;
 
155
                i++;
 
156
        }
 
157
}
 
158
 
 
159
/*
 
160
 * Fill in the cmd array /GDC FIFO commands/ to draw a 16bit image.
 
161
 * Make sure cmd has enough room!
 
162
 */
 
163
static void mb86290fb_imageblit16(u32 *cmd, u16 step, u16 dx, u16 dy,
 
164
                                  u16 width, u16 height, u32 fgcolor,
 
165
                                  u32 bgcolor, const struct fb_image *image,
 
166
                                  struct fb_info *info)
 
167
{
 
168
        int i;
 
169
        unsigned const char *line;
 
170
        u16 bytes;
 
171
 
 
172
        i = 0;
 
173
        line = image->data;
 
174
        bytes = image->width << 1;
 
175
 
 
176
        cmd[0] = (GDC_TYPE_DRAWBITMAPP << 24) |
 
177
            (GDC_CMD_BLT_DRAW << 16) | (2 + step * height);
 
178
        cmd[1] = (dy << 16) | dx;
 
179
        cmd[2] = (height << 16) | width;
 
180
 
 
181
        while (i < height) {
 
182
                memcpy(&cmd[3 + i * step], line, step);
 
183
                line += bytes;
 
184
                i++;
 
185
        }
 
186
}
 
187
 
 
188
static void mb86290fb_imageblit(struct fb_info *info,
 
189
                                const struct fb_image *image)
 
190
{
 
191
        int mdr;
 
192
        u32 *cmd = NULL;
 
193
        void (*cmdfn) (u32 *, u16, u16, u16, u16, u16, u32, u32,
 
194
                       const struct fb_image *, struct fb_info *) = NULL;
 
195
        u32 cmdlen;
 
196
        u32 fgcolor = 0, bgcolor = 0;
 
197
        u16 step;
 
198
 
 
199
        u16 width = image->width, height = image->height;
 
200
        u16 dx = image->dx, dy = image->dy;
 
201
        int x2, y2, vxres, vyres;
 
202
 
 
203
        mdr = (GDC_ROP_COPY << 9);
 
204
        x2 = image->dx + image->width;
 
205
        y2 = image->dy + image->height;
 
206
        vxres = info->var.xres_virtual;
 
207
        vyres = info->var.yres_virtual;
 
208
        x2 = min(x2, vxres);
 
209
        y2 = min(y2, vyres);
 
210
        width = x2 - dx;
 
211
        height = y2 - dy;
 
212
 
 
213
        switch (image->depth) {
 
214
        case 1:
 
215
                step = (width + 31) >> 5;
 
216
                cmdlen = 9 + height * step;
 
217
                cmdfn = mb86290fb_imageblit1;
 
218
                if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
 
219
                    info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
 
220
                        fgcolor =
 
221
                            ((u32 *) (info->pseudo_palette))[image->fg_color];
 
222
                        bgcolor =
 
223
                            ((u32 *) (info->pseudo_palette))[image->bg_color];
 
224
                } else {
 
225
                        fgcolor = image->fg_color;
 
226
                        bgcolor = image->bg_color;
 
227
                }
 
228
 
 
229
                break;
 
230
 
 
231
        case 8:
 
232
                step = (width + 1) >> 1;
 
233
                cmdlen = 3 + height * step;
 
234
                cmdfn = mb86290fb_imageblit8;
 
235
                break;
 
236
 
 
237
        case 16:
 
238
                step = (width + 1) >> 1;
 
239
                cmdlen = 3 + height * step;
 
240
                cmdfn = mb86290fb_imageblit16;
 
241
                break;
 
242
 
 
243
        default:
 
244
                cfb_imageblit(info, image);
 
245
                return;
 
246
        }
 
247
 
 
248
        cmd = kmalloc(cmdlen * 4, GFP_DMA);
 
249
        if (!cmd)
 
250
                return cfb_imageblit(info, image);
 
251
        cmdfn(cmd, step, dx, dy, width, height, fgcolor, bgcolor, image, info);
 
252
        mb862xxfb_write_fifo(cmdlen, cmd, info);
 
253
        kfree(cmd);
 
254
}
 
255
 
 
256
static void mb86290fb_fillrect(struct fb_info *info,
 
257
                               const struct fb_fillrect *rect)
 
258
{
 
259
 
 
260
        u32 x2, y2, vxres, vyres, height, width, fg;
 
261
        u32 cmd[7];
 
262
 
 
263
        vxres = info->var.xres_virtual;
 
264
        vyres = info->var.yres_virtual;
 
265
 
 
266
        if (!rect->width || !rect->height || rect->dx > vxres
 
267
            || rect->dy > vyres)
 
268
                return;
 
269
 
 
270
        /* We could use hardware clipping but on many cards you get around
 
271
         * hardware clipping by writing to framebuffer directly. */
 
272
        x2 = rect->dx + rect->width;
 
273
        y2 = rect->dy + rect->height;
 
274
        x2 = min(x2, vxres);
 
275
        y2 = min(y2, vyres);
 
276
        width = x2 - rect->dx;
 
277
        height = y2 - rect->dy;
 
278
        if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
 
279
            info->fix.visual == FB_VISUAL_DIRECTCOLOR)
 
280
                fg = ((u32 *) (info->pseudo_palette))[rect->color];
 
281
        else
 
282
                fg = rect->color;
 
283
 
 
284
        switch (rect->rop) {
 
285
 
 
286
        case ROP_XOR:
 
287
                /* Set raster operation */
 
288
                cmd[1] = (2 << 7) | (GDC_ROP_XOR << 9);
 
289
                break;
 
290
 
 
291
        case ROP_COPY:
 
292
                /* Set raster operation */
 
293
                cmd[1] = (2 << 7) | (GDC_ROP_COPY << 9);
 
294
                break;
 
295
 
 
296
        }
 
297
 
 
298
        cmd[0] = (GDC_TYPE_SETREGISTER << 24) | (1 << 16) | GDC_REG_MODE_BITMAP;
 
299
        /* cmd[1] set earlier */
 
300
        cmd[2] =
 
301
            (GDC_TYPE_SETCOLORREGISTER << 24) | (GDC_CMD_BODY_FORE_COLOR << 16);
 
302
        cmd[3] = fg;
 
303
        cmd[4] = (GDC_TYPE_DRAWRECTP << 24) | (GDC_CMD_BLT_FILL << 16);
 
304
        cmd[5] = (rect->dy << 16) | (rect->dx);
 
305
        cmd[6] = (height << 16) | width;
 
306
 
 
307
        mb862xxfb_write_fifo(7, cmd, info);
 
308
}
 
309
 
 
310
void mb862xxfb_init_accel(struct fb_info *info, int xres)
 
311
{
 
312
        struct mb862xxfb_par *par = info->par;
 
313
 
 
314
        if (info->var.bits_per_pixel == 32) {
 
315
                info->fbops->fb_fillrect = cfb_fillrect;
 
316
                info->fbops->fb_copyarea = cfb_copyarea;
 
317
                info->fbops->fb_imageblit = cfb_imageblit;
 
318
        } else {
 
319
                outreg(disp, GC_L0EM, 3);
 
320
                info->fbops->fb_fillrect = mb86290fb_fillrect;
 
321
                info->fbops->fb_copyarea = mb86290fb_copyarea;
 
322
                info->fbops->fb_imageblit = mb86290fb_imageblit;
 
323
        }
 
324
        outreg(draw, GDC_REG_DRAW_BASE, 0);
 
325
        outreg(draw, GDC_REG_MODE_MISC, 0x8000);
 
326
        outreg(draw, GDC_REG_X_RESOLUTION, xres);
 
327
 
 
328
        info->flags |=
 
329
            FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
 
330
            FBINFO_HWACCEL_IMAGEBLIT;
 
331
        info->fix.accel = 0xff; /*FIXME: add right define */
 
332
}
 
333
EXPORT_SYMBOL(mb862xxfb_init_accel);
 
334
 
 
335
MODULE_LICENSE("GPL v2");