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>
This commit is contained in:
@@ -28,6 +28,7 @@
|
||||
#include <drm/radeon_drm.h>
|
||||
#include "radeon_fixed.h"
|
||||
#include "radeon.h"
|
||||
#include "atom.h"
|
||||
|
||||
static void radeon_legacy_rmx_mode_set(struct drm_crtc *crtc,
|
||||
struct drm_display_mode *mode,
|
||||
@@ -501,6 +502,7 @@ static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mod
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
|
||||
struct drm_encoder *encoder;
|
||||
int format;
|
||||
int hsync_start;
|
||||
int hsync_wid;
|
||||
@@ -509,8 +511,19 @@ static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mod
|
||||
uint32_t crtc_h_sync_strt_wid;
|
||||
uint32_t crtc_v_total_disp;
|
||||
uint32_t crtc_v_sync_strt_wid;
|
||||
bool is_tv = false;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
||||
if (encoder->crtc == crtc) {
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
if (radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT) {
|
||||
is_tv = true;
|
||||
DRM_INFO("crtc %d is connected to a TV\n", radeon_crtc->crtc_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (crtc->fb->bits_per_pixel) {
|
||||
case 15: /* 555 */
|
||||
@@ -642,6 +655,11 @@ static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mod
|
||||
WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
|
||||
}
|
||||
|
||||
if (is_tv)
|
||||
radeon_legacy_tv_adjust_crtc_reg(encoder, &crtc_h_total_disp,
|
||||
&crtc_h_sync_strt_wid, &crtc_v_total_disp,
|
||||
&crtc_v_sync_strt_wid);
|
||||
|
||||
WREG32(RADEON_CRTC_H_TOTAL_DISP + radeon_crtc->crtc_offset, crtc_h_total_disp);
|
||||
WREG32(RADEON_CRTC_H_SYNC_STRT_WID + radeon_crtc->crtc_offset, crtc_h_sync_strt_wid);
|
||||
WREG32(RADEON_CRTC_V_TOTAL_DISP + radeon_crtc->crtc_offset, crtc_v_total_disp);
|
||||
@@ -668,7 +686,7 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
|
||||
uint32_t pll_ref_div = 0;
|
||||
uint32_t pll_fb_post_div = 0;
|
||||
uint32_t htotal_cntl = 0;
|
||||
|
||||
bool is_tv = false;
|
||||
struct radeon_pll *pll;
|
||||
|
||||
struct {
|
||||
@@ -703,6 +721,13 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
|
||||
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
||||
if (encoder->crtc == crtc) {
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
|
||||
if (radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT) {
|
||||
is_tv = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (encoder->encoder_type != DRM_MODE_ENCODER_DAC)
|
||||
pll_flags |= RADEON_PLL_NO_ODD_POST_DIV;
|
||||
if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) {
|
||||
@@ -766,6 +791,12 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
|
||||
~(RADEON_PIX2CLK_SRC_SEL_MASK)) |
|
||||
RADEON_PIX2CLK_SRC_SEL_P2PLLCLK);
|
||||
|
||||
if (is_tv) {
|
||||
radeon_legacy_tv_adjust_pll2(encoder, &htotal_cntl,
|
||||
&pll_ref_div, &pll_fb_post_div,
|
||||
&pixclks_cntl);
|
||||
}
|
||||
|
||||
WREG32_PLL_P(RADEON_PIXCLKS_CNTL,
|
||||
RADEON_PIX2CLK_SRC_SEL_CPUCLK,
|
||||
~(RADEON_PIX2CLK_SRC_SEL_MASK));
|
||||
@@ -820,6 +851,15 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
|
||||
|
||||
WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
|
||||
} else {
|
||||
uint32_t pixclks_cntl;
|
||||
|
||||
|
||||
if (is_tv) {
|
||||
pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL);
|
||||
radeon_legacy_tv_adjust_pll1(encoder, &htotal_cntl, &pll_ref_div,
|
||||
&pll_fb_post_div, &pixclks_cntl);
|
||||
}
|
||||
|
||||
if (rdev->flags & RADEON_IS_MOBILITY) {
|
||||
/* A temporal workaround for the occational blanking on certain laptop panels.
|
||||
This appears to related to the PLL divider registers (fail to lock?).
|
||||
@@ -914,6 +954,8 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
|
||||
RADEON_VCLK_SRC_SEL_PPLLCLK,
|
||||
~(RADEON_VCLK_SRC_SEL_MASK));
|
||||
|
||||
if (is_tv)
|
||||
WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user