From 9a57d80a114fd0fafd506bdb1ac0e55937c81336 Mon Sep 17 00:00:00 2001 From: fritsch Date: Mon, 23 Feb 2015 20:53:27 +0100 Subject: [PATCH] linux: implement limited color range for amd dce6+ asics (agd5f) --- ...linux-999.10-amd-limited-color-range.patch | 273 ++++++++++++++++++ 1 file changed, 273 insertions(+) create mode 100644 packages/linux/patches/3.19.1/linux-999.10-amd-limited-color-range.patch diff --git a/packages/linux/patches/3.19.1/linux-999.10-amd-limited-color-range.patch b/packages/linux/patches/3.19.1/linux-999.10-amd-limited-color-range.patch new file mode 100644 index 0000000000..54a0772493 --- /dev/null +++ b/packages/linux/patches/3.19.1/linux-999.10-amd-limited-color-range.patch @@ -0,0 +1,273 @@ +From 7b3d1747b3345ecc7b1d49b7b920b7ada5e1eb36 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Mon, 23 Feb 2015 10:11:49 -0500 +Subject: [PATCH 1/2] drm/radeon: add an output_csc property + +This adds the drm property for output csc (e.g., +transform of output display colorspace). Currently +only common ones (TV RGB, BT.601, BT.709) are supported, +but bypass and tv rgb are really the only useful ones at +the moment. Additionally we could expose a user adjustable +matrix in the future. + +This commit just adds the property. The hw support will +be added in subsequent patches. + +bug: +https://bugs.freedesktop.org/show_bug.cgi?id=83226 + +Signed-off-by: Alex Deucher +--- + drivers/gpu/drm/radeon/radeon_display.c | 13 +++++++++++++ + drivers/gpu/drm/radeon/radeon_mode.h | 9 +++++++++ + 2 files changed, 22 insertions(+) + +diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c +index 913fafa..d57dfb9 100644 +--- a/drivers/gpu/drm/radeon/radeon_display.c ++++ b/drivers/gpu/drm/radeon/radeon_display.c +@@ -1382,6 +1382,13 @@ static struct drm_prop_enum_list radeon_dither_enum_list[] = + { RADEON_FMT_DITHER_ENABLE, "on" }, + }; + ++static struct drm_prop_enum_list radeon_output_csc_enum_list[] = ++{ { RADEON_OUTPUT_CSC_BYPASS, "bypass" }, ++ { RADEON_OUTPUT_CSC_TVRGB, "tvrgb" }, ++ { RADEON_OUTPUT_CSC_YCBCR601, "ycbcr601" }, ++ { RADEON_OUTPUT_CSC_YCBCR709, "ycbcr709" }, ++}; ++ + static int radeon_modeset_create_props(struct radeon_device *rdev) + { + int sz; +@@ -1444,6 +1451,12 @@ static int radeon_modeset_create_props(struct radeon_device *rdev) + "dither", + radeon_dither_enum_list, sz); + ++ sz = ARRAY_SIZE(radeon_output_csc_enum_list); ++ rdev->mode_info.output_csc_property = ++ drm_property_create_enum(rdev->ddev, 0, ++ "output_csc", ++ radeon_output_csc_enum_list, sz); ++ + return 0; + } + +diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h +index 390db89..d912939 100644 +--- a/drivers/gpu/drm/radeon/radeon_mode.h ++++ b/drivers/gpu/drm/radeon/radeon_mode.h +@@ -85,6 +85,13 @@ enum radeon_hpd_id { + RADEON_HPD_NONE = 0xff, + }; + ++enum radeon_output_csc { ++ RADEON_OUTPUT_CSC_BYPASS = 0, ++ RADEON_OUTPUT_CSC_TVRGB = 1, ++ RADEON_OUTPUT_CSC_YCBCR601 = 2, ++ RADEON_OUTPUT_CSC_YCBCR709 = 3, ++}; ++ + #define RADEON_MAX_I2C_BUS 16 + + /* radeon gpio-based i2c +@@ -255,6 +262,8 @@ struct radeon_mode_info { + struct drm_property *audio_property; + /* FMT dithering */ + struct drm_property *dither_property; ++ /* Output CSC */ ++ struct drm_property *output_csc_property; + /* hardcoded DFP edid from BIOS */ + struct edid *bios_hardcoded_edid; + int bios_hardcoded_edid_size; +-- +1.9.1 + + +From d0208d7f03c19ad3ec6d486bf95836679ad31d02 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Mon, 23 Feb 2015 10:59:36 -0500 +Subject: [PATCH 2/2] drm/radeon: implement output csc property for DCE5+ + +Implement the property for DCE5+ asics. Older asics +require a slightly more complex process. + +bug: +https://bugs.freedesktop.org/show_bug.cgi?id=83226 + +Signed-off-by: Alex Deucher + +Conflicts: + drivers/gpu/drm/radeon/radeon_mode.h +--- + drivers/gpu/drm/radeon/atombios_crtc.c | 6 ++++ + drivers/gpu/drm/radeon/radeon_connectors.c | 52 ++++++++++++++++++++++++++++++ + drivers/gpu/drm/radeon/radeon_display.c | 2 +- + drivers/gpu/drm/radeon/radeon_mode.h | 2 ++ + 4 files changed, 61 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c +index ed644a4..7d827cb 100644 +--- a/drivers/gpu/drm/radeon/atombios_crtc.c ++++ b/drivers/gpu/drm/radeon/atombios_crtc.c +@@ -2066,6 +2066,12 @@ static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc, + radeon_crtc->connector = NULL; + return false; + } ++ if (radeon_crtc->encoder) { ++ struct radeon_encoder *radeon_encoder = ++ to_radeon_encoder(radeon_crtc->encoder); ++ ++ radeon_crtc->output_csc = radeon_encoder->output_csc; ++ } + if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode)) + return false; + if (!atombios_crtc_prepare_pll(crtc, adjusted_mode)) +diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c +index 26baa9c..aa68f8c 100644 +--- a/drivers/gpu/drm/radeon/radeon_connectors.c ++++ b/drivers/gpu/drm/radeon/radeon_connectors.c +@@ -724,6 +724,30 @@ static int radeon_connector_set_property(struct drm_connector *connector, struct + radeon_property_change_mode(&radeon_encoder->base); + } + ++ if (property == rdev->mode_info.output_csc_property) { ++ if (connector->encoder) ++ radeon_encoder = to_radeon_encoder(connector->encoder); ++ else { ++ struct drm_connector_helper_funcs *connector_funcs = connector->helper_private; ++ radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector)); ++ } ++ ++ if (radeon_encoder->output_csc == val) ++ return 0; ++ ++ radeon_encoder->output_csc = val; ++ ++ if (connector->encoder->crtc) { ++ struct drm_crtc *crtc = connector->encoder->crtc; ++ struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; ++ struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); ++ ++ radeon_crtc->output_csc = radeon_encoder->output_csc; ++ ++ (*crtc_funcs->load_lut)(crtc); ++ } ++ } ++ + return 0; + } + +@@ -1864,6 +1888,10 @@ radeon_add_atom_connector(struct drm_device *dev, + drm_object_attach_property(&radeon_connector->base.base, + dev->mode_config.scaling_mode_property, + DRM_MODE_SCALE_NONE); ++ if (ASIC_IS_DCE5(rdev)) ++ drm_object_attach_property(&radeon_connector->base.base, ++ rdev->mode_info.output_csc_property, ++ RADEON_OUTPUT_CSC_BYPASS); + break; + case DRM_MODE_CONNECTOR_DVII: + case DRM_MODE_CONNECTOR_DVID: +@@ -1896,6 +1924,10 @@ radeon_add_atom_connector(struct drm_device *dev, + drm_object_attach_property(&radeon_connector->base.base, + rdev->mode_info.audio_property, + RADEON_AUDIO_AUTO); ++ if (ASIC_IS_DCE5(rdev)) ++ drm_object_attach_property(&radeon_connector->base.base, ++ rdev->mode_info.output_csc_property, ++ RADEON_OUTPUT_CSC_BYPASS); + + subpixel_order = SubPixelHorizontalRGB; + connector->interlace_allowed = true; +@@ -1942,6 +1974,10 @@ radeon_add_atom_connector(struct drm_device *dev, + drm_object_attach_property(&radeon_connector->base.base, + dev->mode_config.scaling_mode_property, + DRM_MODE_SCALE_NONE); ++ if (ASIC_IS_DCE5(rdev)) ++ drm_object_attach_property(&radeon_connector->base.base, ++ rdev->mode_info.output_csc_property, ++ RADEON_OUTPUT_CSC_BYPASS); + /* no HPD on analog connectors */ + radeon_connector->hpd.hpd = RADEON_HPD_NONE; + connector->polled = DRM_CONNECTOR_POLL_CONNECT; +@@ -1964,6 +2000,10 @@ radeon_add_atom_connector(struct drm_device *dev, + drm_object_attach_property(&radeon_connector->base.base, + dev->mode_config.scaling_mode_property, + DRM_MODE_SCALE_NONE); ++ if (ASIC_IS_DCE5(rdev)) ++ drm_object_attach_property(&radeon_connector->base.base, ++ rdev->mode_info.output_csc_property, ++ RADEON_OUTPUT_CSC_BYPASS); + /* no HPD on analog connectors */ + radeon_connector->hpd.hpd = RADEON_HPD_NONE; + connector->interlace_allowed = true; +@@ -2015,6 +2055,10 @@ radeon_add_atom_connector(struct drm_device *dev, + rdev->mode_info.load_detect_property, + 1); + } ++ if (ASIC_IS_DCE5(rdev)) ++ drm_object_attach_property(&radeon_connector->base.base, ++ rdev->mode_info.output_csc_property, ++ RADEON_OUTPUT_CSC_BYPASS); + connector->interlace_allowed = true; + if (connector_type == DRM_MODE_CONNECTOR_DVII) + connector->doublescan_allowed = true; +@@ -2060,6 +2104,10 @@ radeon_add_atom_connector(struct drm_device *dev, + rdev->mode_info.audio_property, + RADEON_AUDIO_AUTO); + } ++ if (ASIC_IS_DCE5(rdev)) ++ drm_object_attach_property(&radeon_connector->base.base, ++ rdev->mode_info.output_csc_property, ++ RADEON_OUTPUT_CSC_BYPASS); + subpixel_order = SubPixelHorizontalRGB; + connector->interlace_allowed = true; + if (connector_type == DRM_MODE_CONNECTOR_HDMIB) +@@ -2108,6 +2156,10 @@ radeon_add_atom_connector(struct drm_device *dev, + rdev->mode_info.audio_property, + RADEON_AUDIO_AUTO); + } ++ if (ASIC_IS_DCE5(rdev)) ++ drm_object_attach_property(&radeon_connector->base.base, ++ rdev->mode_info.output_csc_property, ++ RADEON_OUTPUT_CSC_BYPASS); + connector->interlace_allowed = true; + /* in theory with a DP to VGA converter... */ + connector->doublescan_allowed = false; +diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c +index d57dfb9..d2e9e9e 100644 +--- a/drivers/gpu/drm/radeon/radeon_display.c ++++ b/drivers/gpu/drm/radeon/radeon_display.c +@@ -154,7 +154,7 @@ static void dce5_crtc_load_lut(struct drm_crtc *crtc) + (NI_GRPH_REGAMMA_MODE(NI_REGAMMA_BYPASS) | + NI_OVL_REGAMMA_MODE(NI_REGAMMA_BYPASS))); + WREG32(NI_OUTPUT_CSC_CONTROL + radeon_crtc->crtc_offset, +- (NI_OUTPUT_CSC_GRPH_MODE(NI_OUTPUT_CSC_BYPASS) | ++ (NI_OUTPUT_CSC_GRPH_MODE(radeon_crtc->output_csc) | + NI_OUTPUT_CSC_OVL_MODE(NI_OUTPUT_CSC_BYPASS))); + /* XXX match this to the depth of the crtc fmt block, move to modeset? */ + WREG32(0x6940 + radeon_crtc->crtc_offset, 0); +diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h +index d912939..25d523c 100644 +--- a/drivers/gpu/drm/radeon/radeon_mode.h ++++ b/drivers/gpu/drm/radeon/radeon_mode.h +@@ -366,6 +366,7 @@ struct radeon_crtc { + u32 wm_low; + u32 wm_high; + struct drm_display_mode hw_mode; ++ enum radeon_output_csc output_csc; + }; + + struct radeon_encoder_primary_dac { +@@ -458,6 +459,7 @@ struct radeon_encoder { + int audio_polling_active; + bool is_ext_encoder; + u16 caps; ++ enum radeon_output_csc output_csc; + }; + + struct radeon_connector_atom_dig { +-- +1.9.1 +