/*
 *
 * 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 const 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.owner = THIS_MODULE;
	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");
		else {
			struct i2c_board_info maven_info = {
				I2C_BOARD_INFO("maven", 0x1b),
			};
			unsigned short const addr_list[2] = {
				0x1b, I2C_CLIENT_END
			};

			i2c_new_probed_device(&m2info->maven.adapter,
					      &maven_info, addr_list);
		}
	}
	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");
