2 * linux/drivers/video/rockchip/bmp_helper.c
4 * Copyright (C) 2012 Rockchip Corporation
5 * Author: Mark Yao <mark.yao@rock-chips.com>
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.
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
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/>.
20 #include <linux/sysfs.h>
21 #include <linux/uaccess.h>
22 #include <linux/kernel.h>
23 #include <linux/rk_fb.h>
25 #include "bmp_helper.h"
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,
62 static void draw_unencoded_bitmap(uint16_t **dst, uint8_t *bmap, uint16_t *cmap,
66 *(*dst)++ = cmap[*bmap++];
71 static void draw_encoded_bitmap(uint16_t **dst, uint16_t c, uint32_t cnt)
74 int cnt_8copy = cnt >> 3;
76 cnt -= cnt_8copy << 3;
77 while (cnt_8copy > 0) {
95 static void yuv_to_rgb(int y, int u, int v, int *r, int *g, int *b)
97 int rdif, invgdif, bdif;
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);
109 int bmpencoder(void *__iomem *vaddr, int width, int height, u8 data_format,
110 void *data, void (*fn)(void *, void *, int))
112 uint32_t *d, *d1, *d2;
113 uint8_t *dst, *yrgb, *uv, *y1, *y2;
114 int y, u, v, r, g, b;
116 int yu = width * 4 % 4;
120 BITMAPINFOHEADER infoheader;
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';
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));
147 * if data_format is ARGB888 or XRGB888, not need convert.
149 if (data_format == ARGB888 || data_format == XRGB888) {
150 fn(data, (char *)vaddr, width * height * 4);
154 * alloc 2 line buffer.
156 buf = kmalloc(width * 2 * 4, GFP_KERNEL);
159 yrgb = (uint8_t *)vaddr;
160 uv = yrgb + width * height;
161 for (j = 0; j < height; j++) {
164 y1 = yrgb + j * width;
170 for (i = 0; i < width; i++) {
171 switch (data_format) {
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;
201 if (data_format == YUV420) {
213 } else if (data_format == YUV422) {
224 yuv_to_rgb(y, u, v, &r, &g, &b);
225 *d = 0xff<<24 | r << 16 | g << 8 | b;
230 pr_err("unsupport now\n");
235 fn(data, (char *)buf, 2 * width * 4);
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)
245 uint32_t cnt, runlen;
248 uint8_t *bmap = psrc;
250 int linesize = width * 2;
254 dst = pdst + y * linesize;
258 if (bmap[0] == BMP_RLE8_ESCAPE) {
280 dst -= bmap[3] * linesize;
284 dst += bmap[3] * linesize;
293 if (y >= height || x >= width) {
297 if (x + runlen > width)
301 draw_unencoded_bitmap((uint16_t **)&dst, bmap,
313 /* aggregate the same code */
314 while (bmap[0] == 0xff &&
315 bmap[2] != BMP_RLE8_ESCAPE &&
316 bmap[1] == bmap[3]) {
320 if (x + runlen > width)
324 draw_encoded_bitmap((uint16_t **)&dst,
334 int bmpdecoder(void *bmp_addr, void *pdst, int *width, int *height, int *bits)
337 BITMAPINFOHEADER infoheader;
340 char *src = bmp_addr;
345 memcpy(&header, src, sizeof(header));
346 src += sizeof(header);
348 if (header.type != 0x4d42) {
349 pr_err("not bmp file type[%x], can't support\n", header.type);
352 memcpy(&infoheader, src, sizeof(infoheader));
353 *width = infoheader.width;
354 *height = infoheader.height;
357 *height = 0 - *height;
361 size = header.size - header.offset;
362 linesize = *width * infoheader.bitcount >> 3;
363 src = bmp_addr + header.offset;
365 switch (infoheader.bitcount) {
368 * only support convert 8bit bmap file to RGB565.
370 decode_rle8_bitmap(src, dst, bmp_logo_palette,
371 infoheader.width, infoheader.height,
372 infoheader.bitcount, 0, 0, flip);
379 pr_info("unsupport bit=%d now\n", infoheader.bitcount);
383 pr_info("wrong bmp file with unalign size\n");
388 src += (*width) * (*height - 1) * 3;
390 for (i = 0; i < *height; i++) {
391 for (j = 0; j < *width; j++) {
399 src -= *width * 3 * 2;
408 pr_info("unsupport bit=%d now\n", infoheader.bitcount);
411 pr_info("unsupport bit=%d now\n", infoheader.bitcount);