/*
 * Copyright (C) 2016 Freescale Semiconductor, Inc. All Rights Reserved.
 *
 * Peng Fan <Peng.Fan@freescale.com>
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */
#include <common.h>
#include <lcd.h>
#include <linux/err.h>
#include <linux/types.h>
#include <malloc.h>
#include <mxc_epdc_fb.h>

#define is_digit(c)	((c) >= '0' && (c) <= '9')
__weak int mmc_get_env_devno(void)
{
	return 0;
}
__weak int check_mmc_autodetect(void)
{
	return 0;
}

int board_setup_waveform_file(ulong waveform_buf)
{
	char *fs_argv[5];
	char addr[17];
	ulong file_len, mmc_dev;

	if (!check_mmc_autodetect())
		mmc_dev = getenv_ulong("mmcdev", 10, 0);
	else
		mmc_dev = mmc_get_env_devno();

	sprintf(addr, "%lx", waveform_buf);

	fs_argv[0] = "fatload";
	fs_argv[1] = "mmc";
	fs_argv[2] = simple_itoa(mmc_dev);
	fs_argv[3] = addr;
	fs_argv[4] = getenv("epdc_waveform");

	if (!fs_argv[4])
		fs_argv[4] = "epdc_splash.bin";

	if (do_fat_fsload(NULL, 0, 5, fs_argv)) {
		printf("File %s not found on MMC Device %lu!\n", fs_argv[4], mmc_dev);
		return -1;
	}

	file_len = getenv_hex("filesize", 0);
	if (!file_len)
		return -1;

	flush_cache(waveform_buf, file_len);

	return 0;
}

int board_setup_logo_file(void *display_buf)
{
	int logo_width, logo_height;
	char *fs_argv[5];
	char addr[17];
	int array[3];
	ulong file_len, mmc_dev;
	char *buf, *s;
	int arg = 0, val = 0, pos = 0;
	int i, j, max_check_length;
	int row, col, row_end, col_end;

	if (!display_buf)
		return -EINVAL;

	/* Assume PGM header not exceeds 128 bytes */
	max_check_length = 128;

	if (!check_mmc_autodetect())
		mmc_dev = getenv_ulong("mmcdev", 10, 0);
	else
		mmc_dev = mmc_get_env_devno();

	memset(display_buf, 0xFF, panel_info.vl_col * panel_info.vl_row);

	fs_argv[0] = "fatsize";
	fs_argv[1] = "mmc";
	fs_argv[2] = simple_itoa(mmc_dev);
	fs_argv[3] = getenv("epdc_logo");
	if (!fs_argv[3])
		fs_argv[3] = "epdc_logo.pgm";
	if (do_fat_size(NULL, 0, 4, fs_argv)) {
		debug("File %s not found on MMC Device %lu, use black border\n", fs_argv[3], mmc_dev);
		/* Draw black border around framebuffer*/
		memset(display_buf, 0x0, 24 * panel_info.vl_col);
		for (i = 24; i < (panel_info.vl_row - 24); i++) {
			memset((u8 *)display_buf + i * panel_info.vl_col,
			       0x00, 24);
			memset((u8 *)display_buf + i * panel_info.vl_col
				+ panel_info.vl_col - 24, 0x00, 24);
		}
		memset((u8 *)display_buf +
		       panel_info.vl_col * (panel_info.vl_row - 24),
		       0x00, 24 * panel_info.vl_col);
		return 0;
	}

	file_len = getenv_hex("filesize", 0);
	if (!file_len)
		return -EINVAL;

	buf = memalign(ARCH_DMA_MINALIGN, file_len);
	if (!buf)
		return -ENOMEM;

	sprintf(addr, "%lx", (ulong)buf);

	fs_argv[0] = "fatload";
	fs_argv[1] = "mmc";
	fs_argv[2] = simple_itoa(mmc_dev);
	fs_argv[3] = addr;
	fs_argv[4] = getenv("epdc_logo");

	if (!fs_argv[4])
		fs_argv[4] = "epdc_logo.pgm";

	if (do_fat_fsload(NULL, 0, 5, fs_argv)) {
		printf("File %s not found on MMC Device %lu!\n", fs_argv[4], mmc_dev);
		free(buf);
		return -1;
	}

	if (strncmp(buf, "P5", 2)) {
		printf("Wrong format for epdc logo, use PGM-P5 format.\n");
		free(buf);
		return -EINVAL;
	}
	/* Skip P5\n */
	pos += 3;
	arg = 0;
	for (i = 3; i < max_check_length; ) {
		/* skip \n \t and space */
		if ((buf[i] == '\n') || (buf[i] == '\t') || (buf[i] == ' ')) {
			i++;
			continue;
		}
		/* skip comment */
		if (buf[i] == '#') {
			while (buf[i++] != '\n')
				;
			continue;
		}

		/* HEIGTH, WIDTH, MAX PIXEL VLAUE total 3 args */
		if (arg > 2)
			break;
		val = 0;
		while (is_digit(buf[i])) {
			val = val * 10 + buf[i] - '0';
			i++;
		}
		array[arg++] = val;

		i++;
	}

	/* Point to data area */
	pos = i;

	logo_width = array[0];
	logo_height = array[1];

	if ((logo_width > panel_info.vl_col) ||
	    (logo_height > panel_info.vl_row)) {
		printf("Picture: too big\n");
		free(buf);
		return -EINVAL;
	}

	/* m,m means center of screen */
	row = 0;
	col = 0;
	s = getenv("splashpos");
	if (s) {
		if (s[0] == 'm')
			col = (panel_info.vl_col  - logo_width) >> 1;
		else
			col = simple_strtol(s, NULL, 0);
		s = strchr(s + 1, ',');
		if (s != NULL) {
			if (s[1] == 'm')
				row = (panel_info.vl_row  - logo_height) >> 1;
			else
				row = simple_strtol(s + 1, NULL, 0);
		}
	}
	if ((col + logo_width > panel_info.vl_col) ||
	    (row + logo_height > panel_info.vl_row)) {
		printf("Incorrect pos, use (0, 0)\n");
		row = 0;
		col = 0;
	}

	/* Draw picture at the center of screen */
	row_end = row + logo_height;
	col_end = col + logo_width;
	for (i = row; i < row_end; i++) {
		for (j = col; j < col_end; j++) {
			*((u8 *)display_buf + i * (panel_info.vl_col) + j) =
				 buf[pos++];
		}
	}

	free(buf);

	flush_cache((ulong)display_buf, file_len - pos - 1);

	return 0;
}
