diff options
author | Dave Airlie <airlied@redhat.com> | 2009-08-13 02:32:14 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2009-09-07 19:24:37 -0400 |
commit | 4ce001abafafe77e5dd943d1480fc9f87894e96f (patch) | |
tree | 4a22b42c58a80450992fcf5d7625b19fe045855b /drivers/gpu/drm/radeon/atombios_crtc.c | |
parent | 551ebd837c75fc75df81811a18b7136c39cab487 (diff) |
drm/radeon/kms: add initial radeon tv-out support.
This ports the tv-out code from the DDX to KMS.
adds a radeon.tv module option, radeon.tv=0 to disable tv
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/atombios_crtc.c')
-rw-r--r-- | drivers/gpu/drm/radeon/atombios_crtc.c | 99 |
1 files changed, 72 insertions, 27 deletions
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 74d034f77c6b..8e31e992ec53 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c | |||
@@ -31,6 +31,10 @@ | |||
31 | #include "atom.h" | 31 | #include "atom.h" |
32 | #include "atom-bits.h" | 32 | #include "atom-bits.h" |
33 | 33 | ||
34 | /* evil but including atombios.h is much worse */ | ||
35 | bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index, | ||
36 | SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION *crtc_timing, | ||
37 | int32_t *pixel_clock); | ||
34 | static void atombios_overscan_setup(struct drm_crtc *crtc, | 38 | static void atombios_overscan_setup(struct drm_crtc *crtc, |
35 | struct drm_display_mode *mode, | 39 | struct drm_display_mode *mode, |
36 | struct drm_display_mode *adjusted_mode) | 40 | struct drm_display_mode *adjusted_mode) |
@@ -89,17 +93,32 @@ static void atombios_scaler_setup(struct drm_crtc *crtc) | |||
89 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | 93 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
90 | ENABLE_SCALER_PS_ALLOCATION args; | 94 | ENABLE_SCALER_PS_ALLOCATION args; |
91 | int index = GetIndexIntoMasterTable(COMMAND, EnableScaler); | 95 | int index = GetIndexIntoMasterTable(COMMAND, EnableScaler); |
96 | |||
92 | /* fixme - fill in enc_priv for atom dac */ | 97 | /* fixme - fill in enc_priv for atom dac */ |
93 | enum radeon_tv_std tv_std = TV_STD_NTSC; | 98 | enum radeon_tv_std tv_std = TV_STD_NTSC; |
99 | bool is_tv = false, is_cv = false; | ||
100 | struct drm_encoder *encoder; | ||
94 | 101 | ||
95 | if (!ASIC_IS_AVIVO(rdev) && radeon_crtc->crtc_id) | 102 | if (!ASIC_IS_AVIVO(rdev) && radeon_crtc->crtc_id) |
96 | return; | 103 | return; |
97 | 104 | ||
105 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | ||
106 | /* find tv std */ | ||
107 | if (encoder->crtc == crtc) { | ||
108 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
109 | if (radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT) { | ||
110 | struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv; | ||
111 | tv_std = tv_dac->tv_std; | ||
112 | is_tv = true; | ||
113 | } | ||
114 | } | ||
115 | } | ||
116 | |||
98 | memset(&args, 0, sizeof(args)); | 117 | memset(&args, 0, sizeof(args)); |
99 | 118 | ||
100 | args.ucScaler = radeon_crtc->crtc_id; | 119 | args.ucScaler = radeon_crtc->crtc_id; |
101 | 120 | ||
102 | if (radeon_crtc->devices & (ATOM_DEVICE_TV_SUPPORT)) { | 121 | if (is_tv) { |
103 | switch (tv_std) { | 122 | switch (tv_std) { |
104 | case TV_STD_NTSC: | 123 | case TV_STD_NTSC: |
105 | default: | 124 | default: |
@@ -128,7 +147,7 @@ static void atombios_scaler_setup(struct drm_crtc *crtc) | |||
128 | break; | 147 | break; |
129 | } | 148 | } |
130 | args.ucEnable = SCALER_ENABLE_MULTITAP_MODE; | 149 | args.ucEnable = SCALER_ENABLE_MULTITAP_MODE; |
131 | } else if (radeon_crtc->devices & (ATOM_DEVICE_CV_SUPPORT)) { | 150 | } else if (is_cv) { |
132 | args.ucTVStandard = ATOM_TV_CV; | 151 | args.ucTVStandard = ATOM_TV_CV; |
133 | args.ucEnable = SCALER_ENABLE_MULTITAP_MODE; | 152 | args.ucEnable = SCALER_ENABLE_MULTITAP_MODE; |
134 | } else { | 153 | } else { |
@@ -151,9 +170,9 @@ static void atombios_scaler_setup(struct drm_crtc *crtc) | |||
151 | } | 170 | } |
152 | } | 171 | } |
153 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | 172 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
154 | if (radeon_crtc->devices & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT) | 173 | if ((is_tv || is_cv) |
155 | && rdev->family >= CHIP_RV515 && rdev->family <= CHIP_RV570) { | 174 | && rdev->family >= CHIP_RV515 && rdev->family <= CHIP_R580) { |
156 | atom_rv515_force_tv_scaler(rdev); | 175 | atom_rv515_force_tv_scaler(rdev, radeon_crtc); |
157 | } | 176 | } |
158 | } | 177 | } |
159 | 178 | ||
@@ -551,42 +570,68 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc, | |||
551 | struct radeon_device *rdev = dev->dev_private; | 570 | struct radeon_device *rdev = dev->dev_private; |
552 | struct drm_encoder *encoder; | 571 | struct drm_encoder *encoder; |
553 | SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION crtc_timing; | 572 | SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION crtc_timing; |
573 | int need_tv_timings = 0; | ||
574 | bool ret; | ||
554 | 575 | ||
555 | /* TODO color tiling */ | 576 | /* TODO color tiling */ |
556 | memset(&crtc_timing, 0, sizeof(crtc_timing)); | 577 | memset(&crtc_timing, 0, sizeof(crtc_timing)); |
557 | 578 | ||
558 | /* TODO tv */ | ||
559 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | 579 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
560 | 580 | /* find tv std */ | |
581 | if (encoder->crtc == crtc) { | ||
582 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
583 | |||
584 | if (radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT) { | ||
585 | struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv; | ||
586 | if (tv_dac) { | ||
587 | if (tv_dac->tv_std == TV_STD_NTSC || | ||
588 | tv_dac->tv_std == TV_STD_NTSC_J || | ||
589 | tv_dac->tv_std == TV_STD_PAL_M) | ||
590 | need_tv_timings = 1; | ||
591 | else | ||
592 | need_tv_timings = 2; | ||
593 | break; | ||
594 | } | ||
595 | } | ||
596 | } | ||
561 | } | 597 | } |
562 | 598 | ||
563 | crtc_timing.ucCRTC = radeon_crtc->crtc_id; | 599 | crtc_timing.ucCRTC = radeon_crtc->crtc_id; |
564 | crtc_timing.usH_Total = adjusted_mode->crtc_htotal; | 600 | if (need_tv_timings) { |
565 | crtc_timing.usH_Disp = adjusted_mode->crtc_hdisplay; | 601 | ret = radeon_atom_get_tv_timings(rdev, need_tv_timings - 1, |
566 | crtc_timing.usH_SyncStart = adjusted_mode->crtc_hsync_start; | 602 | &crtc_timing, &adjusted_mode->clock); |
567 | crtc_timing.usH_SyncWidth = | 603 | if (ret == false) |
568 | adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start; | 604 | need_tv_timings = 0; |
605 | } | ||
606 | |||
607 | if (!need_tv_timings) { | ||
608 | crtc_timing.usH_Total = adjusted_mode->crtc_htotal; | ||
609 | crtc_timing.usH_Disp = adjusted_mode->crtc_hdisplay; | ||
610 | crtc_timing.usH_SyncStart = adjusted_mode->crtc_hsync_start; | ||
611 | crtc_timing.usH_SyncWidth = | ||
612 | adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start; | ||
569 | 613 | ||
570 | crtc_timing.usV_Total = adjusted_mode->crtc_vtotal; | 614 | crtc_timing.usV_Total = adjusted_mode->crtc_vtotal; |
571 | crtc_timing.usV_Disp = adjusted_mode->crtc_vdisplay; | 615 | crtc_timing.usV_Disp = adjusted_mode->crtc_vdisplay; |
572 | crtc_timing.usV_SyncStart = adjusted_mode->crtc_vsync_start; | 616 | crtc_timing.usV_SyncStart = adjusted_mode->crtc_vsync_start; |
573 | crtc_timing.usV_SyncWidth = | 617 | crtc_timing.usV_SyncWidth = |
574 | adjusted_mode->crtc_vsync_end - adjusted_mode->crtc_vsync_start; | 618 | adjusted_mode->crtc_vsync_end - adjusted_mode->crtc_vsync_start; |
575 | 619 | ||
576 | if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) | 620 | if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) |
577 | crtc_timing.susModeMiscInfo.usAccess |= ATOM_VSYNC_POLARITY; | 621 | crtc_timing.susModeMiscInfo.usAccess |= ATOM_VSYNC_POLARITY; |
578 | 622 | ||
579 | if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) | 623 | if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) |
580 | crtc_timing.susModeMiscInfo.usAccess |= ATOM_HSYNC_POLARITY; | 624 | crtc_timing.susModeMiscInfo.usAccess |= ATOM_HSYNC_POLARITY; |
581 | 625 | ||
582 | if (adjusted_mode->flags & DRM_MODE_FLAG_CSYNC) | 626 | if (adjusted_mode->flags & DRM_MODE_FLAG_CSYNC) |
583 | crtc_timing.susModeMiscInfo.usAccess |= ATOM_COMPOSITESYNC; | 627 | crtc_timing.susModeMiscInfo.usAccess |= ATOM_COMPOSITESYNC; |
584 | 628 | ||
585 | if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) | 629 | if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) |
586 | crtc_timing.susModeMiscInfo.usAccess |= ATOM_INTERLACE; | 630 | crtc_timing.susModeMiscInfo.usAccess |= ATOM_INTERLACE; |
587 | 631 | ||
588 | if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) | 632 | if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) |
589 | crtc_timing.susModeMiscInfo.usAccess |= ATOM_DOUBLE_CLOCK_MODE; | 633 | crtc_timing.susModeMiscInfo.usAccess |= ATOM_DOUBLE_CLOCK_MODE; |
634 | } | ||
590 | 635 | ||
591 | atombios_crtc_set_pll(crtc, adjusted_mode); | 636 | atombios_crtc_set_pll(crtc, adjusted_mode); |
592 | atombios_crtc_set_timing(crtc, &crtc_timing); | 637 | atombios_crtc_set_timing(crtc, &crtc_timing); |