1 /*
2  * linux/drivers/video/nvidia/nvidia-i2c.c - nVidia i2c
3  *
4  * Copyright 2004 Antonino A. Daplas <adaplas @pol.net>
5  *
6  * Based on rivafb-i2c.c
7  *
8  * This file is subject to the terms and conditions of the GNU General Public
9  * License.  See the file COPYING in the main directory of this archive
10  * 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 
28 static 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 	else
39 		val &= ~0x20;
40 
41 	NVWriteCrtc(par, chan->ddc_base + 1, val | 0x01);
42 }
43 
44 static 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 	else
55 		val &= ~0x10;
56 
57 	NVWriteCrtc(par, chan->ddc_base + 1, val | 0x01);
58 }
59 
60 static 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 
72 static 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 
84 static int nvidia_setup_i2c_bus(struct nvidia_i2c_chan *chan, const char *name,
85 				unsigned int i2c_class)
86 {
87 	int rc;
88 
89 	strcpy(chan->adapter.name, 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 
122 void 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 
140 void 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 
152 int 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