/*
 * Copyright (C) 2010-2015 Freescale Semiconductor, Inc. All Rights Reserved.
 */

/*
 * The code contained herein is licensed under the GNU General Public
 * License. You may obtain a copy of the GNU General Public License
 * Version 2 or later at the following locations:
 *
 * http://www.opensource.org/licenses/gpl-license.html
 * http://www.gnu.org/copyleft/gpl.html
 */

/*!
 * @defgroup Framebuffer Framebuffer Driver for Sii902x.
 */

/*!
 * @file mxsfb_sii902x.c
 *
 * @brief  Frame buffer driver for SII902x
 *
 * @ingroup Framebuffer
 */

/*!
 * Include files
 */
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/console.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/i2c.h>
#include <linux/fsl_devices.h>
#include <linux/interrupt.h>
#include <linux/reset.h>
#include <asm/mach-types.h>
#include <video/mxc_edid.h>

#define SII_EDID_LEN	512
#define DRV_NAME "sii902x"

struct sii902x_data {
	struct i2c_client *client;
	struct delayed_work det_work;
	struct fb_info *fbi;
	struct mxc_edid_cfg edid_cfg;
	u8 cable_plugin;
	u8 edid[SII_EDID_LEN];
	bool dft_mode_set;
	const char *mode_str;
	int bits_per_pixel;
} sii902x;

static void sii902x_poweron(void);
static void sii902x_poweroff(void);

static int sii902x_in_init_state;

#ifdef DEBUG
static void dump_fb_videomode(struct fb_videomode *m)
{
	pr_debug("fb_videomode = %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
		m->refresh, m->xres, m->yres, m->pixclock, m->left_margin,
		m->right_margin, m->upper_margin, m->lower_margin,
		m->hsync_len, m->vsync_len, m->sync, m->vmode, m->flag);
}
#else
static void dump_fb_videomode(struct fb_videomode *m)
{}
#endif

static __attribute__ ((unused)) void dump_regs(u8 reg, int len)
{
	u8 buf[50];
	int i;

	i2c_smbus_read_i2c_block_data(sii902x.client, reg, len, buf);
	for (i = 0; i < len; i++)
		dev_dbg(&sii902x.client->dev, "reg[0x%02X]: 0x%02X\n",
				i+reg, buf[i]);
}

static ssize_t sii902x_show_name(struct device *dev,
		struct device_attribute *attr, char *buf)
{
	strcpy(buf, sii902x.fbi->fix.id);
	sprintf(buf+strlen(buf), "\n");

	return strlen(buf);
}

static DEVICE_ATTR(fb_name, S_IRUGO, sii902x_show_name, NULL);

static ssize_t sii902x_show_state(struct device *dev,
		struct device_attribute *attr, char *buf)
{
	if (sii902x.cable_plugin == 0)
		strcpy(buf, "plugout\n");
	else
		strcpy(buf, "plugin\n");

	return strlen(buf);
}

static DEVICE_ATTR(cable_state, S_IRUGO, sii902x_show_state, NULL);

static ssize_t sii902x_show_edid(struct device *dev,
		struct device_attribute *attr, char *buf)
{
	int i, j, len = 0;

	for (j = 0; j < SII_EDID_LEN/16; j++) {
		for (i = 0; i < 16; i++)
			len += sprintf(buf+len, "0x%02X ",
					sii902x.edid[j*16 + i]);
		len += sprintf(buf+len, "\n");
	}

	return len;
}

static DEVICE_ATTR(edid, S_IRUGO, sii902x_show_edid, NULL);

static void sii902x_setup(struct fb_info *fbi)
{
	u16 data[4];
	u32 refresh;
	u8 *tmp;
	int i;

	dev_dbg(&sii902x.client->dev, "Sii902x: setup..\n");

	/* Power up */
	i2c_smbus_write_byte_data(sii902x.client, 0x1E, 0x00);

	/* set TPI video mode */
	data[0] = PICOS2KHZ(fbi->var.pixclock) / 10;
	data[2] = fbi->var.hsync_len + fbi->var.left_margin +
		  fbi->var.xres + fbi->var.right_margin;
	data[3] = fbi->var.vsync_len + fbi->var.upper_margin +
		  fbi->var.yres + fbi->var.lower_margin;
	refresh = data[2] * data[3];
	refresh = (PICOS2KHZ(fbi->var.pixclock) * 1000) / refresh;
	data[1] = refresh * 100;
	tmp = (u8 *)data;
	for (i = 0; i < 8; i++)
		i2c_smbus_write_byte_data(sii902x.client, i, tmp[i]);

	/* input bus/pixel: full pixel wide (24bit), rising edge */
	i2c_smbus_write_byte_data(sii902x.client, 0x08, 0x70);
	/* Set input format to RGB */
	i2c_smbus_write_byte_data(sii902x.client, 0x09, 0x00);
	/* set output format to RGB */
	i2c_smbus_write_byte_data(sii902x.client, 0x0A, 0x00);
}

static void sii902x_audio_setup(void)
{
	/* audio setup */
	i2c_smbus_write_byte_data(sii902x.client, 0x25, 0x00);
	i2c_smbus_write_byte_data(sii902x.client, 0x26, 0x40);
	i2c_smbus_write_byte_data(sii902x.client, 0x27, 0x00);
}

#ifdef CONFIG_FB_MODE_HELPERS
static int sii902x_read_edid(struct fb_info *fbi)
{
	int old, dat, ret, cnt = 100;
	unsigned short addr = 0x50;

	dev_dbg(&sii902x.client->dev, "%s\n", __func__);

	old = i2c_smbus_read_byte_data(sii902x.client, 0x1A);

	i2c_smbus_write_byte_data(sii902x.client, 0x1A, old | 0x4);
	do {
		cnt--;
		msleep(10);
		dat = i2c_smbus_read_byte_data(sii902x.client, 0x1A);
	} while ((!(dat & 0x2)) && cnt);

	if (!cnt) {
		ret = -1;
		goto done;
	}

	i2c_smbus_write_byte_data(sii902x.client, 0x1A, old | 0x06);

	/* edid reading */
	ret = mxc_edid_read(sii902x.client->adapter, addr,
				sii902x.edid, &sii902x.edid_cfg, fbi);

	cnt = 100;
	do {
		cnt--;
		i2c_smbus_write_byte_data(sii902x.client, 0x1A, old & ~0x6);
		msleep(10);
		dat = i2c_smbus_read_byte_data(sii902x.client, 0x1A);
	} while ((dat & 0x6) && cnt);

	if (!cnt)
		ret = -1;

done:

	i2c_smbus_write_byte_data(sii902x.client, 0x1A, old);
	return ret;
}
#else
static int sii902x_read_edid(struct fb_info *fbi)
{
	return -1;
}
#endif

static void sii902x_cable_connected(void)
{
	int i;
	const struct fb_videomode *mode;
	struct fb_videomode m;

	if (sii902x_read_edid(sii902x.fbi) < 0)
		dev_err(&sii902x.client->dev,
			"Sii902x: read edid fail\n");
	else {
		if (sii902x.fbi->monspecs.modedb_len > 0) {

			fb_destroy_modelist(&sii902x.fbi->modelist);

			for (i = 0; i < sii902x.fbi->monspecs.modedb_len; i++) {

				mode = &sii902x.fbi->monspecs.modedb[i];

				if (!(mode->vmode & FB_VMODE_INTERLACED)) {
					dev_dbg(&sii902x.client->dev, "Added mode %d:", i);
					dev_dbg(&sii902x.client->dev,
						"xres = %d, yres = %d, freq = %d, vmode = %d, flag = %d\n",
						mode->xres, mode->yres, mode->refresh,
						mode->vmode, mode->flag);

					fb_add_videomode(mode, &sii902x.fbi->modelist);
				}
			}

			/* Set the default mode only once. */
			if (!sii902x.dft_mode_set &&
					sii902x.mode_str && sii902x.bits_per_pixel) {

				dev_dbg(&sii902x.client->dev, "%s: setting to default=%s bpp=%d\n",
						__func__, sii902x.mode_str, sii902x.bits_per_pixel);

				fb_find_mode(&sii902x.fbi->var, sii902x.fbi,
						sii902x.mode_str, NULL, 0, NULL,
						sii902x.bits_per_pixel);

				sii902x.dft_mode_set = true;
			}

			fb_var_to_videomode(&m, &sii902x.fbi->var);
			dump_fb_videomode(&m);

			mode = fb_find_nearest_mode(&m,
					&sii902x.fbi->modelist);

			/* update fbi mode  */
			sii902x.fbi->mode = (struct fb_videomode *)mode;

			fb_videomode_to_var(&sii902x.fbi->var, mode);

			sii902x.fbi->var.activate |= FB_ACTIVATE_FORCE;
			console_lock();
			sii902x.fbi->flags |= FBINFO_MISC_USEREVENT;
			fb_set_var(sii902x.fbi, &sii902x.fbi->var);
			sii902x.fbi->flags &= ~FBINFO_MISC_USEREVENT;
			console_unlock();
		}
		/* Power on sii902x */
		sii902x_poweron();
	}
}

static void det_worker(struct work_struct *work)
{
	int dat;
	char event_string[16];
	char *envp[] = { event_string, NULL };

	dev_dbg(&sii902x.client->dev, "%s\n", __func__);

	dat = i2c_smbus_read_byte_data(sii902x.client, 0x3D);

	/* cable connection state */
	if (dat & 0x4) {
		sii902x.cable_plugin = 1;
		dev_dbg(&sii902x.client->dev, "EVENT=plugin\n");
		sprintf(event_string, "EVENT=plugin");
		sii902x_cable_connected();
	} else {
		sii902x.cable_plugin = 0;
		dev_dbg(&sii902x.client->dev, "EVENT=plugout\n");
		sprintf(event_string, "EVENT=plugout");
		/* Power off sii902x */
		sii902x_poweroff();
	}
	kobject_uevent_env(&sii902x.client->dev.kobj, KOBJ_CHANGE, envp);

	i2c_smbus_write_byte_data(sii902x.client, 0x3D, dat);

	dev_dbg(&sii902x.client->dev, "exit %s\n", __func__);

}

static irqreturn_t sii902x_detect_handler(int irq, void *data)
{
	if (sii902x.fbi)
		schedule_delayed_work(&(sii902x.det_work), msecs_to_jiffies(50));

	return IRQ_HANDLED;
}

static int sii902x_fb_event(struct notifier_block *nb, unsigned long val, void *v)
{
	struct fb_event *event = v;
	struct fb_info *fbi = event->info;

	/* Check if our FB just registered */
	if (!sii902x.fbi && val == FB_EVENT_FB_REGISTERED &&
			!strncmp(fbi->fix.id, "mxs-lcdif", 9)) {
		pr_info("sii902x bound to %s from %s\n",
				fbi->fix.id, dev_name(fbi->device));
		sii902x.fbi = fbi;
	}

	/* Ignore if not our FB */
	if (fbi != sii902x.fbi)
		return 0;

	/* Ignore if driver did not probe yet */
	if (sii902x_in_init_state)
		return 0;

	switch (val) {
	case FB_EVENT_FB_REGISTERED:
		/* Manually trigger a plugin/plugout interrupter to check cable state */
		schedule_delayed_work(&(sii902x.det_work), msecs_to_jiffies(50));

		fb_show_logo(fbi, 0);

		break;
	case FB_EVENT_MODE_CHANGE:
		sii902x_setup(fbi);
		break;
	case FB_EVENT_BLANK:
		if (*((int *)event->data) == FB_BLANK_UNBLANK) {
			dev_dbg(&sii902x.client->dev, "FB_BLANK_UNBLANK\n");
			sii902x_poweron();
		} else {
			dev_dbg(&sii902x.client->dev, "FB_BLANK_BLANK\n");
			sii902x_poweroff();
		}
		break;
	}
	return 0;
}

static struct notifier_block nb = {
	.notifier_call = sii902x_fb_event,
};

static int mxsfb_get_of_property(void)
{
	struct device_node *np = sii902x.client->dev.of_node;
	const char *mode_str;
	int bits_per_pixel, ret;

	ret = of_property_read_string(np, "mode_str", &mode_str);
	if (ret < 0) {
		dev_warn(&sii902x.client->dev, "get of property mode_str fail\n");
		return ret;
	}
	ret = of_property_read_u32(np, "bits-per-pixel", &bits_per_pixel);
	if (ret) {
		dev_warn(&sii902x.client->dev, "get of property bpp fail\n");
		return ret;
	}

	sii902x.mode_str = mode_str;
	sii902x.bits_per_pixel = bits_per_pixel;

	return ret;
}

static int sii902x_probe(struct i2c_client *client,
		const struct i2c_device_id *id)
{
	int i, dat, ret;
	struct fb_info edid_fbi;
	struct fb_info *init_fbi = sii902x.fbi;

	memset(&sii902x, 0, sizeof(sii902x));

	sii902x.client = client;

	dev_dbg(&sii902x.client->dev, "%s\n", __func__);;

	/* Reset sii902x */
	ret = device_reset(&sii902x.client->dev);
	if (ret)
		dev_warn(&sii902x.client->dev, "No reset pin found\n");
	if (ret == -EPROBE_DEFER)
		return ret;

	/* Set 902x in hardware TPI mode on and jump out of D3 state */
	if (i2c_smbus_write_byte_data(sii902x.client, 0xc7, 0x00) < 0) {
		dev_err(&sii902x.client->dev,
			"Sii902x: cound not find device\n");
		return -ENODEV;
	}

	/* read device ID */
	for (i = 10; i > 0; i--) {
		dat = i2c_smbus_read_byte_data(sii902x.client, 0x1B);
		dev_dbg(&sii902x.client->dev, "Sii902x: read id = 0x%02X", dat);
		if (dat == 0xb0) {
			dat = i2c_smbus_read_byte_data(sii902x.client, 0x1C);
			dev_dbg(&sii902x.client->dev, "-0x%02X", dat);
			dat = i2c_smbus_read_byte_data(sii902x.client, 0x1D);
			dev_dbg(&sii902x.client->dev, "-0x%02X", dat);
			dat = i2c_smbus_read_byte_data(sii902x.client, 0x30);
			dev_dbg(&sii902x.client->dev, "-0x%02X\n", dat);
			break;
		}
	}
	if (i == 0) {
		dev_err(&sii902x.client->dev,
			"Sii902x: cound not find device\n");
		return -ENODEV;
	}

	/* enable hmdi audio */
	sii902x_audio_setup();

	/* try to read edid, only if cable is plugged in */
	dat = i2c_smbus_read_byte_data(sii902x.client, 0x3D);
	if (dat & 0x04) {
		ret = sii902x_read_edid(&edid_fbi);
		if (ret < 0)
			dev_warn(&sii902x.client->dev, "Can not read edid\n");
	}

	if (sii902x.client->irq) {
		ret = request_irq(sii902x.client->irq, sii902x_detect_handler,
				IRQF_TRIGGER_FALLING,
				"SII902x_det", &sii902x);
		if (ret < 0)
			dev_warn(&sii902x.client->dev,
				"Sii902x: cound not request det irq %d\n",
				sii902x.client->irq);
		else {
			/*enable cable hot plug irq*/
			i2c_smbus_write_byte_data(sii902x.client, 0x3c, 0x01);
			INIT_DELAYED_WORK(&(sii902x.det_work), det_worker);
		}
		ret = device_create_file(&sii902x.client->dev, &dev_attr_fb_name);
		if (ret < 0)
			dev_warn(&sii902x.client->dev,
				"Sii902x: cound not create sys node for fb name\n");
		ret = device_create_file(&sii902x.client->dev, &dev_attr_cable_state);
		if (ret < 0)
			dev_warn(&sii902x.client->dev,
				"Sii902x: cound not create sys node for cable state\n");
		ret = device_create_file(&sii902x.client->dev, &dev_attr_edid);
		if (ret < 0)
			dev_warn(&sii902x.client->dev,
				"Sii902x: cound not create sys node for edid\n");

	}

	mxsfb_get_of_property();

	if (init_fbi) {
		sii902x.fbi = init_fbi;

		/* Manually trigger a plugin/plugout interrupter to check cable state */
		schedule_delayed_work(&(sii902x.det_work), msecs_to_jiffies(50));
	}

	sii902x_in_init_state = 0;

	return 0;
}

static int sii902x_remove(struct i2c_client *client)
{
	fb_unregister_client(&nb);
	sii902x_poweroff();

	return 0;
}

static void sii902x_poweron(void)
{
	/* Turn on DVI or HDMI */
	if (sii902x.edid_cfg.hdmi_cap)
		i2c_smbus_write_byte_data(sii902x.client, 0x1A, 0x01);
	else
		i2c_smbus_write_byte_data(sii902x.client, 0x1A, 0x00);
	return;
}

static void sii902x_poweroff(void)
{
	/* disable tmds before changing resolution */
	if (sii902x.edid_cfg.hdmi_cap)
		i2c_smbus_write_byte_data(sii902x.client, 0x1A, 0x11);
	else
		i2c_smbus_write_byte_data(sii902x.client, 0x1A, 0x10);

	return;
}

static int __init sii902x_init(void)
{
	sii902x_in_init_state = 1;

	return fb_register_client(&nb);
}
fs_initcall_sync(sii902x_init);

static const struct i2c_device_id sii902x_id[] = {
	{ DRV_NAME, 0},
	{ },
};
MODULE_DEVICE_TABLE(i2c, sii902x_id);

static const struct of_device_id sii902x_dt_ids[] = {
	{ .compatible = "SiI,sii902x", },
	{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, sii902x_dt_ids);

static struct i2c_driver sii902x_driver = {
	.driver = {
		.name = DRV_NAME,
		.owner = THIS_MODULE,
		.of_match_table = sii902x_dt_ids,
	},
	.probe		= sii902x_probe,
	.remove		= sii902x_remove,
	.id_table	= sii902x_id,
};

module_i2c_driver(sii902x_driver);

MODULE_AUTHOR("Freescale Semiconductor, Inc.");
MODULE_DESCRIPTION("SII902x DVI/HDMI driver");
MODULE_LICENSE("GPL");
