/*
 *  LCD / Backlight control code for Sharp SL-6000x (tosa)
 *
 *  Copyright (c) 2005		Dirk Opfer
 *  Copyright (c) 2007,2008	Dmitry Baryshkov
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 2 as
 *  published by the Free Software Foundation.
 *
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/spi/spi.h>
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/lcd.h>
#include <linux/fb.h>

#include <asm/mach/sharpsl_param.h>

#include <mach/tosa.h>

#define POWER_IS_ON(pwr)	((pwr) <= FB_BLANK_NORMAL)

#define TG_REG0_VQV	0x0001
#define TG_REG0_COLOR	0x0002
#define TG_REG0_UD	0x0004
#define TG_REG0_LR	0x0008

#define	DAC_BASE	0x4e

struct tosa_lcd_data {
	struct spi_device *spi;
	struct lcd_device *lcd;
	struct i2c_client *i2c;

	int lcd_power;
};

static int tosa_tg_send(struct spi_device *spi, int adrs, uint8_t data)
{
	u8 buf[1];
	struct spi_message msg;
	struct spi_transfer xfer = {
		.len		= 1,
		.cs_change	= 1,
		.tx_buf		= buf,
	};

	buf[0] = ((adrs & 0x07) << 5) | (data & 0x1f);
	spi_message_init(&msg);
	spi_message_add_tail(&xfer, &msg);

	return spi_sync(spi, &msg);
}

int tosa_bl_enable(struct spi_device *spi, int enable)
{
	/* bl_enable GP04=1 otherwise GP04=0*/
	return tosa_tg_send(spi, TG_GPODR2, enable? 0x01 : 0x00);
}
EXPORT_SYMBOL(tosa_bl_enable);

static void tosa_lcd_tg_init(struct tosa_lcd_data *data)
{
	/* TG on */
	gpio_set_value(TOSA_GPIO_TG_ON, 0);

	mdelay(60);

	/* delayed 0clk TCTL signal for VGA */
	tosa_tg_send(data->spi, TG_TPOSCTL, 0x00);
	/* GPOS0=powercontrol, GPOS1=GPIO, GPOS2=TCTL */
	tosa_tg_send(data->spi, TG_GPOSR, 0x02);
}

static void tosa_lcd_tg_on(struct tosa_lcd_data *data)
{
	struct spi_device *spi = data->spi;
	const int value = TG_REG0_COLOR | TG_REG0_UD | TG_REG0_LR;
	tosa_tg_send(spi, TG_PNLCTL, value | TG_REG0_VQV); /* this depends on mode */

	/* TG LCD pannel power up */
	tosa_tg_send(spi, TG_PINICTL,0x4);
	mdelay(50);

	/* TG LCD GVSS */
	tosa_tg_send(spi, TG_PINICTL,0x0);

	if (!data->i2c) {
		/* after the pannel is powered up the first time, we can access the i2c bus */
		/* so probe for the DAC */
		struct i2c_adapter *adap = i2c_get_adapter(0);
		struct i2c_board_info info = {
			.type	= "tosa-bl",
			.addr	= DAC_BASE,
			.platform_data = data->spi,
		};
		data->i2c = i2c_new_device(adap, &info);
	}
}

static void tosa_lcd_tg_off(struct tosa_lcd_data *data)
{
	struct spi_device *spi = data->spi;

	/* TG LCD VHSA off */
	tosa_tg_send(spi, TG_PINICTL,0x4);
	mdelay(50);

	/* TG LCD signal off */
	tosa_tg_send(spi, TG_PINICTL,0x6);
	mdelay(50);

	/* TG Off */
	gpio_set_value(TOSA_GPIO_TG_ON, 1);
	mdelay(100);
}

int tosa_lcd_set_power(struct lcd_device *lcd, int power)
{
	struct tosa_lcd_data *data = lcd_get_data(lcd);

	if (POWER_IS_ON(power) && !POWER_IS_ON(data->lcd_power))
		tosa_lcd_tg_on(data);

	if (!POWER_IS_ON(power) && POWER_IS_ON(data->lcd_power))
		tosa_lcd_tg_off(data);

	data->lcd_power = power;
	return 0;
}

static int tosa_lcd_get_power(struct lcd_device *lcd)
{
	struct tosa_lcd_data *data = lcd_get_data(lcd);

	return data->lcd_power;
}

static struct lcd_ops tosa_lcd_ops = {
	.set_power = tosa_lcd_set_power,
	.get_power = tosa_lcd_get_power,
};

static int __devinit tosa_lcd_probe(struct spi_device *spi)
{
	int ret;
	struct tosa_lcd_data *data;

	data = kzalloc(sizeof(struct tosa_lcd_data), GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	/*
	 * bits_per_word cannot be configured in platform data
	 */
	spi->bits_per_word = 8;

	ret = spi_setup(spi);
	if (ret < 0)
		goto err_spi;

	data->spi = spi;
	dev_set_drvdata(&spi->dev, data);

	ret = gpio_request(TOSA_GPIO_TG_ON, "tg #pwr");
	if (ret < 0)
		goto err_gpio_tg;

	mdelay(60);

	ret = gpio_direction_output(TOSA_GPIO_TG_ON, 0);
	if (ret < 0)
		goto err_gpio_dir;

	mdelay(60);
	tosa_lcd_tg_init(data);

	tosa_lcd_tg_on(data);

	data->lcd = lcd_device_register("tosa-lcd", &spi->dev, data,
			&tosa_lcd_ops);

	if (IS_ERR(data->lcd)) {
		ret = PTR_ERR(data->lcd);
		data->lcd = NULL;
		goto err_register;
	}

	return 0;

err_register:
	tosa_lcd_tg_off(data);
err_gpio_dir:
	gpio_free(TOSA_GPIO_TG_ON);
err_gpio_tg:
	dev_set_drvdata(&spi->dev, NULL);
err_spi:
	kfree(data);
	return ret;
}

static int __devexit tosa_lcd_remove(struct spi_device *spi)
{
	struct tosa_lcd_data *data = dev_get_drvdata(&spi->dev);

	lcd_device_unregister(data->lcd);

	if (data->i2c)
		i2c_unregister_device(data->i2c);

	tosa_lcd_tg_off(data);

	gpio_free(TOSA_GPIO_TG_ON);
	dev_set_drvdata(&spi->dev, NULL);
	kfree(data);

	return 0;
}

#ifdef CONFIG_PM
static int tosa_lcd_suspend(struct spi_device *spi, pm_message_t state)
{
	struct tosa_lcd_data *data = dev_get_drvdata(&spi->dev);

	tosa_lcd_tg_off(data);

	return 0;
}

static int tosa_lcd_resume(struct spi_device *spi)
{
	struct tosa_lcd_data *data = dev_get_drvdata(&spi->dev);

	tosa_lcd_tg_init(data);
	if (POWER_IS_ON(data->lcd_power))
		tosa_lcd_tg_on(data);
	else
		tosa_lcd_tg_off(data);

	return 0;
}
#else
#define tosa_lcd_suspend	NULL
#define tosa_lcd_reume NULL
#endif

static struct spi_driver tosa_lcd_driver = {
	.driver = {
		.name		= "tosa-lcd",
		.owner		= THIS_MODULE,
	},
	.probe		= tosa_lcd_probe,
	.remove		= __devexit_p(tosa_lcd_remove),
	.suspend	= tosa_lcd_suspend,
	.resume		= tosa_lcd_resume,
};

static int __init tosa_lcd_init(void)
{
	return spi_register_driver(&tosa_lcd_driver);
}

static void __exit tosa_lcd_exit(void)
{
	spi_unregister_driver(&tosa_lcd_driver);
}

module_init(tosa_lcd_init);
module_exit(tosa_lcd_exit);

MODULE_AUTHOR("Dmitry Baryshkov");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("LCD/Backlight control for Sharp SL-6000 PDA");

