/* SPDX-License-Identifier: GPL-2.0+ */
/*
 * Copyright (C) 2016 Freescale Semiconductor, Inc. All Rights Reserved.
 *
 * Peng Fan <Peng.Fan@freescale.com>
 */
#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 = env_get_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] = env_get("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 = env_get_hex("filesize", 0);
	if (!file_len)
		return -1;

	flush_cache(waveform_buf, roundup(file_len, ARCH_DMA_MINALIGN));

	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 = env_get_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] = env_get("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 = env_get_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] = env_get("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 = env_get("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;
}
