Rev 6084 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2330 | Serge | 1 | /* |
2 | * Copyright 2006 Dave Airlie |
||
3 | * Copyright © 2006-2007 Intel Corporation |
||
4 | * |
||
5 | * Permission is hereby granted, free of charge, to any person obtaining a |
||
6 | * copy of this software and associated documentation files (the "Software"), |
||
7 | * to deal in the Software without restriction, including without limitation |
||
8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||
9 | * and/or sell copies of the Software, and to permit persons to whom the |
||
10 | * Software is furnished to do so, subject to the following conditions: |
||
11 | * |
||
12 | * The above copyright notice and this permission notice (including the next |
||
13 | * paragraph) shall be included in all copies or substantial portions of the |
||
14 | * Software. |
||
15 | * |
||
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||
19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||
21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||
22 | * DEALINGS IN THE SOFTWARE. |
||
23 | * |
||
24 | * Authors: |
||
25 | * Eric Anholt |
||
26 | */ |
||
27 | #include |
||
28 | #include |
||
3031 | serge | 29 | #include |
6084 | serge | 30 | #include |
3031 | serge | 31 | #include |
2330 | Serge | 32 | #include "intel_drv.h" |
3031 | serge | 33 | #include |
2330 | Serge | 34 | #include "i915_drv.h" |
35 | #include "dvo.h" |
||
36 | |||
37 | #define SIL164_ADDR 0x38 |
||
38 | #define CH7xxx_ADDR 0x76 |
||
39 | #define TFP410_ADDR 0x38 |
||
3031 | serge | 40 | #define NS2501_ADDR 0x38 |
2330 | Serge | 41 | |
42 | static const struct intel_dvo_device intel_dvo_devices[] = { |
||
43 | { |
||
44 | .type = INTEL_DVO_CHIP_TMDS, |
||
45 | .name = "sil164", |
||
46 | .dvo_reg = DVOC, |
||
6937 | serge | 47 | .dvo_srcdim_reg = DVOC_SRCDIM, |
2330 | Serge | 48 | .slave_addr = SIL164_ADDR, |
49 | .dev_ops = &sil164_ops, |
||
50 | }, |
||
51 | { |
||
52 | .type = INTEL_DVO_CHIP_TMDS, |
||
53 | .name = "ch7xxx", |
||
54 | .dvo_reg = DVOC, |
||
6937 | serge | 55 | .dvo_srcdim_reg = DVOC_SRCDIM, |
2330 | Serge | 56 | .slave_addr = CH7xxx_ADDR, |
57 | .dev_ops = &ch7xxx_ops, |
||
58 | }, |
||
59 | { |
||
4104 | Serge | 60 | .type = INTEL_DVO_CHIP_TMDS, |
61 | .name = "ch7xxx", |
||
62 | .dvo_reg = DVOC, |
||
6937 | serge | 63 | .dvo_srcdim_reg = DVOC_SRCDIM, |
4104 | Serge | 64 | .slave_addr = 0x75, /* For some ch7010 */ |
65 | .dev_ops = &ch7xxx_ops, |
||
66 | }, |
||
67 | { |
||
2330 | Serge | 68 | .type = INTEL_DVO_CHIP_LVDS, |
69 | .name = "ivch", |
||
70 | .dvo_reg = DVOA, |
||
6937 | serge | 71 | .dvo_srcdim_reg = DVOA_SRCDIM, |
2330 | Serge | 72 | .slave_addr = 0x02, /* Might also be 0x44, 0x84, 0xc4 */ |
73 | .dev_ops = &ivch_ops, |
||
74 | }, |
||
75 | { |
||
76 | .type = INTEL_DVO_CHIP_TMDS, |
||
77 | .name = "tfp410", |
||
78 | .dvo_reg = DVOC, |
||
6937 | serge | 79 | .dvo_srcdim_reg = DVOC_SRCDIM, |
2330 | Serge | 80 | .slave_addr = TFP410_ADDR, |
81 | .dev_ops = &tfp410_ops, |
||
82 | }, |
||
83 | { |
||
84 | .type = INTEL_DVO_CHIP_LVDS, |
||
85 | .name = "ch7017", |
||
86 | .dvo_reg = DVOC, |
||
6937 | serge | 87 | .dvo_srcdim_reg = DVOC_SRCDIM, |
2330 | Serge | 88 | .slave_addr = 0x75, |
6084 | serge | 89 | .gpio = GMBUS_PIN_DPB, |
2330 | Serge | 90 | .dev_ops = &ch7017_ops, |
3031 | serge | 91 | }, |
92 | { |
||
93 | .type = INTEL_DVO_CHIP_TMDS, |
||
94 | .name = "ns2501", |
||
5354 | serge | 95 | .dvo_reg = DVOB, |
6937 | serge | 96 | .dvo_srcdim_reg = DVOB_SRCDIM, |
3031 | serge | 97 | .slave_addr = NS2501_ADDR, |
98 | .dev_ops = &ns2501_ops, |
||
6084 | serge | 99 | } |
2330 | Serge | 100 | }; |
101 | |||
102 | struct intel_dvo { |
||
103 | struct intel_encoder base; |
||
104 | |||
105 | struct intel_dvo_device dev; |
||
106 | |||
6084 | serge | 107 | struct intel_connector *attached_connector; |
108 | |||
2330 | Serge | 109 | bool panel_wants_dither; |
110 | }; |
||
111 | |||
4104 | Serge | 112 | static struct intel_dvo *enc_to_dvo(struct intel_encoder *encoder) |
2330 | Serge | 113 | { |
4104 | Serge | 114 | return container_of(encoder, struct intel_dvo, base); |
2330 | Serge | 115 | } |
116 | |||
117 | static struct intel_dvo *intel_attached_dvo(struct drm_connector *connector) |
||
118 | { |
||
4104 | Serge | 119 | return enc_to_dvo(intel_attached_encoder(connector)); |
2330 | Serge | 120 | } |
121 | |||
3031 | serge | 122 | static bool intel_dvo_connector_get_hw_state(struct intel_connector *connector) |
2330 | Serge | 123 | { |
5060 | serge | 124 | struct drm_device *dev = connector->base.dev; |
125 | struct drm_i915_private *dev_priv = dev->dev_private; |
||
3031 | serge | 126 | struct intel_dvo *intel_dvo = intel_attached_dvo(&connector->base); |
5060 | serge | 127 | u32 tmp; |
3031 | serge | 128 | |
5060 | serge | 129 | tmp = I915_READ(intel_dvo->dev.dvo_reg); |
130 | |||
131 | if (!(tmp & DVO_ENABLE)) |
||
132 | return false; |
||
133 | |||
3031 | serge | 134 | return intel_dvo->dev.dev_ops->get_hw_state(&intel_dvo->dev); |
135 | } |
||
136 | |||
137 | static bool intel_dvo_get_hw_state(struct intel_encoder *encoder, |
||
138 | enum pipe *pipe) |
||
139 | { |
||
140 | struct drm_device *dev = encoder->base.dev; |
||
141 | struct drm_i915_private *dev_priv = dev->dev_private; |
||
4104 | Serge | 142 | struct intel_dvo *intel_dvo = enc_to_dvo(encoder); |
3031 | serge | 143 | u32 tmp; |
144 | |||
145 | tmp = I915_READ(intel_dvo->dev.dvo_reg); |
||
146 | |||
147 | if (!(tmp & DVO_ENABLE)) |
||
148 | return false; |
||
149 | |||
150 | *pipe = PORT_TO_PIPE(tmp); |
||
151 | |||
152 | return true; |
||
153 | } |
||
154 | |||
4104 | Serge | 155 | static void intel_dvo_get_config(struct intel_encoder *encoder, |
6084 | serge | 156 | struct intel_crtc_state *pipe_config) |
4104 | Serge | 157 | { |
158 | struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; |
||
159 | struct intel_dvo *intel_dvo = enc_to_dvo(encoder); |
||
160 | u32 tmp, flags = 0; |
||
161 | |||
162 | tmp = I915_READ(intel_dvo->dev.dvo_reg); |
||
163 | if (tmp & DVO_HSYNC_ACTIVE_HIGH) |
||
164 | flags |= DRM_MODE_FLAG_PHSYNC; |
||
165 | else |
||
166 | flags |= DRM_MODE_FLAG_NHSYNC; |
||
167 | if (tmp & DVO_VSYNC_ACTIVE_HIGH) |
||
168 | flags |= DRM_MODE_FLAG_PVSYNC; |
||
169 | else |
||
170 | flags |= DRM_MODE_FLAG_NVSYNC; |
||
171 | |||
6084 | serge | 172 | pipe_config->base.adjusted_mode.flags |= flags; |
4560 | Serge | 173 | |
6084 | serge | 174 | pipe_config->base.adjusted_mode.crtc_clock = pipe_config->port_clock; |
4104 | Serge | 175 | } |
176 | |||
3031 | serge | 177 | static void intel_disable_dvo(struct intel_encoder *encoder) |
178 | { |
||
179 | struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; |
||
4104 | Serge | 180 | struct intel_dvo *intel_dvo = enc_to_dvo(encoder); |
6937 | serge | 181 | i915_reg_t dvo_reg = intel_dvo->dev.dvo_reg; |
2330 | Serge | 182 | u32 temp = I915_READ(dvo_reg); |
183 | |||
3031 | serge | 184 | intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, false); |
185 | I915_WRITE(dvo_reg, temp & ~DVO_ENABLE); |
||
186 | I915_READ(dvo_reg); |
||
187 | } |
||
188 | |||
189 | static void intel_enable_dvo(struct intel_encoder *encoder) |
||
190 | { |
||
191 | struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; |
||
4104 | Serge | 192 | struct intel_dvo *intel_dvo = enc_to_dvo(encoder); |
4398 | Serge | 193 | struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); |
6937 | serge | 194 | i915_reg_t dvo_reg = intel_dvo->dev.dvo_reg; |
3031 | serge | 195 | u32 temp = I915_READ(dvo_reg); |
196 | |||
4398 | Serge | 197 | intel_dvo->dev.dev_ops->mode_set(&intel_dvo->dev, |
6084 | serge | 198 | &crtc->config->base.mode, |
199 | &crtc->config->base.adjusted_mode); |
||
4398 | Serge | 200 | |
5354 | serge | 201 | I915_WRITE(dvo_reg, temp | DVO_ENABLE); |
202 | I915_READ(dvo_reg); |
||
203 | |||
3031 | serge | 204 | intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, true); |
205 | } |
||
206 | |||
4560 | Serge | 207 | static enum drm_mode_status |
208 | intel_dvo_mode_valid(struct drm_connector *connector, |
||
6084 | serge | 209 | struct drm_display_mode *mode) |
2330 | Serge | 210 | { |
211 | struct intel_dvo *intel_dvo = intel_attached_dvo(connector); |
||
6084 | serge | 212 | const struct drm_display_mode *fixed_mode = |
213 | to_intel_connector(connector)->panel.fixed_mode; |
||
214 | int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; |
||
215 | int target_clock = mode->clock; |
||
2330 | Serge | 216 | |
217 | if (mode->flags & DRM_MODE_FLAG_DBLSCAN) |
||
218 | return MODE_NO_DBLESCAN; |
||
219 | |||
220 | /* XXX: Validate clock range */ |
||
221 | |||
6084 | serge | 222 | if (fixed_mode) { |
223 | if (mode->hdisplay > fixed_mode->hdisplay) |
||
2330 | Serge | 224 | return MODE_PANEL; |
6084 | serge | 225 | if (mode->vdisplay > fixed_mode->vdisplay) |
2330 | Serge | 226 | return MODE_PANEL; |
6084 | serge | 227 | |
228 | target_clock = fixed_mode->clock; |
||
2330 | Serge | 229 | } |
230 | |||
6084 | serge | 231 | if (target_clock > max_dotclk) |
232 | return MODE_CLOCK_HIGH; |
||
233 | |||
2330 | Serge | 234 | return intel_dvo->dev.dev_ops->mode_valid(&intel_dvo->dev, mode); |
235 | } |
||
236 | |||
4104 | Serge | 237 | static bool intel_dvo_compute_config(struct intel_encoder *encoder, |
6084 | serge | 238 | struct intel_crtc_state *pipe_config) |
2330 | Serge | 239 | { |
4104 | Serge | 240 | struct intel_dvo *intel_dvo = enc_to_dvo(encoder); |
6084 | serge | 241 | const struct drm_display_mode *fixed_mode = |
242 | intel_dvo->attached_connector->panel.fixed_mode; |
||
243 | struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; |
||
2330 | Serge | 244 | |
245 | /* If we have timings from the BIOS for the panel, put them in |
||
246 | * to the adjusted mode. The CRTC will be set up for this mode, |
||
247 | * with the panel scaling set up to source from the H/VDisplay |
||
248 | * of the original mode. |
||
249 | */ |
||
6084 | serge | 250 | if (fixed_mode) |
251 | intel_fixed_panel_mode(fixed_mode, adjusted_mode); |
||
4104 | Serge | 252 | |
2330 | Serge | 253 | return true; |
254 | } |
||
255 | |||
5060 | serge | 256 | static void intel_dvo_pre_enable(struct intel_encoder *encoder) |
2330 | Serge | 257 | { |
4104 | Serge | 258 | struct drm_device *dev = encoder->base.dev; |
2330 | Serge | 259 | struct drm_i915_private *dev_priv = dev->dev_private; |
4104 | Serge | 260 | struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); |
6084 | serge | 261 | const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode; |
4104 | Serge | 262 | struct intel_dvo *intel_dvo = enc_to_dvo(encoder); |
263 | int pipe = crtc->pipe; |
||
2330 | Serge | 264 | u32 dvo_val; |
6937 | serge | 265 | i915_reg_t dvo_reg = intel_dvo->dev.dvo_reg; |
266 | i915_reg_t dvo_srcdim_reg = intel_dvo->dev.dvo_srcdim_reg; |
||
2330 | Serge | 267 | |
268 | /* Save the data order, since I don't know what it should be set to. */ |
||
269 | dvo_val = I915_READ(dvo_reg) & |
||
270 | (DVO_PRESERVE_MASK | DVO_DATA_ORDER_GBRG); |
||
271 | dvo_val |= DVO_DATA_ORDER_FP | DVO_BORDER_ENABLE | |
||
272 | DVO_BLANK_ACTIVE_HIGH; |
||
273 | |||
274 | if (pipe == 1) |
||
275 | dvo_val |= DVO_PIPE_B_SELECT; |
||
276 | dvo_val |= DVO_PIPE_STALL; |
||
277 | if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) |
||
278 | dvo_val |= DVO_HSYNC_ACTIVE_HIGH; |
||
279 | if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) |
||
280 | dvo_val |= DVO_VSYNC_ACTIVE_HIGH; |
||
281 | |||
282 | /*I915_WRITE(DVOB_SRCDIM, |
||
6084 | serge | 283 | (adjusted_mode->crtc_hdisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) | |
284 | (adjusted_mode->crtc_vdisplay << DVO_SRCDIM_VERTICAL_SHIFT));*/ |
||
2330 | Serge | 285 | I915_WRITE(dvo_srcdim_reg, |
6084 | serge | 286 | (adjusted_mode->crtc_hdisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) | |
287 | (adjusted_mode->crtc_vdisplay << DVO_SRCDIM_VERTICAL_SHIFT)); |
||
2330 | Serge | 288 | /*I915_WRITE(DVOB, dvo_val);*/ |
289 | I915_WRITE(dvo_reg, dvo_val); |
||
290 | } |
||
291 | |||
292 | /** |
||
293 | * Detect the output connection on our DVO device. |
||
294 | * |
||
295 | * Unimplemented. |
||
296 | */ |
||
297 | static enum drm_connector_status |
||
298 | intel_dvo_detect(struct drm_connector *connector, bool force) |
||
299 | { |
||
300 | struct intel_dvo *intel_dvo = intel_attached_dvo(connector); |
||
4104 | Serge | 301 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", |
5060 | serge | 302 | connector->base.id, connector->name); |
2330 | Serge | 303 | return intel_dvo->dev.dev_ops->detect(&intel_dvo->dev); |
304 | } |
||
305 | |||
306 | static int intel_dvo_get_modes(struct drm_connector *connector) |
||
307 | { |
||
308 | struct drm_i915_private *dev_priv = connector->dev->dev_private; |
||
6084 | serge | 309 | const struct drm_display_mode *fixed_mode = |
310 | to_intel_connector(connector)->panel.fixed_mode; |
||
2330 | Serge | 311 | |
312 | /* We should probably have an i2c driver get_modes function for those |
||
313 | * devices which will have a fixed set of modes determined by the chip |
||
314 | * (TV-out, for example), but for now with just TMDS and LVDS, |
||
315 | * that's not the case. |
||
316 | */ |
||
317 | intel_ddc_get_modes(connector, |
||
6084 | serge | 318 | intel_gmbus_get_adapter(dev_priv, GMBUS_PIN_DPC)); |
2330 | Serge | 319 | if (!list_empty(&connector->probed_modes)) |
320 | return 1; |
||
321 | |||
6084 | serge | 322 | if (fixed_mode) { |
2330 | Serge | 323 | struct drm_display_mode *mode; |
6084 | serge | 324 | mode = drm_mode_duplicate(connector->dev, fixed_mode); |
2330 | Serge | 325 | if (mode) { |
326 | drm_mode_probed_add(connector, mode); |
||
327 | return 1; |
||
328 | } |
||
329 | } |
||
330 | |||
331 | return 0; |
||
332 | } |
||
333 | |||
334 | static void intel_dvo_destroy(struct drm_connector *connector) |
||
335 | { |
||
336 | drm_connector_cleanup(connector); |
||
6084 | serge | 337 | intel_panel_fini(&to_intel_connector(connector)->panel); |
2330 | Serge | 338 | kfree(connector); |
339 | } |
||
340 | |||
341 | static const struct drm_connector_funcs intel_dvo_connector_funcs = { |
||
6084 | serge | 342 | .dpms = drm_atomic_helper_connector_dpms, |
2330 | Serge | 343 | .detect = intel_dvo_detect, |
344 | .destroy = intel_dvo_destroy, |
||
345 | .fill_modes = drm_helper_probe_single_connector_modes, |
||
6084 | serge | 346 | .atomic_get_property = intel_connector_atomic_get_property, |
347 | .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, |
||
348 | .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, |
||
2330 | Serge | 349 | }; |
350 | |||
351 | static const struct drm_connector_helper_funcs intel_dvo_connector_helper_funcs = { |
||
352 | .mode_valid = intel_dvo_mode_valid, |
||
353 | .get_modes = intel_dvo_get_modes, |
||
354 | .best_encoder = intel_best_encoder, |
||
355 | }; |
||
356 | |||
357 | static void intel_dvo_enc_destroy(struct drm_encoder *encoder) |
||
358 | { |
||
4104 | Serge | 359 | struct intel_dvo *intel_dvo = enc_to_dvo(to_intel_encoder(encoder)); |
2330 | Serge | 360 | |
361 | if (intel_dvo->dev.dev_ops->destroy) |
||
362 | intel_dvo->dev.dev_ops->destroy(&intel_dvo->dev); |
||
363 | |||
364 | intel_encoder_destroy(encoder); |
||
365 | } |
||
366 | |||
367 | static const struct drm_encoder_funcs intel_dvo_enc_funcs = { |
||
368 | .destroy = intel_dvo_enc_destroy, |
||
369 | }; |
||
370 | |||
371 | /** |
||
372 | * Attempts to get a fixed panel timing for LVDS (currently only the i830). |
||
373 | * |
||
374 | * Other chips with DVO LVDS will need to extend this to deal with the LVDS |
||
375 | * chip being on DVOB/C and having multiple pipes. |
||
376 | */ |
||
377 | static struct drm_display_mode * |
||
378 | intel_dvo_get_current_mode(struct drm_connector *connector) |
||
379 | { |
||
380 | struct drm_device *dev = connector->dev; |
||
381 | struct drm_i915_private *dev_priv = dev->dev_private; |
||
382 | struct intel_dvo *intel_dvo = intel_attached_dvo(connector); |
||
383 | uint32_t dvo_val = I915_READ(intel_dvo->dev.dvo_reg); |
||
384 | struct drm_display_mode *mode = NULL; |
||
385 | |||
386 | /* If the DVO port is active, that'll be the LVDS, so we can pull out |
||
387 | * its timings to get how the BIOS set up the panel. |
||
388 | */ |
||
389 | if (dvo_val & DVO_ENABLE) { |
||
390 | struct drm_crtc *crtc; |
||
391 | int pipe = (dvo_val & DVO_PIPE_B_SELECT) ? 1 : 0; |
||
392 | |||
393 | crtc = intel_get_crtc_for_pipe(dev, pipe); |
||
394 | if (crtc) { |
||
395 | mode = intel_crtc_mode_get(dev, crtc); |
||
396 | if (mode) { |
||
397 | mode->type |= DRM_MODE_TYPE_PREFERRED; |
||
398 | if (dvo_val & DVO_HSYNC_ACTIVE_HIGH) |
||
399 | mode->flags |= DRM_MODE_FLAG_PHSYNC; |
||
400 | if (dvo_val & DVO_VSYNC_ACTIVE_HIGH) |
||
401 | mode->flags |= DRM_MODE_FLAG_PVSYNC; |
||
402 | } |
||
403 | } |
||
404 | } |
||
405 | |||
406 | return mode; |
||
407 | } |
||
408 | |||
409 | void intel_dvo_init(struct drm_device *dev) |
||
410 | { |
||
411 | struct drm_i915_private *dev_priv = dev->dev_private; |
||
412 | struct intel_encoder *intel_encoder; |
||
413 | struct intel_dvo *intel_dvo; |
||
414 | struct intel_connector *intel_connector; |
||
415 | int i; |
||
416 | int encoder_type = DRM_MODE_ENCODER_NONE; |
||
417 | |||
4560 | Serge | 418 | intel_dvo = kzalloc(sizeof(*intel_dvo), GFP_KERNEL); |
2330 | Serge | 419 | if (!intel_dvo) |
420 | return; |
||
421 | |||
6084 | serge | 422 | intel_connector = intel_connector_alloc(); |
2330 | Serge | 423 | if (!intel_connector) { |
424 | kfree(intel_dvo); |
||
425 | return; |
||
426 | } |
||
427 | |||
6084 | serge | 428 | intel_dvo->attached_connector = intel_connector; |
429 | |||
2330 | Serge | 430 | intel_encoder = &intel_dvo->base; |
431 | drm_encoder_init(dev, &intel_encoder->base, |
||
6937 | serge | 432 | &intel_dvo_enc_funcs, encoder_type, NULL); |
2330 | Serge | 433 | |
3031 | serge | 434 | intel_encoder->disable = intel_disable_dvo; |
435 | intel_encoder->enable = intel_enable_dvo; |
||
436 | intel_encoder->get_hw_state = intel_dvo_get_hw_state; |
||
4104 | Serge | 437 | intel_encoder->get_config = intel_dvo_get_config; |
438 | intel_encoder->compute_config = intel_dvo_compute_config; |
||
5060 | serge | 439 | intel_encoder->pre_enable = intel_dvo_pre_enable; |
3031 | serge | 440 | intel_connector->get_hw_state = intel_dvo_connector_get_hw_state; |
5060 | serge | 441 | intel_connector->unregister = intel_connector_unregister; |
3031 | serge | 442 | |
2330 | Serge | 443 | /* Now, try to find a controller */ |
444 | for (i = 0; i < ARRAY_SIZE(intel_dvo_devices); i++) { |
||
445 | struct drm_connector *connector = &intel_connector->base; |
||
446 | const struct intel_dvo_device *dvo = &intel_dvo_devices[i]; |
||
447 | struct i2c_adapter *i2c; |
||
448 | int gpio; |
||
3746 | Serge | 449 | bool dvoinit; |
6084 | serge | 450 | enum pipe pipe; |
451 | uint32_t dpll[I915_MAX_PIPES]; |
||
2330 | Serge | 452 | |
453 | /* Allow the I2C driver info to specify the GPIO to be used in |
||
454 | * special cases, but otherwise default to what's defined |
||
455 | * in the spec. |
||
456 | */ |
||
6084 | serge | 457 | if (intel_gmbus_is_valid_pin(dev_priv, dvo->gpio)) |
2330 | Serge | 458 | gpio = dvo->gpio; |
459 | else if (dvo->type == INTEL_DVO_CHIP_LVDS) |
||
6084 | serge | 460 | gpio = GMBUS_PIN_SSC; |
2330 | Serge | 461 | else |
6084 | serge | 462 | gpio = GMBUS_PIN_DPB; |
2330 | Serge | 463 | |
464 | /* Set up the I2C bus necessary for the chip we're probing. |
||
465 | * It appears that everything is on GPIOE except for panels |
||
466 | * on i830 laptops, which are on GPIOB (DVOA). |
||
467 | */ |
||
3031 | serge | 468 | i2c = intel_gmbus_get_adapter(dev_priv, gpio); |
2330 | Serge | 469 | |
470 | intel_dvo->dev = *dvo; |
||
3746 | Serge | 471 | |
472 | /* GMBUS NAK handling seems to be unstable, hence let the |
||
473 | * transmitter detection run in bit banging mode for now. |
||
474 | */ |
||
475 | intel_gmbus_force_bit(i2c, true); |
||
476 | |||
6084 | serge | 477 | /* ns2501 requires the DVO 2x clock before it will |
478 | * respond to i2c accesses, so make sure we have |
||
479 | * have the clock enabled before we attempt to |
||
480 | * initialize the device. |
||
481 | */ |
||
482 | for_each_pipe(dev_priv, pipe) { |
||
483 | dpll[pipe] = I915_READ(DPLL(pipe)); |
||
484 | I915_WRITE(DPLL(pipe), dpll[pipe] | DPLL_DVO_2X_MODE); |
||
485 | } |
||
486 | |||
3746 | Serge | 487 | dvoinit = dvo->dev_ops->init(&intel_dvo->dev, i2c); |
488 | |||
6084 | serge | 489 | /* restore the DVO 2x clock state to original */ |
490 | for_each_pipe(dev_priv, pipe) { |
||
491 | I915_WRITE(DPLL(pipe), dpll[pipe]); |
||
492 | } |
||
493 | |||
3746 | Serge | 494 | intel_gmbus_force_bit(i2c, false); |
495 | |||
496 | if (!dvoinit) |
||
2330 | Serge | 497 | continue; |
498 | |||
499 | intel_encoder->type = INTEL_OUTPUT_DVO; |
||
500 | intel_encoder->crtc_mask = (1 << 0) | (1 << 1); |
||
501 | switch (dvo->type) { |
||
502 | case INTEL_DVO_CHIP_TMDS: |
||
5060 | serge | 503 | intel_encoder->cloneable = (1 << INTEL_OUTPUT_ANALOG) | |
504 | (1 << INTEL_OUTPUT_DVO); |
||
2330 | Serge | 505 | drm_connector_init(dev, connector, |
506 | &intel_dvo_connector_funcs, |
||
507 | DRM_MODE_CONNECTOR_DVII); |
||
508 | encoder_type = DRM_MODE_ENCODER_TMDS; |
||
509 | break; |
||
510 | case INTEL_DVO_CHIP_LVDS: |
||
5060 | serge | 511 | intel_encoder->cloneable = 0; |
2330 | Serge | 512 | drm_connector_init(dev, connector, |
513 | &intel_dvo_connector_funcs, |
||
514 | DRM_MODE_CONNECTOR_LVDS); |
||
515 | encoder_type = DRM_MODE_ENCODER_LVDS; |
||
516 | break; |
||
517 | } |
||
518 | |||
519 | drm_connector_helper_add(connector, |
||
520 | &intel_dvo_connector_helper_funcs); |
||
521 | connector->display_info.subpixel_order = SubPixelHorizontalRGB; |
||
522 | connector->interlace_allowed = false; |
||
523 | connector->doublescan_allowed = false; |
||
524 | |||
525 | intel_connector_attach_encoder(intel_connector, intel_encoder); |
||
526 | if (dvo->type == INTEL_DVO_CHIP_LVDS) { |
||
527 | /* For our LVDS chipsets, we should hopefully be able |
||
528 | * to dig the fixed panel mode out of the BIOS data. |
||
529 | * However, it's in a different format from the BIOS |
||
530 | * data on chipsets with integrated LVDS (stored in AIM |
||
531 | * headers, likely), so for now, just get the current |
||
532 | * mode being output through DVO. |
||
533 | */ |
||
6084 | serge | 534 | intel_panel_init(&intel_connector->panel, |
535 | intel_dvo_get_current_mode(connector), |
||
536 | NULL); |
||
2330 | Serge | 537 | intel_dvo->panel_wants_dither = true; |
538 | } |
||
539 | |||
5060 | serge | 540 | drm_connector_register(connector); |
2330 | Serge | 541 | return; |
542 | } |
||
543 | |||
544 | drm_encoder_cleanup(&intel_encoder->base); |
||
545 | kfree(intel_dvo); |
||
546 | kfree(intel_connector); |
||
547 | }><>><>><>><>>><>><>><>><> |