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 static void yuv_to_rgb(int y, int u, int v, int *r, int *g, int *b)
29 int rdif, invgdif, bdif;
33 rdif = v + ((v * 103) >> 8);
34 invgdif = ((u * 88) >> 8) + ((v * 183) >> 8);
35 bdif = u + ((u*198) >> 8);
36 *r = range(y + rdif, 0, 0xff);
37 *g = range(y - invgdif, 0, 0xff);
38 *b = range(y + bdif, 0, 0xff);
41 int datatobmp(void *__iomem *vaddr, int width, int height, u8 data_format,
42 void *data, void (*fn)(void *, void *, int))
44 uint32_t *d, *d1, *d2;
45 uint8_t *dst, *yrgb, *uv, *y1, *y2;
48 int yu = width * 4 % 4;
52 BITMAPINFOHEADER infoheader;
56 yu = yu != 0 ? 4 - yu : yu;
57 byteperline = width * 4 + yu;
58 size = byteperline * height + 54;
59 memset(&header, 0, sizeof(header));
60 memset(&infoheader, 0, sizeof(infoheader));
61 header.type = 'M'<<8|'B';
66 infoheader.width = width;
67 infoheader.height = 0 - height;
68 infoheader.bitcount = 4 * 8;
69 infoheader.compression = 0;
70 infoheader.imagesize = byteperline * height;
71 infoheader.xpelspermeter = 0;
72 infoheader.ypelspermeter = 0;
73 infoheader.colors = 0;
74 infoheader.colorsimportant = 0;
75 fn(data, (void *)&header, sizeof(header));
76 fn(data, (void *)&infoheader, sizeof(infoheader));
79 * if data_format is ARGB888 or XRGB888, not need convert.
81 if (data_format == ARGB888 || data_format == XRGB888) {
82 fn(data, (char *)vaddr, width * height * 4);
86 * alloc 2 line buffer.
88 buf = kmalloc(width * 2 * 4, GFP_KERNEL);
91 yrgb = (uint8_t *)vaddr;
92 uv = yrgb + width * height;
93 for (j = 0; j < height; j++) {
96 y1 = yrgb + j * width;
102 for (i = 0; i < width; i++) {
103 switch (data_format) {
122 dst[0] = (yrgb[0] & 0x1f) << 3;
123 dst[1] = (yrgb[0] & 0xe0) >> 3 |
124 (yrgb[1] & 0x7) << 5;
125 dst[2] = yrgb[1] & 0xf8;
133 if (data_format == YUV420) {
145 } else if (data_format == YUV422) {
156 yuv_to_rgb(y, u, v, &r, &g, &b);
157 *d = 0xff<<24 | r << 16 | g << 8 | b;
162 pr_err("unsupport now\n");
167 fn(data, (char *)buf, 2 * width * 4);