Merge tag 'lsk-v3.10-android-15.02'
[firefly-linux-kernel-4.4.55.git] / drivers / video / rockchip / bmp_helper.c
1 /*
2  * linux/drivers/video/rockchip/bmp_helper.c
3  *
4  * Copyright (C) 2012 Rockchip Corporation
5  * Author: Mark Yao <mark.yao@rock-chips.com>
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License version 2 as published by
9  * the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU General Public License along with
17  * this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <linux/sysfs.h>
21 #include <linux/uaccess.h>
22 #include <linux/kernel.h>
23 #include <linux/rk_fb.h>
24
25 #include "bmp_helper.h"
26
27 unsigned short bmp_logo_palette[] = {
28         0x0000, 0x0021, 0x0840, 0x0841, 0x0041, 0x0862, 0x0043, 0x1060,
29         0x1061, 0x1081, 0x18a1, 0x1082, 0x18c3, 0x18c2, 0x18e4, 0x1904,
30         0x20e2, 0x2901, 0x2123, 0x2902, 0x3123, 0x3983, 0x2104, 0x2945,
31         0x2924, 0x2966, 0x3144, 0x3185, 0x3984, 0x39a5, 0x31a6, 0x39c7,
32         0x51a2, 0x41c4, 0x61e4, 0x4a02, 0x4a24, 0x5a65, 0x5245, 0x5226,
33         0x5a66, 0x62a3, 0x7202, 0x6ac4, 0x62c7, 0x72c5, 0x7285, 0x7b03,
34         0x6b05, 0x6b07, 0x7b46, 0x7326, 0x4228, 0x4a69, 0x5a88, 0x528a,
35         0x5aeb, 0x62a8, 0x7b4a, 0x7ba9, 0x630c, 0x6b4d, 0x73ae, 0x7bcf,
36         0x92c4, 0x8b25, 0x83a4, 0x8bc6, 0x9b65, 0x9ba6, 0xa2a2, 0xa364,
37         0xa324, 0xabe5, 0xb364, 0xb3a4, 0xb386, 0x8369, 0x83a8, 0x8b8b,
38         0x93a8, 0x8bcc, 0xc3c4, 0xebc1, 0x9c23, 0x9c04, 0x9406, 0x9427,
39         0xac23, 0xb483, 0xa445, 0xa407, 0xacc7, 0xbc64, 0xb4c4, 0xbd26,
40         0x9c2d, 0xac4c, 0xbd29, 0xc4c2, 0xc4e4, 0xc4a4, 0xdce5, 0xcc44,
41         0xc563, 0xdd02, 0xdd03, 0xdd83, 0xc544, 0xcd87, 0xd544, 0xdd24,
42         0xdd84, 0xddc4, 0xd5c7, 0xe462, 0xe463, 0xe4c1, 0xeca3, 0xecc2,
43         0xecc2, 0xf442, 0xf4a3, 0xe444, 0xec65, 0xe485, 0xeca5, 0xecc4,
44         0xecc5, 0xe4a4, 0xf465, 0xf4a4, 0xed22, 0xed23, 0xed62, 0xed63,
45         0xe522, 0xedc2, 0xfd20, 0xfd02, 0xfde1, 0xfdc1, 0xf5c3, 0xf5c3,
46         0xe5c1, 0xed04, 0xed25, 0xed64, 0xed65, 0xe505, 0xed66, 0xed26,
47         0xed84, 0xeda5, 0xede4, 0xedc5, 0xe5e4, 0xf525, 0xf5e4, 0xf5e5,
48         0xf5a4, 0xed49, 0xeda8, 0xedab, 0xf5eb, 0xf5cb, 0xedac, 0xf5cc,
49         0xf5ce, 0xee21, 0xee42, 0xee22, 0xfe21, 0xf602, 0xfe63, 0xfe22,
50         0xfea0, 0xfea3, 0xfee2, 0xfec3, 0xf682, 0xee65, 0xe624, 0xee85,
51         0xf625, 0xf664, 0xf645, 0xfe64, 0xf624, 0xf606, 0xf684, 0xf685,
52         0xfea4, 0xfee4, 0xf6c4, 0xf6a6, 0xff03, 0xff02, 0xee2f, 0xf60d,
53         0xf62e, 0xf64f, 0xf64e, 0x8410, 0x8c51, 0x94b2, 0x9cd3, 0xa4b0,
54         0xbd30, 0xbd72, 0xa534, 0xad55, 0xb596, 0xbdd7, 0xde75, 0xf671,
55         0xf691, 0xf692, 0xf6b3, 0xf6d3, 0xfeb3, 0xf673, 0xe6b6, 0xf6d4,
56         0xf6f5, 0xfef5, 0xf6f6, 0xfef6, 0xff15, 0xf716, 0xff16, 0xff17,
57         0xc618, 0xce79, 0xd69a, 0xdefb, 0xef19, 0xff38, 0xff58, 0xff79,
58         0xf718, 0xff7a, 0xf75a, 0xff99, 0xff9a, 0xffbb, 0xffdb, 0xe73c,
59         0xef5d, 0xfffc, 0xf7be, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000,
60 };
61
62 static void draw_unencoded_bitmap(uint16_t **dst, uint8_t *bmap, uint16_t *cmap,
63                                   uint32_t cnt)
64 {
65         while (cnt > 0) {
66                 *(*dst)++ = cmap[*bmap++];
67                 cnt--;
68         }
69 }
70
71 static void draw_encoded_bitmap(uint16_t **dst, uint16_t c, uint32_t cnt)
72 {
73         uint16_t *fb = *dst;
74         int cnt_8copy = cnt >> 3;
75
76         cnt -= cnt_8copy << 3;
77         while (cnt_8copy > 0) {
78                 *fb++ = c;
79                 *fb++ = c;
80                 *fb++ = c;
81                 *fb++ = c;
82                 *fb++ = c;
83                 *fb++ = c;
84                 *fb++ = c;
85                 *fb++ = c;
86                 cnt_8copy--;
87         }
88         while (cnt > 0) {
89                 *fb++ = c;
90                 cnt--;
91         }
92         *dst = fb;
93 }
94
95 static void yuv_to_rgb(int y, int u, int v, int *r, int *g, int *b)
96 {
97         int rdif, invgdif, bdif;
98
99         u -= 128;
100         v -= 128;
101         rdif = v + ((v * 103) >> 8);
102         invgdif = ((u * 88) >> 8) + ((v * 183) >> 8);
103         bdif = u + ((u*198) >> 8);
104         *r = range(y + rdif, 0, 0xff);
105         *g = range(y - invgdif, 0, 0xff);
106         *b = range(y + bdif, 0, 0xff);
107 }
108
109 int bmpencoder(void *__iomem *vaddr, int width, int height, u8 data_format,
110                void *data, void (*fn)(void *, void *, int))
111 {
112         uint32_t *d, *d1, *d2;
113         uint8_t *dst, *yrgb, *uv, *y1, *y2;
114         int y, u, v, r, g, b;
115
116         int yu = width * 4 % 4;
117         int byteperline;
118         unsigned int size;
119         BITMAPHEADER header;
120         BITMAPINFOHEADER infoheader;
121         void *buf;
122         int i, j;
123
124         yu = yu != 0 ? 4 - yu : yu;
125         byteperline = width * 4 + yu;
126         size = byteperline * height + 54;
127         memset(&header, 0, sizeof(header));
128         memset(&infoheader, 0, sizeof(infoheader));
129         header.type = 'M'<<8|'B';
130         header.size = size;
131         header.offset = 54;
132
133         infoheader.size = 40;
134         infoheader.width = width;
135         infoheader.height = 0 - height;
136         infoheader.bitcount = 4 * 8;
137         infoheader.compression = 0;
138         infoheader.imagesize = byteperline * height;
139         infoheader.xpelspermeter = 0;
140         infoheader.ypelspermeter = 0;
141         infoheader.colors = 0;
142         infoheader.colorsimportant = 0;
143         fn(data, (void *)&header, sizeof(header));
144         fn(data, (void *)&infoheader, sizeof(infoheader));
145
146         /*
147          * if data_format is ARGB888 or XRGB888, not need convert.
148          */
149         if (data_format == ARGB888 || data_format == XRGB888) {
150                 fn(data, (char *)vaddr, width * height * 4);
151                 return 0;
152         }
153         /*
154          * alloc 2 line buffer.
155          */
156         buf = kmalloc(width * 2 * 4, GFP_KERNEL);
157         if (!buf)
158                 return -ENOMEM;
159         yrgb = (uint8_t *)vaddr;
160         uv = yrgb + width * height;
161         for (j = 0; j < height; j++) {
162                 if (j % 2 == 0) {
163                         dst = buf;
164                         y1 = yrgb + j * width;
165                         y2 = y1 + width;
166                         d1 = buf;
167                         d2 = d1 + width;
168                 }
169
170                 for (i = 0; i < width; i++) {
171                         switch (data_format) {
172                         case XBGR888:
173                         case ABGR888:
174                                 dst[0] = yrgb[2];
175                                 dst[1] = yrgb[1];
176                                 dst[2] = yrgb[0];
177                                 dst[3] = yrgb[3];
178                                 dst += 4;
179                                 yrgb += 4;
180                                 break;
181                         case RGB888:
182                                 dst[0] = yrgb[0];
183                                 dst[1] = yrgb[1];
184                                 dst[2] = yrgb[2];
185                                 dst[3] = 0xff;
186                                 dst += 4;
187                                 yrgb += 3;
188                                 break;
189                         case RGB565:
190                                 dst[0] = (yrgb[0] & 0x1f) << 3;
191                                 dst[1] = (yrgb[0] & 0xe0) >> 3 |
192                                                 (yrgb[1] & 0x7) << 5;
193                                 dst[2] = yrgb[1] & 0xf8;
194                                 dst[3] = 0xff;
195                                 dst += 4;
196                                 yrgb += 2;
197                                 break;
198                         case YUV420:
199                         case YUV422:
200                         case YUV444:
201                                 if (data_format == YUV420) {
202                                         if (i % 2 == 0) {
203                                                 d = d1++;
204                                                 y = *y1++;
205                                         } else {
206                                                 d = d2++;
207                                                 y = *y2++;
208                                         }
209                                         if (i % 4 == 0) {
210                                                 u = *uv++;
211                                                 v = *uv++;
212                                         }
213                                 } else if (data_format == YUV422) {
214                                         if (i % 2 == 0) {
215                                                 u = *uv++;
216                                                 v = *uv++;
217                                         }
218                                         d = d1++;
219                                 } else {
220                                         u = *uv++;
221                                         v = *uv++;
222                                         d = d1++;
223                                 }
224                                 yuv_to_rgb(y, u, v, &r, &g, &b);
225                                 *d = 0xff<<24 | r << 16 | g << 8 | b;
226                                 break;
227                         case YUV422_A:
228                         case YUV444_A:
229                         default:
230                                 pr_err("unsupport now\n");
231                                 return -EINVAL;
232                         }
233                 }
234                 if (j % 2 == 1)
235                         fn(data, (char *)buf, 2 * width * 4);
236         }
237
238         return 0;
239 }
240
241 static void decode_rle8_bitmap(uint8_t *psrc, uint8_t *pdst, uint16_t *cmap,
242                                unsigned int width, unsigned int height,
243                                int bits, int x_off, int y_off, bool flip)
244 {
245         uint32_t cnt, runlen;
246         int x = 0, y = 0;
247         int decode = 1;
248         uint8_t *bmap = psrc;
249         uint8_t *dst = pdst;
250         int linesize = width * 2;
251
252         if (flip) {
253                 y = height - 1;
254                 dst = pdst + y * linesize;
255         }
256
257         while (decode) {
258                 if (bmap[0] == BMP_RLE8_ESCAPE) {
259                         switch (bmap[1]) {
260                         case BMP_RLE8_EOL:
261                                 /* end of line */
262                                 bmap += 2;
263                                 x = 0;
264                                 if (flip) {
265                                         y--;
266                                         dst -= linesize * 2;
267                                 } else {
268                                         y++;
269                                 }
270                                 break;
271                         case BMP_RLE8_EOBMP:
272                                 /* end of bitmap */
273                                 decode = 0;
274                                 break;
275                         case BMP_RLE8_DELTA:
276                                 /* delta run */
277                                 x += bmap[2];
278                                 if (flip) {
279                                         y -= bmap[3];
280                                         dst -= bmap[3] * linesize;
281                                         dst += bmap[2] * 2;
282                                 } else {
283                                         y += bmap[3];
284                                         dst += bmap[3] * linesize;
285                                         dst += bmap[2] * 2;
286                                 }
287                                 bmap += 4;
288                                 break;
289                         default:
290                                 /* unencoded run */
291                                 runlen = bmap[1];
292                                 bmap += 2;
293                                 if (y >= height || x >= width) {
294                                         decode = 0;
295                                         break;
296                                 }
297                                 if (x + runlen > width)
298                                         cnt = width - x;
299                                 else
300                                         cnt = runlen;
301                                 draw_unencoded_bitmap((uint16_t **)&dst, bmap,
302                                                       cmap, cnt);
303                                 x += runlen;
304                                 bmap += runlen;
305                                 if (runlen & 1)
306                                         bmap++;
307                         }
308                 } else {
309                         /* encoded run */
310                         if (y < height) {
311                                 runlen = bmap[0];
312                                 if (x < width) {
313                                         /* aggregate the same code */
314                                         while (bmap[0] == 0xff &&
315                                                bmap[2] != BMP_RLE8_ESCAPE &&
316                                                bmap[1] == bmap[3]) {
317                                                 runlen += bmap[2];
318                                                 bmap += 2;
319                                         }
320                                         if (x + runlen > width)
321                                                 cnt = width - x;
322                                         else
323                                                 cnt = runlen;
324                                         draw_encoded_bitmap((uint16_t **)&dst,
325                                                             cmap[bmap[1]], cnt);
326                                 }
327                                 x += runlen;
328                         }
329                         bmap += 2;
330                 }
331         }
332 }
333
334 int bmpdecoder(void *bmp_addr, void *pdst, int *width, int *height, int *bits)
335 {
336         BITMAPHEADER header;
337         BITMAPINFOHEADER infoheader;
338         uint32_t size;
339         uint16_t linesize;
340         char *src = bmp_addr;
341         char *dst = pdst;
342         int i;
343         bool flip = false;
344
345         memcpy(&header, src, sizeof(header));
346         src += sizeof(header);
347
348         if (header.type != 0x4d42) {
349                 pr_err("not bmp file type[%x], can't support\n", header.type);
350                 return -1;
351         }
352         memcpy(&infoheader, src, sizeof(infoheader));
353         *width = infoheader.width;
354         *height = infoheader.height;
355
356         if (*height < 0)
357                 *height = 0 - *height;
358         else
359                 flip = true;
360
361         size = header.size - header.offset;
362         linesize = *width * infoheader.bitcount >> 3;
363         src = bmp_addr + header.offset;
364
365         switch (infoheader.bitcount) {
366         case 8:
367                 /*
368                  * only support convert 8bit bmap file to RGB565.
369                  */
370                 decode_rle8_bitmap(src, dst, bmp_logo_palette,
371                                    infoheader.width, infoheader.height,
372                                    infoheader.bitcount, 0, 0, flip);
373                 *bits = 16;
374                 break;
375         case 16:
376                 /*
377                  * Todo
378                  */
379                 pr_info("unsupport bit=%d now\n", infoheader.bitcount);
380                 break;
381         case 24:
382                 if (flip)
383                         src += (*width) * (*height - 1) * 3;
384
385                 for (i = 0; i < *height; i++) {
386                         memcpy(dst, src, 3 * (*width));
387                         dst += *width * 3;
388                         src += *width * 3;
389                         if (flip)
390                                 src -= *width * 3 * 2;
391                 }
392
393                 *bits = 24;
394                 break;
395         case 32:
396                 /*
397                  * Todo
398                  */
399                 pr_info("unsupport bit=%d now\n", infoheader.bitcount);
400                 break;
401         default:
402                 pr_info("unsupport bit=%d now\n", infoheader.bitcount);
403                 break;
404         }
405
406         return 0;
407 }