-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
drm/i915: Extract out gamma table and CSC to their own file
The moves a couple of functions programming the gamma LUT and CSC units into their own file. On generations prior to Haswell there is only a gamma LUT. From haswell on there is also a new enhanced color correction unit that isn't used yet. This is why we need to set the GAMMA_MODE register, either we're using the legacy 8bits LUT or enhanced LUTs (of 10 or 12bits). The CSC unit is only available from Haswell on. We also need to make a special case for CherryView which is recognized as a gen 8 but doesn't have the same enhanced color correction unit from Haswell on. v2: Fix access to GAMMA_MODE register on older generations than Haswell (from Matt Roper's comments) Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com> Reviewed-by: Matt Roper <matthew.d.roper@intel.com> Signed-off-by: Matt Roper <matthew.d.roper@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/1458125837-2576-2-git-send-email-lionel.g.landwerlin@intel.com
- Loading branch information
Lionel Landwerlin
authored and
Matt Roper
committed
Mar 21, 2016
1 parent
2e85ab4
commit 8563b1e
Showing
5 changed files
with
216 additions
and
159 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,191 @@ | ||
/* | ||
* Copyright © 2016 Intel Corporation | ||
* | ||
* Permission is hereby granted, free of charge, to any person obtaining a | ||
* copy of this software and associated documentation files (the "Software"), | ||
* to deal in the Software without restriction, including without limitation | ||
* the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
* and/or sell copies of the Software, and to permit persons to whom the | ||
* Software is furnished to do so, subject to the following conditions: | ||
* | ||
* The above copyright notice and this permission notice (including the next | ||
* paragraph) shall be included in all copies or substantial portions of the | ||
* Software. | ||
* | ||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
* DEALINGS IN THE SOFTWARE. | ||
* | ||
*/ | ||
|
||
#include "intel_drv.h" | ||
|
||
/* | ||
* Set up the pipe CSC unit. | ||
* | ||
* Currently only full range RGB to limited range RGB conversion | ||
* is supported, but eventually this should handle various | ||
* RGB<->YCbCr scenarios as well. | ||
*/ | ||
static void i9xx_load_csc_matrix(struct drm_crtc *crtc) | ||
{ | ||
struct drm_device *dev = crtc->dev; | ||
struct drm_i915_private *dev_priv = dev->dev_private; | ||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
int pipe = intel_crtc->pipe; | ||
uint16_t coeff = 0x7800; /* 1.0 */ | ||
|
||
/* | ||
* TODO: Check what kind of values actually come out of the pipe | ||
* with these coeff/postoff values and adjust to get the best | ||
* accuracy. Perhaps we even need to take the bpc value into | ||
* consideration. | ||
*/ | ||
|
||
if (intel_crtc->config->limited_color_range) | ||
coeff = ((235 - 16) * (1 << 12) / 255) & 0xff8; /* 0.xxx... */ | ||
|
||
I915_WRITE(PIPE_CSC_COEFF_RY_GY(pipe), coeff << 16); | ||
I915_WRITE(PIPE_CSC_COEFF_BY(pipe), 0); | ||
|
||
I915_WRITE(PIPE_CSC_COEFF_RU_GU(pipe), coeff); | ||
I915_WRITE(PIPE_CSC_COEFF_BU(pipe), 0); | ||
|
||
I915_WRITE(PIPE_CSC_COEFF_RV_GV(pipe), 0); | ||
I915_WRITE(PIPE_CSC_COEFF_BV(pipe), coeff << 16); | ||
|
||
I915_WRITE(PIPE_CSC_PREOFF_HI(pipe), 0); | ||
I915_WRITE(PIPE_CSC_PREOFF_ME(pipe), 0); | ||
I915_WRITE(PIPE_CSC_PREOFF_LO(pipe), 0); | ||
|
||
if (INTEL_INFO(dev)->gen > 6) { | ||
uint16_t postoff = 0; | ||
|
||
if (intel_crtc->config->limited_color_range) | ||
postoff = (16 * (1 << 12) / 255) & 0x1fff; | ||
|
||
I915_WRITE(PIPE_CSC_POSTOFF_HI(pipe), postoff); | ||
I915_WRITE(PIPE_CSC_POSTOFF_ME(pipe), postoff); | ||
I915_WRITE(PIPE_CSC_POSTOFF_LO(pipe), postoff); | ||
|
||
I915_WRITE(PIPE_CSC_MODE(pipe), 0); | ||
} else { | ||
uint32_t mode = CSC_MODE_YUV_TO_RGB; | ||
|
||
if (intel_crtc->config->limited_color_range) | ||
mode |= CSC_BLACK_SCREEN_OFFSET; | ||
|
||
I915_WRITE(PIPE_CSC_MODE(pipe), mode); | ||
} | ||
} | ||
|
||
void intel_color_set_csc(struct drm_crtc *crtc) | ||
{ | ||
i9xx_load_csc_matrix(crtc); | ||
} | ||
|
||
/* Loads the palette/gamma unit for the CRTC with the prepared values. */ | ||
static void i9xx_load_luts(struct drm_crtc *crtc) | ||
{ | ||
struct drm_device *dev = crtc->dev; | ||
struct drm_i915_private *dev_priv = dev->dev_private; | ||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
enum pipe pipe = intel_crtc->pipe; | ||
int i; | ||
|
||
if (HAS_GMCH_DISPLAY(dev)) { | ||
if (intel_crtc->config->has_dsi_encoder) | ||
assert_dsi_pll_enabled(dev_priv); | ||
else | ||
assert_pll_enabled(dev_priv, pipe); | ||
} | ||
|
||
for (i = 0; i < 256; i++) { | ||
uint32_t word = (intel_crtc->lut_r[i] << 16) | | ||
(intel_crtc->lut_g[i] << 8) | | ||
intel_crtc->lut_b[i]; | ||
if (HAS_GMCH_DISPLAY(dev)) | ||
I915_WRITE(PALETTE(pipe, i), word); | ||
else | ||
I915_WRITE(LGC_PALETTE(pipe, i), word); | ||
} | ||
} | ||
|
||
/* Loads the legacy palette/gamma unit for the CRTC on Haswell+. */ | ||
static void haswell_load_luts(struct drm_crtc *crtc) | ||
{ | ||
struct drm_device *dev = crtc->dev; | ||
struct drm_i915_private *dev_priv = dev->dev_private; | ||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
bool reenable_ips = false; | ||
|
||
/* | ||
* Workaround : Do not read or write the pipe palette/gamma data while | ||
* GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled. | ||
*/ | ||
if (IS_HASWELL(dev) && intel_crtc->config->ips_enabled && | ||
((I915_READ(GAMMA_MODE(intel_crtc->pipe)) & GAMMA_MODE_MODE_MASK) == | ||
GAMMA_MODE_MODE_SPLIT)) { | ||
hsw_disable_ips(intel_crtc); | ||
reenable_ips = true; | ||
} | ||
I915_WRITE(GAMMA_MODE(intel_crtc->pipe), GAMMA_MODE_MODE_8BIT); | ||
|
||
i9xx_load_luts(crtc); | ||
|
||
if (reenable_ips) | ||
hsw_enable_ips(intel_crtc); | ||
} | ||
|
||
void intel_color_load_luts(struct drm_crtc *crtc) | ||
{ | ||
struct drm_device *dev = crtc->dev; | ||
struct drm_i915_private *dev_priv = dev->dev_private; | ||
|
||
/* The clocks have to be on to load the palette. */ | ||
if (!crtc->state->active) | ||
return; | ||
|
||
dev_priv->display.load_luts(crtc); | ||
} | ||
|
||
void intel_color_legacy_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, | ||
u16 *blue, uint32_t start, uint32_t size) | ||
{ | ||
int end = (start + size > 256) ? 256 : start + size, i; | ||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
|
||
for (i = start; i < end; i++) { | ||
intel_crtc->lut_r[i] = red[i] >> 8; | ||
intel_crtc->lut_g[i] = green[i] >> 8; | ||
intel_crtc->lut_b[i] = blue[i] >> 8; | ||
} | ||
|
||
intel_color_load_luts(crtc); | ||
} | ||
|
||
void intel_color_init(struct drm_crtc *crtc) | ||
{ | ||
struct drm_device *dev = crtc->dev; | ||
struct drm_i915_private *dev_priv = dev->dev_private; | ||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
int i; | ||
|
||
drm_mode_crtc_set_gamma_size(crtc, 256); | ||
for (i = 0; i < 256; i++) { | ||
intel_crtc->lut_r[i] = i; | ||
intel_crtc->lut_g[i] = i; | ||
intel_crtc->lut_b[i] = i; | ||
} | ||
|
||
if (IS_HASWELL(dev) || | ||
(INTEL_INFO(dev)->gen >= 8 && !IS_CHERRYVIEW(dev))) { | ||
dev_priv->display.load_luts = haswell_load_luts; | ||
} else { | ||
dev_priv->display.load_luts = i9xx_load_luts; | ||
} | ||
} |
Oops, something went wrong.