diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_display.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_display.c | 145 |
1 files changed, 133 insertions, 12 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index c85df4afcb7a..a133b833e45d 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c | |||
@@ -250,6 +250,16 @@ static const char *connector_names[13] = { | |||
250 | "HDMI-B", | 250 | "HDMI-B", |
251 | }; | 251 | }; |
252 | 252 | ||
253 | static const char *hpd_names[7] = { | ||
254 | "NONE", | ||
255 | "HPD1", | ||
256 | "HPD2", | ||
257 | "HPD3", | ||
258 | "HPD4", | ||
259 | "HPD5", | ||
260 | "HPD6", | ||
261 | }; | ||
262 | |||
253 | static void radeon_print_display_setup(struct drm_device *dev) | 263 | static void radeon_print_display_setup(struct drm_device *dev) |
254 | { | 264 | { |
255 | struct drm_connector *connector; | 265 | struct drm_connector *connector; |
@@ -264,16 +274,18 @@ static void radeon_print_display_setup(struct drm_device *dev) | |||
264 | radeon_connector = to_radeon_connector(connector); | 274 | radeon_connector = to_radeon_connector(connector); |
265 | DRM_INFO("Connector %d:\n", i); | 275 | DRM_INFO("Connector %d:\n", i); |
266 | DRM_INFO(" %s\n", connector_names[connector->connector_type]); | 276 | DRM_INFO(" %s\n", connector_names[connector->connector_type]); |
277 | if (radeon_connector->hpd.hpd != RADEON_HPD_NONE) | ||
278 | DRM_INFO(" %s\n", hpd_names[radeon_connector->hpd.hpd]); | ||
267 | if (radeon_connector->ddc_bus) | 279 | if (radeon_connector->ddc_bus) |
268 | DRM_INFO(" DDC: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", | 280 | DRM_INFO(" DDC: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", |
269 | radeon_connector->ddc_bus->rec.mask_clk_reg, | 281 | radeon_connector->ddc_bus->rec.mask_clk_reg, |
270 | radeon_connector->ddc_bus->rec.mask_data_reg, | 282 | radeon_connector->ddc_bus->rec.mask_data_reg, |
271 | radeon_connector->ddc_bus->rec.a_clk_reg, | 283 | radeon_connector->ddc_bus->rec.a_clk_reg, |
272 | radeon_connector->ddc_bus->rec.a_data_reg, | 284 | radeon_connector->ddc_bus->rec.a_data_reg, |
273 | radeon_connector->ddc_bus->rec.put_clk_reg, | 285 | radeon_connector->ddc_bus->rec.en_clk_reg, |
274 | radeon_connector->ddc_bus->rec.put_data_reg, | 286 | radeon_connector->ddc_bus->rec.en_data_reg, |
275 | radeon_connector->ddc_bus->rec.get_clk_reg, | 287 | radeon_connector->ddc_bus->rec.y_clk_reg, |
276 | radeon_connector->ddc_bus->rec.get_data_reg); | 288 | radeon_connector->ddc_bus->rec.y_data_reg); |
277 | DRM_INFO(" Encoders:\n"); | 289 | DRM_INFO(" Encoders:\n"); |
278 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | 290 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
279 | radeon_encoder = to_radeon_encoder(encoder); | 291 | radeon_encoder = to_radeon_encoder(encoder); |
@@ -324,6 +336,7 @@ static bool radeon_setup_enc_conn(struct drm_device *dev) | |||
324 | ret = radeon_get_legacy_connector_info_from_table(dev); | 336 | ret = radeon_get_legacy_connector_info_from_table(dev); |
325 | } | 337 | } |
326 | if (ret) { | 338 | if (ret) { |
339 | radeon_setup_encoder_clones(dev); | ||
327 | radeon_print_display_setup(dev); | 340 | radeon_print_display_setup(dev); |
328 | list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head) | 341 | list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head) |
329 | radeon_ddc_dump(drm_connector); | 342 | radeon_ddc_dump(drm_connector); |
@@ -336,12 +349,17 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector) | |||
336 | { | 349 | { |
337 | int ret = 0; | 350 | int ret = 0; |
338 | 351 | ||
352 | if (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) { | ||
353 | struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; | ||
354 | if (dig->dp_i2c_bus) | ||
355 | radeon_connector->edid = drm_get_edid(&radeon_connector->base, &dig->dp_i2c_bus->adapter); | ||
356 | } | ||
339 | if (!radeon_connector->ddc_bus) | 357 | if (!radeon_connector->ddc_bus) |
340 | return -1; | 358 | return -1; |
341 | if (!radeon_connector->edid) { | 359 | if (!radeon_connector->edid) { |
342 | radeon_i2c_do_lock(radeon_connector, 1); | 360 | radeon_i2c_do_lock(radeon_connector->ddc_bus, 1); |
343 | radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter); | 361 | radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter); |
344 | radeon_i2c_do_lock(radeon_connector, 0); | 362 | radeon_i2c_do_lock(radeon_connector->ddc_bus, 0); |
345 | } | 363 | } |
346 | 364 | ||
347 | if (radeon_connector->edid) { | 365 | if (radeon_connector->edid) { |
@@ -361,9 +379,9 @@ static int radeon_ddc_dump(struct drm_connector *connector) | |||
361 | 379 | ||
362 | if (!radeon_connector->ddc_bus) | 380 | if (!radeon_connector->ddc_bus) |
363 | return -1; | 381 | return -1; |
364 | radeon_i2c_do_lock(radeon_connector, 1); | 382 | radeon_i2c_do_lock(radeon_connector->ddc_bus, 1); |
365 | edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter); | 383 | edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter); |
366 | radeon_i2c_do_lock(radeon_connector, 0); | 384 | radeon_i2c_do_lock(radeon_connector->ddc_bus, 0); |
367 | if (edid) { | 385 | if (edid) { |
368 | kfree(edid); | 386 | kfree(edid); |
369 | } | 387 | } |
@@ -542,6 +560,98 @@ void radeon_compute_pll(struct radeon_pll *pll, | |||
542 | *post_div_p = best_post_div; | 560 | *post_div_p = best_post_div; |
543 | } | 561 | } |
544 | 562 | ||
563 | void radeon_compute_pll_avivo(struct radeon_pll *pll, | ||
564 | uint64_t freq, | ||
565 | uint32_t *dot_clock_p, | ||
566 | uint32_t *fb_div_p, | ||
567 | uint32_t *frac_fb_div_p, | ||
568 | uint32_t *ref_div_p, | ||
569 | uint32_t *post_div_p, | ||
570 | int flags) | ||
571 | { | ||
572 | fixed20_12 m, n, frac_n, p, f_vco, f_pclk, best_freq; | ||
573 | fixed20_12 pll_out_max, pll_out_min; | ||
574 | fixed20_12 pll_in_max, pll_in_min; | ||
575 | fixed20_12 reference_freq; | ||
576 | fixed20_12 error, ffreq, a, b; | ||
577 | |||
578 | pll_out_max.full = rfixed_const(pll->pll_out_max); | ||
579 | pll_out_min.full = rfixed_const(pll->pll_out_min); | ||
580 | pll_in_max.full = rfixed_const(pll->pll_in_max); | ||
581 | pll_in_min.full = rfixed_const(pll->pll_in_min); | ||
582 | reference_freq.full = rfixed_const(pll->reference_freq); | ||
583 | do_div(freq, 10); | ||
584 | ffreq.full = rfixed_const(freq); | ||
585 | error.full = rfixed_const(100 * 100); | ||
586 | |||
587 | /* max p */ | ||
588 | p.full = rfixed_div(pll_out_max, ffreq); | ||
589 | p.full = rfixed_floor(p); | ||
590 | |||
591 | /* min m */ | ||
592 | m.full = rfixed_div(reference_freq, pll_in_max); | ||
593 | m.full = rfixed_ceil(m); | ||
594 | |||
595 | while (1) { | ||
596 | n.full = rfixed_div(ffreq, reference_freq); | ||
597 | n.full = rfixed_mul(n, m); | ||
598 | n.full = rfixed_mul(n, p); | ||
599 | |||
600 | f_vco.full = rfixed_div(n, m); | ||
601 | f_vco.full = rfixed_mul(f_vco, reference_freq); | ||
602 | |||
603 | f_pclk.full = rfixed_div(f_vco, p); | ||
604 | |||
605 | if (f_pclk.full > ffreq.full) | ||
606 | error.full = f_pclk.full - ffreq.full; | ||
607 | else | ||
608 | error.full = ffreq.full - f_pclk.full; | ||
609 | error.full = rfixed_div(error, f_pclk); | ||
610 | a.full = rfixed_const(100 * 100); | ||
611 | error.full = rfixed_mul(error, a); | ||
612 | |||
613 | a.full = rfixed_mul(m, p); | ||
614 | a.full = rfixed_div(n, a); | ||
615 | best_freq.full = rfixed_mul(reference_freq, a); | ||
616 | |||
617 | if (rfixed_trunc(error) < 25) | ||
618 | break; | ||
619 | |||
620 | a.full = rfixed_const(1); | ||
621 | m.full = m.full + a.full; | ||
622 | a.full = rfixed_div(reference_freq, m); | ||
623 | if (a.full >= pll_in_min.full) | ||
624 | continue; | ||
625 | |||
626 | m.full = rfixed_div(reference_freq, pll_in_max); | ||
627 | m.full = rfixed_ceil(m); | ||
628 | a.full= rfixed_const(1); | ||
629 | p.full = p.full - a.full; | ||
630 | a.full = rfixed_mul(p, ffreq); | ||
631 | if (a.full >= pll_out_min.full) | ||
632 | continue; | ||
633 | else { | ||
634 | DRM_ERROR("Unable to find pll dividers\n"); | ||
635 | break; | ||
636 | } | ||
637 | } | ||
638 | |||
639 | a.full = rfixed_const(10); | ||
640 | b.full = rfixed_mul(n, a); | ||
641 | |||
642 | frac_n.full = rfixed_floor(n); | ||
643 | frac_n.full = rfixed_mul(frac_n, a); | ||
644 | frac_n.full = b.full - frac_n.full; | ||
645 | |||
646 | *dot_clock_p = rfixed_trunc(best_freq); | ||
647 | *fb_div_p = rfixed_trunc(n); | ||
648 | *frac_fb_div_p = rfixed_trunc(frac_n); | ||
649 | *ref_div_p = rfixed_trunc(m); | ||
650 | *post_div_p = rfixed_trunc(p); | ||
651 | |||
652 | DRM_DEBUG("%u %d.%d, %d, %d\n", *dot_clock_p * 10, *fb_div_p, *frac_fb_div_p, *ref_div_p, *post_div_p); | ||
653 | } | ||
654 | |||
545 | static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb) | 655 | static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb) |
546 | { | 656 | { |
547 | struct radeon_framebuffer *radeon_fb = to_radeon_framebuffer(fb); | 657 | struct radeon_framebuffer *radeon_fb = to_radeon_framebuffer(fb); |
@@ -642,7 +752,7 @@ int radeon_modeset_create_props(struct radeon_device *rdev) | |||
642 | return -ENOMEM; | 752 | return -ENOMEM; |
643 | 753 | ||
644 | rdev->mode_info.coherent_mode_property->values[0] = 0; | 754 | rdev->mode_info.coherent_mode_property->values[0] = 0; |
645 | rdev->mode_info.coherent_mode_property->values[0] = 1; | 755 | rdev->mode_info.coherent_mode_property->values[1] = 1; |
646 | } | 756 | } |
647 | 757 | ||
648 | if (!ASIC_IS_AVIVO(rdev)) { | 758 | if (!ASIC_IS_AVIVO(rdev)) { |
@@ -666,7 +776,7 @@ int radeon_modeset_create_props(struct radeon_device *rdev) | |||
666 | if (!rdev->mode_info.load_detect_property) | 776 | if (!rdev->mode_info.load_detect_property) |
667 | return -ENOMEM; | 777 | return -ENOMEM; |
668 | rdev->mode_info.load_detect_property->values[0] = 0; | 778 | rdev->mode_info.load_detect_property->values[0] = 0; |
669 | rdev->mode_info.load_detect_property->values[0] = 1; | 779 | rdev->mode_info.load_detect_property->values[1] = 1; |
670 | 780 | ||
671 | drm_mode_create_scaling_mode_property(rdev->ddev); | 781 | drm_mode_create_scaling_mode_property(rdev->ddev); |
672 | 782 | ||
@@ -723,6 +833,8 @@ int radeon_modeset_init(struct radeon_device *rdev) | |||
723 | if (!ret) { | 833 | if (!ret) { |
724 | return ret; | 834 | return ret; |
725 | } | 835 | } |
836 | /* initialize hpd */ | ||
837 | radeon_hpd_init(rdev); | ||
726 | drm_helper_initial_config(rdev->ddev); | 838 | drm_helper_initial_config(rdev->ddev); |
727 | return 0; | 839 | return 0; |
728 | } | 840 | } |
@@ -730,6 +842,7 @@ int radeon_modeset_init(struct radeon_device *rdev) | |||
730 | void radeon_modeset_fini(struct radeon_device *rdev) | 842 | void radeon_modeset_fini(struct radeon_device *rdev) |
731 | { | 843 | { |
732 | if (rdev->mode_info.mode_config_initialized) { | 844 | if (rdev->mode_info.mode_config_initialized) { |
845 | radeon_hpd_fini(rdev); | ||
733 | drm_mode_config_cleanup(rdev->ddev); | 846 | drm_mode_config_cleanup(rdev->ddev); |
734 | rdev->mode_info.mode_config_initialized = false; | 847 | rdev->mode_info.mode_config_initialized = false; |
735 | } | 848 | } |
@@ -750,9 +863,17 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, | |||
750 | if (encoder->crtc != crtc) | 863 | if (encoder->crtc != crtc) |
751 | continue; | 864 | continue; |
752 | if (first) { | 865 | if (first) { |
753 | radeon_crtc->rmx_type = radeon_encoder->rmx_type; | 866 | /* set scaling */ |
867 | if (radeon_encoder->rmx_type == RMX_OFF) | ||
868 | radeon_crtc->rmx_type = RMX_OFF; | ||
869 | else if (mode->hdisplay < radeon_encoder->native_mode.hdisplay || | ||
870 | mode->vdisplay < radeon_encoder->native_mode.vdisplay) | ||
871 | radeon_crtc->rmx_type = radeon_encoder->rmx_type; | ||
872 | else | ||
873 | radeon_crtc->rmx_type = RMX_OFF; | ||
874 | /* copy native mode */ | ||
754 | memcpy(&radeon_crtc->native_mode, | 875 | memcpy(&radeon_crtc->native_mode, |
755 | &radeon_encoder->native_mode, | 876 | &radeon_encoder->native_mode, |
756 | sizeof(struct drm_display_mode)); | 877 | sizeof(struct drm_display_mode)); |
757 | first = false; | 878 | first = false; |
758 | } else { | 879 | } else { |