/* * (C) Copyright 2007-2019 * Allwinner Technology Co., Ltd. * * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and * may be copied, distributed, and modified under those terms. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * See file CREDITS for list of people who contributed to this * project. * */ #include #include #include #include #include #include #include #include "../disp2/eink200/include/eink_sys_source.h" DECLARE_GLOBAL_DATA_PTR; extern long eink_ioctl(struct file *file, unsigned int cmd, void *arg); /* * Subroutine: bmp_display * * Description: Display bmp file located in memory * * Inputs: addr address of the bmp file * * Return: None * */ int sunxi_bmp_decode(unsigned long addr, sunxi_bmp_store_t *bmp_info) { char *tmp_buffer; char *bmp_data; int zero_num = 0; struct bmp_image *bmp = (struct bmp_image *)addr; int x, y, bmp_bpix; int tmp; if ((bmp->header.signature[0] != 'B') || (bmp->header.signature[1] != 'M')) { printf("this is not a bmp picture\n"); return -1; } debug("bmp dectece\n"); bmp_bpix = bmp->header.bit_count / 8; if ((bmp_bpix != 3) && (bmp_bpix != 4)) { printf("no support bmp picture without bpix 24 or 32\n"); return -1; } if (bmp_bpix == 3) { zero_num = (4 - ((3 * bmp->header.width) % 4)) & 3; } debug("bmp bitcount %d\n", bmp->header.bit_count); x = bmp->header.width; y = (bmp->header.height & 0x80000000) ? (-bmp->header.height) : (bmp->header.height); debug("bmp x = %x, bmp y = %x\n", x, y); tmp = bmp->header.height; if (0 == (bmp->header.height & 0x80000000)) bmp->header.height = (-bmp->header.height); memcpy(bmp_info->buffer, bmp, sizeof(struct bmp_header)); bmp_info->buffer += sizeof(struct bmp_header); bmp->header.height = tmp; tmp_buffer = (char *)bmp_info->buffer; bmp_data = (char *)(addr + bmp->header.data_offset); if (bmp->header.height & 0x80000000) { if (zero_num == 0) { memcpy(tmp_buffer, bmp_data, x * y * bmp_bpix); } else { int i, line_bytes, real_line_byte; char *src; line_bytes = (x * bmp_bpix) + zero_num; real_line_byte = x * bmp_bpix; for (i = 0; i < y; i++) { src = bmp_data + i * line_bytes; memcpy(tmp_buffer, src, real_line_byte); tmp_buffer += real_line_byte; } } } else { uint i, line_bytes, real_line_byte; char *src; line_bytes = (x * bmp_bpix) + zero_num; real_line_byte = x * bmp_bpix; for (i = 0; i < y; i++) { src = bmp_data + (y - i - 1) * line_bytes; memcpy(tmp_buffer, src, real_line_byte); tmp_buffer += real_line_byte; } } bmp_info->x = x; bmp_info->y = y; bmp_info->bit = bmp->header.bit_count; // flush_cache((uint)bmp_info->buffer, x * y * bmp_bpix); flush_cache((uint)bmp_info->buffer - sizeof(struct bmp_header), x * y * bmp_bpix + sizeof(struct bmp_header)); return 0; } int bmp_buffer_change2Gray(sunxi_bmp_store_t *bmp_info, char *dst_buf) { int ret = 1; if (bmp_info->bit == 24) { int i, j; char *tmp; tmp = bmp_info->buffer; for (i = 0; i < bmp_info->y; i++) { for (j = 0; j < bmp_info->x; j++) { *dst_buf = (unsigned char)(0.299 * tmp[0] + 0.587 * tmp[1] + 0.114 * tmp[2]); /* set Y */ dst_buf++; tmp += 3; } } } else if (bmp_info->bit == 32) { int i, j; char *tmp; tmp = bmp_info->buffer; for (i = 0; i < bmp_info->y; i++) { for (j = 0; j < bmp_info->x; j++) { *dst_buf = (unsigned char)(0.299 * tmp[0] + 0.587 * tmp[1] + 0.114 * tmp[2]); /* set Y */ dst_buf++; tmp += 4; } } } else { printf("[%s]: ERR LINE %d\n", __func__, __LINE__); ret = -1; } EINK_INFO_MSG("[%s]: success!\n", __func__); return ret; } int sunxi_eink_get_bmp_buffer(char *name, char *bmp_gray_buf) { int ret; int partno = -1; sunxi_bmp_store_t bmp_info; char bmp_addr[32] = {0}; char bmp_name[32]; char *bmp_argv[6] = {"fatload", "sunxi_flash", "0:0", "00000000", bmp_name, NULL}; partno = sunxi_partition_get_partno_byname("bootloader"); if (partno < 0) { partno = sunxi_partition_get_partno_byname("boot-resource"); if (partno < 0) { printf("[%s]:Get bootloader or boot-resource partition number fail!\n", __func__); } else { sprintf(bmp_argv[2], "0:%x", partno); EINK_INFO_MSG("[%s]: get boot-resource part\n", __func__); } if (!bmp_gray_buf) { printf("sunxi_Eink_Get_bmp_buffer: bmp_gray_buffor is null for %s\n", name); return -1; } } EINK_INFO_MSG(" partno = %d\n", partno); sprintf(bmp_addr, "%lx", (ulong)bmp_gray_buf); bmp_argv[3] = bmp_addr; memset(bmp_name, 0, 32); strcpy(bmp_name, name); if (do_fat_fsload(0, 0, 5, bmp_argv)) { printf("[%s]:error : unable to open logo file %s\n", __func__, bmp_argv[4]); return -1; } bmp_info.buffer = (void *)CONFIG_SYS_SDRAM_BASE; if (sunxi_bmp_decode((ulong)bmp_gray_buf, &bmp_info)) { printf("[%s]:decode bmp fail\n", __func__); return -1; } ret = bmp_buffer_change2Gray(&bmp_info, bmp_gray_buf); return ret; } int sunxi_eink_fresh_image(char *name, __u32 update_mode) { unsigned long arg[4] = { 0 }; uint cmd = 0; int ret; u32 width = 800; u32 height = 600; u32 buf_size = 0; char *bmp_buffer = NULL; char primary_key[25]; s32 value = 0; struct eink_img cimage; sprintf(primary_key, "eink"); ret = eink_sys_script_get_item(primary_key, "eink_width", &value, 1); if (ret == 1) width = value; ret = eink_sys_script_get_item(primary_key, "eink_height", &value, 1); if (ret == 1) height = value; printf("[%s]: width = %d, height = %d\n", __func__, width, height); buf_size = (width * height) << 2; bmp_buffer = (char *)malloc_aligned(buf_size, ARCH_DMA_MINALIGN); if (!bmp_buffer) { printf("fail to alloc memory for eink decode bmp.\n"); return -1; } sunxi_eink_get_bmp_buffer(name, bmp_buffer); cimage.paddr = bmp_buffer; cimage.vaddr = bmp_buffer; cimage.force_fresh = 0; cimage.win_calc_en = 0; cimage.de_bypass_flag = 0; cimage.upd_all_en = 1; cimage.upd_mode = update_mode; cimage.size.height = height; cimage.size.width = width; cimage.size.align = 4; cimage.pitch = EINKALIGN(width, cimage.size.align); cimage.out_fmt = EINK_Y8; cimage.dither_mode = 0; cimage.upd_win.top = 0; cimage.upd_win.left = 0; cimage.upd_win.right = width - 1; cimage.upd_win.bottom = height - 1; arg[0] = (unsigned long)&cimage; arg[1] = 0; arg[2] = 0; arg[3] = 0; cmd = EINK_UPDATE_IMG; ret = eink_ioctl(NULL, cmd, (void *)arg); if (ret != 0) { printf("update eink image fail\n"); return -1; } if (bmp_buffer) { free_aligned(bmp_buffer); bmp_buffer = NULL; } return 0; } EXPORT_SYMBOL(sunxi_eink_fresh_image);