1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28#include <linux/module.h>
29#include <linux/kernel.h>
30#include <linux/delay.h>
31#include <linux/pci.h>
32#include <linux/fb.h>
33
34#include <linux/i2c.h>
35#include <linux/i2c-algo-bit.h>
36
37#include <asm/io.h>
38
39#include "intelfb.h"
40#include "intelfbhw.h"
41
42
43#define SCL_DIR_MASK 0x0001
44#define SCL_DIR 0x0002
45#define SCL_VAL_MASK 0x0004
46#define SCL_VAL_OUT 0x0008
47#define SCL_VAL_IN 0x0010
48#define SDA_DIR_MASK 0x0100
49#define SDA_DIR 0x0200
50#define SDA_VAL_MASK 0x0400
51#define SDA_VAL_OUT 0x0800
52#define SDA_VAL_IN 0x1000
53
54static void intelfb_gpio_setscl(void *data, int state)
55{
56 struct intelfb_i2c_chan *chan = data;
57 struct intelfb_info *dinfo = chan->dinfo;
58 u32 val;
59
60 OUTREG(chan->reg, (state ? SCL_VAL_OUT : 0) |
61 SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK);
62 val = INREG(chan->reg);
63}
64
65static void intelfb_gpio_setsda(void *data, int state)
66{
67 struct intelfb_i2c_chan *chan = data;
68 struct intelfb_info *dinfo = chan->dinfo;
69 u32 val;
70
71 OUTREG(chan->reg, (state ? SDA_VAL_OUT : 0) |
72 SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK);
73 val = INREG(chan->reg);
74}
75
76static int intelfb_gpio_getscl(void *data)
77{
78 struct intelfb_i2c_chan *chan = data;
79 struct intelfb_info *dinfo = chan->dinfo;
80 u32 val;
81
82 OUTREG(chan->reg, SCL_DIR_MASK);
83 OUTREG(chan->reg, 0);
84 val = INREG(chan->reg);
85 return ((val & SCL_VAL_IN) != 0);
86}
87
88static int intelfb_gpio_getsda(void *data)
89{
90 struct intelfb_i2c_chan *chan = data;
91 struct intelfb_info *dinfo = chan->dinfo;
92 u32 val;
93
94 OUTREG(chan->reg, SDA_DIR_MASK);
95 OUTREG(chan->reg, 0);
96 val = INREG(chan->reg);
97 return ((val & SDA_VAL_IN) != 0);
98}
99
100static int intelfb_setup_i2c_bus(struct intelfb_info *dinfo,
101 struct intelfb_i2c_chan *chan,
102 const u32 reg, const char *name,
103 int class)
104{
105 int rc;
106
107 chan->dinfo = dinfo;
108 chan->reg = reg;
109 snprintf(chan->adapter.name, sizeof(chan->adapter.name),
110 "intelfb %s", name);
111 chan->adapter.class = class;
112 chan->adapter.owner = THIS_MODULE;
113 chan->adapter.algo_data = &chan->algo;
114 chan->adapter.dev.parent = &chan->dinfo->pdev->dev;
115 chan->algo.setsda = intelfb_gpio_setsda;
116 chan->algo.setscl = intelfb_gpio_setscl;
117 chan->algo.getsda = intelfb_gpio_getsda;
118 chan->algo.getscl = intelfb_gpio_getscl;
119 chan->algo.udelay = 40;
120 chan->algo.timeout = 20;
121 chan->algo.data = chan;
122
123 i2c_set_adapdata(&chan->adapter, chan);
124
125
126 intelfb_gpio_setsda(chan, 1);
127 intelfb_gpio_setscl(chan, 1);
128 udelay(20);
129
130 rc = i2c_bit_add_bus(&chan->adapter);
131 if (rc == 0)
132 DBG_MSG("I2C bus %s registered.\n", name);
133 else
134 WRN_MSG("Failed to register I2C bus %s.\n", name);
135 return rc;
136}
137
138void intelfb_create_i2c_busses(struct intelfb_info *dinfo)
139{
140 int i = 0;
141
142
143 dinfo->num_outputs = 1;
144 dinfo->output[i].type = INTELFB_OUTPUT_ANALOG;
145
146
147 intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].ddc_bus, GPIOA,
148 "CRTDDC_A", I2C_CLASS_DDC);
149 i++;
150
151
152
153
154
155 switch(dinfo->chipset) {
156 case INTEL_830M:
157 case INTEL_845G:
158 case INTEL_854:
159 case INTEL_855GM:
160 case INTEL_865G:
161 dinfo->output[i].type = INTELFB_OUTPUT_DVO;
162 intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].ddc_bus,
163 GPIOD, "DVODDC_D", I2C_CLASS_DDC);
164 intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].i2c_bus,
165 GPIOE, "DVOI2C_E", 0);
166 i++;
167 break;
168 case INTEL_915G:
169 case INTEL_915GM:
170
171 case INTEL_945G:
172 case INTEL_945GM:
173 case INTEL_945GME:
174 case INTEL_965G:
175 case INTEL_965GM:
176
177 dinfo->output[i].type = INTELFB_OUTPUT_SDVO;
178 intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].i2c_bus,
179 GPIOE, "SDVOCTRL_E", 0);
180
181
182 i++;
183
184
185 dinfo->output[i].type = INTELFB_OUTPUT_SDVO;
186 dinfo->output[i].i2c_bus = dinfo->output[i - 1].i2c_bus;
187
188
189 i++;
190 break;
191 }
192 dinfo->num_outputs = i;
193}
194
195void intelfb_delete_i2c_busses(struct intelfb_info *dinfo)
196{
197 int i;
198
199 for (i = 0; i < MAX_OUTPUTS; i++) {
200 if (dinfo->output[i].i2c_bus.dinfo) {
201 i2c_del_adapter(&dinfo->output[i].i2c_bus.adapter);
202 dinfo->output[i].i2c_bus.dinfo = NULL;
203 }
204 if (dinfo->output[i].ddc_bus.dinfo) {
205 i2c_del_adapter(&dinfo->output[i].ddc_bus.adapter);
206 dinfo->output[i].ddc_bus.dinfo = NULL;
207 }
208 }
209}
210