video: rockchip: hdmi: add dts property rockchip,defaultdepth
[firefly-linux-kernel-4.4.55.git] / drivers / video / rockchip / bmp_helper.c
index ac2406c558f4c3ef19f9c4f1557e5a41de228797..e8f74b7da4f441286625fe0485021bb7c262b2af 100755 (executable)
 
 #include "bmp_helper.h"
 
+static void draw_unencoded_bitmap(uint16_t **dst, uint8_t *bmap, uint16_t *cmap,
+                                 uint32_t cnt)
+{
+       while (cnt > 0) {
+               *(*dst)++ = cmap[*bmap++];
+               cnt--;
+       }
+}
+
+static void draw_encoded_bitmap(uint16_t **dst, uint16_t c, uint32_t cnt)
+{
+       uint16_t *fb = *dst;
+       int cnt_8copy = cnt >> 3;
+
+       cnt -= cnt_8copy << 3;
+       while (cnt_8copy > 0) {
+               *fb++ = c;
+               *fb++ = c;
+               *fb++ = c;
+               *fb++ = c;
+               *fb++ = c;
+               *fb++ = c;
+               *fb++ = c;
+               *fb++ = c;
+               cnt_8copy--;
+       }
+       while (cnt > 0) {
+               *fb++ = c;
+               cnt--;
+       }
+       *dst = fb;
+}
+
 static void yuv_to_rgb(int y, int u, int v, int *r, int *g, int *b)
 {
        int rdif, invgdif, bdif;
@@ -38,12 +71,12 @@ static void yuv_to_rgb(int y, int u, int v, int *r, int *g, int *b)
        *b = range(y + bdif, 0, 0xff);
 }
 
-int datatobmp(void *__iomem *vaddr, int width, int height, u8 data_format,
-             void *data, void (*fn)(void *, void *, int))
+int bmpencoder(void *__iomem *vaddr, int width, int height, u8 data_format,
+              void *data, void (*fn)(void *, void *, int))
 {
-       uint32_t *d, *d1, *d2;
-       uint8_t *dst, *yrgb, *uv, *y1, *y2;
-       int y, u, v, r, g, b;
+       uint32_t *d = NULL, *d1 = NULL, *d2 = NULL;
+       uint8_t *dst = NULL, *yrgb = NULL, *uv = NULL, *y1 = NULL, *y2 = NULL;
+       int y = 0, u = 0, v = 0, r = 0, g = 0, b = 0;
 
        int yu = width * 4 % 4;
        int byteperline;
@@ -169,3 +202,188 @@ int datatobmp(void *__iomem *vaddr, int width, int height, u8 data_format,
 
        return 0;
 }
+
+static void decode_rle8_bitmap(uint8_t *psrc, uint8_t *pdst, uint16_t *cmap,
+                              unsigned int width, unsigned int height,
+                              int bits, int x_off, int y_off, bool flip)
+{
+       uint32_t cnt, runlen;
+       int x = 0, y = 0;
+       int decode = 1;
+       uint8_t *bmap = psrc;
+       uint8_t *dst = pdst;
+       int linesize = width * 2;
+
+       if (flip) {
+               y = height - 1;
+               dst = pdst + y * linesize;
+       }
+
+       while (decode) {
+               if (bmap[0] == BMP_RLE8_ESCAPE) {
+                       switch (bmap[1]) {
+                       case BMP_RLE8_EOL:
+                               /* end of line */
+                               bmap += 2;
+                               x = 0;
+                               if (flip) {
+                                       y--;
+                                       dst -= linesize * 2;
+                               } else {
+                                       y++;
+                               }
+                               break;
+                       case BMP_RLE8_EOBMP:
+                               /* end of bitmap */
+                               decode = 0;
+                               break;
+                       case BMP_RLE8_DELTA:
+                               /* delta run */
+                               x += bmap[2];
+                               if (flip) {
+                                       y -= bmap[3];
+                                       dst -= bmap[3] * linesize;
+                                       dst += bmap[2] * 2;
+                               } else {
+                                       y += bmap[3];
+                                       dst += bmap[3] * linesize;
+                                       dst += bmap[2] * 2;
+                               }
+                               bmap += 4;
+                               break;
+                       default:
+                               /* unencoded run */
+                               runlen = bmap[1];
+                               bmap += 2;
+                               if (y >= height || x >= width) {
+                                       decode = 0;
+                                       break;
+                               }
+                               if (x + runlen > width)
+                                       cnt = width - x;
+                               else
+                                       cnt = runlen;
+                               draw_unencoded_bitmap((uint16_t **)&dst, bmap,
+                                                     cmap, cnt);
+                               x += runlen;
+                               bmap += runlen;
+                               if (runlen & 1)
+                                       bmap++;
+                       }
+               } else {
+                       /* encoded run */
+                       if (y < height) {
+                               runlen = bmap[0];
+                               if (x < width) {
+                                       /* aggregate the same code */
+                                       while (bmap[0] == 0xff &&
+                                              bmap[2] != BMP_RLE8_ESCAPE &&
+                                              bmap[1] == bmap[3]) {
+                                               runlen += bmap[2];
+                                               bmap += 2;
+                                       }
+                                       if (x + runlen > width)
+                                               cnt = width - x;
+                                       else
+                                               cnt = runlen;
+                                       draw_encoded_bitmap((uint16_t **)&dst,
+                                                           cmap[bmap[1]], cnt);
+                               }
+                               x += runlen;
+                       }
+                       bmap += 2;
+               }
+       }
+}
+
+int bmpdecoder(void *bmp_addr, void *pdst, int *width, int *height, int *bits)
+{
+       BITMAPHEADER header;
+       BITMAPINFOHEADER infoheader;
+       uint16_t *bmp_logo_palette;
+       uint32_t size;
+       uint16_t linesize;
+       int stride;
+       char *cmap_base;
+       char *src = bmp_addr;
+       char *dst = pdst;
+       int i;
+       bool flip = false;
+
+       memcpy(&header, src, sizeof(header));
+       src += sizeof(header);
+
+       if (header.type != 0x4d42) {
+               pr_err("not bmp file type[%x], can't support\n", header.type);
+               return -1;
+       }
+       memcpy(&infoheader, src, sizeof(infoheader));
+       *width = infoheader.width;
+       *height = infoheader.height;
+
+       if (*height < 0)
+               *height = 0 - *height;
+       else
+               flip = true;
+
+       size = header.size - header.offset;
+       linesize = *width * infoheader.bitcount >> 3;
+       cmap_base = src + sizeof(infoheader);
+       src = bmp_addr + header.offset;
+
+       switch (infoheader.bitcount) {
+       case 8:
+               bmp_logo_palette = kmalloc(sizeof(bmp_logo_palette) * 256, GFP_KERNEL);
+
+               /* Set color map */
+               for (i = 0; i < 256; i++) {
+                       ushort colreg = ((cmap_base[2] << 8) & 0xf800) |
+                                       ((cmap_base[1] << 3) & 0x07e0) |
+                                       ((cmap_base[0] >> 3) & 0x001f) ;
+                       cmap_base += 4;
+                       bmp_logo_palette[i] = colreg;
+               }
+
+               /*
+                * only support convert 8bit bmap file to RGB565.
+                */
+               decode_rle8_bitmap(src, dst, bmp_logo_palette,
+                                  infoheader.width, infoheader.height,
+                                  infoheader.bitcount, 0, 0, flip);
+               kfree(bmp_logo_palette);
+               *bits = 16;
+               break;
+       case 16:
+               /*
+                * Todo
+                */
+               pr_info("unsupport bit=%d now\n", infoheader.bitcount);
+               break;
+       case 24:
+               stride = ALIGN(*width * 3, 4);
+               if (flip)
+                       src += stride * (*height - 1);
+
+               for (i = 0; i < *height; i++) {
+                       memcpy(dst, src, 3 * (*width));
+                       dst += stride;
+                       src += stride;
+                       if (flip)
+                               src -= stride * 2;
+               }
+
+               *bits = 24;
+               break;
+       case 32:
+               /*
+                * Todo
+                */
+               pr_info("unsupport bit=%d now\n", infoheader.bitcount);
+               break;
+       default:
+               pr_info("unsupport bit=%d now\n", infoheader.bitcount);
+               break;
+       }
+
+       return 0;
+}