From db11a801a300c2fdd0752c03ac479f148f709c71 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 8 Mar 2012 10:22:20 +0000 Subject: [PATCH] drm/radeon/kms: implement legacy tv properties for horiz size, pos and vert pos (v5) These were exposed in the UMS driver, but never over KMS, expose over KMS. v2: update tv_on var. v3: maybe negative values aren't working v4: adjust values back down for programming to hw. v5: fixup values and allow hpos to be done in increments of one. Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_connectors.c | 39 +++++++++++++++++++++++ drivers/gpu/drm/radeon/radeon_display.c | 27 ++++++++++++++++ drivers/gpu/drm/radeon/radeon_legacy_encoders.c | 5 +++ drivers/gpu/drm/radeon/radeon_legacy_tv.c | 32 ++++++++++++++---- drivers/gpu/drm/radeon/radeon_mode.h | 11 ++++++ 5 files changed, 107 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 8c9a811..680bfc7 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -427,6 +427,32 @@ int radeon_connector_set_property(struct drm_connector *connector, struct drm_pr radeon_property_change_mode(&radeon_encoder->base); } + if (property == rdev->mode_info.tv_hsize_property || + property == rdev->mode_info.tv_hpos_property || + property == rdev->mode_info.tv_vpos_property) { + struct radeon_encoder_tv_dac *dac_int; + encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TVDAC); + if (!encoder) { + encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_DAC); + } + + if (!encoder) + return 0; + + radeon_encoder = to_radeon_encoder(encoder); + if (!radeon_encoder->enc_priv) + return 0; + + dac_int = radeon_encoder->enc_priv; + if (property == rdev->mode_info.tv_hsize_property) + dac_int->h_size = val; + else if (property == rdev->mode_info.tv_hpos_property) + dac_int->h_pos = val; + else if (property == rdev->mode_info.tv_vpos_property) + dac_int->v_pos = val; + if (dac_int->tv_on) + radeon_legacy_tv_update_hv_position(encoder); + } return 0; } @@ -1873,6 +1899,19 @@ radeon_add_legacy_connector(struct drm_device *dev, drm_connector_attach_property(&radeon_connector->base, rdev->mode_info.tv_std_property, radeon_combios_get_tv_info(rdev)); + + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.tv_hsize_property, + MAX_H_SIZE / 2); + + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.tv_hpos_property, + MAX_H_POSITION / 2); + + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.tv_vpos_property, + MAX_V_POSITION / 2); + /* no HPD on analog connectors */ radeon_connector->hpd.hpd = RADEON_HPD_NONE; connector->interlace_allowed = false; diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 3d31433..d3ae7b2 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -1246,6 +1246,33 @@ static int radeon_modeset_create_props(struct radeon_device *rdev) rdev->mode_info.underscan_vborder_property->values[0] = 0; rdev->mode_info.underscan_vborder_property->values[1] = 128; + rdev->mode_info.tv_hsize_property = + drm_property_create(rdev->ddev, + DRM_MODE_PROP_RANGE, + "tv horizontal size", 2); + if (!rdev->mode_info.tv_hsize_property) + return -ENOMEM; + rdev->mode_info.tv_hsize_property->values[0] = 0; + rdev->mode_info.tv_hsize_property->values[1] = MAX_H_SIZE; + + rdev->mode_info.tv_hpos_property = + drm_property_create(rdev->ddev, + DRM_MODE_PROP_RANGE, + "tv horizontal position", 2); + if (!rdev->mode_info.tv_hpos_property) + return -ENOMEM; + rdev->mode_info.tv_hpos_property->values[0] = 0; + rdev->mode_info.tv_hpos_property->values[1] = MAX_H_POSITION; + + rdev->mode_info.tv_vpos_property = + drm_property_create(rdev->ddev, + DRM_MODE_PROP_RANGE, + "tv vertical position", 2); + if (!rdev->mode_info.tv_vpos_property) + return -ENOMEM; + rdev->mode_info.tv_vpos_property->values[0] = 0; + rdev->mode_info.tv_vpos_property->values[1] = MAX_V_POSITION; + return 0; } diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index 2f46e0c..1ba0d42 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -1002,6 +1002,7 @@ static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode) struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv; uint32_t fp2_gen_cntl = 0, crtc2_gen_cntl = 0, tv_dac_cntl = 0; uint32_t tv_master_cntl = 0; bool is_tv; @@ -1042,6 +1043,8 @@ static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode) RADEON_TV_DAC_BDACPD | RADEON_TV_DAC_BGSLEEP); } + if (is_tv) + tv_dac->tv_on = true; break; case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_SUSPEND: @@ -1067,6 +1070,8 @@ static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode) RADEON_TV_DAC_BDACPD | RADEON_TV_DAC_BGSLEEP); } + if (is_tv) + tv_dac->tv_on = false; break; } diff --git a/drivers/gpu/drm/radeon/radeon_legacy_tv.c b/drivers/gpu/drm/radeon/radeon_legacy_tv.c index b37ec0f..25e1a9b 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_tv.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_tv.c @@ -11,8 +11,6 @@ /* * Limits of h/v positions (hPos & vPos) */ -#define MAX_H_POSITION 5 /* Range: [-5..5], negative is on the left, 0 is default, positive is on the right */ -#define MAX_V_POSITION 5 /* Range: [-5..5], negative is up, 0 is default, positive is down */ /* * Unit for hPos (in TV clock periods) @@ -25,10 +23,6 @@ #define H_TABLE_POS1 6 #define H_TABLE_POS2 8 -/* - * Limits of hor. size (hSize) - */ -#define MAX_H_SIZE 5 /* Range: [-5..5], negative is smaller, positive is larger */ /* tv standard constants */ #define NTSC_TV_CLOCK_T 233 @@ -455,7 +449,7 @@ static bool radeon_legacy_tv_init_restarts(struct drm_encoder *encoder) f_total = PAL_TV_VFTOTAL + 1; /* adjust positions 1&2 in hor. cod timing table */ - h_offset = tv_dac->h_pos * H_POS_UNIT; + h_offset = tv_dac->h_pos; if (tv_dac->tv_std == TV_STD_NTSC || tv_dac->tv_std == TV_STD_NTSC_J || @@ -921,3 +915,27 @@ void radeon_legacy_tv_adjust_pll2(struct drm_encoder *encoder, *pixclks_cntl |= RADEON_PIX2CLK_SRC_SEL_P2PLLCLK | RADEON_PIXCLK_TV_SRC_SEL; } +void radeon_legacy_tv_update_hv_position(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + bool reload_table; + uint32_t tmp; + + reload_table = radeon_legacy_tv_init_restarts(encoder); + + radeon_legacy_write_tv_restarts(radeon_encoder); + + WREG32(RADEON_TV_TIMING_CNTL, RREG32(RADEON_TV_TIMING_CNTL)); + + if (reload_table) { + tmp = RREG32(RADEON_TV_MASTER_CNTL); + WREG32(RADEON_TV_MASTER_CNTL, tmp | RADEON_TV_ASYNC_RST | + RADEON_CRT_ASYNC_RST | RADEON_RESTART_PHASE_FIX); + + radeon_restore_tv_timing_tables(radeon_encoder); + + WREG32(RADEON_TV_MASTER_CNTL, tmp); + } +} diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 8a85598..7f30b9f 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -231,6 +231,9 @@ struct radeon_mode_info { struct drm_property *load_detect_property; /* TV standard */ struct drm_property *tv_std_property; + struct drm_property *tv_hsize_property; + struct drm_property *tv_hpos_property; + struct drm_property *tv_vpos_property; /* legacy TMDS PLL detect */ struct drm_property *tmds_pll_property; /* underscan */ @@ -245,6 +248,13 @@ struct radeon_mode_info { struct radeon_fbdev *rfbdev; }; +#define MAX_H_POSITION 100 /* Range: [0..100], 50 is in the middle, 0-25 on the left, 50 is default, > 50 is on the right */ +#define MAX_V_POSITION 10 /* Range: [0..10], 5 is in the middle */ +/* + * Limits of hor. size (hSize) + */ +#define MAX_H_SIZE 10 /* Range: [0..10], 5 is middle < 5 is smaller, > 5 is larger */ + #define MAX_H_CODE_TIMING_LEN 32 #define MAX_V_CODE_TIMING_LEN 32 @@ -690,6 +700,7 @@ void radeon_legacy_tv_adjust_pll2(struct drm_encoder *encoder, void radeon_legacy_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); +void radeon_legacy_tv_update_hv_position(struct drm_encoder *encoder); /* fbdev layer */ int radeon_fbdev_init(struct radeon_device *rdev); -- 1.7.7.6