Branch data Line data Source code
1 : : /**************************************************************************
2 : :
3 : : Copyright © 2006 Dave Airlie
4 : :
5 : : All Rights Reserved.
6 : :
7 : : Permission is hereby granted, free of charge, to any person obtaining a
8 : : copy of this software and associated documentation files (the
9 : : "Software"), to deal in the Software without restriction, including
10 : : without limitation the rights to use, copy, modify, merge, publish,
11 : : distribute, sub license, and/or sell copies of the Software, and to
12 : : permit persons to whom the Software is furnished to do so, subject to
13 : : the following conditions:
14 : :
15 : : The above copyright notice and this permission notice (including the
16 : : next paragraph) shall be included in all copies or substantial portions
17 : : of the Software.
18 : :
19 : : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 : : OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 : : MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22 : : IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
23 : : ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 : : TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 : : SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
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 : :
62 : : struct sil164_priv {
63 : : //I2CDevRec d;
64 : : bool quiet;
65 : : };
66 : :
67 : : #define SILPTR(d) ((SIL164Ptr)(d->DriverPrivate.ptr))
68 : :
69 : 0 : static bool sil164_readb(struct intel_dvo_device *dvo, int addr, u8 *ch)
70 : : {
71 : 0 : struct sil164_priv *sil = dvo->dev_priv;
72 : 0 : struct i2c_adapter *adapter = dvo->i2c_bus;
73 : 0 : u8 out_buf[2];
74 : 0 : u8 in_buf[2];
75 : :
76 : 0 : struct i2c_msg msgs[] = {
77 : : {
78 : 0 : .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 : 0 : out_buf[0] = addr;
92 : 0 : out_buf[1] = 0;
93 : :
94 [ # # ]: 0 : if (i2c_transfer(adapter, msgs, 2) == 2) {
95 : 0 : *ch = in_buf[0];
96 : 0 : return true;
97 : : }
98 : :
99 [ # # ]: 0 : if (!sil->quiet) {
100 : 0 : 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 : :
106 : 0 : static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, u8 ch)
107 : : {
108 : 0 : struct sil164_priv *sil = dvo->dev_priv;
109 : 0 : struct i2c_adapter *adapter = dvo->i2c_bus;
110 : 0 : u8 out_buf[2];
111 : 0 : struct i2c_msg msg = {
112 : 0 : .addr = dvo->slave_addr,
113 : : .flags = 0,
114 : : .len = 2,
115 : : .buf = out_buf,
116 : : };
117 : :
118 : 0 : out_buf[0] = addr;
119 : 0 : out_buf[1] = ch;
120 : :
121 [ # # ]: 0 : if (i2c_transfer(adapter, &msg, 1) == 1)
122 : : return true;
123 : :
124 [ # # ]: 0 : if (!sil->quiet) {
125 : 0 : 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 : : /* Silicon Image 164 driver for chip on i2c bus */
133 : 0 : static bool sil164_init(struct intel_dvo_device *dvo,
134 : : struct i2c_adapter *adapter)
135 : : {
136 : : /* this will detect the SIL164 chip on the specified i2c bus */
137 : 0 : struct sil164_priv *sil;
138 : 0 : unsigned char ch;
139 : :
140 : 0 : sil = kzalloc(sizeof(struct sil164_priv), GFP_KERNEL);
141 [ # # ]: 0 : if (sil == NULL)
142 : : return false;
143 : :
144 : 0 : dvo->i2c_bus = adapter;
145 : 0 : dvo->dev_priv = sil;
146 : 0 : sil->quiet = true;
147 : :
148 [ # # ]: 0 : if (!sil164_readb(dvo, SIL164_VID_LO, &ch))
149 : 0 : goto out;
150 : :
151 [ # # ]: 0 : if (ch != (SIL164_VID & 0xff)) {
152 : 0 : DRM_DEBUG_KMS("sil164 not detected got %d: from %s Slave %d.\n",
153 : : ch, adapter->name, dvo->slave_addr);
154 : 0 : goto out;
155 : : }
156 : :
157 [ # # ]: 0 : if (!sil164_readb(dvo, SIL164_DID_LO, &ch))
158 : 0 : goto out;
159 : :
160 [ # # ]: 0 : if (ch != (SIL164_DID & 0xff)) {
161 : 0 : DRM_DEBUG_KMS("sil164 not detected got %d: from %s Slave %d.\n",
162 : : ch, adapter->name, dvo->slave_addr);
163 : 0 : goto out;
164 : : }
165 : 0 : sil->quiet = false;
166 : :
167 : 0 : DRM_DEBUG_KMS("init sil164 dvo controller successfully!\n");
168 : 0 : return true;
169 : :
170 : 0 : out:
171 : 0 : kfree(sil);
172 : 0 : return false;
173 : : }
174 : :
175 : 0 : static enum drm_connector_status sil164_detect(struct intel_dvo_device *dvo)
176 : : {
177 : 0 : u8 reg9;
178 : :
179 : 0 : sil164_readb(dvo, SIL164_REG9, ®9);
180 : :
181 [ # # ]: 0 : if (reg9 & SIL164_9_HTPLG)
182 : : return connector_status_connected;
183 : : else
184 : 0 : return connector_status_disconnected;
185 : : }
186 : :
187 : 0 : static enum drm_mode_status sil164_mode_valid(struct intel_dvo_device *dvo,
188 : : struct drm_display_mode *mode)
189 : : {
190 : 0 : return MODE_OK;
191 : : }
192 : :
193 : 0 : static 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 : : /* As long as the basics are set up, since we don't have clock
198 : : * dependencies in the mode setup, we can just leave the
199 : : * registers alone and everything will work fine.
200 : : */
201 : : /* recommended programming sequence from doc */
202 : : /*sil164_writeb(sil, 0x08, 0x30);
203 : : sil164_writeb(sil, 0x09, 0x00);
204 : : sil164_writeb(sil, 0x0a, 0x90);
205 : : sil164_writeb(sil, 0x0c, 0x89);
206 : : sil164_writeb(sil, 0x08, 0x31);*/
207 : : /* don't do much */
208 : 0 : return;
209 : : }
210 : :
211 : : /* set the SIL164 power state */
212 : 0 : static void sil164_dpms(struct intel_dvo_device *dvo, bool enable)
213 : : {
214 : 0 : int ret;
215 : 0 : unsigned char ch;
216 : :
217 : 0 : ret = sil164_readb(dvo, SIL164_REG8, &ch);
218 [ # # ]: 0 : if (ret == false)
219 : : return;
220 : :
221 [ # # ]: 0 : if (enable)
222 : 0 : ch |= SIL164_8_PD;
223 : : else
224 : 0 : ch &= ~SIL164_8_PD;
225 : :
226 : 0 : sil164_writeb(dvo, SIL164_REG8, ch);
227 : 0 : return;
228 : : }
229 : :
230 : 0 : static bool sil164_get_hw_state(struct intel_dvo_device *dvo)
231 : : {
232 : 0 : int ret;
233 : 0 : unsigned char ch;
234 : :
235 : 0 : ret = sil164_readb(dvo, SIL164_REG8, &ch);
236 [ # # ]: 0 : if (ret == false)
237 : : return false;
238 : :
239 [ # # ]: 0 : if (ch & SIL164_8_PD)
240 : : return true;
241 : : else
242 : 0 : return false;
243 : : }
244 : :
245 : 0 : static void sil164_dump_regs(struct intel_dvo_device *dvo)
246 : : {
247 : 0 : u8 val;
248 : :
249 : 0 : sil164_readb(dvo, SIL164_FREQ_LO, &val);
250 : 0 : DRM_DEBUG_KMS("SIL164_FREQ_LO: 0x%02x\n", val);
251 : 0 : sil164_readb(dvo, SIL164_FREQ_HI, &val);
252 : 0 : DRM_DEBUG_KMS("SIL164_FREQ_HI: 0x%02x\n", val);
253 : 0 : sil164_readb(dvo, SIL164_REG8, &val);
254 : 0 : DRM_DEBUG_KMS("SIL164_REG8: 0x%02x\n", val);
255 : 0 : sil164_readb(dvo, SIL164_REG9, &val);
256 : 0 : DRM_DEBUG_KMS("SIL164_REG9: 0x%02x\n", val);
257 : 0 : sil164_readb(dvo, SIL164_REGC, &val);
258 : 0 : DRM_DEBUG_KMS("SIL164_REGC: 0x%02x\n", val);
259 : 0 : }
260 : :
261 : 0 : static void sil164_destroy(struct intel_dvo_device *dvo)
262 : : {
263 : 0 : struct sil164_priv *sil = dvo->dev_priv;
264 : :
265 [ # # ]: 0 : if (sil) {
266 : 0 : kfree(sil);
267 : 0 : dvo->dev_priv = NULL;
268 : : }
269 : 0 : }
270 : :
271 : : const 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 : : };
|