/*
 *
 * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450.
 *
 * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
 *
 * Version: 1.64 2002/06/10
 *
 * See matroxfb_base.c for contributors.
 *
 */

#include "matroxfb_base.h"
#include "matroxfb_maven.h"
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>

/* MGA-TVO I2C for G200, G400 */
#define MAT_CLK		0x20
#define MAT_DATA	0x10
/* primary head DDC for Mystique(?), G100, G200, G400 */
#define DDC1_CLK	0x08
#define DDC1_DATA	0x02
/* primary head DDC for Millennium, Millennium II */
#define DDC1B_CLK	0x10
#define DDC1B_DATA	0x04
/* secondary head DDC for G400 */
#define DDC2_CLK	0x04
#define DDC2_DATA	0x01

/******************************************************/

struct matroxfb_dh_maven_info {
	struct i2c_bit_adapter	maven;
	struct i2c_bit_adapter	ddc1;
	struct i2c_bit_adapter	ddc2;
};

static int matroxfb_read_gpio(struct matrox_fb_info* minfo) {
	unsigned long flags;
	int v;

	matroxfb_DAC_lock_irqsave(flags);
	v = matroxfb_DAC_in(PMINFO DAC_XGENIODATA);
	matroxfb_DAC_unlock_irqrestore(flags);
	return v;
}

static void matroxfb_set_gpio(struct matrox_fb_info* minfo, int mask, int val) {
	unsigned long flags;
	int v;

	matroxfb_DAC_lock_irqsave(flags);
	v = (matroxfb_DAC_in(PMINFO DAC_XGENIOCTRL) & mask) | val;
	matroxfb_DAC_out(PMINFO DAC_XGENIOCTRL, v);
	/* We must reset GENIODATA very often... XFree plays with this register */
	matroxfb_DAC_out(PMINFO DAC_XGENIODATA, 0x00);
	matroxfb_DAC_unlock_irqrestore(flags);
}

/* software I2C functions */
static inline void matroxfb_i2c_set(struct matrox_fb_info* minfo, int mask, int state) {
	if (state)
		state = 0;
	else
		state = mask;
	matroxfb_set_gpio(minfo, ~mask, state);
}

static void matroxfb_gpio_setsda(void* data, int state) {
	struct i2c_bit_adapter* b = data;
	matroxfb_i2c_set(b->minfo, b->mask.data, state);
}

static void matroxfb_gpio_setscl(void* data, int state) {
	struct i2c_bit_adapter* b = data;
	matroxfb_i2c_set(b->minfo, b->mask.clock, state);
}

static int matroxfb_gpio_getsda(void* data) {
	struct i2c_bit_adapter* b = data;
	return (matroxfb_read_gpio(b->minfo) & b->mask.data) ? 1 : 0;
}

static int matroxfb_gpio_getscl(void* data) {
	struct i2c_bit_adapter* b = data;
	return (matroxfb_read_gpio(b->minfo) & b->mask.clock) ? 1 : 0;
}

static struct i2c_adapter matrox_i2c_adapter_template =
{
	.owner =	THIS_MODULE,
	.id =		I2C_HW_B_G400,
};

static struct i2c_algo_bit_data matrox_i2c_algo_template =
{
	.setsda		= matroxfb_gpio_setsda,
	.setscl		= matroxfb_gpio_setscl,
	.getsda		= matroxfb_gpio_getsda,
	.getscl		= matroxfb_gpio_getscl,
	.udelay		= 10,
	.timeout	= 100,
};

static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo, 
		unsigned int data, unsigned int clock, const char *name,
		int class)
{
	int err;

	b->minfo = minfo;
	b->mask.data = data;
	b->mask.clock = clock;
	b->adapter = matrox_i2c_adapter_template;
	snprintf(b->adapter.name, sizeof(b->adapter.name), name,
		minfo->fbcon.node);
	i2c_set_adapdata(&b->adapter, b);
	b->adapter.class = class;
	b->adapter.algo_data = &b->bac;
	b->adapter.dev.parent = &ACCESS_FBINFO(pcidev)->dev;
	b->bac = matrox_i2c_algo_template;
	b->bac.data = b;
	err = i2c_bit_add_bus(&b->adapter);
	b->initialized = !err;
	return err;
}

static void i2c_bit_bus_del(struct i2c_bit_adapter* b) {
	if (b->initialized) {
		i2c_del_adapter(&b->adapter);
		b->initialized = 0;
	}
}

static inline void i2c_maven_done(struct matroxfb_dh_maven_info* minfo2) {
	i2c_bit_bus_del(&minfo2->maven);
}

static inline void i2c_ddc1_done(struct matroxfb_dh_maven_info* minfo2) {
	i2c_bit_bus_del(&minfo2->ddc1);
}

static inline void i2c_ddc2_done(struct matroxfb_dh_maven_info* minfo2) {
	i2c_bit_bus_del(&minfo2->ddc2);
}

static void* i2c_matroxfb_probe(struct matrox_fb_info* minfo) {
	int err;
	unsigned long flags;
	struct matroxfb_dh_maven_info* m2info;

	m2info = kzalloc(sizeof(*m2info), GFP_KERNEL);
	if (!m2info)
		return NULL;

	matroxfb_DAC_lock_irqsave(flags);
	matroxfb_DAC_out(PMINFO DAC_XGENIODATA, 0xFF);
	matroxfb_DAC_out(PMINFO DAC_XGENIOCTRL, 0x00);
	matroxfb_DAC_unlock_irqrestore(flags);

	switch (ACCESS_FBINFO(chip)) {
		case MGA_2064:
		case MGA_2164:
			err = i2c_bus_reg(&m2info->ddc1, minfo,
					  DDC1B_DATA, DDC1B_CLK,
					  "DDC:fb%u #0", I2C_CLASS_DDC);
			break;
		default:
			err = i2c_bus_reg(&m2info->ddc1, minfo,
					  DDC1_DATA, DDC1_CLK,
					  "DDC:fb%u #0", I2C_CLASS_DDC);
			break;
	}
	if (err)
		goto fail_ddc1;
	if (ACCESS_FBINFO(devflags.dualhead)) {
		err = i2c_bus_reg(&m2info->ddc2, minfo,
				  DDC2_DATA, DDC2_CLK,
				  "DDC:fb%u #1", I2C_CLASS_DDC);
		if (err == -ENODEV) {
			printk(KERN_INFO "i2c-matroxfb: VGA->TV plug detected, DDC unavailable.\n");
		} else if (err)
			printk(KERN_INFO "i2c-matroxfb: Could not register secondary output i2c bus. Continuing anyway.\n");
		/* Register maven bus even on G450/G550 */
		err = i2c_bus_reg(&m2info->maven, minfo,
				  MAT_DATA, MAT_CLK, "MAVEN:fb%u", 0);
		if (err)
			printk(KERN_INFO "i2c-matroxfb: Could not register Maven i2c bus. Continuing anyway.\n");
	}
	return m2info;
fail_ddc1:;
	kfree(m2info);
	printk(KERN_ERR "i2c-matroxfb: Could not register primary adapter DDC bus.\n");
	return NULL;
}

static void i2c_matroxfb_remove(struct matrox_fb_info* minfo, void* data) {
	struct matroxfb_dh_maven_info* m2info = data;

	i2c_maven_done(m2info);
	i2c_ddc2_done(m2info);
	i2c_ddc1_done(m2info);
	kfree(m2info);
}

static struct matroxfb_driver i2c_matroxfb = {
	.node =		LIST_HEAD_INIT(i2c_matroxfb.node),
	.name =		"i2c-matroxfb",
	.probe = 	i2c_matroxfb_probe,
	.remove =	i2c_matroxfb_remove,
};

static int __init i2c_matroxfb_init(void) {
	if (matroxfb_register_driver(&i2c_matroxfb)) {
		printk(KERN_ERR "i2c-matroxfb: failed to register driver\n");
		return -ENXIO;
	}
	return 0;
}

static void __exit i2c_matroxfb_exit(void) {
	matroxfb_unregister_driver(&i2c_matroxfb);
}

MODULE_AUTHOR("(c) 1999-2002 Petr Vandrovec <vandrove@vc.cvut.cz>");
MODULE_DESCRIPTION("Support module providing I2C buses present on Matrox videocards");

module_init(i2c_matroxfb_init);
module_exit(i2c_matroxfb_exit);
/* no __setup required */
MODULE_LICENSE("GPL");
