drm/i915: Extract out gamma table and CSC to their own file
[deliverable/linux.git] / drivers / gpu / drm / i915 / intel_color.c
CommitLineData
8563b1e8
LL
1/*
2 * Copyright © 2016 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 */
24
25#include "intel_drv.h"
26
27/*
28 * Set up the pipe CSC unit.
29 *
30 * Currently only full range RGB to limited range RGB conversion
31 * is supported, but eventually this should handle various
32 * RGB<->YCbCr scenarios as well.
33 */
34static void i9xx_load_csc_matrix(struct drm_crtc *crtc)
35{
36 struct drm_device *dev = crtc->dev;
37 struct drm_i915_private *dev_priv = dev->dev_private;
38 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
39 int pipe = intel_crtc->pipe;
40 uint16_t coeff = 0x7800; /* 1.0 */
41
42 /*
43 * TODO: Check what kind of values actually come out of the pipe
44 * with these coeff/postoff values and adjust to get the best
45 * accuracy. Perhaps we even need to take the bpc value into
46 * consideration.
47 */
48
49 if (intel_crtc->config->limited_color_range)
50 coeff = ((235 - 16) * (1 << 12) / 255) & 0xff8; /* 0.xxx... */
51
52 I915_WRITE(PIPE_CSC_COEFF_RY_GY(pipe), coeff << 16);
53 I915_WRITE(PIPE_CSC_COEFF_BY(pipe), 0);
54
55 I915_WRITE(PIPE_CSC_COEFF_RU_GU(pipe), coeff);
56 I915_WRITE(PIPE_CSC_COEFF_BU(pipe), 0);
57
58 I915_WRITE(PIPE_CSC_COEFF_RV_GV(pipe), 0);
59 I915_WRITE(PIPE_CSC_COEFF_BV(pipe), coeff << 16);
60
61 I915_WRITE(PIPE_CSC_PREOFF_HI(pipe), 0);
62 I915_WRITE(PIPE_CSC_PREOFF_ME(pipe), 0);
63 I915_WRITE(PIPE_CSC_PREOFF_LO(pipe), 0);
64
65 if (INTEL_INFO(dev)->gen > 6) {
66 uint16_t postoff = 0;
67
68 if (intel_crtc->config->limited_color_range)
69 postoff = (16 * (1 << 12) / 255) & 0x1fff;
70
71 I915_WRITE(PIPE_CSC_POSTOFF_HI(pipe), postoff);
72 I915_WRITE(PIPE_CSC_POSTOFF_ME(pipe), postoff);
73 I915_WRITE(PIPE_CSC_POSTOFF_LO(pipe), postoff);
74
75 I915_WRITE(PIPE_CSC_MODE(pipe), 0);
76 } else {
77 uint32_t mode = CSC_MODE_YUV_TO_RGB;
78
79 if (intel_crtc->config->limited_color_range)
80 mode |= CSC_BLACK_SCREEN_OFFSET;
81
82 I915_WRITE(PIPE_CSC_MODE(pipe), mode);
83 }
84}
85
86void intel_color_set_csc(struct drm_crtc *crtc)
87{
88 i9xx_load_csc_matrix(crtc);
89}
90
91/* Loads the palette/gamma unit for the CRTC with the prepared values. */
92static void i9xx_load_luts(struct drm_crtc *crtc)
93{
94 struct drm_device *dev = crtc->dev;
95 struct drm_i915_private *dev_priv = dev->dev_private;
96 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
97 enum pipe pipe = intel_crtc->pipe;
98 int i;
99
100 if (HAS_GMCH_DISPLAY(dev)) {
101 if (intel_crtc->config->has_dsi_encoder)
102 assert_dsi_pll_enabled(dev_priv);
103 else
104 assert_pll_enabled(dev_priv, pipe);
105 }
106
107 for (i = 0; i < 256; i++) {
108 uint32_t word = (intel_crtc->lut_r[i] << 16) |
109 (intel_crtc->lut_g[i] << 8) |
110 intel_crtc->lut_b[i];
111 if (HAS_GMCH_DISPLAY(dev))
112 I915_WRITE(PALETTE(pipe, i), word);
113 else
114 I915_WRITE(LGC_PALETTE(pipe, i), word);
115 }
116}
117
118/* Loads the legacy palette/gamma unit for the CRTC on Haswell+. */
119static void haswell_load_luts(struct drm_crtc *crtc)
120{
121 struct drm_device *dev = crtc->dev;
122 struct drm_i915_private *dev_priv = dev->dev_private;
123 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
124 bool reenable_ips = false;
125
126 /*
127 * Workaround : Do not read or write the pipe palette/gamma data while
128 * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled.
129 */
130 if (IS_HASWELL(dev) && intel_crtc->config->ips_enabled &&
131 ((I915_READ(GAMMA_MODE(intel_crtc->pipe)) & GAMMA_MODE_MODE_MASK) ==
132 GAMMA_MODE_MODE_SPLIT)) {
133 hsw_disable_ips(intel_crtc);
134 reenable_ips = true;
135 }
136 I915_WRITE(GAMMA_MODE(intel_crtc->pipe), GAMMA_MODE_MODE_8BIT);
137
138 i9xx_load_luts(crtc);
139
140 if (reenable_ips)
141 hsw_enable_ips(intel_crtc);
142}
143
144void intel_color_load_luts(struct drm_crtc *crtc)
145{
146 struct drm_device *dev = crtc->dev;
147 struct drm_i915_private *dev_priv = dev->dev_private;
148
149 /* The clocks have to be on to load the palette. */
150 if (!crtc->state->active)
151 return;
152
153 dev_priv->display.load_luts(crtc);
154}
155
156void intel_color_legacy_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
157 u16 *blue, uint32_t start, uint32_t size)
158{
159 int end = (start + size > 256) ? 256 : start + size, i;
160 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
161
162 for (i = start; i < end; i++) {
163 intel_crtc->lut_r[i] = red[i] >> 8;
164 intel_crtc->lut_g[i] = green[i] >> 8;
165 intel_crtc->lut_b[i] = blue[i] >> 8;
166 }
167
168 intel_color_load_luts(crtc);
169}
170
171void intel_color_init(struct drm_crtc *crtc)
172{
173 struct drm_device *dev = crtc->dev;
174 struct drm_i915_private *dev_priv = dev->dev_private;
175 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
176 int i;
177
178 drm_mode_crtc_set_gamma_size(crtc, 256);
179 for (i = 0; i < 256; i++) {
180 intel_crtc->lut_r[i] = i;
181 intel_crtc->lut_g[i] = i;
182 intel_crtc->lut_b[i] = i;
183 }
184
185 if (IS_HASWELL(dev) ||
186 (INTEL_INFO(dev)->gen >= 8 && !IS_CHERRYVIEW(dev))) {
187 dev_priv->display.load_luts = haswell_load_luts;
188 } else {
189 dev_priv->display.load_luts = i9xx_load_luts;
190 }
191}
This page took 0.031618 seconds and 5 git commands to generate.