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