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) ...@@ -7427,10 +7427,13 @@ void dce8_program_fmt(struct drm_encoder *encoder)
struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
int bpc = 0; int bpc = 0;
u32 tmp = 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); bpc = radeon_get_monitor_bpc(connector);
dither = radeon_connector->dither;
}
/* LVDS/eDP FMT is set up by atom */ /* LVDS/eDP FMT is set up by atom */
if (radeon_encoder->devices & ATOM_DEVICE_LCD_SUPPORT) if (radeon_encoder->devices & ATOM_DEVICE_LCD_SUPPORT)
...@@ -7446,7 +7449,7 @@ void dce8_program_fmt(struct drm_encoder *encoder) ...@@ -7446,7 +7449,7 @@ void dce8_program_fmt(struct drm_encoder *encoder)
switch (bpc) { switch (bpc) {
case 6: case 6:
if (dither) if (dither == RADEON_FMT_DITHER_ENABLE)
/* XXX sort out optimal dither settings */ /* XXX sort out optimal dither settings */
tmp |= (FMT_FRAME_RANDOM_ENABLE | FMT_HIGHPASS_RANDOM_ENABLE | tmp |= (FMT_FRAME_RANDOM_ENABLE | FMT_HIGHPASS_RANDOM_ENABLE |
FMT_SPATIAL_DITHER_EN | FMT_SPATIAL_DITHER_DEPTH(0)); FMT_SPATIAL_DITHER_EN | FMT_SPATIAL_DITHER_DEPTH(0));
...@@ -7454,7 +7457,7 @@ void dce8_program_fmt(struct drm_encoder *encoder) ...@@ -7454,7 +7457,7 @@ void dce8_program_fmt(struct drm_encoder *encoder)
tmp |= (FMT_TRUNCATE_EN | FMT_TRUNCATE_DEPTH(0)); tmp |= (FMT_TRUNCATE_EN | FMT_TRUNCATE_DEPTH(0));
break; break;
case 8: case 8:
if (dither) if (dither == RADEON_FMT_DITHER_ENABLE)
/* XXX sort out optimal dither settings */ /* XXX sort out optimal dither settings */
tmp |= (FMT_FRAME_RANDOM_ENABLE | FMT_HIGHPASS_RANDOM_ENABLE | tmp |= (FMT_FRAME_RANDOM_ENABLE | FMT_HIGHPASS_RANDOM_ENABLE |
FMT_RGB_RANDOM_ENABLE | FMT_RGB_RANDOM_ENABLE |
...@@ -7463,7 +7466,7 @@ void dce8_program_fmt(struct drm_encoder *encoder) ...@@ -7463,7 +7466,7 @@ void dce8_program_fmt(struct drm_encoder *encoder)
tmp |= (FMT_TRUNCATE_EN | FMT_TRUNCATE_DEPTH(1)); tmp |= (FMT_TRUNCATE_EN | FMT_TRUNCATE_DEPTH(1));
break; break;
case 10: case 10:
if (dither) if (dither == RADEON_FMT_DITHER_ENABLE)
/* XXX sort out optimal dither settings */ /* XXX sort out optimal dither settings */
tmp |= (FMT_FRAME_RANDOM_ENABLE | FMT_HIGHPASS_RANDOM_ENABLE | tmp |= (FMT_FRAME_RANDOM_ENABLE | FMT_HIGHPASS_RANDOM_ENABLE |
FMT_RGB_RANDOM_ENABLE | FMT_RGB_RANDOM_ENABLE |
......
...@@ -1202,10 +1202,13 @@ void dce4_program_fmt(struct drm_encoder *encoder) ...@@ -1202,10 +1202,13 @@ void dce4_program_fmt(struct drm_encoder *encoder)
struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
int bpc = 0; int bpc = 0;
u32 tmp = 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); bpc = radeon_get_monitor_bpc(connector);
dither = radeon_connector->dither;
}
/* LVDS/eDP FMT is set up by atom */ /* LVDS/eDP FMT is set up by atom */
if (radeon_encoder->devices & ATOM_DEVICE_LCD_SUPPORT) if (radeon_encoder->devices & ATOM_DEVICE_LCD_SUPPORT)
...@@ -1221,7 +1224,7 @@ void dce4_program_fmt(struct drm_encoder *encoder) ...@@ -1221,7 +1224,7 @@ void dce4_program_fmt(struct drm_encoder *encoder)
switch (bpc) { switch (bpc) {
case 6: case 6:
if (dither) if (dither == RADEON_FMT_DITHER_ENABLE)
/* XXX sort out optimal dither settings */ /* XXX sort out optimal dither settings */
tmp |= (FMT_FRAME_RANDOM_ENABLE | FMT_HIGHPASS_RANDOM_ENABLE | tmp |= (FMT_FRAME_RANDOM_ENABLE | FMT_HIGHPASS_RANDOM_ENABLE |
FMT_SPATIAL_DITHER_EN); FMT_SPATIAL_DITHER_EN);
...@@ -1229,7 +1232,7 @@ void dce4_program_fmt(struct drm_encoder *encoder) ...@@ -1229,7 +1232,7 @@ void dce4_program_fmt(struct drm_encoder *encoder)
tmp |= FMT_TRUNCATE_EN; tmp |= FMT_TRUNCATE_EN;
break; break;
case 8: case 8:
if (dither) if (dither == RADEON_FMT_DITHER_ENABLE)
/* XXX sort out optimal dither settings */ /* XXX sort out optimal dither settings */
tmp |= (FMT_FRAME_RANDOM_ENABLE | FMT_HIGHPASS_RANDOM_ENABLE | tmp |= (FMT_FRAME_RANDOM_ENABLE | FMT_HIGHPASS_RANDOM_ENABLE |
FMT_RGB_RANDOM_ENABLE | FMT_RGB_RANDOM_ENABLE |
......
...@@ -133,10 +133,13 @@ void dce3_program_fmt(struct drm_encoder *encoder) ...@@ -133,10 +133,13 @@ void dce3_program_fmt(struct drm_encoder *encoder)
struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
int bpc = 0; int bpc = 0;
u32 tmp = 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); bpc = radeon_get_monitor_bpc(connector);
dither = radeon_connector->dither;
}
/* LVDS FMT is set up by atom */ /* LVDS FMT is set up by atom */
if (radeon_encoder->devices & ATOM_DEVICE_LCD_SUPPORT) if (radeon_encoder->devices & ATOM_DEVICE_LCD_SUPPORT)
...@@ -152,14 +155,14 @@ void dce3_program_fmt(struct drm_encoder *encoder) ...@@ -152,14 +155,14 @@ void dce3_program_fmt(struct drm_encoder *encoder)
switch (bpc) { switch (bpc) {
case 6: case 6:
if (dither) if (dither == RADEON_FMT_DITHER_ENABLE)
/* XXX sort out optimal dither settings */ /* XXX sort out optimal dither settings */
tmp |= FMT_SPATIAL_DITHER_EN; tmp |= FMT_SPATIAL_DITHER_EN;
else else
tmp |= FMT_TRUNCATE_EN; tmp |= FMT_TRUNCATE_EN;
break; break;
case 8: case 8:
if (dither) if (dither == RADEON_FMT_DITHER_ENABLE)
/* XXX sort out optimal dither settings */ /* XXX sort out optimal dither settings */
tmp |= (FMT_SPATIAL_DITHER_EN | FMT_SPATIAL_DITHER_DEPTH); tmp |= (FMT_SPATIAL_DITHER_EN | FMT_SPATIAL_DITHER_DEPTH);
else else
......
...@@ -411,6 +411,21 @@ static int radeon_connector_set_property(struct drm_connector *connector, struct ...@@ -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) { if (property == rdev->mode_info.underscan_property) {
/* need to find digital encoder on connector */ /* need to find digital encoder on connector */
encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS); encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS);
...@@ -1661,6 +1676,9 @@ radeon_add_atom_connector(struct drm_device *dev, ...@@ -1661,6 +1676,9 @@ radeon_add_atom_connector(struct drm_device *dev,
drm_object_attach_property(&radeon_connector->base.base, drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.audio_property, rdev->mode_info.audio_property,
RADEON_AUDIO_DISABLE); RADEON_AUDIO_DISABLE);
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.dither_property,
RADEON_FMT_DITHER_DISABLE);
subpixel_order = SubPixelHorizontalRGB; subpixel_order = SubPixelHorizontalRGB;
connector->interlace_allowed = true; connector->interlace_allowed = true;
if (connector_type == DRM_MODE_CONNECTOR_HDMIB) if (connector_type == DRM_MODE_CONNECTOR_HDMIB)
...@@ -1759,6 +1777,11 @@ radeon_add_atom_connector(struct drm_device *dev, ...@@ -1759,6 +1777,11 @@ radeon_add_atom_connector(struct drm_device *dev,
rdev->mode_info.audio_property, rdev->mode_info.audio_property,
RADEON_AUDIO_DISABLE); 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) { if (connector_type == DRM_MODE_CONNECTOR_DVII) {
radeon_connector->dac_load_detect = true; radeon_connector->dac_load_detect = true;
drm_object_attach_property(&radeon_connector->base.base, drm_object_attach_property(&radeon_connector->base.base,
...@@ -1804,6 +1827,11 @@ radeon_add_atom_connector(struct drm_device *dev, ...@@ -1804,6 +1827,11 @@ radeon_add_atom_connector(struct drm_device *dev,
rdev->mode_info.audio_property, rdev->mode_info.audio_property,
RADEON_AUDIO_DISABLE); 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; subpixel_order = SubPixelHorizontalRGB;
connector->interlace_allowed = true; connector->interlace_allowed = true;
if (connector_type == DRM_MODE_CONNECTOR_HDMIB) if (connector_type == DRM_MODE_CONNECTOR_HDMIB)
...@@ -1848,6 +1876,11 @@ radeon_add_atom_connector(struct drm_device *dev, ...@@ -1848,6 +1876,11 @@ radeon_add_atom_connector(struct drm_device *dev,
rdev->mode_info.audio_property, rdev->mode_info.audio_property,
RADEON_AUDIO_DISABLE); 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; connector->interlace_allowed = true;
/* in theory with a DP to VGA converter... */ /* in theory with a DP to VGA converter... */
connector->doublescan_allowed = false; connector->doublescan_allowed = false;
......
...@@ -1178,6 +1178,12 @@ static struct drm_prop_enum_list radeon_audio_enum_list[] = ...@@ -1178,6 +1178,12 @@ static struct drm_prop_enum_list radeon_audio_enum_list[] =
{ RADEON_AUDIO_AUTO, "auto" }, { 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) static int radeon_modeset_create_props(struct radeon_device *rdev)
{ {
int sz; int sz;
...@@ -1234,6 +1240,12 @@ static int radeon_modeset_create_props(struct radeon_device *rdev) ...@@ -1234,6 +1240,12 @@ static int radeon_modeset_create_props(struct radeon_device *rdev)
"audio", "audio",
radeon_audio_enum_list, sz); 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; return 0;
} }
......
...@@ -249,6 +249,8 @@ struct radeon_mode_info { ...@@ -249,6 +249,8 @@ struct radeon_mode_info {
struct drm_property *underscan_vborder_property; struct drm_property *underscan_vborder_property;
/* audio */ /* audio */
struct drm_property *audio_property; struct drm_property *audio_property;
/* FMT dithering */
struct drm_property *dither_property;
/* hardcoded DFP edid from BIOS */ /* hardcoded DFP edid from BIOS */
struct edid *bios_hardcoded_edid; struct edid *bios_hardcoded_edid;
int bios_hardcoded_edid_size; int bios_hardcoded_edid_size;
...@@ -479,6 +481,11 @@ enum radeon_connector_audio { ...@@ -479,6 +481,11 @@ enum radeon_connector_audio {
RADEON_AUDIO_AUTO = 2 RADEON_AUDIO_AUTO = 2
}; };
enum radeon_connector_dither {
RADEON_FMT_DITHER_DISABLE = 0,
RADEON_FMT_DITHER_ENABLE = 1,
};
struct radeon_connector { struct radeon_connector {
struct drm_connector base; struct drm_connector base;
uint32_t connector_id; uint32_t connector_id;
...@@ -498,6 +505,7 @@ struct radeon_connector { ...@@ -498,6 +505,7 @@ struct radeon_connector {
struct radeon_router router; struct radeon_router router;
struct radeon_i2c_chan *router_bus; struct radeon_i2c_chan *router_bus;
enum radeon_connector_audio audio; enum radeon_connector_audio audio;
enum radeon_connector_dither dither;
}; };
struct radeon_framebuffer { struct radeon_framebuffer {
......
...@@ -161,10 +161,13 @@ void avivo_program_fmt(struct drm_encoder *encoder) ...@@ -161,10 +161,13 @@ void avivo_program_fmt(struct drm_encoder *encoder)
struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
int bpc = 0; int bpc = 0;
u32 tmp = 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); bpc = radeon_get_monitor_bpc(connector);
dither = radeon_connector->dither;
}
/* LVDS FMT is set up by atom */ /* LVDS FMT is set up by atom */
if (radeon_encoder->devices & ATOM_DEVICE_LCD_SUPPORT) if (radeon_encoder->devices & ATOM_DEVICE_LCD_SUPPORT)
...@@ -175,14 +178,14 @@ void avivo_program_fmt(struct drm_encoder *encoder) ...@@ -175,14 +178,14 @@ void avivo_program_fmt(struct drm_encoder *encoder)
switch (bpc) { switch (bpc) {
case 6: case 6:
if (dither) if (dither == RADEON_FMT_DITHER_ENABLE)
/* XXX sort out optimal dither settings */ /* XXX sort out optimal dither settings */
tmp |= AVIVO_TMDS_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN; tmp |= AVIVO_TMDS_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN;
else else
tmp |= AVIVO_TMDS_BIT_DEPTH_CONTROL_TRUNCATE_EN; tmp |= AVIVO_TMDS_BIT_DEPTH_CONTROL_TRUNCATE_EN;
break; break;
case 8: case 8:
if (dither) if (dither == RADEON_FMT_DITHER_ENABLE)
/* XXX sort out optimal dither settings */ /* XXX sort out optimal dither settings */
tmp |= (AVIVO_TMDS_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN | tmp |= (AVIVO_TMDS_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN |
AVIVO_TMDS_BIT_DEPTH_CONTROL_SPATIAL_DITHER_DEPTH); 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