diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_connectors.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_connectors.c | 199 |
1 files changed, 153 insertions, 46 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index e376be47a4a0..fce4c4087fda 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c | |||
@@ -178,25 +178,12 @@ static struct drm_display_mode *radeon_fp_native_mode(struct drm_encoder *encode | |||
178 | struct drm_device *dev = encoder->dev; | 178 | struct drm_device *dev = encoder->dev; |
179 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 179 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
180 | struct drm_display_mode *mode = NULL; | 180 | struct drm_display_mode *mode = NULL; |
181 | struct radeon_native_mode *native_mode = &radeon_encoder->native_mode; | 181 | struct drm_display_mode *native_mode = &radeon_encoder->native_mode; |
182 | |||
183 | if (native_mode->panel_xres != 0 && | ||
184 | native_mode->panel_yres != 0 && | ||
185 | native_mode->dotclock != 0) { | ||
186 | mode = drm_mode_create(dev); | ||
187 | |||
188 | mode->hdisplay = native_mode->panel_xres; | ||
189 | mode->vdisplay = native_mode->panel_yres; | ||
190 | |||
191 | mode->htotal = mode->hdisplay + native_mode->hblank; | ||
192 | mode->hsync_start = mode->hdisplay + native_mode->hoverplus; | ||
193 | mode->hsync_end = mode->hsync_start + native_mode->hsync_width; | ||
194 | mode->vtotal = mode->vdisplay + native_mode->vblank; | ||
195 | mode->vsync_start = mode->vdisplay + native_mode->voverplus; | ||
196 | mode->vsync_end = mode->vsync_start + native_mode->vsync_width; | ||
197 | mode->clock = native_mode->dotclock; | ||
198 | mode->flags = 0; | ||
199 | 182 | ||
183 | if (native_mode->hdisplay != 0 && | ||
184 | native_mode->vdisplay != 0 && | ||
185 | native_mode->clock != 0) { | ||
186 | mode = drm_mode_duplicate(dev, native_mode); | ||
200 | mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER; | 187 | mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER; |
201 | drm_mode_set_name(mode); | 188 | drm_mode_set_name(mode); |
202 | 189 | ||
@@ -210,7 +197,7 @@ static void radeon_add_common_modes(struct drm_encoder *encoder, struct drm_conn | |||
210 | struct drm_device *dev = encoder->dev; | 197 | struct drm_device *dev = encoder->dev; |
211 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 198 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
212 | struct drm_display_mode *mode = NULL; | 199 | struct drm_display_mode *mode = NULL; |
213 | struct radeon_native_mode *native_mode = &radeon_encoder->native_mode; | 200 | struct drm_display_mode *native_mode = &radeon_encoder->native_mode; |
214 | int i; | 201 | int i; |
215 | struct mode_size { | 202 | struct mode_size { |
216 | int w; | 203 | int w; |
@@ -236,11 +223,16 @@ static void radeon_add_common_modes(struct drm_encoder *encoder, struct drm_conn | |||
236 | }; | 223 | }; |
237 | 224 | ||
238 | for (i = 0; i < 17; i++) { | 225 | for (i = 0; i < 17; i++) { |
226 | if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT)) { | ||
227 | if (common_modes[i].w > 1024 || | ||
228 | common_modes[i].h > 768) | ||
229 | continue; | ||
230 | } | ||
239 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { | 231 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { |
240 | if (common_modes[i].w > native_mode->panel_xres || | 232 | if (common_modes[i].w > native_mode->hdisplay || |
241 | common_modes[i].h > native_mode->panel_yres || | 233 | common_modes[i].h > native_mode->vdisplay || |
242 | (common_modes[i].w == native_mode->panel_xres && | 234 | (common_modes[i].w == native_mode->hdisplay && |
243 | common_modes[i].h == native_mode->panel_yres)) | 235 | common_modes[i].h == native_mode->vdisplay)) |
244 | continue; | 236 | continue; |
245 | } | 237 | } |
246 | if (common_modes[i].w < 320 || common_modes[i].h < 200) | 238 | if (common_modes[i].w < 320 || common_modes[i].h < 200) |
@@ -344,28 +336,23 @@ static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder, | |||
344 | struct drm_connector *connector) | 336 | struct drm_connector *connector) |
345 | { | 337 | { |
346 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 338 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
347 | struct radeon_native_mode *native_mode = &radeon_encoder->native_mode; | 339 | struct drm_display_mode *native_mode = &radeon_encoder->native_mode; |
348 | 340 | ||
349 | /* Try to get native mode details from EDID if necessary */ | 341 | /* Try to get native mode details from EDID if necessary */ |
350 | if (!native_mode->dotclock) { | 342 | if (!native_mode->clock) { |
351 | struct drm_display_mode *t, *mode; | 343 | struct drm_display_mode *t, *mode; |
352 | 344 | ||
353 | list_for_each_entry_safe(mode, t, &connector->probed_modes, head) { | 345 | list_for_each_entry_safe(mode, t, &connector->probed_modes, head) { |
354 | if (mode->hdisplay == native_mode->panel_xres && | 346 | if (mode->hdisplay == native_mode->hdisplay && |
355 | mode->vdisplay == native_mode->panel_yres) { | 347 | mode->vdisplay == native_mode->vdisplay) { |
356 | native_mode->hblank = mode->htotal - mode->hdisplay; | 348 | *native_mode = *mode; |
357 | native_mode->hoverplus = mode->hsync_start - mode->hdisplay; | 349 | drm_mode_set_crtcinfo(native_mode, CRTC_INTERLACE_HALVE_V); |
358 | native_mode->hsync_width = mode->hsync_end - mode->hsync_start; | ||
359 | native_mode->vblank = mode->vtotal - mode->vdisplay; | ||
360 | native_mode->voverplus = mode->vsync_start - mode->vdisplay; | ||
361 | native_mode->vsync_width = mode->vsync_end - mode->vsync_start; | ||
362 | native_mode->dotclock = mode->clock; | ||
363 | DRM_INFO("Determined LVDS native mode details from EDID\n"); | 350 | DRM_INFO("Determined LVDS native mode details from EDID\n"); |
364 | break; | 351 | break; |
365 | } | 352 | } |
366 | } | 353 | } |
367 | } | 354 | } |
368 | if (!native_mode->dotclock) { | 355 | if (!native_mode->clock) { |
369 | DRM_INFO("No LVDS native mode details, disabling RMX\n"); | 356 | DRM_INFO("No LVDS native mode details, disabling RMX\n"); |
370 | radeon_encoder->rmx_type = RMX_OFF; | 357 | radeon_encoder->rmx_type = RMX_OFF; |
371 | } | 358 | } |
@@ -410,13 +397,64 @@ static int radeon_lvds_get_modes(struct drm_connector *connector) | |||
410 | static int radeon_lvds_mode_valid(struct drm_connector *connector, | 397 | static int radeon_lvds_mode_valid(struct drm_connector *connector, |
411 | struct drm_display_mode *mode) | 398 | struct drm_display_mode *mode) |
412 | { | 399 | { |
400 | struct drm_encoder *encoder = radeon_best_single_encoder(connector); | ||
401 | |||
402 | if ((mode->hdisplay < 320) || (mode->vdisplay < 240)) | ||
403 | return MODE_PANEL; | ||
404 | |||
405 | if (encoder) { | ||
406 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
407 | struct drm_display_mode *native_mode = &radeon_encoder->native_mode; | ||
408 | |||
409 | /* AVIVO hardware supports downscaling modes larger than the panel | ||
410 | * to the panel size, but I'm not sure this is desirable. | ||
411 | */ | ||
412 | if ((mode->hdisplay > native_mode->hdisplay) || | ||
413 | (mode->vdisplay > native_mode->vdisplay)) | ||
414 | return MODE_PANEL; | ||
415 | |||
416 | /* if scaling is disabled, block non-native modes */ | ||
417 | if (radeon_encoder->rmx_type == RMX_OFF) { | ||
418 | if ((mode->hdisplay != native_mode->hdisplay) || | ||
419 | (mode->vdisplay != native_mode->vdisplay)) | ||
420 | return MODE_PANEL; | ||
421 | } | ||
422 | } | ||
423 | |||
413 | return MODE_OK; | 424 | return MODE_OK; |
414 | } | 425 | } |
415 | 426 | ||
416 | static enum drm_connector_status radeon_lvds_detect(struct drm_connector *connector) | 427 | static enum drm_connector_status radeon_lvds_detect(struct drm_connector *connector) |
417 | { | 428 | { |
418 | enum drm_connector_status ret = connector_status_connected; | 429 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
430 | struct drm_encoder *encoder = radeon_best_single_encoder(connector); | ||
431 | enum drm_connector_status ret = connector_status_disconnected; | ||
432 | |||
433 | if (encoder) { | ||
434 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
435 | struct drm_display_mode *native_mode = &radeon_encoder->native_mode; | ||
436 | |||
437 | /* check if panel is valid */ | ||
438 | if (native_mode->hdisplay >= 320 && native_mode->vdisplay >= 240) | ||
439 | ret = connector_status_connected; | ||
440 | |||
441 | } | ||
442 | |||
443 | /* check for edid as well */ | ||
444 | if (radeon_connector->edid) | ||
445 | ret = connector_status_connected; | ||
446 | else { | ||
447 | if (radeon_connector->ddc_bus) { | ||
448 | radeon_i2c_do_lock(radeon_connector, 1); | ||
449 | radeon_connector->edid = drm_get_edid(&radeon_connector->base, | ||
450 | &radeon_connector->ddc_bus->adapter); | ||
451 | radeon_i2c_do_lock(radeon_connector, 0); | ||
452 | if (radeon_connector->edid) | ||
453 | ret = connector_status_connected; | ||
454 | } | ||
455 | } | ||
419 | /* check acpi lid status ??? */ | 456 | /* check acpi lid status ??? */ |
457 | |||
420 | radeon_connector_update_scratch_regs(connector, ret); | 458 | radeon_connector_update_scratch_regs(connector, ret); |
421 | return ret; | 459 | return ret; |
422 | } | 460 | } |
@@ -427,6 +465,8 @@ static void radeon_connector_destroy(struct drm_connector *connector) | |||
427 | 465 | ||
428 | if (radeon_connector->ddc_bus) | 466 | if (radeon_connector->ddc_bus) |
429 | radeon_i2c_destroy(radeon_connector->ddc_bus); | 467 | radeon_i2c_destroy(radeon_connector->ddc_bus); |
468 | if (radeon_connector->edid) | ||
469 | kfree(radeon_connector->edid); | ||
430 | kfree(radeon_connector->con_priv); | 470 | kfree(radeon_connector->con_priv); |
431 | drm_sysfs_connector_remove(connector); | 471 | drm_sysfs_connector_remove(connector); |
432 | drm_connector_cleanup(connector); | 472 | drm_connector_cleanup(connector); |
@@ -496,6 +536,8 @@ static int radeon_vga_get_modes(struct drm_connector *connector) | |||
496 | static int radeon_vga_mode_valid(struct drm_connector *connector, | 536 | static int radeon_vga_mode_valid(struct drm_connector *connector, |
497 | struct drm_display_mode *mode) | 537 | struct drm_display_mode *mode) |
498 | { | 538 | { |
539 | /* XXX check mode bandwidth */ | ||
540 | /* XXX verify against max DAC output frequency */ | ||
499 | return MODE_OK; | 541 | return MODE_OK; |
500 | } | 542 | } |
501 | 543 | ||
@@ -514,9 +556,32 @@ static enum drm_connector_status radeon_vga_detect(struct drm_connector *connect | |||
514 | radeon_i2c_do_lock(radeon_connector, 1); | 556 | radeon_i2c_do_lock(radeon_connector, 1); |
515 | dret = radeon_ddc_probe(radeon_connector); | 557 | dret = radeon_ddc_probe(radeon_connector); |
516 | radeon_i2c_do_lock(radeon_connector, 0); | 558 | radeon_i2c_do_lock(radeon_connector, 0); |
517 | if (dret) | 559 | if (dret) { |
518 | ret = connector_status_connected; | 560 | if (radeon_connector->edid) { |
519 | else { | 561 | kfree(radeon_connector->edid); |
562 | radeon_connector->edid = NULL; | ||
563 | } | ||
564 | radeon_i2c_do_lock(radeon_connector, 1); | ||
565 | radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter); | ||
566 | radeon_i2c_do_lock(radeon_connector, 0); | ||
567 | |||
568 | if (!radeon_connector->edid) { | ||
569 | DRM_ERROR("DDC responded but not EDID found for %s\n", | ||
570 | drm_get_connector_name(connector)); | ||
571 | } else { | ||
572 | radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL); | ||
573 | |||
574 | /* some oems have boards with separate digital and analog connectors | ||
575 | * with a shared ddc line (often vga + hdmi) | ||
576 | */ | ||
577 | if (radeon_connector->use_digital && radeon_connector->shared_ddc) { | ||
578 | kfree(radeon_connector->edid); | ||
579 | radeon_connector->edid = NULL; | ||
580 | ret = connector_status_disconnected; | ||
581 | } else | ||
582 | ret = connector_status_connected; | ||
583 | } | ||
584 | } else { | ||
520 | if (radeon_connector->dac_load_detect) { | 585 | if (radeon_connector->dac_load_detect) { |
521 | encoder_funcs = encoder->helper_private; | 586 | encoder_funcs = encoder->helper_private; |
522 | ret = encoder_funcs->detect(encoder, connector); | 587 | ret = encoder_funcs->detect(encoder, connector); |
@@ -570,6 +635,8 @@ static int radeon_tv_get_modes(struct drm_connector *connector) | |||
570 | static int radeon_tv_mode_valid(struct drm_connector *connector, | 635 | static int radeon_tv_mode_valid(struct drm_connector *connector, |
571 | struct drm_display_mode *mode) | 636 | struct drm_display_mode *mode) |
572 | { | 637 | { |
638 | if ((mode->hdisplay > 1024) || (mode->vdisplay > 768)) | ||
639 | return MODE_CLOCK_RANGE; | ||
573 | return MODE_OK; | 640 | return MODE_OK; |
574 | } | 641 | } |
575 | 642 | ||
@@ -644,6 +711,10 @@ static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connect | |||
644 | dret = radeon_ddc_probe(radeon_connector); | 711 | dret = radeon_ddc_probe(radeon_connector); |
645 | radeon_i2c_do_lock(radeon_connector, 0); | 712 | radeon_i2c_do_lock(radeon_connector, 0); |
646 | if (dret) { | 713 | if (dret) { |
714 | if (radeon_connector->edid) { | ||
715 | kfree(radeon_connector->edid); | ||
716 | radeon_connector->edid = NULL; | ||
717 | } | ||
647 | radeon_i2c_do_lock(radeon_connector, 1); | 718 | radeon_i2c_do_lock(radeon_connector, 1); |
648 | radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter); | 719 | radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter); |
649 | radeon_i2c_do_lock(radeon_connector, 0); | 720 | radeon_i2c_do_lock(radeon_connector, 0); |
@@ -654,10 +725,15 @@ static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connect | |||
654 | } else { | 725 | } else { |
655 | radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL); | 726 | radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL); |
656 | 727 | ||
657 | /* if this isn't a digital monitor | 728 | /* some oems have boards with separate digital and analog connectors |
658 | then we need to make sure we don't have any | 729 | * with a shared ddc line (often vga + hdmi) |
659 | TV conflicts */ | 730 | */ |
660 | ret = connector_status_connected; | 731 | if ((!radeon_connector->use_digital) && radeon_connector->shared_ddc) { |
732 | kfree(radeon_connector->edid); | ||
733 | radeon_connector->edid = NULL; | ||
734 | ret = connector_status_disconnected; | ||
735 | } else | ||
736 | ret = connector_status_connected; | ||
661 | } | 737 | } |
662 | } | 738 | } |
663 | 739 | ||
@@ -753,9 +829,27 @@ static void radeon_dvi_force(struct drm_connector *connector) | |||
753 | radeon_connector->use_digital = true; | 829 | radeon_connector->use_digital = true; |
754 | } | 830 | } |
755 | 831 | ||
832 | static int radeon_dvi_mode_valid(struct drm_connector *connector, | ||
833 | struct drm_display_mode *mode) | ||
834 | { | ||
835 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | ||
836 | |||
837 | /* XXX check mode bandwidth */ | ||
838 | |||
839 | if (radeon_connector->use_digital && (mode->clock > 165000)) { | ||
840 | if ((radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I) || | ||
841 | (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D) || | ||
842 | (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_HDMI_TYPE_B)) | ||
843 | return MODE_OK; | ||
844 | else | ||
845 | return MODE_CLOCK_HIGH; | ||
846 | } | ||
847 | return MODE_OK; | ||
848 | } | ||
849 | |||
756 | struct drm_connector_helper_funcs radeon_dvi_connector_helper_funcs = { | 850 | struct drm_connector_helper_funcs radeon_dvi_connector_helper_funcs = { |
757 | .get_modes = radeon_dvi_get_modes, | 851 | .get_modes = radeon_dvi_get_modes, |
758 | .mode_valid = radeon_vga_mode_valid, | 852 | .mode_valid = radeon_dvi_mode_valid, |
759 | .best_encoder = radeon_dvi_encoder, | 853 | .best_encoder = radeon_dvi_encoder, |
760 | }; | 854 | }; |
761 | 855 | ||
@@ -775,13 +869,15 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
775 | int connector_type, | 869 | int connector_type, |
776 | struct radeon_i2c_bus_rec *i2c_bus, | 870 | struct radeon_i2c_bus_rec *i2c_bus, |
777 | bool linkb, | 871 | bool linkb, |
778 | uint32_t igp_lane_info) | 872 | uint32_t igp_lane_info, |
873 | uint16_t connector_object_id) | ||
779 | { | 874 | { |
780 | struct radeon_device *rdev = dev->dev_private; | 875 | struct radeon_device *rdev = dev->dev_private; |
781 | struct drm_connector *connector; | 876 | struct drm_connector *connector; |
782 | struct radeon_connector *radeon_connector; | 877 | struct radeon_connector *radeon_connector; |
783 | struct radeon_connector_atom_dig *radeon_dig_connector; | 878 | struct radeon_connector_atom_dig *radeon_dig_connector; |
784 | uint32_t subpixel_order = SubPixelNone; | 879 | uint32_t subpixel_order = SubPixelNone; |
880 | bool shared_ddc = false; | ||
785 | int ret; | 881 | int ret; |
786 | 882 | ||
787 | /* fixme - tv/cv/din */ | 883 | /* fixme - tv/cv/din */ |
@@ -795,6 +891,13 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
795 | radeon_connector->devices |= supported_device; | 891 | radeon_connector->devices |= supported_device; |
796 | return; | 892 | return; |
797 | } | 893 | } |
894 | if (radeon_connector->ddc_bus && i2c_bus->valid) { | ||
895 | if (memcmp(&radeon_connector->ddc_bus->rec, i2c_bus, | ||
896 | sizeof(struct radeon_i2c_bus_rec)) == 0) { | ||
897 | radeon_connector->shared_ddc = true; | ||
898 | shared_ddc = true; | ||
899 | } | ||
900 | } | ||
798 | } | 901 | } |
799 | 902 | ||
800 | radeon_connector = kzalloc(sizeof(struct radeon_connector), GFP_KERNEL); | 903 | radeon_connector = kzalloc(sizeof(struct radeon_connector), GFP_KERNEL); |
@@ -805,6 +908,8 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
805 | 908 | ||
806 | radeon_connector->connector_id = connector_id; | 909 | radeon_connector->connector_id = connector_id; |
807 | radeon_connector->devices = supported_device; | 910 | radeon_connector->devices = supported_device; |
911 | radeon_connector->shared_ddc = shared_ddc; | ||
912 | radeon_connector->connector_object_id = connector_object_id; | ||
808 | switch (connector_type) { | 913 | switch (connector_type) { |
809 | case DRM_MODE_CONNECTOR_VGA: | 914 | case DRM_MODE_CONNECTOR_VGA: |
810 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); | 915 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); |
@@ -956,7 +1061,8 @@ radeon_add_legacy_connector(struct drm_device *dev, | |||
956 | uint32_t connector_id, | 1061 | uint32_t connector_id, |
957 | uint32_t supported_device, | 1062 | uint32_t supported_device, |
958 | int connector_type, | 1063 | int connector_type, |
959 | struct radeon_i2c_bus_rec *i2c_bus) | 1064 | struct radeon_i2c_bus_rec *i2c_bus, |
1065 | uint16_t connector_object_id) | ||
960 | { | 1066 | { |
961 | struct radeon_device *rdev = dev->dev_private; | 1067 | struct radeon_device *rdev = dev->dev_private; |
962 | struct drm_connector *connector; | 1068 | struct drm_connector *connector; |
@@ -985,6 +1091,7 @@ radeon_add_legacy_connector(struct drm_device *dev, | |||
985 | 1091 | ||
986 | radeon_connector->connector_id = connector_id; | 1092 | radeon_connector->connector_id = connector_id; |
987 | radeon_connector->devices = supported_device; | 1093 | radeon_connector->devices = supported_device; |
1094 | radeon_connector->connector_object_id = connector_object_id; | ||
988 | switch (connector_type) { | 1095 | switch (connector_type) { |
989 | case DRM_MODE_CONNECTOR_VGA: | 1096 | case DRM_MODE_CONNECTOR_VGA: |
990 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); | 1097 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); |