/*
 * (C) Copyright 2006
 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

#include <common.h>
#include <lcd.h>
#include <mpc5xxx.h>
#include <malloc.h>

#ifdef CONFIG_LCD

#undef SWAPPED_LCD /* For the previous h/w version */
/*
 *  The name of the device used for communication
 * with the PSoC.
 */
#define PSOC_PSC	MPC5XXX_PSC2
#define PSOC_BAUD	230400UL

#define RTS_ASSERT	1
#define RTS_NEGATE	0
#define CTS_ASSERT	1
#define CTS_NEGATE	0

/*
 * Dimensions in pixels
 */
#define LCD_WIDTH	160
#define LCD_HEIGHT	100

/*
 * Dimensions in bytes
 */
#define LCD_BUF_SIZE	((LCD_WIDTH*LCD_HEIGHT)>>3)

#if LCD_BPP != LCD_MONOCHROME
#error "MCC200 support only monochrome displays (1 bpp)!"
#endif

#define PSOC_RETRIES	10	/* each of PSOC_WAIT_TIME */
#define PSOC_WAIT_TIME	10	/* usec */

#include <video_font.h>
#define FONT_WIDTH	VIDEO_FONT_WIDTH

DECLARE_GLOBAL_DATA_PTR;

/*
 * LCD information
 */
vidinfo_t panel_info = {
	LCD_WIDTH, LCD_HEIGHT, LCD_BPP
};


/*
 *  The device we use to communicate with PSoC
 */
int serial_inited = 0;

/*
 *  Imported functions to support the PSoC protocol
 */
extern int serial_init_dev (unsigned long dev_base);
extern void serial_setrts_dev (unsigned long dev_base, int s);
extern int serial_getcts_dev (unsigned long dev_base);
extern void serial_putc_raw_dev(unsigned long dev_base, const char c);

/*
 *  Just stubs for our driver, needed for compiling compabilty with
 * the common LCD driver code.
 */
void lcd_initcolregs (void)
{
}

void lcd_ctrl_init (void *lcdbase)
{
}

/*
 * Function sends the contents of the frame-buffer to the LCD
 */
void lcd_enable (void)
{
	int i, retries, fb_size;

	if (!serial_inited) {
		unsigned long baud;

		baud = gd->baudrate;
		gd->baudrate = PSOC_BAUD;
		serial_init_dev(PSOC_PSC);
		gd->baudrate = baud;
		serial_setrts_dev (PSOC_PSC, RTS_ASSERT);
		serial_inited = 1;
	}

	/*
	 *  Implement PSoC communication protocol:
	 * 1. Assert RTS, wait CTS assertion
	 * 2. Transmit data
	 * 3. Negate RTS, wait CTS negation
	 */

	/* 1 */
	serial_setrts_dev (PSOC_PSC, RTS_ASSERT);
	for (retries = PSOC_RETRIES; retries; retries--) {
		if (serial_getcts_dev(PSOC_PSC) == CTS_ASSERT)
			break;
		udelay (PSOC_WAIT_TIME);
	}
	if (!retries) {
		printf ("%s Error: PSoC doesn't respond on "
			"RTS ASSERT\n",	__FUNCTION__);
	}

	/* 2 */
	fb_size = panel_info.vl_row * (panel_info.vl_col >> 3);

#if !defined(SWAPPED_LCD)
	for (i=0; i<fb_size; i++) {
		serial_putc_raw_dev(PSOC_PSC, ((char *)gd->fb_base)[i]);
	}
#else
    {
	int x, y, pwidth;
	char *p = (char *)gd->fb_base;

	pwidth = ((panel_info.vl_col+7) >> 3);
	for (y=0; y<panel_info.vl_row; y++) {
		i = y * pwidth;
		for (x=0; x<pwidth; x+=5) {
			serial_putc_raw_dev (PSOC_PSC, (p[i+x+2]<<4 & 0xF0) | (p[i+x+3]>>4 & 0x0F));
			serial_putc_raw_dev (PSOC_PSC, (p[i+x+3]<<4 & 0xF0) | (p[i+x+4]>>4 & 0x0F));
			serial_putc_raw_dev (PSOC_PSC, (p[i+x+4]<<4 & 0xF0) | (p[i+x]>>4 & 0x0F));
			serial_putc_raw_dev (PSOC_PSC, (p[i+x]<<4 & 0xF0) | (p[i+x+1]>>4 & 0x0F));
			serial_putc_raw_dev (PSOC_PSC, (p[i+x+1]<<4 & 0xF0) | (p[i+x+2]>>4 & 0x0F));
		}
	}
    }
#endif

	/* 3 */
	serial_setrts_dev (PSOC_PSC, RTS_NEGATE);
	for (retries = PSOC_RETRIES; retries; retries--) {
		if (serial_getcts_dev(PSOC_PSC) == CTS_NEGATE)
			break;
		udelay (PSOC_WAIT_TIME);
	}

	return;
}
#ifdef CONFIG_PROGRESSBAR

void show_progress (int size, int tot)
{
	int cnt;
	int i;
	static int rc = 0;

	rc += size;

	cnt = ((LCD_WIDTH/FONT_WIDTH) * rc) / tot;

	rc -= (cnt * tot) / (LCD_WIDTH/FONT_WIDTH);

	for (i = 0; i < cnt; i++) {
		lcd_putc(0xdc);
	}

	if (cnt) {
		lcd_enable(); /* MCC200-specific - send the framebuffer to PSoC */
	}
}

#endif

int bmp_display(ulong addr, int x, int y)
{
	int ret;
	bmp_image_t *bmp = (bmp_image_t *)addr;

	if (!bmp) {
		printf("There is no valid bmp file at the given address\n");
		return 1;
	}

	ret = lcd_display_bitmap((ulong)bmp, x, y);

	if ((unsigned long)bmp != addr)
		free(bmp);

	return ret;
}

#endif /* CONFIG_LCD */
