blob: 1dd52dbfad46041951c7dc9389cfc7933710e1a6 [file] [log] [blame]
Ben Skeggs6ee73862009-12-11 19:24:15 +10001/*
2 * Copyright (C) 2008 Maarten Maathuis.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 */
26
Ben Skeggsa1470892010-01-18 11:42:37 +100027#include <acpi/button.h>
28
Ben Skeggs6ee73862009-12-11 19:24:15 +100029#include "drmP.h"
30#include "drm_edid.h"
31#include "drm_crtc_helper.h"
Ben Skeggsa1470892010-01-18 11:42:37 +100032
Ben Skeggs6ee73862009-12-11 19:24:15 +100033#include "nouveau_reg.h"
34#include "nouveau_drv.h"
35#include "nouveau_encoder.h"
36#include "nouveau_crtc.h"
37#include "nouveau_connector.h"
38#include "nouveau_hw.h"
39
Ben Skeggs6ee73862009-12-11 19:24:15 +100040static struct nouveau_encoder *
41find_encoder_by_type(struct drm_connector *connector, int type)
42{
43 struct drm_device *dev = connector->dev;
44 struct nouveau_encoder *nv_encoder;
45 struct drm_mode_object *obj;
46 int i, id;
47
48 for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
49 id = connector->encoder_ids[i];
50 if (!id)
51 break;
52
53 obj = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_ENCODER);
54 if (!obj)
55 continue;
56 nv_encoder = nouveau_encoder(obj_to_encoder(obj));
57
58 if (type == OUTPUT_ANY || nv_encoder->dcb->type == type)
59 return nv_encoder;
60 }
61
62 return NULL;
63}
64
65struct nouveau_connector *
66nouveau_encoder_connector_get(struct nouveau_encoder *encoder)
67{
68 struct drm_device *dev = to_drm_encoder(encoder)->dev;
69 struct drm_connector *drm_connector;
70
71 list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head) {
72 if (drm_connector->encoder == to_drm_encoder(encoder))
73 return nouveau_connector(drm_connector);
74 }
75
76 return NULL;
77}
78
Ben Skeggs62acdc72010-09-28 10:23:20 +100079/*TODO: This could use improvement, and learn to handle the fixed
80 * BIOS tables etc. It's fine currently, for its only user.
81 */
82int
83nouveau_connector_bpp(struct drm_connector *connector)
84{
85 struct nouveau_connector *nv_connector = nouveau_connector(connector);
86
87 if (nv_connector->edid && nv_connector->edid->revision >= 4) {
88 u8 bpc = ((nv_connector->edid->input & 0x70) >> 3) + 4;
89 if (bpc > 4)
90 return bpc;
91 }
92
93 return 18;
94}
Ben Skeggs6ee73862009-12-11 19:24:15 +100095
96static void
97nouveau_connector_destroy(struct drm_connector *drm_connector)
98{
Xavier Chantryc8ebe272010-01-11 22:42:21 +010099 struct nouveau_connector *nv_connector =
100 nouveau_connector(drm_connector);
Marcin Slusarzdd19e442010-01-30 15:41:00 +0100101 struct drm_device *dev;
Ben Skeggs6ee73862009-12-11 19:24:15 +1000102
Xavier Chantryc8ebe272010-01-11 22:42:21 +0100103 if (!nv_connector)
Ben Skeggs6ee73862009-12-11 19:24:15 +1000104 return;
105
Marcin Slusarzdd19e442010-01-30 15:41:00 +0100106 dev = nv_connector->base.dev;
107 NV_DEBUG_KMS(dev, "\n");
108
Xavier Chantryc8ebe272010-01-11 22:42:21 +0100109 kfree(nv_connector->edid);
Ben Skeggs6ee73862009-12-11 19:24:15 +1000110 drm_sysfs_connector_remove(drm_connector);
111 drm_connector_cleanup(drm_connector);
112 kfree(drm_connector);
113}
114
Ben Skeggs6ee73862009-12-11 19:24:15 +1000115static struct nouveau_i2c_chan *
116nouveau_connector_ddc_detect(struct drm_connector *connector,
117 struct nouveau_encoder **pnv_encoder)
118{
119 struct drm_device *dev = connector->dev;
Francisco Jerez03cd06c2010-07-20 03:08:25 +0200120 int i;
Ben Skeggs6ee73862009-12-11 19:24:15 +1000121
Ben Skeggs6ee73862009-12-11 19:24:15 +1000122 for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
Francisco Jerez4ca2b712010-08-08 21:35:57 +0200123 struct nouveau_i2c_chan *i2c = NULL;
Ben Skeggs6ee73862009-12-11 19:24:15 +1000124 struct nouveau_encoder *nv_encoder;
125 struct drm_mode_object *obj;
126 int id;
127
128 id = connector->encoder_ids[i];
129 if (!id)
130 break;
131
132 obj = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_ENCODER);
133 if (!obj)
134 continue;
135 nv_encoder = nouveau_encoder(obj_to_encoder(obj));
Francisco Jerez4ca2b712010-08-08 21:35:57 +0200136
137 if (nv_encoder->dcb->i2c_index < 0xf)
138 i2c = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
Ben Skeggs6ee73862009-12-11 19:24:15 +1000139
Francisco Jerez03cd06c2010-07-20 03:08:25 +0200140 if (i2c && nouveau_probe_i2c_addr(i2c, 0x50)) {
Ben Skeggs6ee73862009-12-11 19:24:15 +1000141 *pnv_encoder = nv_encoder;
142 return i2c;
143 }
144 }
145
146 return NULL;
147}
148
Francisco Jerezc16c5702010-09-09 14:33:17 +0200149static struct nouveau_encoder *
150nouveau_connector_of_detect(struct drm_connector *connector)
151{
152#ifdef __powerpc__
153 struct drm_device *dev = connector->dev;
154 struct nouveau_connector *nv_connector = nouveau_connector(connector);
155 struct nouveau_encoder *nv_encoder;
156 struct device_node *cn, *dn = pci_device_to_OF_node(dev->pdev);
157
158 if (!dn ||
159 !((nv_encoder = find_encoder_by_type(connector, OUTPUT_TMDS)) ||
160 (nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG))))
161 return NULL;
162
163 for_each_child_of_node(dn, cn) {
164 const char *name = of_get_property(cn, "name", NULL);
165 const void *edid = of_get_property(cn, "EDID", NULL);
166 int idx = name ? name[strlen(name) - 1] - 'A' : 0;
167
168 if (nv_encoder->dcb->i2c_index == idx && edid) {
169 nv_connector->edid =
170 kmemdup(edid, EDID_LENGTH, GFP_KERNEL);
171 of_node_put(cn);
172 return nv_encoder;
173 }
174 }
175#endif
176 return NULL;
177}
178
Ben Skeggs6ee73862009-12-11 19:24:15 +1000179static void
180nouveau_connector_set_encoder(struct drm_connector *connector,
181 struct nouveau_encoder *nv_encoder)
182{
183 struct nouveau_connector *nv_connector = nouveau_connector(connector);
184 struct drm_nouveau_private *dev_priv = connector->dev->dev_private;
185 struct drm_device *dev = connector->dev;
186
187 if (nv_connector->detected_encoder == nv_encoder)
188 return;
189 nv_connector->detected_encoder = nv_encoder;
190
191 if (nv_encoder->dcb->type == OUTPUT_LVDS ||
192 nv_encoder->dcb->type == OUTPUT_TMDS) {
193 connector->doublescan_allowed = false;
194 connector->interlace_allowed = false;
195 } else {
196 connector->doublescan_allowed = true;
197 if (dev_priv->card_type == NV_20 ||
198 (dev_priv->card_type == NV_10 &&
199 (dev->pci_device & 0x0ff0) != 0x0100 &&
200 (dev->pci_device & 0x0ff0) != 0x0150))
201 /* HW is broken */
202 connector->interlace_allowed = false;
203 else
204 connector->interlace_allowed = true;
205 }
206
Ben Skeggsbe079e92010-02-24 14:01:40 +1000207 if (nv_connector->dcb->type == DCB_CONNECTOR_DVI_I) {
Ben Skeggs6ee73862009-12-11 19:24:15 +1000208 drm_connector_property_set_value(connector,
209 dev->mode_config.dvi_i_subconnector_property,
210 nv_encoder->dcb->type == OUTPUT_TMDS ?
211 DRM_MODE_SUBCONNECTOR_DVID :
212 DRM_MODE_SUBCONNECTOR_DVIA);
213 }
214}
215
Francisco Jerez01db3632010-10-21 17:43:08 +0200216static bool
217nouveau_connector_poll_allowed(struct drm_connector *connector)
218{
219 struct drm_device *dev = connector->dev;
220 struct drm_nouveau_private *dev_priv = dev->dev_private;
221 struct drm_crtc *crtc;
222 bool spare_crtc = false;
223
224 if (dev_priv->card_type >= NV_50) {
225 return true;
226 } else {
227 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
228 spare_crtc |= !crtc->enabled;
229
230 return spare_crtc;
231 }
232}
233
Ben Skeggs6ee73862009-12-11 19:24:15 +1000234static enum drm_connector_status
Chris Wilson930a9e22010-09-14 11:07:23 +0100235nouveau_connector_detect(struct drm_connector *connector, bool force)
Ben Skeggs6ee73862009-12-11 19:24:15 +1000236{
237 struct drm_device *dev = connector->dev;
238 struct nouveau_connector *nv_connector = nouveau_connector(connector);
239 struct nouveau_encoder *nv_encoder = NULL;
240 struct nouveau_i2c_chan *i2c;
Francisco Jerez03cd06c2010-07-20 03:08:25 +0200241 int type;
Ben Skeggs6ee73862009-12-11 19:24:15 +1000242
Francisco Jerezb8780e22010-01-14 15:54:23 +0100243 /* Cleanup the previous EDID block. */
244 if (nv_connector->edid) {
245 drm_mode_connector_update_edid_property(connector, NULL);
246 kfree(nv_connector->edid);
247 nv_connector->edid = NULL;
248 }
Xavier Chantryc8ebe272010-01-11 22:42:21 +0100249
Ben Skeggs6ee73862009-12-11 19:24:15 +1000250 i2c = nouveau_connector_ddc_detect(connector, &nv_encoder);
251 if (i2c) {
Ben Skeggs6ee73862009-12-11 19:24:15 +1000252 nv_connector->edid = drm_get_edid(connector, &i2c->adapter);
Ben Skeggs6ee73862009-12-11 19:24:15 +1000253 drm_mode_connector_update_edid_property(connector,
254 nv_connector->edid);
255 if (!nv_connector->edid) {
256 NV_ERROR(dev, "DDC responded, but no EDID for %s\n",
257 drm_get_connector_name(connector));
Francisco Jerez0ed31652010-01-14 15:47:03 +0100258 goto detect_analog;
Ben Skeggs6ee73862009-12-11 19:24:15 +1000259 }
260
261 if (nv_encoder->dcb->type == OUTPUT_DP &&
262 !nouveau_dp_detect(to_drm_encoder(nv_encoder))) {
263 NV_ERROR(dev, "Detected %s, but failed init\n",
264 drm_get_connector_name(connector));
265 return connector_status_disconnected;
266 }
267
268 /* Override encoder type for DVI-I based on whether EDID
269 * says the display is digital or analog, both use the
270 * same i2c channel so the value returned from ddc_detect
271 * isn't necessarily correct.
272 */
Ben Skeggsbe079e92010-02-24 14:01:40 +1000273 if (nv_connector->dcb->type == DCB_CONNECTOR_DVI_I) {
Ben Skeggs6ee73862009-12-11 19:24:15 +1000274 if (nv_connector->edid->input & DRM_EDID_INPUT_DIGITAL)
275 type = OUTPUT_TMDS;
276 else
277 type = OUTPUT_ANALOG;
278
279 nv_encoder = find_encoder_by_type(connector, type);
280 if (!nv_encoder) {
281 NV_ERROR(dev, "Detected %d encoder on %s, "
282 "but no object!\n", type,
283 drm_get_connector_name(connector));
284 return connector_status_disconnected;
285 }
286 }
287
288 nouveau_connector_set_encoder(connector, nv_encoder);
289 return connector_status_connected;
290 }
291
Francisco Jerezc16c5702010-09-09 14:33:17 +0200292 nv_encoder = nouveau_connector_of_detect(connector);
293 if (nv_encoder) {
294 nouveau_connector_set_encoder(connector, nv_encoder);
295 return connector_status_connected;
296 }
297
Francisco Jerez0ed31652010-01-14 15:47:03 +0100298detect_analog:
Ben Skeggs6ee73862009-12-11 19:24:15 +1000299 nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG);
Ben Skeggsf4053502010-03-15 09:43:51 +1000300 if (!nv_encoder && !nouveau_tv_disable)
Ben Skeggs6ee73862009-12-11 19:24:15 +1000301 nv_encoder = find_encoder_by_type(connector, OUTPUT_TV);
Francisco Jerez01db3632010-10-21 17:43:08 +0200302 if (nv_encoder &&
303 (force || nouveau_connector_poll_allowed(connector))) {
Ben Skeggs6ee73862009-12-11 19:24:15 +1000304 struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
305 struct drm_encoder_helper_funcs *helper =
306 encoder->helper_private;
307
308 if (helper->detect(encoder, connector) ==
309 connector_status_connected) {
310 nouveau_connector_set_encoder(connector, nv_encoder);
311 return connector_status_connected;
312 }
313
314 }
315
316 return connector_status_disconnected;
317}
318
Ben Skeggsd17f3952010-06-01 13:32:42 +1000319static enum drm_connector_status
Chris Wilson930a9e22010-09-14 11:07:23 +0100320nouveau_connector_detect_lvds(struct drm_connector *connector, bool force)
Ben Skeggsd17f3952010-06-01 13:32:42 +1000321{
322 struct drm_device *dev = connector->dev;
323 struct drm_nouveau_private *dev_priv = dev->dev_private;
324 struct nouveau_connector *nv_connector = nouveau_connector(connector);
325 struct nouveau_encoder *nv_encoder = NULL;
326 enum drm_connector_status status = connector_status_disconnected;
327
328 /* Cleanup the previous EDID block. */
329 if (nv_connector->edid) {
330 drm_mode_connector_update_edid_property(connector, NULL);
331 kfree(nv_connector->edid);
332 nv_connector->edid = NULL;
333 }
334
335 nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS);
336 if (!nv_encoder)
337 return connector_status_disconnected;
338
Ben Skeggsa6ed76d2010-07-12 15:33:07 +1000339 /* Try retrieving EDID via DDC */
Ben Skeggsd17f3952010-06-01 13:32:42 +1000340 if (!dev_priv->vbios.fp_no_ddc) {
Chris Wilson930a9e22010-09-14 11:07:23 +0100341 status = nouveau_connector_detect(connector, force);
Ben Skeggsd17f3952010-06-01 13:32:42 +1000342 if (status == connector_status_connected)
343 goto out;
344 }
345
Ben Skeggsa6ed76d2010-07-12 15:33:07 +1000346 /* On some laptops (Sony, i'm looking at you) there appears to
347 * be no direct way of accessing the panel's EDID. The only
348 * option available to us appears to be to ask ACPI for help..
349 *
350 * It's important this check's before trying straps, one of the
351 * said manufacturer's laptops are configured in such a way
352 * the nouveau decides an entry in the VBIOS FP mode table is
353 * valid - it's not (rh#613284)
354 */
355 if (nv_encoder->dcb->lvdsconf.use_acpi_for_edid) {
356 if (!nouveau_acpi_edid(dev, connector)) {
357 status = connector_status_connected;
358 goto out;
359 }
360 }
361
Ben Skeggsd17f3952010-06-01 13:32:42 +1000362 /* If no EDID found above, and the VBIOS indicates a hardcoded
363 * modeline is avalilable for the panel, set it as the panel's
364 * native mode and exit.
365 */
366 if (nouveau_bios_fp_mode(dev, NULL) && (dev_priv->vbios.fp_no_ddc ||
367 nv_encoder->dcb->lvdsconf.use_straps_for_mode)) {
368 status = connector_status_connected;
369 goto out;
370 }
371
372 /* Still nothing, some VBIOS images have a hardcoded EDID block
373 * stored for the panel stored in them.
374 */
375 if (!dev_priv->vbios.fp_no_ddc) {
376 struct edid *edid =
377 (struct edid *)nouveau_bios_embedded_edid(dev);
378 if (edid) {
379 nv_connector->edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
380 *(nv_connector->edid) = *edid;
381 status = connector_status_connected;
382 }
383 }
384
385out:
386#if defined(CONFIG_ACPI_BUTTON) || \
387 (defined(CONFIG_ACPI_BUTTON_MODULE) && defined(MODULE))
388 if (status == connector_status_connected &&
389 !nouveau_ignorelid && !acpi_lid_open())
390 status = connector_status_unknown;
391#endif
392
393 drm_mode_connector_update_edid_property(connector, nv_connector->edid);
Albert Damen3195c5f2010-06-20 16:57:57 +0200394 nouveau_connector_set_encoder(connector, nv_encoder);
Ben Skeggsd17f3952010-06-01 13:32:42 +1000395 return status;
396}
397
Ben Skeggs6ee73862009-12-11 19:24:15 +1000398static void
399nouveau_connector_force(struct drm_connector *connector)
400{
Ben Skeggsbe079e92010-02-24 14:01:40 +1000401 struct nouveau_connector *nv_connector = nouveau_connector(connector);
Ben Skeggs6ee73862009-12-11 19:24:15 +1000402 struct nouveau_encoder *nv_encoder;
403 int type;
404
Ben Skeggsbe079e92010-02-24 14:01:40 +1000405 if (nv_connector->dcb->type == DCB_CONNECTOR_DVI_I) {
Ben Skeggs6ee73862009-12-11 19:24:15 +1000406 if (connector->force == DRM_FORCE_ON_DIGITAL)
407 type = OUTPUT_TMDS;
408 else
409 type = OUTPUT_ANALOG;
410 } else
411 type = OUTPUT_ANY;
412
413 nv_encoder = find_encoder_by_type(connector, type);
414 if (!nv_encoder) {
Ben Skeggsbe079e92010-02-24 14:01:40 +1000415 NV_ERROR(connector->dev, "can't find encoder to force %s on!\n",
Ben Skeggs6ee73862009-12-11 19:24:15 +1000416 drm_get_connector_name(connector));
417 connector->status = connector_status_disconnected;
418 return;
419 }
420
421 nouveau_connector_set_encoder(connector, nv_encoder);
422}
423
424static int
425nouveau_connector_set_property(struct drm_connector *connector,
426 struct drm_property *property, uint64_t value)
427{
428 struct nouveau_connector *nv_connector = nouveau_connector(connector);
429 struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
Francisco Jerez4a9f8222010-07-20 16:48:08 +0200430 struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
Ben Skeggs6ee73862009-12-11 19:24:15 +1000431 struct drm_device *dev = connector->dev;
432 int ret;
433
434 /* Scaling mode */
435 if (property == dev->mode_config.scaling_mode_property) {
436 struct nouveau_crtc *nv_crtc = NULL;
437 bool modeset = false;
438
439 switch (value) {
440 case DRM_MODE_SCALE_NONE:
441 case DRM_MODE_SCALE_FULLSCREEN:
442 case DRM_MODE_SCALE_CENTER:
443 case DRM_MODE_SCALE_ASPECT:
444 break;
445 default:
446 return -EINVAL;
447 }
448
449 /* LVDS always needs gpu scaling */
Ben Skeggsbe079e92010-02-24 14:01:40 +1000450 if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS &&
Ben Skeggs6ee73862009-12-11 19:24:15 +1000451 value == DRM_MODE_SCALE_NONE)
452 return -EINVAL;
453
454 /* Changing between GPU and panel scaling requires a full
455 * modeset
456 */
457 if ((nv_connector->scaling_mode == DRM_MODE_SCALE_NONE) ||
458 (value == DRM_MODE_SCALE_NONE))
459 modeset = true;
460 nv_connector->scaling_mode = value;
461
462 if (connector->encoder && connector->encoder->crtc)
463 nv_crtc = nouveau_crtc(connector->encoder->crtc);
464 if (!nv_crtc)
465 return 0;
466
467 if (modeset || !nv_crtc->set_scale) {
468 ret = drm_crtc_helper_set_mode(&nv_crtc->base,
469 &nv_crtc->base.mode,
470 nv_crtc->base.x,
471 nv_crtc->base.y, NULL);
472 if (!ret)
473 return -EINVAL;
474 } else {
475 ret = nv_crtc->set_scale(nv_crtc, value, true);
476 if (ret)
477 return ret;
478 }
479
480 return 0;
481 }
482
483 /* Dithering */
484 if (property == dev->mode_config.dithering_mode_property) {
485 struct nouveau_crtc *nv_crtc = NULL;
486
487 if (value == DRM_MODE_DITHERING_ON)
488 nv_connector->use_dithering = true;
489 else
490 nv_connector->use_dithering = false;
491
492 if (connector->encoder && connector->encoder->crtc)
493 nv_crtc = nouveau_crtc(connector->encoder->crtc);
494
495 if (!nv_crtc || !nv_crtc->set_dither)
496 return 0;
497
498 return nv_crtc->set_dither(nv_crtc, nv_connector->use_dithering,
499 true);
500 }
501
502 if (nv_encoder && nv_encoder->dcb->type == OUTPUT_TV)
Francisco Jerez4a9f8222010-07-20 16:48:08 +0200503 return get_slave_funcs(encoder)->set_property(
504 encoder, connector, property, value);
Ben Skeggs6ee73862009-12-11 19:24:15 +1000505
506 return -EINVAL;
507}
508
509static struct drm_display_mode *
Ben Skeggs26099a72010-05-28 10:13:16 +1000510nouveau_connector_native_mode(struct drm_connector *connector)
Ben Skeggs6ee73862009-12-11 19:24:15 +1000511{
Ben Skeggs26099a72010-05-28 10:13:16 +1000512 struct drm_connector_helper_funcs *helper = connector->helper_private;
513 struct nouveau_connector *nv_connector = nouveau_connector(connector);
514 struct drm_device *dev = connector->dev;
Ben Skeggs6ee73862009-12-11 19:24:15 +1000515 struct drm_display_mode *mode, *largest = NULL;
516 int high_w = 0, high_h = 0, high_v = 0;
517
Ben Skeggs26099a72010-05-28 10:13:16 +1000518 list_for_each_entry(mode, &nv_connector->base.probed_modes, head) {
Francisco Jereza5afb772010-07-18 16:19:16 +0200519 if (helper->mode_valid(connector, mode) != MODE_OK ||
520 (mode->flags & DRM_MODE_FLAG_INTERLACE))
Ben Skeggs26099a72010-05-28 10:13:16 +1000521 continue;
522
523 /* Use preferred mode if there is one.. */
Ben Skeggs6ee73862009-12-11 19:24:15 +1000524 if (mode->type & DRM_MODE_TYPE_PREFERRED) {
Maarten Maathuisef2bb502009-12-13 16:53:12 +0100525 NV_DEBUG_KMS(dev, "native mode from preferred\n");
Ben Skeggs6ee73862009-12-11 19:24:15 +1000526 return drm_mode_duplicate(dev, mode);
527 }
Ben Skeggs6ee73862009-12-11 19:24:15 +1000528
Ben Skeggs26099a72010-05-28 10:13:16 +1000529 /* Otherwise, take the resolution with the largest width, then
530 * height, then vertical refresh
531 */
Ben Skeggs6ee73862009-12-11 19:24:15 +1000532 if (mode->hdisplay < high_w)
533 continue;
534
535 if (mode->hdisplay == high_w && mode->vdisplay < high_h)
536 continue;
537
538 if (mode->hdisplay == high_w && mode->vdisplay == high_h &&
539 mode->vrefresh < high_v)
540 continue;
541
542 high_w = mode->hdisplay;
543 high_h = mode->vdisplay;
544 high_v = mode->vrefresh;
545 largest = mode;
546 }
547
Maarten Maathuisef2bb502009-12-13 16:53:12 +0100548 NV_DEBUG_KMS(dev, "native mode from largest: %dx%d@%d\n",
Ben Skeggs6ee73862009-12-11 19:24:15 +1000549 high_w, high_h, high_v);
550 return largest ? drm_mode_duplicate(dev, largest) : NULL;
551}
552
553struct moderec {
554 int hdisplay;
555 int vdisplay;
556};
557
558static struct moderec scaler_modes[] = {
559 { 1920, 1200 },
560 { 1920, 1080 },
561 { 1680, 1050 },
562 { 1600, 1200 },
563 { 1400, 1050 },
564 { 1280, 1024 },
565 { 1280, 960 },
566 { 1152, 864 },
567 { 1024, 768 },
568 { 800, 600 },
569 { 720, 400 },
570 { 640, 480 },
571 { 640, 400 },
572 { 640, 350 },
573 {}
574};
575
576static int
577nouveau_connector_scaler_modes_add(struct drm_connector *connector)
578{
579 struct nouveau_connector *nv_connector = nouveau_connector(connector);
580 struct drm_display_mode *native = nv_connector->native_mode, *m;
581 struct drm_device *dev = connector->dev;
582 struct moderec *mode = &scaler_modes[0];
583 int modes = 0;
584
585 if (!native)
586 return 0;
587
588 while (mode->hdisplay) {
589 if (mode->hdisplay <= native->hdisplay &&
590 mode->vdisplay <= native->vdisplay) {
591 m = drm_cvt_mode(dev, mode->hdisplay, mode->vdisplay,
592 drm_mode_vrefresh(native), false,
593 false, false);
594 if (!m)
595 continue;
596
597 m->type |= DRM_MODE_TYPE_DRIVER;
598
599 drm_mode_probed_add(connector, m);
600 modes++;
601 }
602
603 mode++;
604 }
605
606 return modes;
607}
608
609static int
610nouveau_connector_get_modes(struct drm_connector *connector)
611{
612 struct drm_device *dev = connector->dev;
Ben Skeggsd17f3952010-06-01 13:32:42 +1000613 struct drm_nouveau_private *dev_priv = dev->dev_private;
Ben Skeggs6ee73862009-12-11 19:24:15 +1000614 struct nouveau_connector *nv_connector = nouveau_connector(connector);
615 struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
Francisco Jerez4a9f8222010-07-20 16:48:08 +0200616 struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
Ben Skeggs6ee73862009-12-11 19:24:15 +1000617 int ret = 0;
618
Ben Skeggsd17f3952010-06-01 13:32:42 +1000619 /* destroy the native mode, the attached monitor could have changed.
Ben Skeggs6ee73862009-12-11 19:24:15 +1000620 */
Ben Skeggsd17f3952010-06-01 13:32:42 +1000621 if (nv_connector->native_mode) {
Ben Skeggs6ee73862009-12-11 19:24:15 +1000622 drm_mode_destroy(dev, nv_connector->native_mode);
623 nv_connector->native_mode = NULL;
624 }
625
626 if (nv_connector->edid)
627 ret = drm_add_edid_modes(connector, nv_connector->edid);
Ben Skeggsd17f3952010-06-01 13:32:42 +1000628 else
629 if (nv_encoder->dcb->type == OUTPUT_LVDS &&
630 (nv_encoder->dcb->lvdsconf.use_straps_for_mode ||
Francisco Jerez6e86e042010-07-03 18:36:39 +0200631 dev_priv->vbios.fp_no_ddc) && nouveau_bios_fp_mode(dev, NULL)) {
Ben Skeggs80dad862010-09-23 16:37:39 +1000632 struct drm_display_mode mode;
633
634 nouveau_bios_fp_mode(dev, &mode);
635 nv_connector->native_mode = drm_mode_duplicate(dev, &mode);
Ben Skeggsd17f3952010-06-01 13:32:42 +1000636 }
Ben Skeggs6ee73862009-12-11 19:24:15 +1000637
638 /* Find the native mode if this is a digital panel, if we didn't
639 * find any modes through DDC previously add the native mode to
640 * the list of modes.
641 */
642 if (!nv_connector->native_mode)
643 nv_connector->native_mode =
Ben Skeggs26099a72010-05-28 10:13:16 +1000644 nouveau_connector_native_mode(connector);
Ben Skeggs6ee73862009-12-11 19:24:15 +1000645 if (ret == 0 && nv_connector->native_mode) {
646 struct drm_display_mode *mode;
647
648 mode = drm_mode_duplicate(dev, nv_connector->native_mode);
649 drm_mode_probed_add(connector, mode);
650 ret = 1;
651 }
652
653 if (nv_encoder->dcb->type == OUTPUT_TV)
Francisco Jerez4a9f8222010-07-20 16:48:08 +0200654 ret = get_slave_funcs(encoder)->get_modes(encoder, connector);
Ben Skeggs6ee73862009-12-11 19:24:15 +1000655
Ben Skeggs646bef22010-07-06 11:27:52 +1000656 if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS ||
657 nv_connector->dcb->type == DCB_CONNECTOR_eDP)
Ben Skeggs6ee73862009-12-11 19:24:15 +1000658 ret += nouveau_connector_scaler_modes_add(connector);
659
660 return ret;
661}
662
Francisco Jerez1f5bd442010-10-02 16:00:35 +0200663static unsigned
664get_tmds_link_bandwidth(struct drm_connector *connector)
665{
666 struct nouveau_connector *nv_connector = nouveau_connector(connector);
667 struct drm_nouveau_private *dev_priv = connector->dev->dev_private;
668 struct dcb_entry *dcb = nv_connector->detected_encoder->dcb;
669
670 if (dcb->location != DCB_LOC_ON_CHIP ||
671 dev_priv->chipset >= 0x46)
672 return 165000;
673 else if (dev_priv->chipset >= 0x40)
674 return 155000;
675 else if (dev_priv->chipset >= 0x18)
676 return 135000;
677 else
678 return 112000;
679}
680
Ben Skeggs6ee73862009-12-11 19:24:15 +1000681static int
682nouveau_connector_mode_valid(struct drm_connector *connector,
683 struct drm_display_mode *mode)
684{
Ben Skeggs6ee73862009-12-11 19:24:15 +1000685 struct nouveau_connector *nv_connector = nouveau_connector(connector);
686 struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
Francisco Jerez4a9f8222010-07-20 16:48:08 +0200687 struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
Ben Skeggs6ee73862009-12-11 19:24:15 +1000688 unsigned min_clock = 25000, max_clock = min_clock;
689 unsigned clock = mode->clock;
690
691 switch (nv_encoder->dcb->type) {
692 case OUTPUT_LVDS:
Ben Skeggs26099a72010-05-28 10:13:16 +1000693 if (nv_connector->native_mode &&
694 (mode->hdisplay > nv_connector->native_mode->hdisplay ||
695 mode->vdisplay > nv_connector->native_mode->vdisplay))
Ben Skeggs6ee73862009-12-11 19:24:15 +1000696 return MODE_PANEL;
697
698 min_clock = 0;
699 max_clock = 400000;
700 break;
701 case OUTPUT_TMDS:
Francisco Jerez1f5bd442010-10-02 16:00:35 +0200702 max_clock = get_tmds_link_bandwidth(connector);
703 if (nouveau_duallink && nv_encoder->dcb->duallink_possible)
704 max_clock *= 2;
Ben Skeggs6ee73862009-12-11 19:24:15 +1000705 break;
706 case OUTPUT_ANALOG:
707 max_clock = nv_encoder->dcb->crtconf.maxfreq;
708 if (!max_clock)
709 max_clock = 350000;
710 break;
711 case OUTPUT_TV:
Francisco Jerez4a9f8222010-07-20 16:48:08 +0200712 return get_slave_funcs(encoder)->mode_valid(encoder, mode);
Ben Skeggs6ee73862009-12-11 19:24:15 +1000713 case OUTPUT_DP:
714 if (nv_encoder->dp.link_bw == DP_LINK_BW_2_7)
715 max_clock = nv_encoder->dp.link_nr * 270000;
716 else
717 max_clock = nv_encoder->dp.link_nr * 162000;
718
Ben Skeggs62acdc72010-09-28 10:23:20 +1000719 clock = clock * nouveau_connector_bpp(connector) / 8;
Ben Skeggs6ee73862009-12-11 19:24:15 +1000720 break;
Ben Skeggse7cc51c2010-02-24 10:31:39 +1000721 default:
722 BUG_ON(1);
723 return MODE_BAD;
Ben Skeggs6ee73862009-12-11 19:24:15 +1000724 }
725
726 if (clock < min_clock)
727 return MODE_CLOCK_LOW;
728
729 if (clock > max_clock)
730 return MODE_CLOCK_HIGH;
731
732 return MODE_OK;
733}
734
735static struct drm_encoder *
736nouveau_connector_best_encoder(struct drm_connector *connector)
737{
738 struct nouveau_connector *nv_connector = nouveau_connector(connector);
739
740 if (nv_connector->detected_encoder)
741 return to_drm_encoder(nv_connector->detected_encoder);
742
743 return NULL;
744}
745
746static const struct drm_connector_helper_funcs
747nouveau_connector_helper_funcs = {
748 .get_modes = nouveau_connector_get_modes,
749 .mode_valid = nouveau_connector_mode_valid,
750 .best_encoder = nouveau_connector_best_encoder,
751};
752
753static const struct drm_connector_funcs
754nouveau_connector_funcs = {
755 .dpms = drm_helper_connector_dpms,
756 .save = NULL,
757 .restore = NULL,
758 .detect = nouveau_connector_detect,
759 .destroy = nouveau_connector_destroy,
760 .fill_modes = drm_helper_probe_single_connector_modes,
761 .set_property = nouveau_connector_set_property,
762 .force = nouveau_connector_force
763};
764
Ben Skeggsd17f3952010-06-01 13:32:42 +1000765static const struct drm_connector_funcs
766nouveau_connector_funcs_lvds = {
767 .dpms = drm_helper_connector_dpms,
768 .save = NULL,
769 .restore = NULL,
770 .detect = nouveau_connector_detect_lvds,
771 .destroy = nouveau_connector_destroy,
772 .fill_modes = drm_helper_probe_single_connector_modes,
773 .set_property = nouveau_connector_set_property,
774 .force = nouveau_connector_force
775};
Ben Skeggs6ee73862009-12-11 19:24:15 +1000776
Ben Skeggs8f1a6082010-06-28 14:35:50 +1000777struct drm_connector *
778nouveau_connector_create(struct drm_device *dev, int index)
Ben Skeggs6ee73862009-12-11 19:24:15 +1000779{
Ben Skeggsd17f3952010-06-01 13:32:42 +1000780 const struct drm_connector_funcs *funcs = &nouveau_connector_funcs;
Ben Skeggs6ee73862009-12-11 19:24:15 +1000781 struct drm_nouveau_private *dev_priv = dev->dev_private;
782 struct nouveau_connector *nv_connector = NULL;
Ben Skeggs8f1a6082010-06-28 14:35:50 +1000783 struct dcb_connector_table_entry *dcb = NULL;
Ben Skeggs6ee73862009-12-11 19:24:15 +1000784 struct drm_connector *connector;
Francisco Jerez2fa67f12010-06-16 15:52:44 +0200785 int type, ret = 0;
Ben Skeggs6ee73862009-12-11 19:24:15 +1000786
Maarten Maathuisef2bb502009-12-13 16:53:12 +0100787 NV_DEBUG_KMS(dev, "\n");
Ben Skeggs6ee73862009-12-11 19:24:15 +1000788
Ben Skeggs8f1a6082010-06-28 14:35:50 +1000789 if (index >= dev_priv->vbios.dcb.connector.entries)
790 return ERR_PTR(-EINVAL);
791
792 dcb = &dev_priv->vbios.dcb.connector.entry[index];
793 if (dcb->drm)
794 return dcb->drm;
795
Ben Skeggs7f612d82010-02-24 12:07:31 +1000796 switch (dcb->type) {
Ben Skeggs7f612d82010-02-24 12:07:31 +1000797 case DCB_CONNECTOR_VGA:
Ben Skeggs7f612d82010-02-24 12:07:31 +1000798 type = DRM_MODE_CONNECTOR_VGA;
799 break;
800 case DCB_CONNECTOR_TV_0:
801 case DCB_CONNECTOR_TV_1:
802 case DCB_CONNECTOR_TV_3:
Ben Skeggs7f612d82010-02-24 12:07:31 +1000803 type = DRM_MODE_CONNECTOR_TV;
804 break;
805 case DCB_CONNECTOR_DVI_I:
Ben Skeggs7f612d82010-02-24 12:07:31 +1000806 type = DRM_MODE_CONNECTOR_DVII;
807 break;
808 case DCB_CONNECTOR_DVI_D:
Ben Skeggs7f612d82010-02-24 12:07:31 +1000809 type = DRM_MODE_CONNECTOR_DVID;
810 break;
Ben Skeggsbe079e92010-02-24 14:01:40 +1000811 case DCB_CONNECTOR_HDMI_0:
812 case DCB_CONNECTOR_HDMI_1:
Ben Skeggsbe079e92010-02-24 14:01:40 +1000813 type = DRM_MODE_CONNECTOR_HDMIA;
814 break;
Ben Skeggs7f612d82010-02-24 12:07:31 +1000815 case DCB_CONNECTOR_LVDS:
Ben Skeggs7f612d82010-02-24 12:07:31 +1000816 type = DRM_MODE_CONNECTOR_LVDS;
Ben Skeggsd17f3952010-06-01 13:32:42 +1000817 funcs = &nouveau_connector_funcs_lvds;
Ben Skeggs7f612d82010-02-24 12:07:31 +1000818 break;
819 case DCB_CONNECTOR_DP:
Ben Skeggs7f612d82010-02-24 12:07:31 +1000820 type = DRM_MODE_CONNECTOR_DisplayPort;
821 break;
Ben Skeggsbe079e92010-02-24 14:01:40 +1000822 case DCB_CONNECTOR_eDP:
Ben Skeggsbe079e92010-02-24 14:01:40 +1000823 type = DRM_MODE_CONNECTOR_eDP;
824 break;
Ben Skeggs7f612d82010-02-24 12:07:31 +1000825 default:
826 NV_ERROR(dev, "unknown connector type: 0x%02x!!\n", dcb->type);
Ben Skeggs8f1a6082010-06-28 14:35:50 +1000827 return ERR_PTR(-EINVAL);
Ben Skeggs7f612d82010-02-24 12:07:31 +1000828 }
829
Ben Skeggs6ee73862009-12-11 19:24:15 +1000830 nv_connector = kzalloc(sizeof(*nv_connector), GFP_KERNEL);
831 if (!nv_connector)
Ben Skeggs8f1a6082010-06-28 14:35:50 +1000832 return ERR_PTR(-ENOMEM);
Ben Skeggs7f612d82010-02-24 12:07:31 +1000833 nv_connector->dcb = dcb;
Ben Skeggs6ee73862009-12-11 19:24:15 +1000834 connector = &nv_connector->base;
835
Ben Skeggs6ee73862009-12-11 19:24:15 +1000836 /* defaults, will get overridden in detect() */
837 connector->interlace_allowed = false;
838 connector->doublescan_allowed = false;
839
Ben Skeggsd17f3952010-06-01 13:32:42 +1000840 drm_connector_init(dev, connector, funcs, type);
Ben Skeggs6ee73862009-12-11 19:24:15 +1000841 drm_connector_helper_add(connector, &nouveau_connector_helper_funcs);
842
Francisco Jerez2fa67f12010-06-16 15:52:44 +0200843 /* Check if we need dithering enabled */
844 if (dcb->type == DCB_CONNECTOR_LVDS) {
845 bool dummy, is_24bit = false;
846
847 ret = nouveau_bios_parse_lvds_table(dev, 0, &dummy, &is_24bit);
848 if (ret) {
849 NV_ERROR(dev, "Error parsing LVDS table, disabling "
850 "LVDS\n");
851 goto fail;
852 }
853
854 nv_connector->use_dithering = !is_24bit;
Ben Skeggs7f612d82010-02-24 12:07:31 +1000855 }
856
Ben Skeggs6ee73862009-12-11 19:24:15 +1000857 /* Init DVI-I specific properties */
Ben Skeggsbe079e92010-02-24 14:01:40 +1000858 if (dcb->type == DCB_CONNECTOR_DVI_I) {
Ben Skeggs6ee73862009-12-11 19:24:15 +1000859 drm_mode_create_dvi_i_properties(dev);
860 drm_connector_attach_property(connector, dev->mode_config.dvi_i_subconnector_property, 0);
861 drm_connector_attach_property(connector, dev->mode_config.dvi_i_select_subconnector_property, 0);
862 }
863
Ben Skeggsbe079e92010-02-24 14:01:40 +1000864 switch (dcb->type) {
865 case DCB_CONNECTOR_VGA:
866 if (dev_priv->card_type >= NV_50) {
Ben Skeggs6ee73862009-12-11 19:24:15 +1000867 drm_connector_attach_property(connector,
868 dev->mode_config.scaling_mode_property,
869 nv_connector->scaling_mode);
870 }
Ben Skeggsbe079e92010-02-24 14:01:40 +1000871 /* fall-through */
872 case DCB_CONNECTOR_TV_0:
873 case DCB_CONNECTOR_TV_1:
874 case DCB_CONNECTOR_TV_3:
875 nv_connector->scaling_mode = DRM_MODE_SCALE_NONE;
Francisco Jerez01db3632010-10-21 17:43:08 +0200876
877 if (nv_gf4_disp_arch(dev))
878 connector->polled = DRM_CONNECTOR_POLL_CONNECT;
Ben Skeggsbe079e92010-02-24 14:01:40 +1000879 break;
880 default:
881 nv_connector->scaling_mode = DRM_MODE_SCALE_FULLSCREEN;
882
883 drm_connector_attach_property(connector,
884 dev->mode_config.scaling_mode_property,
885 nv_connector->scaling_mode);
886 drm_connector_attach_property(connector,
887 dev->mode_config.dithering_mode_property,
888 nv_connector->use_dithering ?
889 DRM_MODE_DITHERING_ON : DRM_MODE_DITHERING_OFF);
Francisco Jerez01db3632010-10-21 17:43:08 +0200890
Francisco Jerez06ef3e62010-10-23 23:12:37 +0200891 if (dcb->type != DCB_CONNECTOR_LVDS) {
892 if (dev_priv->card_type >= NV_50)
893 connector->polled = DRM_CONNECTOR_POLL_HPD;
894 else
895 connector->polled = DRM_CONNECTOR_POLL_CONNECT;
896 }
Ben Skeggsbe079e92010-02-24 14:01:40 +1000897 break;
Ben Skeggs6ee73862009-12-11 19:24:15 +1000898 }
899
Ben Skeggs6ee73862009-12-11 19:24:15 +1000900 drm_sysfs_connector_add(connector);
Ben Skeggs8f1a6082010-06-28 14:35:50 +1000901 dcb->drm = connector;
902 return dcb->drm;
Francisco Jerez2fa67f12010-06-16 15:52:44 +0200903
904fail:
905 drm_connector_cleanup(connector);
906 kfree(connector);
Ben Skeggs8f1a6082010-06-28 14:35:50 +1000907 return ERR_PTR(ret);
Francisco Jerez2fa67f12010-06-16 15:52:44 +0200908
Ben Skeggs6ee73862009-12-11 19:24:15 +1000909}