/*
 *  Cobalt server LCD frame buffer driver.
 *
 *  Copyright (C) 2008  Yoichi Yuasa <yuasa@linux-mips.org>
 *
 *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */
#include <linux/delay.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/uaccess.h>
#include <linux/platform_device.h>

/*
 * Cursor position address
 * \X  0    1    2  ...  14   15
 * Y+----+----+----+---+----+----+
 * 0|0x00|0x01|0x02|...|0x0e|0x0f|
 *  +----+----+----+---+----+----+
 * 1|0x40|0x41|0x42|...|0x4e|0x4f|
 *  +----+----+----+---+----+----+
 */
#define LCD_DATA_REG_OFFSET	0x10
#define LCD_XRES_MAX		16
#define LCD_YRES_MAX		2
#define LCD_CHARS_MAX		32

#define LCD_CLEAR		0x01
#define LCD_CURSOR_MOVE_HOME	0x02
#define LCD_RESET		0x06
#define LCD_OFF			0x08
#define LCD_CURSOR_OFF		0x0c
#define LCD_CURSOR_BLINK_OFF	0x0e
#define LCD_CURSOR_ON		0x0f
#define LCD_ON			LCD_CURSOR_ON
#define LCD_CURSOR_MOVE_LEFT	0x10
#define LCD_CURSOR_MOVE_RIGHT	0x14
#define LCD_DISPLAY_LEFT	0x18
#define LCD_DISPLAY_RIGHT	0x1c
#define LCD_PRERESET		0x3f	/* execute 4 times continuously */
#define LCD_BUSY		0x80

#define LCD_GRAPHIC_MODE	0x40
#define LCD_TEXT_MODE		0x80
#define LCD_CUR_POS_MASK	0x7f

#define LCD_CUR_POS(x)		((x) & LCD_CUR_POS_MASK)
#define LCD_TEXT_POS(x)		((x) | LCD_TEXT_MODE)

static inline void lcd_write_control(struct fb_info *info, u8 control)
{
	writel((u32)control << 24, info->screen_base);
}

static inline u8 lcd_read_control(struct fb_info *info)
{
	return readl(info->screen_base) >> 24;
}

static inline void lcd_write_data(struct fb_info *info, u8 data)
{
	writel((u32)data << 24, info->screen_base + LCD_DATA_REG_OFFSET);
}

static inline u8 lcd_read_data(struct fb_info *info)
{
	return readl(info->screen_base + LCD_DATA_REG_OFFSET) >> 24;
}

static int lcd_busy_wait(struct fb_info *info)
{
	u8 val = 0;
	int timeout = 10, retval = 0;

	do {
		val = lcd_read_control(info);
		val &= LCD_BUSY;
		if (val != LCD_BUSY)
			break;

		if (msleep_interruptible(1))
			return -EINTR;

		timeout--;
	} while (timeout);

	if (val == LCD_BUSY)
		retval = -EBUSY;

	return retval;
}

static void lcd_clear(struct fb_info *info)
{
	int i;

	for (i = 0; i < 4; i++) {
		udelay(150);

		lcd_write_control(info, LCD_PRERESET);
	}

	udelay(150);

	lcd_write_control(info, LCD_CLEAR);

	udelay(150);

	lcd_write_control(info, LCD_RESET);
}

static struct fb_fix_screeninfo cobalt_lcdfb_fix __devinitdata = {
	.id		= "cobalt-lcd",
	.type		= FB_TYPE_TEXT,
	.type_aux	= FB_AUX_TEXT_MDA,
	.visual		= FB_VISUAL_MONO01,
	.line_length	= LCD_XRES_MAX,
	.accel		= FB_ACCEL_NONE,
};

static ssize_t cobalt_lcdfb_read(struct fb_info *info, char __user *buf,
				 size_t count, loff_t *ppos)
{
	char src[LCD_CHARS_MAX];
	unsigned long pos;
	int len, retval = 0;

	pos = *ppos;
	if (pos >= LCD_CHARS_MAX || count == 0)
		return 0;

	if (count > LCD_CHARS_MAX)
		count = LCD_CHARS_MAX;

	if (pos + count > LCD_CHARS_MAX)
		count = LCD_CHARS_MAX - pos;

	for (len = 0; len < count; len++) {
		retval = lcd_busy_wait(info);
		if (retval < 0)
			break;

		lcd_write_control(info, LCD_TEXT_POS(pos));

		retval = lcd_busy_wait(info);
		if (retval < 0)
			break;

		src[len] = lcd_read_data(info);
		if (pos == 0x0f)
			pos = 0x40;
		else
			pos++;
	}

	if (retval < 0 && signal_pending(current))
		return -ERESTARTSYS;

	if (copy_to_user(buf, src, len))
		return -EFAULT;

	*ppos += len;

	return len;
}

static ssize_t cobalt_lcdfb_write(struct fb_info *info, const char __user *buf,
				  size_t count, loff_t *ppos)
{
	char dst[LCD_CHARS_MAX];
	unsigned long pos;
	int len, retval = 0;

	pos = *ppos;
	if (pos >= LCD_CHARS_MAX || count == 0)
		return 0;

	if (count > LCD_CHARS_MAX)
		count = LCD_CHARS_MAX;

	if (pos + count > LCD_CHARS_MAX)
		count = LCD_CHARS_MAX - pos;

	if (copy_from_user(dst, buf, count))
		return -EFAULT;

	for (len = 0; len < count; len++) {
		retval = lcd_busy_wait(info);
		if (retval < 0)
			break;

		lcd_write_control(info, LCD_TEXT_POS(pos));

		retval = lcd_busy_wait(info);
		if (retval < 0)
			break;

		lcd_write_data(info, dst[len]);
		if (pos == 0x0f)
			pos = 0x40;
		else
			pos++;
	}

	if (retval < 0 && signal_pending(current))
		return -ERESTARTSYS;

	*ppos += len;

	return len;
}

static int cobalt_lcdfb_blank(int blank_mode, struct fb_info *info)
{
	int retval;

	retval = lcd_busy_wait(info);
	if (retval < 0)
		return retval;

	switch (blank_mode) {
	case FB_BLANK_UNBLANK:
		lcd_write_control(info, LCD_ON);
		break;
	default:
		lcd_write_control(info, LCD_OFF);
		break;
	}

	return 0;
}

static int cobalt_lcdfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
{
	u32 x, y;
	int retval;

	switch (cursor->set) {
	case FB_CUR_SETPOS:
		x = cursor->image.dx;
		y = cursor->image.dy;
		if (x >= LCD_XRES_MAX || y >= LCD_YRES_MAX)
			return -EINVAL;

		retval = lcd_busy_wait(info);
		if (retval < 0)
			return retval;

		lcd_write_control(info,
				  LCD_TEXT_POS(info->fix.line_length * y + x));
		break;
	default:
		return -EINVAL;
	}

	retval = lcd_busy_wait(info);
	if (retval < 0)
		return retval;

	if (cursor->enable)
		lcd_write_control(info, LCD_CURSOR_ON);
	else
		lcd_write_control(info, LCD_CURSOR_OFF);

	return 0;
}

static struct fb_ops cobalt_lcd_fbops = {
	.owner		= THIS_MODULE,
	.fb_read	= cobalt_lcdfb_read,
	.fb_write	= cobalt_lcdfb_write,
	.fb_blank	= cobalt_lcdfb_blank,
	.fb_cursor	= cobalt_lcdfb_cursor,
};

static int __devinit cobalt_lcdfb_probe(struct platform_device *dev)
{
	struct fb_info *info;
	struct resource *res;
	int retval;

	info = framebuffer_alloc(0, &dev->dev);
	if (!info)
		return -ENOMEM;

	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
	if (!res) {
		framebuffer_release(info);
		return -EBUSY;
	}

	info->screen_size = resource_size(res);
	info->screen_base = ioremap(res->start, info->screen_size);
	info->fbops = &cobalt_lcd_fbops;
	info->fix = cobalt_lcdfb_fix;
	info->fix.smem_start = res->start;
	info->fix.smem_len = info->screen_size;
	info->pseudo_palette = NULL;
	info->par = NULL;
	info->flags = FBINFO_DEFAULT;

	retval = register_framebuffer(info);
	if (retval < 0) {
		iounmap(info->screen_base);
		framebuffer_release(info);
		return retval;
	}

	platform_set_drvdata(dev, info);

	lcd_clear(info);

	printk(KERN_INFO "fb%d: Cobalt server LCD frame buffer device\n",
		info->node);

	return 0;
}

static int __devexit cobalt_lcdfb_remove(struct platform_device *dev)
{
	struct fb_info *info;

	info = platform_get_drvdata(dev);
	if (info) {
		iounmap(info->screen_base);
		unregister_framebuffer(info);
		framebuffer_release(info);
	}

	return 0;
}

static struct platform_driver cobalt_lcdfb_driver = {
	.probe	= cobalt_lcdfb_probe,
	.remove	= __devexit_p(cobalt_lcdfb_remove),
	.driver	= {
		.name	= "cobalt-lcd",
		.owner	= THIS_MODULE,
	},
};

static int __init cobalt_lcdfb_init(void)
{
	return platform_driver_register(&cobalt_lcdfb_driver);
}

static void __exit cobalt_lcdfb_exit(void)
{
	platform_driver_unregister(&cobalt_lcdfb_driver);
}

module_init(cobalt_lcdfb_init);
module_exit(cobalt_lcdfb_exit);

MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Yoichi Yuasa");
MODULE_DESCRIPTION("Cobalt server LCD frame buffer driver");
