brintos

brintos / linux-shallow public Read only

0
0
Text · 3.7 KiB · 0b48965 Raw
172 lines · c
1/*2 * linux/drivers/video/nvidia/nvidia-i2c.c - nVidia i2c3 *4 * Copyright 2004 Antonino A. Daplas <adaplas @pol.net>5 *6 * Based 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 22#include "nv_type.h"23#include "nv_local.h"24#include "nv_proto.h"25 26#include "../edid.h"27 28static void nvidia_gpio_setscl(void *data, int state)29{30	struct nvidia_i2c_chan *chan = data;31	struct nvidia_par *par = chan->par;32	u32 val;33 34	val = NVReadCrtc(par, chan->ddc_base + 1) & 0xf0;35 36	if (state)37		val |= 0x20;38	else39		val &= ~0x20;40 41	NVWriteCrtc(par, chan->ddc_base + 1, val | 0x01);42}43 44static void nvidia_gpio_setsda(void *data, int state)45{46	struct nvidia_i2c_chan *chan = data;47	struct nvidia_par *par = chan->par;48	u32 val;49 50	val = NVReadCrtc(par, chan->ddc_base + 1) & 0xf0;51 52	if (state)53		val |= 0x10;54	else55		val &= ~0x10;56 57	NVWriteCrtc(par, chan->ddc_base + 1, val | 0x01);58}59 60static int nvidia_gpio_getscl(void *data)61{62	struct nvidia_i2c_chan *chan = data;63	struct nvidia_par *par = chan->par;64	u32 val = 0;65 66	if (NVReadCrtc(par, chan->ddc_base) & 0x04)67		val = 1;68 69	return val;70}71 72static int nvidia_gpio_getsda(void *data)73{74	struct nvidia_i2c_chan *chan = data;75	struct nvidia_par *par = chan->par;76	u32 val = 0;77 78	if (NVReadCrtc(par, chan->ddc_base) & 0x08)79		val = 1;80 81	return val;82}83 84static int nvidia_setup_i2c_bus(struct nvidia_i2c_chan *chan, const char *name,85				unsigned int i2c_class)86{87	int rc;88 89	strscpy(chan->adapter.name, name, sizeof(chan->adapter.name));90	chan->adapter.owner = THIS_MODULE;91	chan->adapter.class = i2c_class;92	chan->adapter.algo_data = &chan->algo;93	chan->adapter.dev.parent = &chan->par->pci_dev->dev;94	chan->algo.setsda = nvidia_gpio_setsda;95	chan->algo.setscl = nvidia_gpio_setscl;96	chan->algo.getsda = nvidia_gpio_getsda;97	chan->algo.getscl = nvidia_gpio_getscl;98	chan->algo.udelay = 40;99	chan->algo.timeout = msecs_to_jiffies(2);100	chan->algo.data = chan;101 102	i2c_set_adapdata(&chan->adapter, chan);103 104	/* Raise SCL and SDA */105	nvidia_gpio_setsda(chan, 1);106	nvidia_gpio_setscl(chan, 1);107	udelay(20);108 109	rc = i2c_bit_add_bus(&chan->adapter);110	if (rc == 0)111		dev_dbg(&chan->par->pci_dev->dev,112			"I2C bus %s registered.\n", name);113	else {114		dev_warn(&chan->par->pci_dev->dev,115			 "Failed to register I2C bus %s.\n", name);116		chan->par = NULL;117	}118 119	return rc;120}121 122void nvidia_create_i2c_busses(struct nvidia_par *par)123{124	par->chan[0].par = par;125	par->chan[1].par = par;126	par->chan[2].par = par;127 128	par->chan[0].ddc_base = (par->reverse_i2c) ? 0x36 : 0x3e;129 	nvidia_setup_i2c_bus(&par->chan[0], "nvidia #0",130			     (par->reverse_i2c) ? I2C_CLASS_HWMON : 0);131 132	par->chan[1].ddc_base = (par->reverse_i2c) ? 0x3e : 0x36;133 	nvidia_setup_i2c_bus(&par->chan[1], "nvidia #1",134			     (par->reverse_i2c) ? 0 : I2C_CLASS_HWMON);135 136	par->chan[2].ddc_base = 0x50;137 	nvidia_setup_i2c_bus(&par->chan[2], "nvidia #2", 0);138}139 140void nvidia_delete_i2c_busses(struct nvidia_par *par)141{142	int i;143 144	for (i = 0; i < 3; i++) {145		if (!par->chan[i].par)146			continue;147		i2c_del_adapter(&par->chan[i].adapter);148		par->chan[i].par = NULL;149	}150}151 152int nvidia_probe_i2c_connector(struct fb_info *info, int conn, u8 **out_edid)153{154	struct nvidia_par *par = info->par;155	u8 *edid = NULL;156 157	if (par->chan[conn - 1].par)158		edid = fb_ddc_read(&par->chan[conn - 1].adapter);159 160	if (!edid && conn == 1) {161		/* try to get from firmware */162		const u8 *e = fb_firmware_edid(info->device);163 164		if (e != NULL)165			edid = kmemdup(e, EDID_LENGTH, GFP_KERNEL);166	}167 168	*out_edid = edid;169 170	return (edid) ? 0 : 1;171}172