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