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
29#include "dvo.h"
30
31#define SIL164_VID 0x0001
32#define SIL164_DID 0x0006
33
34#define SIL164_VID_LO 0x00
35#define SIL164_VID_HI 0x01
36#define SIL164_DID_LO 0x02
37#define SIL164_DID_HI 0x03
38#define SIL164_REV 0x04
39#define SIL164_RSVD 0x05
40#define SIL164_FREQ_LO 0x06
41#define SIL164_FREQ_HI 0x07
42
43#define SIL164_REG8 0x08
44#define SIL164_8_VEN (1<<5)
45#define SIL164_8_HEN (1<<4)
46#define SIL164_8_DSEL (1<<3)
47#define SIL164_8_BSEL (1<<2)
48#define SIL164_8_EDGE (1<<1)
49#define SIL164_8_PD (1<<0)
50
51#define SIL164_REG9 0x09
52#define SIL164_9_VLOW (1<<7)
53#define SIL164_9_MSEL_MASK (0x7<<4)
54#define SIL164_9_TSEL (1<<3)
55#define SIL164_9_RSEN (1<<2)
56#define SIL164_9_HTPLG (1<<1)
57#define SIL164_9_MDI (1<<0)
58
59#define SIL164_REGC 0x0c
60
61struct sil164_priv {
62
63 bool quiet;
64};
65
66#define SILPTR(d) ((SIL164Ptr)(d->DriverPrivate.ptr))
67
68static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
69{
70 struct sil164_priv *sil = dvo->dev_priv;
71 struct i2c_adapter *adapter = dvo->i2c_bus;
72 u8 out_buf[2];
73 u8 in_buf[2];
74
75 struct i2c_msg msgs[] = {
76 {
77 .addr = dvo->slave_addr,
78 .flags = 0,
79 .len = 1,
80 .buf = out_buf,
81 },
82 {
83 .addr = dvo->slave_addr,
84 .flags = I2C_M_RD,
85 .len = 1,
86 .buf = in_buf,
87 }
88 };
89
90 out_buf[0] = addr;
91 out_buf[1] = 0;
92
93 if (i2c_transfer(adapter, msgs, 2) == 2) {
94 *ch = in_buf[0];
95 return true;
96 }
97
98 if (!sil->quiet) {
99 DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n",
100 addr, adapter->name, dvo->slave_addr);
101 }
102 return false;
103}
104
105static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
106{
107 struct sil164_priv *sil = dvo->dev_priv;
108 struct i2c_adapter *adapter = dvo->i2c_bus;
109 uint8_t out_buf[2];
110 struct i2c_msg msg = {
111 .addr = dvo->slave_addr,
112 .flags = 0,
113 .len = 2,
114 .buf = out_buf,
115 };
116
117 out_buf[0] = addr;
118 out_buf[1] = ch;
119
120 if (i2c_transfer(adapter, &msg, 1) == 1)
121 return true;
122
123 if (!sil->quiet) {
124 DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n",
125 addr, adapter->name, dvo->slave_addr);
126 }
127
128 return false;
129}
130
131
132static bool sil164_init(struct intel_dvo_device *dvo,
133 struct i2c_adapter *adapter)
134{
135
136 struct sil164_priv *sil;
137 unsigned char ch;
138
139 sil = kzalloc(sizeof(struct sil164_priv), GFP_KERNEL);
140 if (sil == NULL)
141 return false;
142
143 dvo->i2c_bus = adapter;
144 dvo->dev_priv = sil;
145 sil->quiet = true;
146
147 if (!sil164_readb(dvo, SIL164_VID_LO, &ch))
148 goto out;
149
150 if (ch != (SIL164_VID & 0xff)) {
151 DRM_DEBUG_KMS("sil164 not detected got %d: from %s Slave %d.\n",
152 ch, adapter->name, dvo->slave_addr);
153 goto out;
154 }
155
156 if (!sil164_readb(dvo, SIL164_DID_LO, &ch))
157 goto out;
158
159 if (ch != (SIL164_DID & 0xff)) {
160 DRM_DEBUG_KMS("sil164 not detected got %d: from %s Slave %d.\n",
161 ch, adapter->name, dvo->slave_addr);
162 goto out;
163 }
164 sil->quiet = false;
165
166 DRM_DEBUG_KMS("init sil164 dvo controller successfully!\n");
167 return true;
168
169out:
170 kfree(sil);
171 return false;
172}
173
174static enum drm_connector_status sil164_detect(struct intel_dvo_device *dvo)
175{
176 uint8_t reg9;
177
178 sil164_readb(dvo, SIL164_REG9, ®9);
179
180 if (reg9 & SIL164_9_HTPLG)
181 return connector_status_connected;
182 else
183 return connector_status_disconnected;
184}
185
186static enum drm_mode_status sil164_mode_valid(struct intel_dvo_device *dvo,
187 struct drm_display_mode *mode)
188{
189 return MODE_OK;
190}
191
192static void sil164_mode_set(struct intel_dvo_device *dvo,
193 struct drm_display_mode *mode,
194 struct drm_display_mode *adjusted_mode)
195{
196
197
198
199
200
201
202
203
204
205
206
207 return;
208}
209
210
211static void sil164_dpms(struct intel_dvo_device *dvo, bool enable)
212{
213 int ret;
214 unsigned char ch;
215
216 ret = sil164_readb(dvo, SIL164_REG8, &ch);
217 if (ret == false)
218 return;
219
220 if (enable)
221 ch |= SIL164_8_PD;
222 else
223 ch &= ~SIL164_8_PD;
224
225 sil164_writeb(dvo, SIL164_REG8, ch);
226 return;
227}
228
229static bool sil164_get_hw_state(struct intel_dvo_device *dvo)
230{
231 int ret;
232 unsigned char ch;
233
234 ret = sil164_readb(dvo, SIL164_REG8, &ch);
235 if (ret == false)
236 return false;
237
238 if (ch & SIL164_8_PD)
239 return true;
240 else
241 return false;
242}
243
244static void sil164_dump_regs(struct intel_dvo_device *dvo)
245{
246 uint8_t val;
247
248 sil164_readb(dvo, SIL164_FREQ_LO, &val);
249 DRM_DEBUG_KMS("SIL164_FREQ_LO: 0x%02x\n", val);
250 sil164_readb(dvo, SIL164_FREQ_HI, &val);
251 DRM_DEBUG_KMS("SIL164_FREQ_HI: 0x%02x\n", val);
252 sil164_readb(dvo, SIL164_REG8, &val);
253 DRM_DEBUG_KMS("SIL164_REG8: 0x%02x\n", val);
254 sil164_readb(dvo, SIL164_REG9, &val);
255 DRM_DEBUG_KMS("SIL164_REG9: 0x%02x\n", val);
256 sil164_readb(dvo, SIL164_REGC, &val);
257 DRM_DEBUG_KMS("SIL164_REGC: 0x%02x\n", val);
258}
259
260static void sil164_destroy(struct intel_dvo_device *dvo)
261{
262 struct sil164_priv *sil = dvo->dev_priv;
263
264 if (sil) {
265 kfree(sil);
266 dvo->dev_priv = NULL;
267 }
268}
269
270struct intel_dvo_dev_ops sil164_ops = {
271 .init = sil164_init,
272 .detect = sil164_detect,
273 .mode_valid = sil164_mode_valid,
274 .mode_set = sil164_mode_set,
275 .dpms = sil164_dpms,
276 .get_hw_state = sil164_get_hw_state,
277 .dump_regs = sil164_dump_regs,
278 .destroy = sil164_destroy,
279};
280