Commit 6214bb74 authored by Alex Deucher's avatar Alex Deucher

drm/radeon: add a connector property for dither

Allows you to enable dither in the display hardware
when the monitor supports lower a lower bpc than the
current framebuffer format.
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 134b480f
......@@ -7427,10 +7427,13 @@ void dce8_program_fmt(struct drm_encoder *encoder)
struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
int bpc = 0;
u32 tmp = 0;
bool dither = false;
enum radeon_connector_dither dither = RADEON_FMT_DITHER_DISABLE;
if (connector)
if (connector) {
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
bpc = radeon_get_monitor_bpc(connector);
dither = radeon_connector->dither;
}
/* LVDS/eDP FMT is set up by atom */
if (radeon_encoder->devices & ATOM_DEVICE_LCD_SUPPORT)
......@@ -7446,7 +7449,7 @@ void dce8_program_fmt(struct drm_encoder *encoder)
switch (bpc) {
case 6:
if (dither)
if (dither == RADEON_FMT_DITHER_ENABLE)
/* XXX sort out optimal dither settings */
tmp |= (FMT_FRAME_RANDOM_ENABLE | FMT_HIGHPASS_RANDOM_ENABLE |
FMT_SPATIAL_DITHER_EN | FMT_SPATIAL_DITHER_DEPTH(0));
......@@ -7454,7 +7457,7 @@ void dce8_program_fmt(struct drm_encoder *encoder)
tmp |= (FMT_TRUNCATE_EN | FMT_TRUNCATE_DEPTH(0));
break;
case 8:
if (dither)
if (dither == RADEON_FMT_DITHER_ENABLE)
/* XXX sort out optimal dither settings */
tmp |= (FMT_FRAME_RANDOM_ENABLE | FMT_HIGHPASS_RANDOM_ENABLE |
FMT_RGB_RANDOM_ENABLE |
......@@ -7463,7 +7466,7 @@ void dce8_program_fmt(struct drm_encoder *encoder)
tmp |= (FMT_TRUNCATE_EN | FMT_TRUNCATE_DEPTH(1));
break;
case 10:
if (dither)
if (dither == RADEON_FMT_DITHER_ENABLE)
/* XXX sort out optimal dither settings */
tmp |= (FMT_FRAME_RANDOM_ENABLE | FMT_HIGHPASS_RANDOM_ENABLE |
FMT_RGB_RANDOM_ENABLE |
......
......@@ -1202,10 +1202,13 @@ void dce4_program_fmt(struct drm_encoder *encoder)
struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
int bpc = 0;
u32 tmp = 0;
bool dither = false;
enum radeon_connector_dither dither = RADEON_FMT_DITHER_DISABLE;
if (connector)
if (connector) {
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
bpc = radeon_get_monitor_bpc(connector);
dither = radeon_connector->dither;
}
/* LVDS/eDP FMT is set up by atom */
if (radeon_encoder->devices & ATOM_DEVICE_LCD_SUPPORT)
......@@ -1221,7 +1224,7 @@ void dce4_program_fmt(struct drm_encoder *encoder)
switch (bpc) {
case 6:
if (dither)
if (dither == RADEON_FMT_DITHER_ENABLE)
/* XXX sort out optimal dither settings */
tmp |= (FMT_FRAME_RANDOM_ENABLE | FMT_HIGHPASS_RANDOM_ENABLE |
FMT_SPATIAL_DITHER_EN);
......@@ -1229,7 +1232,7 @@ void dce4_program_fmt(struct drm_encoder *encoder)
tmp |= FMT_TRUNCATE_EN;
break;
case 8:
if (dither)
if (dither == RADEON_FMT_DITHER_ENABLE)
/* XXX sort out optimal dither settings */
tmp |= (FMT_FRAME_RANDOM_ENABLE | FMT_HIGHPASS_RANDOM_ENABLE |
FMT_RGB_RANDOM_ENABLE |
......
......@@ -133,10 +133,13 @@ void dce3_program_fmt(struct drm_encoder *encoder)
struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
int bpc = 0;
u32 tmp = 0;
bool dither = false;
enum radeon_connector_dither dither = RADEON_FMT_DITHER_DISABLE;
if (connector)
if (connector) {
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
bpc = radeon_get_monitor_bpc(connector);
dither = radeon_connector->dither;
}
/* LVDS FMT is set up by atom */
if (radeon_encoder->devices & ATOM_DEVICE_LCD_SUPPORT)
......@@ -152,14 +155,14 @@ void dce3_program_fmt(struct drm_encoder *encoder)
switch (bpc) {
case 6:
if (dither)
if (dither == RADEON_FMT_DITHER_ENABLE)
/* XXX sort out optimal dither settings */
tmp |= FMT_SPATIAL_DITHER_EN;
else
tmp |= FMT_TRUNCATE_EN;
break;
case 8:
if (dither)
if (dither == RADEON_FMT_DITHER_ENABLE)
/* XXX sort out optimal dither settings */
tmp |= (FMT_SPATIAL_DITHER_EN | FMT_SPATIAL_DITHER_DEPTH);
else
......
......@@ -411,6 +411,21 @@ static int radeon_connector_set_property(struct drm_connector *connector, struct
}
}
if (property == rdev->mode_info.dither_property) {
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
/* need to find digital encoder on connector */
encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS);
if (!encoder)
return 0;
radeon_encoder = to_radeon_encoder(encoder);
if (radeon_connector->dither != val) {
radeon_connector->dither = val;
radeon_property_change_mode(&radeon_encoder->base);
}
}
if (property == rdev->mode_info.underscan_property) {
/* need to find digital encoder on connector */
encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS);
......@@ -1661,6 +1676,9 @@ radeon_add_atom_connector(struct drm_device *dev,
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.audio_property,
RADEON_AUDIO_DISABLE);
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.dither_property,
RADEON_FMT_DITHER_DISABLE);
subpixel_order = SubPixelHorizontalRGB;
connector->interlace_allowed = true;
if (connector_type == DRM_MODE_CONNECTOR_HDMIB)
......@@ -1759,6 +1777,11 @@ radeon_add_atom_connector(struct drm_device *dev,
rdev->mode_info.audio_property,
RADEON_AUDIO_DISABLE);
}
if (ASIC_IS_AVIVO(rdev)) {
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.dither_property,
RADEON_FMT_DITHER_DISABLE);
}
if (connector_type == DRM_MODE_CONNECTOR_DVII) {
radeon_connector->dac_load_detect = true;
drm_object_attach_property(&radeon_connector->base.base,
......@@ -1804,6 +1827,11 @@ radeon_add_atom_connector(struct drm_device *dev,
rdev->mode_info.audio_property,
RADEON_AUDIO_DISABLE);
}
if (ASIC_IS_AVIVO(rdev)) {
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.dither_property,
RADEON_FMT_DITHER_DISABLE);
}
subpixel_order = SubPixelHorizontalRGB;
connector->interlace_allowed = true;
if (connector_type == DRM_MODE_CONNECTOR_HDMIB)
......@@ -1848,6 +1876,11 @@ radeon_add_atom_connector(struct drm_device *dev,
rdev->mode_info.audio_property,
RADEON_AUDIO_DISABLE);
}
if (ASIC_IS_AVIVO(rdev)) {
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.dither_property,
RADEON_FMT_DITHER_DISABLE);
}
connector->interlace_allowed = true;
/* in theory with a DP to VGA converter... */
connector->doublescan_allowed = false;
......
......@@ -1178,6 +1178,12 @@ static struct drm_prop_enum_list radeon_audio_enum_list[] =
{ RADEON_AUDIO_AUTO, "auto" },
};
/* XXX support different dither options? spatial, temporal, both, etc. */
static struct drm_prop_enum_list radeon_dither_enum_list[] =
{ { RADEON_FMT_DITHER_DISABLE, "off" },
{ RADEON_FMT_DITHER_ENABLE, "on" },
};
static int radeon_modeset_create_props(struct radeon_device *rdev)
{
int sz;
......@@ -1234,6 +1240,12 @@ static int radeon_modeset_create_props(struct radeon_device *rdev)
"audio",
radeon_audio_enum_list, sz);
sz = ARRAY_SIZE(radeon_dither_enum_list);
rdev->mode_info.dither_property =
drm_property_create_enum(rdev->ddev, 0,
"dither",
radeon_dither_enum_list, sz);
return 0;
}
......
......@@ -249,6 +249,8 @@ struct radeon_mode_info {
struct drm_property *underscan_vborder_property;
/* audio */
struct drm_property *audio_property;
/* FMT dithering */
struct drm_property *dither_property;
/* hardcoded DFP edid from BIOS */
struct edid *bios_hardcoded_edid;
int bios_hardcoded_edid_size;
......@@ -479,6 +481,11 @@ enum radeon_connector_audio {
RADEON_AUDIO_AUTO = 2
};
enum radeon_connector_dither {
RADEON_FMT_DITHER_DISABLE = 0,
RADEON_FMT_DITHER_ENABLE = 1,
};
struct radeon_connector {
struct drm_connector base;
uint32_t connector_id;
......@@ -498,6 +505,7 @@ struct radeon_connector {
struct radeon_router router;
struct radeon_i2c_chan *router_bus;
enum radeon_connector_audio audio;
enum radeon_connector_dither dither;
};
struct radeon_framebuffer {
......
......@@ -161,10 +161,13 @@ void avivo_program_fmt(struct drm_encoder *encoder)
struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
int bpc = 0;
u32 tmp = 0;
bool dither = false;
enum radeon_connector_dither dither = RADEON_FMT_DITHER_DISABLE;
if (connector)
if (connector) {
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
bpc = radeon_get_monitor_bpc(connector);
dither = radeon_connector->dither;
}
/* LVDS FMT is set up by atom */
if (radeon_encoder->devices & ATOM_DEVICE_LCD_SUPPORT)
......@@ -175,14 +178,14 @@ void avivo_program_fmt(struct drm_encoder *encoder)
switch (bpc) {
case 6:
if (dither)
if (dither == RADEON_FMT_DITHER_ENABLE)
/* XXX sort out optimal dither settings */
tmp |= AVIVO_TMDS_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN;
else
tmp |= AVIVO_TMDS_BIT_DEPTH_CONTROL_TRUNCATE_EN;
break;
case 8:
if (dither)
if (dither == RADEON_FMT_DITHER_ENABLE)
/* XXX sort out optimal dither settings */
tmp |= (AVIVO_TMDS_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN |
AVIVO_TMDS_BIT_DEPTH_CONTROL_SPATIAL_DITHER_DEPTH);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment