brintos

brintos / linux-shallow public Read only

0
0
Text · 5.6 KiB · 80fa87e Raw
242 lines · c
1/*2 * linux/drivers/video/savage/savagefb-i2c.c - S3 Savage DDC23 *4 * Copyright 2004 Antonino A. Daplas <adaplas @pol.net>5 *6 * Based partly on rivafb-i2c.c7 *8 * This file is subject to the terms and conditions of the GNU General Public9 * License.  See the file COPYING in the main directory of this archive10 * for more details.11 */12 13#include <linux/module.h>14#include <linux/kernel.h>15#include <linux/delay.h>16#include <linux/gfp.h>17#include <linux/pci.h>18#include <linux/fb.h>19 20#include <asm/io.h>21#include "savagefb.h"22 23#define SAVAGE_DDC 	0x5024 25#define VGA_CR_IX	0x3d426#define VGA_CR_DATA	0x3d527 28#define CR_SERIAL1	0xa0	/* I2C serial communications interface */29#define MM_SERIAL1	0xff2030#define CR_SERIAL2	0xb1	/* DDC2 monitor communications interface */31 32/* based on vt8365 documentation */33#define PROSAVAGE_I2C_ENAB	0x1034#define PROSAVAGE_I2C_SCL_OUT	0x0135#define PROSAVAGE_I2C_SDA_OUT	0x0236#define PROSAVAGE_I2C_SCL_IN	0x0437#define PROSAVAGE_I2C_SDA_IN	0x0838 39#define SAVAGE4_I2C_ENAB	0x0000002040#define SAVAGE4_I2C_SCL_OUT	0x0000000141#define SAVAGE4_I2C_SDA_OUT	0x0000000242#define SAVAGE4_I2C_SCL_IN	0x0000000843#define SAVAGE4_I2C_SDA_IN	0x0000001044 45static void savage4_gpio_setscl(void *data, int val)46{47	struct savagefb_i2c_chan *chan = data;48	unsigned int r;49 50	r = readl(chan->ioaddr + chan->reg);51	if(val)52		r |= SAVAGE4_I2C_SCL_OUT;53	else54		r &= ~SAVAGE4_I2C_SCL_OUT;55	writel(r, chan->ioaddr + chan->reg);56	readl(chan->ioaddr + chan->reg);	/* flush posted write */57}58 59static void savage4_gpio_setsda(void *data, int val)60{61	struct savagefb_i2c_chan *chan = data;62 63	unsigned int r;64	r = readl(chan->ioaddr + chan->reg);65	if(val)66		r |= SAVAGE4_I2C_SDA_OUT;67	else68		r &= ~SAVAGE4_I2C_SDA_OUT;69	writel(r, chan->ioaddr + chan->reg);70	readl(chan->ioaddr + chan->reg);	/* flush posted write */71}72 73static int savage4_gpio_getscl(void *data)74{75	struct savagefb_i2c_chan *chan = data;76 77	return (0 != (readl(chan->ioaddr + chan->reg) & SAVAGE4_I2C_SCL_IN));78}79 80static int savage4_gpio_getsda(void *data)81{82	struct savagefb_i2c_chan *chan = data;83 84	return (0 != (readl(chan->ioaddr + chan->reg) & SAVAGE4_I2C_SDA_IN));85}86 87static void prosavage_gpio_setscl(void* data, int val)88{89	struct savagefb_i2c_chan *chan = data;90	u32			  r;91 92	r = VGArCR(chan->reg, chan->par);93	r |= PROSAVAGE_I2C_ENAB;94	if (val) {95		r |= PROSAVAGE_I2C_SCL_OUT;96	} else {97		r &= ~PROSAVAGE_I2C_SCL_OUT;98	}99 100	VGAwCR(chan->reg, r, chan->par);101}102 103static void prosavage_gpio_setsda(void* data, int val)104{105	struct savagefb_i2c_chan *chan = data;106	unsigned int r;107 108	r = VGArCR(chan->reg, chan->par);109	r |= PROSAVAGE_I2C_ENAB;110	if (val) {111		r |= PROSAVAGE_I2C_SDA_OUT;112	} else {113		r &= ~PROSAVAGE_I2C_SDA_OUT;114	}115 116	VGAwCR(chan->reg, r, chan->par);117}118 119static int prosavage_gpio_getscl(void* data)120{121	struct savagefb_i2c_chan *chan = data;122 123	return (VGArCR(chan->reg, chan->par) & PROSAVAGE_I2C_SCL_IN) ? 1 : 0;124}125 126static int prosavage_gpio_getsda(void* data)127{128	struct savagefb_i2c_chan *chan = data;129 130	return (VGArCR(chan->reg, chan->par) & PROSAVAGE_I2C_SDA_IN) ? 1 : 0;131}132 133static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan,134				const char *name)135{136	int rc = 0;137 138	if (chan->par) {139		strcpy(chan->adapter.name, name);140		chan->adapter.owner		= THIS_MODULE;141		chan->adapter.algo_data		= &chan->algo;142		chan->adapter.dev.parent	= &chan->par->pcidev->dev;143		chan->algo.udelay		= 10;144		chan->algo.timeout		= 20;145		chan->algo.data 		= chan;146 147		i2c_set_adapdata(&chan->adapter, chan);148 149		/* Raise SCL and SDA */150		chan->algo.setsda(chan, 1);151		chan->algo.setscl(chan, 1);152		udelay(20);153 154		rc = i2c_bit_add_bus(&chan->adapter);155 156		if (rc == 0)157			dev_dbg(&chan->par->pcidev->dev,158				"I2C bus %s registered.\n", name);159		else160			dev_warn(&chan->par->pcidev->dev,161				 "Failed to register I2C bus %s.\n", name);162	}163 164	return rc;165}166 167void savagefb_create_i2c_busses(struct fb_info *info)168{169	struct savagefb_par *par = info->par;170	par->chan.par	= par;171 172	switch (par->chip) {173	case S3_PROSAVAGE:174	case S3_PROSAVAGEDDR:175	case S3_TWISTER:176		par->chan.reg         = CR_SERIAL2;177		par->chan.ioaddr      = par->mmio.vbase;178		par->chan.algo.setsda = prosavage_gpio_setsda;179		par->chan.algo.setscl = prosavage_gpio_setscl;180		par->chan.algo.getsda = prosavage_gpio_getsda;181		par->chan.algo.getscl = prosavage_gpio_getscl;182		break;183	case S3_SAVAGE4:184		par->chan.reg = CR_SERIAL1;185		if (par->pcidev->revision > 1 && !(VGArCR(0xa6, par) & 0x40))186			par->chan.reg = CR_SERIAL2;187		par->chan.ioaddr      = par->mmio.vbase;188		par->chan.algo.setsda = prosavage_gpio_setsda;189		par->chan.algo.setscl = prosavage_gpio_setscl;190		par->chan.algo.getsda = prosavage_gpio_getsda;191		par->chan.algo.getscl = prosavage_gpio_getscl;192		break;193	case S3_SAVAGE2000:194		par->chan.reg         = MM_SERIAL1;195		par->chan.ioaddr      = par->mmio.vbase;196		par->chan.algo.setsda = savage4_gpio_setsda;197		par->chan.algo.setscl = savage4_gpio_setscl;198		par->chan.algo.getsda = savage4_gpio_getsda;199		par->chan.algo.getscl = savage4_gpio_getscl;200		break;201	default:202		par->chan.par = NULL;203	}204 205	savage_setup_i2c_bus(&par->chan, "SAVAGE DDC2");206}207 208void savagefb_delete_i2c_busses(struct fb_info *info)209{210	struct savagefb_par *par = info->par;211 212	if (par->chan.par)213		i2c_del_adapter(&par->chan.adapter);214 215	par->chan.par = NULL;216}217 218int savagefb_probe_i2c_connector(struct fb_info *info, u8 **out_edid)219{220	struct savagefb_par *par = info->par;221	u8 *edid;222 223	if (par->chan.par)224		edid = fb_ddc_read(&par->chan.adapter);225	else226		edid = NULL;227 228	if (!edid) {229		/* try to get from firmware */230		const u8 *e = fb_firmware_edid(info->device);231 232		if (e)233			edid = kmemdup(e, EDID_LENGTH, GFP_KERNEL);234	}235 236	*out_edid = edid;237 238	return (edid) ? 0 : 1;239}240 241MODULE_LICENSE("GPL");242