File: | dev/pci/drm/i915/display/intel_hdmi.c |
Warning: | line 3119, column 2 Value stored to 'slice_width' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* |
2 | * Copyright 2006 Dave Airlie <airlied@linux.ie> |
3 | * Copyright © 2006-2009 Intel Corporation |
4 | * |
5 | * Permission is hereby granted, free of charge, to any person obtaining a |
6 | * copy of this software and associated documentation files (the "Software"), |
7 | * to deal in the Software without restriction, including without limitation |
8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
9 | * and/or sell copies of the Software, and to permit persons to whom the |
10 | * Software is furnished to do so, subject to the following conditions: |
11 | * |
12 | * The above copyright notice and this permission notice (including the next |
13 | * paragraph) shall be included in all copies or substantial portions of the |
14 | * Software. |
15 | * |
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
22 | * DEALINGS IN THE SOFTWARE. |
23 | * |
24 | * Authors: |
25 | * Eric Anholt <eric@anholt.net> |
26 | * Jesse Barnes <jesse.barnes@intel.com> |
27 | */ |
28 | |
29 | #include <linux/delay.h> |
30 | #include <linux/hdmi.h> |
31 | #include <linux/i2c.h> |
32 | #include <linux/slab.h> |
33 | #include <linux/string_helpers.h> |
34 | |
35 | #include <drm/display/drm_hdcp_helper.h> |
36 | #include <drm/display/drm_hdmi_helper.h> |
37 | #include <drm/display/drm_scdc_helper.h> |
38 | #include <drm/drm_atomic_helper.h> |
39 | #include <drm/drm_crtc.h> |
40 | #include <drm/drm_edid.h> |
41 | #include <drm/intel_lpe_audio.h> |
42 | |
43 | #include "i915_debugfs.h" |
44 | #include "i915_drv.h" |
45 | #include "intel_atomic.h" |
46 | #include "intel_connector.h" |
47 | #include "intel_ddi.h" |
48 | #include "intel_de.h" |
49 | #include "intel_display_types.h" |
50 | #include "intel_dp.h" |
51 | #include "intel_gmbus.h" |
52 | #include "intel_hdcp.h" |
53 | #include "intel_hdcp_regs.h" |
54 | #include "intel_hdmi.h" |
55 | #include "intel_lspcon.h" |
56 | #include "intel_panel.h" |
57 | #include "intel_snps_phy.h" |
58 | |
59 | static struct drm_i915_privateinteldrm_softc *intel_hdmi_to_i915(struct intel_hdmi *intel_hdmi) |
60 | { |
61 | return to_i915(hdmi_to_dig_port(intel_hdmi)->base.base.dev); |
62 | } |
63 | |
64 | static void |
65 | assert_hdmi_port_disabled(struct intel_hdmi *intel_hdmi) |
66 | { |
67 | struct drm_i915_privateinteldrm_softc *dev_priv = intel_hdmi_to_i915(intel_hdmi); |
68 | u32 enabled_bits; |
69 | |
70 | enabled_bits = HAS_DDI(dev_priv)((&(dev_priv)->__info)->display.has_ddi) ? DDI_BUF_CTL_ENABLE(1 << 31) : SDVO_ENABLE(1 << 31); |
71 | |
72 | drm_WARN(&dev_priv->drm,({ int __ret = !!(intel_de_read(dev_priv, intel_hdmi->hdmi_reg ) & enabled_bits); if (__ret) printf("%s %s: " "HDMI port enabled, expecting disabled\n" , dev_driver_string((&dev_priv->drm)->dev), ""); __builtin_expect (!!(__ret), 0); }) |
73 | intel_de_read(dev_priv, intel_hdmi->hdmi_reg) & enabled_bits,({ int __ret = !!(intel_de_read(dev_priv, intel_hdmi->hdmi_reg ) & enabled_bits); if (__ret) printf("%s %s: " "HDMI port enabled, expecting disabled\n" , dev_driver_string((&dev_priv->drm)->dev), ""); __builtin_expect (!!(__ret), 0); }) |
74 | "HDMI port enabled, expecting disabled\n")({ int __ret = !!(intel_de_read(dev_priv, intel_hdmi->hdmi_reg ) & enabled_bits); if (__ret) printf("%s %s: " "HDMI port enabled, expecting disabled\n" , dev_driver_string((&dev_priv->drm)->dev), ""); __builtin_expect (!!(__ret), 0); }); |
75 | } |
76 | |
77 | static void |
78 | assert_hdmi_transcoder_func_disabled(struct drm_i915_privateinteldrm_softc *dev_priv, |
79 | enum transcoder cpu_transcoder) |
80 | { |
81 | drm_WARN(&dev_priv->drm,({ int __ret = !!(intel_de_read(dev_priv, ((const i915_reg_t) { .reg = ((&(dev_priv)->__info)->display.trans_offsets [(cpu_transcoder)] - (&(dev_priv)->__info)->display .trans_offsets[TRANSCODER_A] + ((&(dev_priv)->__info)-> display.mmio_offset) + (0x60400)) })) & (1 << 31)); if (__ret) printf("%s %s: " "HDMI transcoder function enabled, expecting disabled\n" , dev_driver_string((&dev_priv->drm)->dev), ""); __builtin_expect (!!(__ret), 0); }) |
82 | intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder)) &({ int __ret = !!(intel_de_read(dev_priv, ((const i915_reg_t) { .reg = ((&(dev_priv)->__info)->display.trans_offsets [(cpu_transcoder)] - (&(dev_priv)->__info)->display .trans_offsets[TRANSCODER_A] + ((&(dev_priv)->__info)-> display.mmio_offset) + (0x60400)) })) & (1 << 31)); if (__ret) printf("%s %s: " "HDMI transcoder function enabled, expecting disabled\n" , dev_driver_string((&dev_priv->drm)->dev), ""); __builtin_expect (!!(__ret), 0); }) |
83 | TRANS_DDI_FUNC_ENABLE,({ int __ret = !!(intel_de_read(dev_priv, ((const i915_reg_t) { .reg = ((&(dev_priv)->__info)->display.trans_offsets [(cpu_transcoder)] - (&(dev_priv)->__info)->display .trans_offsets[TRANSCODER_A] + ((&(dev_priv)->__info)-> display.mmio_offset) + (0x60400)) })) & (1 << 31)); if (__ret) printf("%s %s: " "HDMI transcoder function enabled, expecting disabled\n" , dev_driver_string((&dev_priv->drm)->dev), ""); __builtin_expect (!!(__ret), 0); }) |
84 | "HDMI transcoder function enabled, expecting disabled\n")({ int __ret = !!(intel_de_read(dev_priv, ((const i915_reg_t) { .reg = ((&(dev_priv)->__info)->display.trans_offsets [(cpu_transcoder)] - (&(dev_priv)->__info)->display .trans_offsets[TRANSCODER_A] + ((&(dev_priv)->__info)-> display.mmio_offset) + (0x60400)) })) & (1 << 31)); if (__ret) printf("%s %s: " "HDMI transcoder function enabled, expecting disabled\n" , dev_driver_string((&dev_priv->drm)->dev), ""); __builtin_expect (!!(__ret), 0); }); |
85 | } |
86 | |
87 | static u32 g4x_infoframe_index(unsigned int type) |
88 | { |
89 | switch (type) { |
90 | case HDMI_PACKET_TYPE_GAMUT_METADATA: |
91 | return VIDEO_DIP_SELECT_GAMUT(2 << 19); |
92 | case HDMI_INFOFRAME_TYPE_AVI: |
93 | return VIDEO_DIP_SELECT_AVI(0 << 19); |
94 | case HDMI_INFOFRAME_TYPE_SPD: |
95 | return VIDEO_DIP_SELECT_SPD(3 << 19); |
96 | case HDMI_INFOFRAME_TYPE_VENDOR: |
97 | return VIDEO_DIP_SELECT_VENDOR(1 << 19); |
98 | default: |
99 | MISSING_CASE(type)({ int __ret = !!(1); if (__ret) printf("Missing case (%s == %ld)\n" , "type", (long)(type)); __builtin_expect(!!(__ret), 0); }); |
100 | return 0; |
101 | } |
102 | } |
103 | |
104 | static u32 g4x_infoframe_enable(unsigned int type) |
105 | { |
106 | switch (type) { |
107 | case HDMI_PACKET_TYPE_GENERAL_CONTROL: |
108 | return VIDEO_DIP_ENABLE_GCP(1 << 25); |
109 | case HDMI_PACKET_TYPE_GAMUT_METADATA: |
110 | return VIDEO_DIP_ENABLE_GAMUT(4 << 21); |
111 | case DP_SDP_VSC0x07: |
112 | return 0; |
113 | case HDMI_INFOFRAME_TYPE_AVI: |
114 | return VIDEO_DIP_ENABLE_AVI(1 << 21); |
115 | case HDMI_INFOFRAME_TYPE_SPD: |
116 | return VIDEO_DIP_ENABLE_SPD(8 << 21); |
117 | case HDMI_INFOFRAME_TYPE_VENDOR: |
118 | return VIDEO_DIP_ENABLE_VENDOR(2 << 21); |
119 | case HDMI_INFOFRAME_TYPE_DRM: |
120 | return 0; |
121 | default: |
122 | MISSING_CASE(type)({ int __ret = !!(1); if (__ret) printf("Missing case (%s == %ld)\n" , "type", (long)(type)); __builtin_expect(!!(__ret), 0); }); |
123 | return 0; |
124 | } |
125 | } |
126 | |
127 | static u32 hsw_infoframe_enable(unsigned int type) |
128 | { |
129 | switch (type) { |
130 | case HDMI_PACKET_TYPE_GENERAL_CONTROL: |
131 | return VIDEO_DIP_ENABLE_GCP_HSW(1 << 16); |
132 | case HDMI_PACKET_TYPE_GAMUT_METADATA: |
133 | return VIDEO_DIP_ENABLE_GMP_HSW(1 << 4); |
134 | case DP_SDP_VSC0x07: |
135 | return VIDEO_DIP_ENABLE_VSC_HSW(1 << 20); |
136 | case DP_SDP_PPS0x10: |
137 | return VDIP_ENABLE_PPS(1 << 24); |
138 | case HDMI_INFOFRAME_TYPE_AVI: |
139 | return VIDEO_DIP_ENABLE_AVI_HSW(1 << 12); |
140 | case HDMI_INFOFRAME_TYPE_SPD: |
141 | return VIDEO_DIP_ENABLE_SPD_HSW(1 << 0); |
142 | case HDMI_INFOFRAME_TYPE_VENDOR: |
143 | return VIDEO_DIP_ENABLE_VS_HSW(1 << 8); |
144 | case HDMI_INFOFRAME_TYPE_DRM: |
145 | return VIDEO_DIP_ENABLE_DRM_GLK(1 << 28); |
146 | default: |
147 | MISSING_CASE(type)({ int __ret = !!(1); if (__ret) printf("Missing case (%s == %ld)\n" , "type", (long)(type)); __builtin_expect(!!(__ret), 0); }); |
148 | return 0; |
149 | } |
150 | } |
151 | |
152 | static i915_reg_t |
153 | hsw_dip_data_reg(struct drm_i915_privateinteldrm_softc *dev_priv, |
154 | enum transcoder cpu_transcoder, |
155 | unsigned int type, |
156 | int i) |
157 | { |
158 | switch (type) { |
159 | case HDMI_PACKET_TYPE_GAMUT_METADATA: |
160 | return HSW_TVIDEO_DIP_GMP_DATA(cpu_transcoder, i)((const i915_reg_t){ .reg = ((&(dev_priv)->__info)-> display.trans_offsets[(cpu_transcoder)] - (&(dev_priv)-> __info)->display.trans_offsets[TRANSCODER_A] + ((&(dev_priv )->__info)->display.mmio_offset) + (0x602E0 + (i) * 4)) }); |
161 | case DP_SDP_VSC0x07: |
162 | return HSW_TVIDEO_DIP_VSC_DATA(cpu_transcoder, i)((const i915_reg_t){ .reg = ((&(dev_priv)->__info)-> display.trans_offsets[(cpu_transcoder)] - (&(dev_priv)-> __info)->display.trans_offsets[TRANSCODER_A] + ((&(dev_priv )->__info)->display.mmio_offset) + (0x60320 + (i) * 4)) }); |
163 | case DP_SDP_PPS0x10: |
164 | return ICL_VIDEO_DIP_PPS_DATA(cpu_transcoder, i)((const i915_reg_t){ .reg = ((&(dev_priv)->__info)-> display.trans_offsets[(cpu_transcoder)] - (&(dev_priv)-> __info)->display.trans_offsets[TRANSCODER_A] + ((&(dev_priv )->__info)->display.mmio_offset) + (0x60350 + (i) * 4)) }); |
165 | case HDMI_INFOFRAME_TYPE_AVI: |
166 | return HSW_TVIDEO_DIP_AVI_DATA(cpu_transcoder, i)((const i915_reg_t){ .reg = ((&(dev_priv)->__info)-> display.trans_offsets[(cpu_transcoder)] - (&(dev_priv)-> __info)->display.trans_offsets[TRANSCODER_A] + ((&(dev_priv )->__info)->display.mmio_offset) + (0x60220 + (i) * 4)) }); |
167 | case HDMI_INFOFRAME_TYPE_SPD: |
168 | return HSW_TVIDEO_DIP_SPD_DATA(cpu_transcoder, i)((const i915_reg_t){ .reg = ((&(dev_priv)->__info)-> display.trans_offsets[(cpu_transcoder)] - (&(dev_priv)-> __info)->display.trans_offsets[TRANSCODER_A] + ((&(dev_priv )->__info)->display.mmio_offset) + (0x602A0 + (i) * 4)) }); |
169 | case HDMI_INFOFRAME_TYPE_VENDOR: |
170 | return HSW_TVIDEO_DIP_VS_DATA(cpu_transcoder, i)((const i915_reg_t){ .reg = ((&(dev_priv)->__info)-> display.trans_offsets[(cpu_transcoder)] - (&(dev_priv)-> __info)->display.trans_offsets[TRANSCODER_A] + ((&(dev_priv )->__info)->display.mmio_offset) + (0x60260 + (i) * 4)) }); |
171 | case HDMI_INFOFRAME_TYPE_DRM: |
172 | return GLK_TVIDEO_DIP_DRM_DATA(cpu_transcoder, i)((const i915_reg_t){ .reg = ((&(dev_priv)->__info)-> display.trans_offsets[(cpu_transcoder)] - (&(dev_priv)-> __info)->display.trans_offsets[TRANSCODER_A] + ((&(dev_priv )->__info)->display.mmio_offset) + (0x60440 + (i) * 4)) }); |
173 | default: |
174 | MISSING_CASE(type)({ int __ret = !!(1); if (__ret) printf("Missing case (%s == %ld)\n" , "type", (long)(type)); __builtin_expect(!!(__ret), 0); }); |
175 | return INVALID_MMIO_REG((const i915_reg_t){ .reg = (0) }); |
176 | } |
177 | } |
178 | |
179 | static int hsw_dip_data_size(struct drm_i915_privateinteldrm_softc *dev_priv, |
180 | unsigned int type) |
181 | { |
182 | switch (type) { |
183 | case DP_SDP_VSC0x07: |
184 | return VIDEO_DIP_VSC_DATA_SIZE36; |
185 | case DP_SDP_PPS0x10: |
186 | return VIDEO_DIP_PPS_DATA_SIZE132; |
187 | case HDMI_PACKET_TYPE_GAMUT_METADATA: |
188 | if (DISPLAY_VER(dev_priv)((&(dev_priv)->__runtime)->display.ip.ver) >= 11) |
189 | return VIDEO_DIP_GMP_DATA_SIZE36; |
190 | else |
191 | return VIDEO_DIP_DATA_SIZE32; |
192 | default: |
193 | return VIDEO_DIP_DATA_SIZE32; |
194 | } |
195 | } |
196 | |
197 | static void g4x_write_infoframe(struct intel_encoder *encoder, |
198 | const struct intel_crtc_state *crtc_state, |
199 | unsigned int type, |
200 | const void *frame, ssize_t len) |
201 | { |
202 | const u32 *data = frame; |
203 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev); |
204 | u32 val = intel_de_read(dev_priv, VIDEO_DIP_CTL((const i915_reg_t){ .reg = (0x61170) })); |
205 | int i; |
206 | |
207 | drm_WARN(&dev_priv->drm, !(val & VIDEO_DIP_ENABLE),({ int __ret = !!(!(val & (1 << 31))); if (__ret) printf ("%s %s: " "Writing DIP with CTL reg disabled\n", dev_driver_string ((&dev_priv->drm)->dev), ""); __builtin_expect(!!(__ret ), 0); }) |
208 | "Writing DIP with CTL reg disabled\n")({ int __ret = !!(!(val & (1 << 31))); if (__ret) printf ("%s %s: " "Writing DIP with CTL reg disabled\n", dev_driver_string ((&dev_priv->drm)->dev), ""); __builtin_expect(!!(__ret ), 0); }); |
209 | |
210 | val &= ~(VIDEO_DIP_SELECT_MASK(3 << 19) | 0xf); /* clear DIP data offset */ |
211 | val |= g4x_infoframe_index(type); |
212 | |
213 | val &= ~g4x_infoframe_enable(type); |
214 | |
215 | intel_de_write(dev_priv, VIDEO_DIP_CTL((const i915_reg_t){ .reg = (0x61170) }), val); |
216 | |
217 | for (i = 0; i < len; i += 4) { |
218 | intel_de_write(dev_priv, VIDEO_DIP_DATA((const i915_reg_t){ .reg = (0x61178) }), *data); |
219 | data++; |
220 | } |
221 | /* Write every possible data byte to force correct ECC calculation. */ |
222 | for (; i < VIDEO_DIP_DATA_SIZE32; i += 4) |
223 | intel_de_write(dev_priv, VIDEO_DIP_DATA((const i915_reg_t){ .reg = (0x61178) }), 0); |
224 | |
225 | val |= g4x_infoframe_enable(type); |
226 | val &= ~VIDEO_DIP_FREQ_MASK(3 << 16); |
227 | val |= VIDEO_DIP_FREQ_VSYNC(1 << 16); |
228 | |
229 | intel_de_write(dev_priv, VIDEO_DIP_CTL((const i915_reg_t){ .reg = (0x61170) }), val); |
230 | intel_de_posting_read(dev_priv, VIDEO_DIP_CTL((const i915_reg_t){ .reg = (0x61170) })); |
231 | } |
232 | |
233 | static void g4x_read_infoframe(struct intel_encoder *encoder, |
234 | const struct intel_crtc_state *crtc_state, |
235 | unsigned int type, |
236 | void *frame, ssize_t len) |
237 | { |
238 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev); |
239 | u32 val, *data = frame; |
240 | int i; |
241 | |
242 | val = intel_de_read(dev_priv, VIDEO_DIP_CTL((const i915_reg_t){ .reg = (0x61170) })); |
243 | |
244 | val &= ~(VIDEO_DIP_SELECT_MASK(3 << 19) | 0xf); /* clear DIP data offset */ |
245 | val |= g4x_infoframe_index(type); |
246 | |
247 | intel_de_write(dev_priv, VIDEO_DIP_CTL((const i915_reg_t){ .reg = (0x61170) }), val); |
248 | |
249 | for (i = 0; i < len; i += 4) |
250 | *data++ = intel_de_read(dev_priv, VIDEO_DIP_DATA((const i915_reg_t){ .reg = (0x61178) })); |
251 | } |
252 | |
253 | static u32 g4x_infoframes_enabled(struct intel_encoder *encoder, |
254 | const struct intel_crtc_state *pipe_config) |
255 | { |
256 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev); |
257 | u32 val = intel_de_read(dev_priv, VIDEO_DIP_CTL((const i915_reg_t){ .reg = (0x61170) })); |
258 | |
259 | if ((val & VIDEO_DIP_ENABLE(1 << 31)) == 0) |
260 | return 0; |
261 | |
262 | if ((val & VIDEO_DIP_PORT_MASK(3 << 29)) != VIDEO_DIP_PORT(encoder->port)((encoder->port) << 29)) |
263 | return 0; |
264 | |
265 | return val & (VIDEO_DIP_ENABLE_AVI(1 << 21) | |
266 | VIDEO_DIP_ENABLE_VENDOR(2 << 21) | VIDEO_DIP_ENABLE_SPD(8 << 21)); |
267 | } |
268 | |
269 | static void ibx_write_infoframe(struct intel_encoder *encoder, |
270 | const struct intel_crtc_state *crtc_state, |
271 | unsigned int type, |
272 | const void *frame, ssize_t len) |
273 | { |
274 | const u32 *data = frame; |
275 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev); |
276 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc)({ const __typeof( ((struct intel_crtc *)0)->base ) *__mptr = (crtc_state->uapi.crtc); (struct intel_crtc *)( (char * )__mptr - __builtin_offsetof(struct intel_crtc, base) );}); |
277 | i915_reg_t reg = TVIDEO_DIP_CTL(crtc->pipe)((const i915_reg_t){ .reg = (((0xe0200) + (crtc->pipe) * ( (0xe1200) - (0xe0200)))) }); |
278 | u32 val = intel_de_read(dev_priv, reg); |
279 | int i; |
280 | |
281 | drm_WARN(&dev_priv->drm, !(val & VIDEO_DIP_ENABLE),({ int __ret = !!(!(val & (1 << 31))); if (__ret) printf ("%s %s: " "Writing DIP with CTL reg disabled\n", dev_driver_string ((&dev_priv->drm)->dev), ""); __builtin_expect(!!(__ret ), 0); }) |
282 | "Writing DIP with CTL reg disabled\n")({ int __ret = !!(!(val & (1 << 31))); if (__ret) printf ("%s %s: " "Writing DIP with CTL reg disabled\n", dev_driver_string ((&dev_priv->drm)->dev), ""); __builtin_expect(!!(__ret ), 0); }); |
283 | |
284 | val &= ~(VIDEO_DIP_SELECT_MASK(3 << 19) | 0xf); /* clear DIP data offset */ |
285 | val |= g4x_infoframe_index(type); |
286 | |
287 | val &= ~g4x_infoframe_enable(type); |
288 | |
289 | intel_de_write(dev_priv, reg, val); |
290 | |
291 | for (i = 0; i < len; i += 4) { |
292 | intel_de_write(dev_priv, TVIDEO_DIP_DATA(crtc->pipe)((const i915_reg_t){ .reg = (((0xe0208) + (crtc->pipe) * ( (0xe1208) - (0xe0208)))) }), |
293 | *data); |
294 | data++; |
295 | } |
296 | /* Write every possible data byte to force correct ECC calculation. */ |
297 | for (; i < VIDEO_DIP_DATA_SIZE32; i += 4) |
298 | intel_de_write(dev_priv, TVIDEO_DIP_DATA(crtc->pipe)((const i915_reg_t){ .reg = (((0xe0208) + (crtc->pipe) * ( (0xe1208) - (0xe0208)))) }), 0); |
299 | |
300 | val |= g4x_infoframe_enable(type); |
301 | val &= ~VIDEO_DIP_FREQ_MASK(3 << 16); |
302 | val |= VIDEO_DIP_FREQ_VSYNC(1 << 16); |
303 | |
304 | intel_de_write(dev_priv, reg, val); |
305 | intel_de_posting_read(dev_priv, reg); |
306 | } |
307 | |
308 | static void ibx_read_infoframe(struct intel_encoder *encoder, |
309 | const struct intel_crtc_state *crtc_state, |
310 | unsigned int type, |
311 | void *frame, ssize_t len) |
312 | { |
313 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev); |
314 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc)({ const __typeof( ((struct intel_crtc *)0)->base ) *__mptr = (crtc_state->uapi.crtc); (struct intel_crtc *)( (char * )__mptr - __builtin_offsetof(struct intel_crtc, base) );}); |
315 | u32 val, *data = frame; |
316 | int i; |
317 | |
318 | val = intel_de_read(dev_priv, TVIDEO_DIP_CTL(crtc->pipe)((const i915_reg_t){ .reg = (((0xe0200) + (crtc->pipe) * ( (0xe1200) - (0xe0200)))) })); |
319 | |
320 | val &= ~(VIDEO_DIP_SELECT_MASK(3 << 19) | 0xf); /* clear DIP data offset */ |
321 | val |= g4x_infoframe_index(type); |
322 | |
323 | intel_de_write(dev_priv, TVIDEO_DIP_CTL(crtc->pipe)((const i915_reg_t){ .reg = (((0xe0200) + (crtc->pipe) * ( (0xe1200) - (0xe0200)))) }), val); |
324 | |
325 | for (i = 0; i < len; i += 4) |
326 | *data++ = intel_de_read(dev_priv, TVIDEO_DIP_DATA(crtc->pipe)((const i915_reg_t){ .reg = (((0xe0208) + (crtc->pipe) * ( (0xe1208) - (0xe0208)))) })); |
327 | } |
328 | |
329 | static u32 ibx_infoframes_enabled(struct intel_encoder *encoder, |
330 | const struct intel_crtc_state *pipe_config) |
331 | { |
332 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev); |
333 | enum pipe pipe = to_intel_crtc(pipe_config->uapi.crtc)({ const __typeof( ((struct intel_crtc *)0)->base ) *__mptr = (pipe_config->uapi.crtc); (struct intel_crtc *)( (char * )__mptr - __builtin_offsetof(struct intel_crtc, base) );})->pipe; |
334 | i915_reg_t reg = TVIDEO_DIP_CTL(pipe)((const i915_reg_t){ .reg = (((0xe0200) + (pipe) * ((0xe1200) - (0xe0200)))) }); |
335 | u32 val = intel_de_read(dev_priv, reg); |
336 | |
337 | if ((val & VIDEO_DIP_ENABLE(1 << 31)) == 0) |
338 | return 0; |
339 | |
340 | if ((val & VIDEO_DIP_PORT_MASK(3 << 29)) != VIDEO_DIP_PORT(encoder->port)((encoder->port) << 29)) |
341 | return 0; |
342 | |
343 | return val & (VIDEO_DIP_ENABLE_AVI(1 << 21) | |
344 | VIDEO_DIP_ENABLE_VENDOR(2 << 21) | VIDEO_DIP_ENABLE_GAMUT(4 << 21) | |
345 | VIDEO_DIP_ENABLE_SPD(8 << 21) | VIDEO_DIP_ENABLE_GCP(1 << 25)); |
346 | } |
347 | |
348 | static void cpt_write_infoframe(struct intel_encoder *encoder, |
349 | const struct intel_crtc_state *crtc_state, |
350 | unsigned int type, |
351 | const void *frame, ssize_t len) |
352 | { |
353 | const u32 *data = frame; |
354 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev); |
355 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc)({ const __typeof( ((struct intel_crtc *)0)->base ) *__mptr = (crtc_state->uapi.crtc); (struct intel_crtc *)( (char * )__mptr - __builtin_offsetof(struct intel_crtc, base) );}); |
356 | i915_reg_t reg = TVIDEO_DIP_CTL(crtc->pipe)((const i915_reg_t){ .reg = (((0xe0200) + (crtc->pipe) * ( (0xe1200) - (0xe0200)))) }); |
357 | u32 val = intel_de_read(dev_priv, reg); |
358 | int i; |
359 | |
360 | drm_WARN(&dev_priv->drm, !(val & VIDEO_DIP_ENABLE),({ int __ret = !!(!(val & (1 << 31))); if (__ret) printf ("%s %s: " "Writing DIP with CTL reg disabled\n", dev_driver_string ((&dev_priv->drm)->dev), ""); __builtin_expect(!!(__ret ), 0); }) |
361 | "Writing DIP with CTL reg disabled\n")({ int __ret = !!(!(val & (1 << 31))); if (__ret) printf ("%s %s: " "Writing DIP with CTL reg disabled\n", dev_driver_string ((&dev_priv->drm)->dev), ""); __builtin_expect(!!(__ret ), 0); }); |
362 | |
363 | val &= ~(VIDEO_DIP_SELECT_MASK(3 << 19) | 0xf); /* clear DIP data offset */ |
364 | val |= g4x_infoframe_index(type); |
365 | |
366 | /* The DIP control register spec says that we need to update the AVI |
367 | * infoframe without clearing its enable bit */ |
368 | if (type != HDMI_INFOFRAME_TYPE_AVI) |
369 | val &= ~g4x_infoframe_enable(type); |
370 | |
371 | intel_de_write(dev_priv, reg, val); |
372 | |
373 | for (i = 0; i < len; i += 4) { |
374 | intel_de_write(dev_priv, TVIDEO_DIP_DATA(crtc->pipe)((const i915_reg_t){ .reg = (((0xe0208) + (crtc->pipe) * ( (0xe1208) - (0xe0208)))) }), |
375 | *data); |
376 | data++; |
377 | } |
378 | /* Write every possible data byte to force correct ECC calculation. */ |
379 | for (; i < VIDEO_DIP_DATA_SIZE32; i += 4) |
380 | intel_de_write(dev_priv, TVIDEO_DIP_DATA(crtc->pipe)((const i915_reg_t){ .reg = (((0xe0208) + (crtc->pipe) * ( (0xe1208) - (0xe0208)))) }), 0); |
381 | |
382 | val |= g4x_infoframe_enable(type); |
383 | val &= ~VIDEO_DIP_FREQ_MASK(3 << 16); |
384 | val |= VIDEO_DIP_FREQ_VSYNC(1 << 16); |
385 | |
386 | intel_de_write(dev_priv, reg, val); |
387 | intel_de_posting_read(dev_priv, reg); |
388 | } |
389 | |
390 | static void cpt_read_infoframe(struct intel_encoder *encoder, |
391 | const struct intel_crtc_state *crtc_state, |
392 | unsigned int type, |
393 | void *frame, ssize_t len) |
394 | { |
395 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev); |
396 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc)({ const __typeof( ((struct intel_crtc *)0)->base ) *__mptr = (crtc_state->uapi.crtc); (struct intel_crtc *)( (char * )__mptr - __builtin_offsetof(struct intel_crtc, base) );}); |
397 | u32 val, *data = frame; |
398 | int i; |
399 | |
400 | val = intel_de_read(dev_priv, TVIDEO_DIP_CTL(crtc->pipe)((const i915_reg_t){ .reg = (((0xe0200) + (crtc->pipe) * ( (0xe1200) - (0xe0200)))) })); |
401 | |
402 | val &= ~(VIDEO_DIP_SELECT_MASK(3 << 19) | 0xf); /* clear DIP data offset */ |
403 | val |= g4x_infoframe_index(type); |
404 | |
405 | intel_de_write(dev_priv, TVIDEO_DIP_CTL(crtc->pipe)((const i915_reg_t){ .reg = (((0xe0200) + (crtc->pipe) * ( (0xe1200) - (0xe0200)))) }), val); |
406 | |
407 | for (i = 0; i < len; i += 4) |
408 | *data++ = intel_de_read(dev_priv, TVIDEO_DIP_DATA(crtc->pipe)((const i915_reg_t){ .reg = (((0xe0208) + (crtc->pipe) * ( (0xe1208) - (0xe0208)))) })); |
409 | } |
410 | |
411 | static u32 cpt_infoframes_enabled(struct intel_encoder *encoder, |
412 | const struct intel_crtc_state *pipe_config) |
413 | { |
414 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev); |
415 | enum pipe pipe = to_intel_crtc(pipe_config->uapi.crtc)({ const __typeof( ((struct intel_crtc *)0)->base ) *__mptr = (pipe_config->uapi.crtc); (struct intel_crtc *)( (char * )__mptr - __builtin_offsetof(struct intel_crtc, base) );})->pipe; |
416 | u32 val = intel_de_read(dev_priv, TVIDEO_DIP_CTL(pipe)((const i915_reg_t){ .reg = (((0xe0200) + (pipe) * ((0xe1200) - (0xe0200)))) })); |
417 | |
418 | if ((val & VIDEO_DIP_ENABLE(1 << 31)) == 0) |
419 | return 0; |
420 | |
421 | return val & (VIDEO_DIP_ENABLE_AVI(1 << 21) | |
422 | VIDEO_DIP_ENABLE_VENDOR(2 << 21) | VIDEO_DIP_ENABLE_GAMUT(4 << 21) | |
423 | VIDEO_DIP_ENABLE_SPD(8 << 21) | VIDEO_DIP_ENABLE_GCP(1 << 25)); |
424 | } |
425 | |
426 | static void vlv_write_infoframe(struct intel_encoder *encoder, |
427 | const struct intel_crtc_state *crtc_state, |
428 | unsigned int type, |
429 | const void *frame, ssize_t len) |
430 | { |
431 | const u32 *data = frame; |
432 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev); |
433 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc)({ const __typeof( ((struct intel_crtc *)0)->base ) *__mptr = (crtc_state->uapi.crtc); (struct intel_crtc *)( (char * )__mptr - __builtin_offsetof(struct intel_crtc, base) );}); |
434 | i915_reg_t reg = VLV_TVIDEO_DIP_CTL(crtc->pipe)((const i915_reg_t){ .reg = ((((const u32 []){ (0x180000 + 0x60200 ), (0x180000 + 0x61170), (0x180000 + 0x611f0) })[(crtc->pipe )])) }); |
435 | u32 val = intel_de_read(dev_priv, reg); |
436 | int i; |
437 | |
438 | drm_WARN(&dev_priv->drm, !(val & VIDEO_DIP_ENABLE),({ int __ret = !!(!(val & (1 << 31))); if (__ret) printf ("%s %s: " "Writing DIP with CTL reg disabled\n", dev_driver_string ((&dev_priv->drm)->dev), ""); __builtin_expect(!!(__ret ), 0); }) |
439 | "Writing DIP with CTL reg disabled\n")({ int __ret = !!(!(val & (1 << 31))); if (__ret) printf ("%s %s: " "Writing DIP with CTL reg disabled\n", dev_driver_string ((&dev_priv->drm)->dev), ""); __builtin_expect(!!(__ret ), 0); }); |
440 | |
441 | val &= ~(VIDEO_DIP_SELECT_MASK(3 << 19) | 0xf); /* clear DIP data offset */ |
442 | val |= g4x_infoframe_index(type); |
443 | |
444 | val &= ~g4x_infoframe_enable(type); |
445 | |
446 | intel_de_write(dev_priv, reg, val); |
447 | |
448 | for (i = 0; i < len; i += 4) { |
449 | intel_de_write(dev_priv, |
450 | VLV_TVIDEO_DIP_DATA(crtc->pipe)((const i915_reg_t){ .reg = ((((const u32 []){ (0x180000 + 0x60208 ), (0x180000 + 0x61174), (0x180000 + 0x611f4) })[(crtc->pipe )])) }), *data); |
451 | data++; |
452 | } |
453 | /* Write every possible data byte to force correct ECC calculation. */ |
454 | for (; i < VIDEO_DIP_DATA_SIZE32; i += 4) |
455 | intel_de_write(dev_priv, |
456 | VLV_TVIDEO_DIP_DATA(crtc->pipe)((const i915_reg_t){ .reg = ((((const u32 []){ (0x180000 + 0x60208 ), (0x180000 + 0x61174), (0x180000 + 0x611f4) })[(crtc->pipe )])) }), 0); |
457 | |
458 | val |= g4x_infoframe_enable(type); |
459 | val &= ~VIDEO_DIP_FREQ_MASK(3 << 16); |
460 | val |= VIDEO_DIP_FREQ_VSYNC(1 << 16); |
461 | |
462 | intel_de_write(dev_priv, reg, val); |
463 | intel_de_posting_read(dev_priv, reg); |
464 | } |
465 | |
466 | static void vlv_read_infoframe(struct intel_encoder *encoder, |
467 | const struct intel_crtc_state *crtc_state, |
468 | unsigned int type, |
469 | void *frame, ssize_t len) |
470 | { |
471 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev); |
472 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc)({ const __typeof( ((struct intel_crtc *)0)->base ) *__mptr = (crtc_state->uapi.crtc); (struct intel_crtc *)( (char * )__mptr - __builtin_offsetof(struct intel_crtc, base) );}); |
473 | u32 val, *data = frame; |
474 | int i; |
475 | |
476 | val = intel_de_read(dev_priv, VLV_TVIDEO_DIP_CTL(crtc->pipe)((const i915_reg_t){ .reg = ((((const u32 []){ (0x180000 + 0x60200 ), (0x180000 + 0x61170), (0x180000 + 0x611f0) })[(crtc->pipe )])) })); |
477 | |
478 | val &= ~(VIDEO_DIP_SELECT_MASK(3 << 19) | 0xf); /* clear DIP data offset */ |
479 | val |= g4x_infoframe_index(type); |
480 | |
481 | intel_de_write(dev_priv, VLV_TVIDEO_DIP_CTL(crtc->pipe)((const i915_reg_t){ .reg = ((((const u32 []){ (0x180000 + 0x60200 ), (0x180000 + 0x61170), (0x180000 + 0x611f0) })[(crtc->pipe )])) }), val); |
482 | |
483 | for (i = 0; i < len; i += 4) |
484 | *data++ = intel_de_read(dev_priv, |
485 | VLV_TVIDEO_DIP_DATA(crtc->pipe)((const i915_reg_t){ .reg = ((((const u32 []){ (0x180000 + 0x60208 ), (0x180000 + 0x61174), (0x180000 + 0x611f4) })[(crtc->pipe )])) })); |
486 | } |
487 | |
488 | static u32 vlv_infoframes_enabled(struct intel_encoder *encoder, |
489 | const struct intel_crtc_state *pipe_config) |
490 | { |
491 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev); |
492 | enum pipe pipe = to_intel_crtc(pipe_config->uapi.crtc)({ const __typeof( ((struct intel_crtc *)0)->base ) *__mptr = (pipe_config->uapi.crtc); (struct intel_crtc *)( (char * )__mptr - __builtin_offsetof(struct intel_crtc, base) );})->pipe; |
493 | u32 val = intel_de_read(dev_priv, VLV_TVIDEO_DIP_CTL(pipe)((const i915_reg_t){ .reg = ((((const u32 []){ (0x180000 + 0x60200 ), (0x180000 + 0x61170), (0x180000 + 0x611f0) })[(pipe)])) })); |
494 | |
495 | if ((val & VIDEO_DIP_ENABLE(1 << 31)) == 0) |
496 | return 0; |
497 | |
498 | if ((val & VIDEO_DIP_PORT_MASK(3 << 29)) != VIDEO_DIP_PORT(encoder->port)((encoder->port) << 29)) |
499 | return 0; |
500 | |
501 | return val & (VIDEO_DIP_ENABLE_AVI(1 << 21) | |
502 | VIDEO_DIP_ENABLE_VENDOR(2 << 21) | VIDEO_DIP_ENABLE_GAMUT(4 << 21) | |
503 | VIDEO_DIP_ENABLE_SPD(8 << 21) | VIDEO_DIP_ENABLE_GCP(1 << 25)); |
504 | } |
505 | |
506 | void hsw_write_infoframe(struct intel_encoder *encoder, |
507 | const struct intel_crtc_state *crtc_state, |
508 | unsigned int type, |
509 | const void *frame, ssize_t len) |
510 | { |
511 | const u32 *data = frame; |
512 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev); |
513 | enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; |
514 | i915_reg_t ctl_reg = HSW_TVIDEO_DIP_CTL(cpu_transcoder)((const i915_reg_t){ .reg = ((&(dev_priv)->__info)-> display.trans_offsets[(cpu_transcoder)] - (&(dev_priv)-> __info)->display.trans_offsets[TRANSCODER_A] + ((&(dev_priv )->__info)->display.mmio_offset) + (0x60200)) }); |
515 | int data_size; |
516 | int i; |
517 | u32 val = intel_de_read(dev_priv, ctl_reg); |
518 | |
519 | data_size = hsw_dip_data_size(dev_priv, type); |
520 | |
521 | drm_WARN_ON(&dev_priv->drm, len > data_size)({ int __ret = !!((len > data_size)); if (__ret) printf("%s %s: " "%s", dev_driver_string(((&dev_priv->drm))->dev), "" , "drm_WARN_ON(" "len > data_size" ")"); __builtin_expect( !!(__ret), 0); }); |
522 | |
523 | val &= ~hsw_infoframe_enable(type); |
524 | intel_de_write(dev_priv, ctl_reg, val); |
525 | |
526 | for (i = 0; i < len; i += 4) { |
527 | intel_de_write(dev_priv, |
528 | hsw_dip_data_reg(dev_priv, cpu_transcoder, type, i >> 2), |
529 | *data); |
530 | data++; |
531 | } |
532 | /* Write every possible data byte to force correct ECC calculation. */ |
533 | for (; i < data_size; i += 4) |
534 | intel_de_write(dev_priv, |
535 | hsw_dip_data_reg(dev_priv, cpu_transcoder, type, i >> 2), |
536 | 0); |
537 | |
538 | /* Wa_14013475917 */ |
539 | if (DISPLAY_VER(dev_priv)((&(dev_priv)->__runtime)->display.ip.ver) == 13 && crtc_state->has_psr && |
540 | type == DP_SDP_VSC0x07) |
541 | return; |
542 | |
543 | val |= hsw_infoframe_enable(type); |
544 | intel_de_write(dev_priv, ctl_reg, val); |
545 | intel_de_posting_read(dev_priv, ctl_reg); |
546 | } |
547 | |
548 | void hsw_read_infoframe(struct intel_encoder *encoder, |
549 | const struct intel_crtc_state *crtc_state, |
550 | unsigned int type, void *frame, ssize_t len) |
551 | { |
552 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev); |
553 | enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; |
554 | u32 *data = frame; |
555 | int i; |
556 | |
557 | for (i = 0; i < len; i += 4) |
558 | *data++ = intel_de_read(dev_priv, |
559 | hsw_dip_data_reg(dev_priv, cpu_transcoder, type, i >> 2)); |
560 | } |
561 | |
562 | static u32 hsw_infoframes_enabled(struct intel_encoder *encoder, |
563 | const struct intel_crtc_state *pipe_config) |
564 | { |
565 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev); |
566 | u32 val = intel_de_read(dev_priv, |
567 | HSW_TVIDEO_DIP_CTL(pipe_config->cpu_transcoder)((const i915_reg_t){ .reg = ((&(dev_priv)->__info)-> display.trans_offsets[(pipe_config->cpu_transcoder)] - (& (dev_priv)->__info)->display.trans_offsets[TRANSCODER_A ] + ((&(dev_priv)->__info)->display.mmio_offset) + ( 0x60200)) })); |
568 | u32 mask; |
569 | |
570 | mask = (VIDEO_DIP_ENABLE_VSC_HSW(1 << 20) | VIDEO_DIP_ENABLE_AVI_HSW(1 << 12) | |
571 | VIDEO_DIP_ENABLE_GCP_HSW(1 << 16) | VIDEO_DIP_ENABLE_VS_HSW(1 << 8) | |
572 | VIDEO_DIP_ENABLE_GMP_HSW(1 << 4) | VIDEO_DIP_ENABLE_SPD_HSW(1 << 0)); |
573 | |
574 | if (DISPLAY_VER(dev_priv)((&(dev_priv)->__runtime)->display.ip.ver) >= 10) |
575 | mask |= VIDEO_DIP_ENABLE_DRM_GLK(1 << 28); |
576 | |
577 | return val & mask; |
578 | } |
579 | |
580 | static const u8 infoframe_type_to_idx[] = { |
581 | HDMI_PACKET_TYPE_GENERAL_CONTROL, |
582 | HDMI_PACKET_TYPE_GAMUT_METADATA, |
583 | DP_SDP_VSC0x07, |
584 | HDMI_INFOFRAME_TYPE_AVI, |
585 | HDMI_INFOFRAME_TYPE_SPD, |
586 | HDMI_INFOFRAME_TYPE_VENDOR, |
587 | HDMI_INFOFRAME_TYPE_DRM, |
588 | }; |
589 | |
590 | u32 intel_hdmi_infoframe_enable(unsigned int type) |
591 | { |
592 | int i; |
593 | |
594 | for (i = 0; i < ARRAY_SIZE(infoframe_type_to_idx)(sizeof((infoframe_type_to_idx)) / sizeof((infoframe_type_to_idx )[0])); i++) { |
595 | if (infoframe_type_to_idx[i] == type) |
596 | return BIT(i)(1UL << (i)); |
597 | } |
598 | |
599 | return 0; |
600 | } |
601 | |
602 | u32 intel_hdmi_infoframes_enabled(struct intel_encoder *encoder, |
603 | const struct intel_crtc_state *crtc_state) |
604 | { |
605 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev); |
606 | struct intel_digital_port *dig_port = enc_to_dig_port(encoder); |
607 | u32 val, ret = 0; |
608 | int i; |
609 | |
610 | val = dig_port->infoframes_enabled(encoder, crtc_state); |
611 | |
612 | /* map from hardware bits to dip idx */ |
613 | for (i = 0; i < ARRAY_SIZE(infoframe_type_to_idx)(sizeof((infoframe_type_to_idx)) / sizeof((infoframe_type_to_idx )[0])); i++) { |
614 | unsigned int type = infoframe_type_to_idx[i]; |
615 | |
616 | if (HAS_DDI(dev_priv)((&(dev_priv)->__info)->display.has_ddi)) { |
617 | if (val & hsw_infoframe_enable(type)) |
618 | ret |= BIT(i)(1UL << (i)); |
619 | } else { |
620 | if (val & g4x_infoframe_enable(type)) |
621 | ret |= BIT(i)(1UL << (i)); |
622 | } |
623 | } |
624 | |
625 | return ret; |
626 | } |
627 | |
628 | /* |
629 | * The data we write to the DIP data buffer registers is 1 byte bigger than the |
630 | * HDMI infoframe size because of an ECC/reserved byte at position 3 (starting |
631 | * at 0). It's also a byte used by DisplayPort so the same DIP registers can be |
632 | * used for both technologies. |
633 | * |
634 | * DW0: Reserved/ECC/DP | HB2 | HB1 | HB0 |
635 | * DW1: DB3 | DB2 | DB1 | DB0 |
636 | * DW2: DB7 | DB6 | DB5 | DB4 |
637 | * DW3: ... |
638 | * |
639 | * (HB is Header Byte, DB is Data Byte) |
640 | * |
641 | * The hdmi pack() functions don't know about that hardware specific hole so we |
642 | * trick them by giving an offset into the buffer and moving back the header |
643 | * bytes by one. |
644 | */ |
645 | static void intel_write_infoframe(struct intel_encoder *encoder, |
646 | const struct intel_crtc_state *crtc_state, |
647 | enum hdmi_infoframe_type type, |
648 | const union hdmi_infoframe *frame) |
649 | { |
650 | struct intel_digital_port *dig_port = enc_to_dig_port(encoder); |
651 | u8 buffer[VIDEO_DIP_DATA_SIZE32]; |
652 | ssize_t len; |
653 | |
654 | if ((crtc_state->infoframes.enable & |
655 | intel_hdmi_infoframe_enable(type)) == 0) |
656 | return; |
657 | |
658 | if (drm_WARN_ON(encoder->base.dev, frame->any.type != type)({ int __ret = !!((frame->any.type != type)); if (__ret) printf ("%s %s: " "%s", dev_driver_string(((encoder->base.dev))-> dev), "", "drm_WARN_ON(" "frame->any.type != type" ")"); __builtin_expect (!!(__ret), 0); })) |
659 | return; |
660 | |
661 | /* see comment above for the reason for this offset */ |
662 | len = hdmi_infoframe_pack_only(frame, buffer + 1, sizeof(buffer) - 1); |
663 | if (drm_WARN_ON(encoder->base.dev, len < 0)({ int __ret = !!((len < 0)); if (__ret) printf("%s %s: " "%s" , dev_driver_string(((encoder->base.dev))->dev), "", "drm_WARN_ON(" "len < 0" ")"); __builtin_expect(!!(__ret), 0); })) |
664 | return; |
665 | |
666 | /* Insert the 'hole' (see big comment above) at position 3 */ |
667 | memmove(&buffer[0], &buffer[1], 3)__builtin_memmove((&buffer[0]), (&buffer[1]), (3)); |
668 | buffer[3] = 0; |
669 | len++; |
670 | |
671 | dig_port->write_infoframe(encoder, crtc_state, type, buffer, len); |
672 | } |
673 | |
674 | void intel_read_infoframe(struct intel_encoder *encoder, |
675 | const struct intel_crtc_state *crtc_state, |
676 | enum hdmi_infoframe_type type, |
677 | union hdmi_infoframe *frame) |
678 | { |
679 | struct intel_digital_port *dig_port = enc_to_dig_port(encoder); |
680 | u8 buffer[VIDEO_DIP_DATA_SIZE32]; |
681 | int ret; |
682 | |
683 | if ((crtc_state->infoframes.enable & |
684 | intel_hdmi_infoframe_enable(type)) == 0) |
685 | return; |
686 | |
687 | dig_port->read_infoframe(encoder, crtc_state, |
688 | type, buffer, sizeof(buffer)); |
689 | |
690 | /* Fill the 'hole' (see big comment above) at position 3 */ |
691 | memmove(&buffer[1], &buffer[0], 3)__builtin_memmove((&buffer[1]), (&buffer[0]), (3)); |
692 | |
693 | /* see comment above for the reason for this offset */ |
694 | ret = hdmi_infoframe_unpack(frame, buffer + 1, sizeof(buffer) - 1); |
695 | if (ret) { |
696 | drm_dbg_kms(encoder->base.dev,__drm_dev_dbg(((void *)0), (encoder->base.dev) ? (encoder-> base.dev)->dev : ((void *)0), DRM_UT_KMS, "Failed to unpack infoframe type 0x%02x\n" , type) |
697 | "Failed to unpack infoframe type 0x%02x\n", type)__drm_dev_dbg(((void *)0), (encoder->base.dev) ? (encoder-> base.dev)->dev : ((void *)0), DRM_UT_KMS, "Failed to unpack infoframe type 0x%02x\n" , type); |
698 | return; |
699 | } |
700 | |
701 | if (frame->any.type != type) |
702 | drm_dbg_kms(encoder->base.dev,__drm_dev_dbg(((void *)0), (encoder->base.dev) ? (encoder-> base.dev)->dev : ((void *)0), DRM_UT_KMS, "Found the wrong infoframe type 0x%x (expected 0x%02x)\n" , frame->any.type, type) |
703 | "Found the wrong infoframe type 0x%x (expected 0x%02x)\n",__drm_dev_dbg(((void *)0), (encoder->base.dev) ? (encoder-> base.dev)->dev : ((void *)0), DRM_UT_KMS, "Found the wrong infoframe type 0x%x (expected 0x%02x)\n" , frame->any.type, type) |
704 | frame->any.type, type)__drm_dev_dbg(((void *)0), (encoder->base.dev) ? (encoder-> base.dev)->dev : ((void *)0), DRM_UT_KMS, "Found the wrong infoframe type 0x%x (expected 0x%02x)\n" , frame->any.type, type); |
705 | } |
706 | |
707 | static bool_Bool |
708 | intel_hdmi_compute_avi_infoframe(struct intel_encoder *encoder, |
709 | struct intel_crtc_state *crtc_state, |
710 | struct drm_connector_state *conn_state) |
711 | { |
712 | struct hdmi_avi_infoframe *frame = &crtc_state->infoframes.avi.avi; |
713 | const struct drm_display_mode *adjusted_mode = |
714 | &crtc_state->hw.adjusted_mode; |
715 | struct drm_connector *connector = conn_state->connector; |
716 | int ret; |
717 | |
718 | if (!crtc_state->has_infoframe) |
719 | return true1; |
720 | |
721 | crtc_state->infoframes.enable |= |
722 | intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_AVI); |
723 | |
724 | ret = drm_hdmi_avi_infoframe_from_display_mode(frame, connector, |
725 | adjusted_mode); |
726 | if (ret) |
727 | return false0; |
728 | |
729 | if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420) |
730 | frame->colorspace = HDMI_COLORSPACE_YUV420; |
731 | else if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR444) |
732 | frame->colorspace = HDMI_COLORSPACE_YUV444; |
733 | else |
734 | frame->colorspace = HDMI_COLORSPACE_RGB; |
735 | |
736 | drm_hdmi_avi_infoframe_colorimetry(frame, conn_state); |
737 | |
738 | /* nonsense combination */ |
739 | drm_WARN_ON(encoder->base.dev, crtc_state->limited_color_range &&({ int __ret = !!((crtc_state->limited_color_range && crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB)); if (__ret) printf("%s %s: " "%s", dev_driver_string(((encoder-> base.dev))->dev), "", "drm_WARN_ON(" "crtc_state->limited_color_range && crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB" ")"); __builtin_expect(!!(__ret), 0); }) |
740 | crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB)({ int __ret = !!((crtc_state->limited_color_range && crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB)); if (__ret) printf("%s %s: " "%s", dev_driver_string(((encoder-> base.dev))->dev), "", "drm_WARN_ON(" "crtc_state->limited_color_range && crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB" ")"); __builtin_expect(!!(__ret), 0); }); |
741 | |
742 | if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_RGB) { |
743 | drm_hdmi_avi_infoframe_quant_range(frame, connector, |
744 | adjusted_mode, |
745 | crtc_state->limited_color_range ? |
746 | HDMI_QUANTIZATION_RANGE_LIMITED : |
747 | HDMI_QUANTIZATION_RANGE_FULL); |
748 | } else { |
749 | frame->quantization_range = HDMI_QUANTIZATION_RANGE_DEFAULT; |
750 | frame->ycc_quantization_range = HDMI_YCC_QUANTIZATION_RANGE_LIMITED; |
751 | } |
752 | |
753 | drm_hdmi_avi_infoframe_content_type(frame, conn_state); |
754 | |
755 | /* TODO: handle pixel repetition for YCBCR420 outputs */ |
756 | |
757 | ret = hdmi_avi_infoframe_check(frame); |
758 | if (drm_WARN_ON(encoder->base.dev, ret)({ int __ret = !!((ret)); if (__ret) printf("%s %s: " "%s", dev_driver_string (((encoder->base.dev))->dev), "", "drm_WARN_ON(" "ret" ")" ); __builtin_expect(!!(__ret), 0); })) |
759 | return false0; |
760 | |
761 | return true1; |
762 | } |
763 | |
764 | static bool_Bool |
765 | intel_hdmi_compute_spd_infoframe(struct intel_encoder *encoder, |
766 | struct intel_crtc_state *crtc_state, |
767 | struct drm_connector_state *conn_state) |
768 | { |
769 | struct hdmi_spd_infoframe *frame = &crtc_state->infoframes.spd.spd; |
770 | int ret; |
771 | |
772 | if (!crtc_state->has_infoframe) |
773 | return true1; |
774 | |
775 | crtc_state->infoframes.enable |= |
776 | intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_SPD); |
777 | |
778 | ret = hdmi_spd_infoframe_init(frame, "Intel", "Integrated gfx"); |
779 | if (drm_WARN_ON(encoder->base.dev, ret)({ int __ret = !!((ret)); if (__ret) printf("%s %s: " "%s", dev_driver_string (((encoder->base.dev))->dev), "", "drm_WARN_ON(" "ret" ")" ); __builtin_expect(!!(__ret), 0); })) |
780 | return false0; |
781 | |
782 | frame->sdi = HDMI_SPD_SDI_PC; |
783 | |
784 | ret = hdmi_spd_infoframe_check(frame); |
785 | if (drm_WARN_ON(encoder->base.dev, ret)({ int __ret = !!((ret)); if (__ret) printf("%s %s: " "%s", dev_driver_string (((encoder->base.dev))->dev), "", "drm_WARN_ON(" "ret" ")" ); __builtin_expect(!!(__ret), 0); })) |
786 | return false0; |
787 | |
788 | return true1; |
789 | } |
790 | |
791 | static bool_Bool |
792 | intel_hdmi_compute_hdmi_infoframe(struct intel_encoder *encoder, |
793 | struct intel_crtc_state *crtc_state, |
794 | struct drm_connector_state *conn_state) |
795 | { |
796 | struct hdmi_vendor_infoframe *frame = |
797 | &crtc_state->infoframes.hdmi.vendor.hdmi; |
798 | const struct drm_display_info *info = |
799 | &conn_state->connector->display_info; |
800 | int ret; |
801 | |
802 | if (!crtc_state->has_infoframe || !info->has_hdmi_infoframe) |
803 | return true1; |
804 | |
805 | crtc_state->infoframes.enable |= |
806 | intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_VENDOR); |
807 | |
808 | ret = drm_hdmi_vendor_infoframe_from_display_mode(frame, |
809 | conn_state->connector, |
810 | &crtc_state->hw.adjusted_mode); |
811 | if (drm_WARN_ON(encoder->base.dev, ret)({ int __ret = !!((ret)); if (__ret) printf("%s %s: " "%s", dev_driver_string (((encoder->base.dev))->dev), "", "drm_WARN_ON(" "ret" ")" ); __builtin_expect(!!(__ret), 0); })) |
812 | return false0; |
813 | |
814 | ret = hdmi_vendor_infoframe_check(frame); |
815 | if (drm_WARN_ON(encoder->base.dev, ret)({ int __ret = !!((ret)); if (__ret) printf("%s %s: " "%s", dev_driver_string (((encoder->base.dev))->dev), "", "drm_WARN_ON(" "ret" ")" ); __builtin_expect(!!(__ret), 0); })) |
816 | return false0; |
817 | |
818 | return true1; |
819 | } |
820 | |
821 | static bool_Bool |
822 | intel_hdmi_compute_drm_infoframe(struct intel_encoder *encoder, |
823 | struct intel_crtc_state *crtc_state, |
824 | struct drm_connector_state *conn_state) |
825 | { |
826 | struct hdmi_drm_infoframe *frame = &crtc_state->infoframes.drm.drm; |
827 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev); |
828 | int ret; |
829 | |
830 | if (DISPLAY_VER(dev_priv)((&(dev_priv)->__runtime)->display.ip.ver) < 10) |
831 | return true1; |
832 | |
833 | if (!crtc_state->has_infoframe) |
834 | return true1; |
835 | |
836 | if (!conn_state->hdr_output_metadata) |
837 | return true1; |
838 | |
839 | crtc_state->infoframes.enable |= |
840 | intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_DRM); |
841 | |
842 | ret = drm_hdmi_infoframe_set_hdr_metadata(frame, conn_state); |
843 | if (ret < 0) { |
844 | drm_dbg_kms(&dev_priv->drm,__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "couldn't set HDR metadata in infoframe\n" ) |
845 | "couldn't set HDR metadata in infoframe\n")__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "couldn't set HDR metadata in infoframe\n" ); |
846 | return false0; |
847 | } |
848 | |
849 | ret = hdmi_drm_infoframe_check(frame); |
850 | if (drm_WARN_ON(&dev_priv->drm, ret)({ int __ret = !!((ret)); if (__ret) printf("%s %s: " "%s", dev_driver_string (((&dev_priv->drm))->dev), "", "drm_WARN_ON(" "ret" ")"); __builtin_expect(!!(__ret), 0); })) |
851 | return false0; |
852 | |
853 | return true1; |
854 | } |
855 | |
856 | static void g4x_set_infoframes(struct intel_encoder *encoder, |
857 | bool_Bool enable, |
858 | const struct intel_crtc_state *crtc_state, |
859 | const struct drm_connector_state *conn_state) |
860 | { |
861 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev); |
862 | struct intel_digital_port *dig_port = enc_to_dig_port(encoder); |
863 | struct intel_hdmi *intel_hdmi = &dig_port->hdmi; |
864 | i915_reg_t reg = VIDEO_DIP_CTL((const i915_reg_t){ .reg = (0x61170) }); |
865 | u32 val = intel_de_read(dev_priv, reg); |
866 | u32 port = VIDEO_DIP_PORT(encoder->port)((encoder->port) << 29); |
867 | |
868 | assert_hdmi_port_disabled(intel_hdmi); |
869 | |
870 | /* If the registers were not initialized yet, they might be zeroes, |
871 | * which means we're selecting the AVI DIP and we're setting its |
872 | * frequency to once. This seems to really confuse the HW and make |
873 | * things stop working (the register spec says the AVI always needs to |
874 | * be sent every VSync). So here we avoid writing to the register more |
875 | * than we need and also explicitly select the AVI DIP and explicitly |
876 | * set its frequency to every VSync. Avoiding to write it twice seems to |
877 | * be enough to solve the problem, but being defensive shouldn't hurt us |
878 | * either. */ |
879 | val |= VIDEO_DIP_SELECT_AVI(0 << 19) | VIDEO_DIP_FREQ_VSYNC(1 << 16); |
880 | |
881 | if (!enable) { |
882 | if (!(val & VIDEO_DIP_ENABLE(1 << 31))) |
883 | return; |
884 | if (port != (val & VIDEO_DIP_PORT_MASK(3 << 29))) { |
885 | drm_dbg_kms(&dev_priv->drm,__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "video DIP still enabled on port %c\n" , (val & (3 << 29)) >> 29) |
886 | "video DIP still enabled on port %c\n",__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "video DIP still enabled on port %c\n" , (val & (3 << 29)) >> 29) |
887 | (val & VIDEO_DIP_PORT_MASK) >> 29)__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "video DIP still enabled on port %c\n" , (val & (3 << 29)) >> 29); |
888 | return; |
889 | } |
890 | val &= ~(VIDEO_DIP_ENABLE(1 << 31) | VIDEO_DIP_ENABLE_AVI(1 << 21) | |
891 | VIDEO_DIP_ENABLE_VENDOR(2 << 21) | VIDEO_DIP_ENABLE_SPD(8 << 21)); |
892 | intel_de_write(dev_priv, reg, val); |
893 | intel_de_posting_read(dev_priv, reg); |
894 | return; |
895 | } |
896 | |
897 | if (port != (val & VIDEO_DIP_PORT_MASK(3 << 29))) { |
898 | if (val & VIDEO_DIP_ENABLE(1 << 31)) { |
899 | drm_dbg_kms(&dev_priv->drm,__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "video DIP already enabled on port %c\n" , (val & (3 << 29)) >> 29) |
900 | "video DIP already enabled on port %c\n",__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "video DIP already enabled on port %c\n" , (val & (3 << 29)) >> 29) |
901 | (val & VIDEO_DIP_PORT_MASK) >> 29)__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "video DIP already enabled on port %c\n" , (val & (3 << 29)) >> 29); |
902 | return; |
903 | } |
904 | val &= ~VIDEO_DIP_PORT_MASK(3 << 29); |
905 | val |= port; |
906 | } |
907 | |
908 | val |= VIDEO_DIP_ENABLE(1 << 31); |
909 | val &= ~(VIDEO_DIP_ENABLE_AVI(1 << 21) | |
910 | VIDEO_DIP_ENABLE_VENDOR(2 << 21) | VIDEO_DIP_ENABLE_SPD(8 << 21)); |
911 | |
912 | intel_de_write(dev_priv, reg, val); |
913 | intel_de_posting_read(dev_priv, reg); |
914 | |
915 | intel_write_infoframe(encoder, crtc_state, |
916 | HDMI_INFOFRAME_TYPE_AVI, |
917 | &crtc_state->infoframes.avi); |
918 | intel_write_infoframe(encoder, crtc_state, |
919 | HDMI_INFOFRAME_TYPE_SPD, |
920 | &crtc_state->infoframes.spd); |
921 | intel_write_infoframe(encoder, crtc_state, |
922 | HDMI_INFOFRAME_TYPE_VENDOR, |
923 | &crtc_state->infoframes.hdmi); |
924 | } |
925 | |
926 | /* |
927 | * Determine if default_phase=1 can be indicated in the GCP infoframe. |
928 | * |
929 | * From HDMI specification 1.4a: |
930 | * - The first pixel of each Video Data Period shall always have a pixel packing phase of 0 |
931 | * - The first pixel following each Video Data Period shall have a pixel packing phase of 0 |
932 | * - The PP bits shall be constant for all GCPs and will be equal to the last packing phase |
933 | * - The first pixel following every transition of HSYNC or VSYNC shall have a pixel packing |
934 | * phase of 0 |
935 | */ |
936 | static bool_Bool gcp_default_phase_possible(int pipe_bpp, |
937 | const struct drm_display_mode *mode) |
938 | { |
939 | unsigned int pixels_per_group; |
940 | |
941 | switch (pipe_bpp) { |
942 | case 30: |
943 | /* 4 pixels in 5 clocks */ |
944 | pixels_per_group = 4; |
945 | break; |
946 | case 36: |
947 | /* 2 pixels in 3 clocks */ |
948 | pixels_per_group = 2; |
949 | break; |
950 | case 48: |
951 | /* 1 pixel in 2 clocks */ |
952 | pixels_per_group = 1; |
953 | break; |
954 | default: |
955 | /* phase information not relevant for 8bpc */ |
956 | return false0; |
957 | } |
958 | |
959 | return mode->crtc_hdisplay % pixels_per_group == 0 && |
960 | mode->crtc_htotal % pixels_per_group == 0 && |
961 | mode->crtc_hblank_start % pixels_per_group == 0 && |
962 | mode->crtc_hblank_end % pixels_per_group == 0 && |
963 | mode->crtc_hsync_start % pixels_per_group == 0 && |
964 | mode->crtc_hsync_end % pixels_per_group == 0 && |
965 | ((mode->flags & DRM_MODE_FLAG_INTERLACE(1<<4)) == 0 || |
966 | mode->crtc_htotal/2 % pixels_per_group == 0); |
967 | } |
968 | |
969 | static bool_Bool intel_hdmi_set_gcp_infoframe(struct intel_encoder *encoder, |
970 | const struct intel_crtc_state *crtc_state, |
971 | const struct drm_connector_state *conn_state) |
972 | { |
973 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev); |
974 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc)({ const __typeof( ((struct intel_crtc *)0)->base ) *__mptr = (crtc_state->uapi.crtc); (struct intel_crtc *)( (char * )__mptr - __builtin_offsetof(struct intel_crtc, base) );}); |
975 | i915_reg_t reg; |
976 | |
977 | if ((crtc_state->infoframes.enable & |
978 | intel_hdmi_infoframe_enable(HDMI_PACKET_TYPE_GENERAL_CONTROL)) == 0) |
979 | return false0; |
980 | |
981 | if (HAS_DDI(dev_priv)((&(dev_priv)->__info)->display.has_ddi)) |
982 | reg = HSW_TVIDEO_DIP_GCP(crtc_state->cpu_transcoder)((const i915_reg_t){ .reg = ((&(dev_priv)->__info)-> display.trans_offsets[(crtc_state->cpu_transcoder)] - (& (dev_priv)->__info)->display.trans_offsets[TRANSCODER_A ] + ((&(dev_priv)->__info)->display.mmio_offset) + ( 0x60210)) }); |
983 | else if (IS_VALLEYVIEW(dev_priv)IS_PLATFORM(dev_priv, INTEL_VALLEYVIEW) || IS_CHERRYVIEW(dev_priv)IS_PLATFORM(dev_priv, INTEL_CHERRYVIEW)) |
984 | reg = VLV_TVIDEO_DIP_GCP(crtc->pipe)((const i915_reg_t){ .reg = ((((const u32 []){ (0x180000 + 0x60210 ), (0x180000 + 0x61178), (0x180000 + 0x611f8) })[(crtc->pipe )])) }); |
985 | else if (HAS_PCH_SPLIT(dev_priv)(((dev_priv)->pch_type) != PCH_NONE)) |
986 | reg = TVIDEO_DIP_GCP(crtc->pipe)((const i915_reg_t){ .reg = (((0xe0210) + (crtc->pipe) * ( (0xe1210) - (0xe0210)))) }); |
987 | else |
988 | return false0; |
989 | |
990 | intel_de_write(dev_priv, reg, crtc_state->infoframes.gcp); |
991 | |
992 | return true1; |
993 | } |
994 | |
995 | void intel_hdmi_read_gcp_infoframe(struct intel_encoder *encoder, |
996 | struct intel_crtc_state *crtc_state) |
997 | { |
998 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev); |
999 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc)({ const __typeof( ((struct intel_crtc *)0)->base ) *__mptr = (crtc_state->uapi.crtc); (struct intel_crtc *)( (char * )__mptr - __builtin_offsetof(struct intel_crtc, base) );}); |
1000 | i915_reg_t reg; |
1001 | |
1002 | if ((crtc_state->infoframes.enable & |
1003 | intel_hdmi_infoframe_enable(HDMI_PACKET_TYPE_GENERAL_CONTROL)) == 0) |
1004 | return; |
1005 | |
1006 | if (HAS_DDI(dev_priv)((&(dev_priv)->__info)->display.has_ddi)) |
1007 | reg = HSW_TVIDEO_DIP_GCP(crtc_state->cpu_transcoder)((const i915_reg_t){ .reg = ((&(dev_priv)->__info)-> display.trans_offsets[(crtc_state->cpu_transcoder)] - (& (dev_priv)->__info)->display.trans_offsets[TRANSCODER_A ] + ((&(dev_priv)->__info)->display.mmio_offset) + ( 0x60210)) }); |
1008 | else if (IS_VALLEYVIEW(dev_priv)IS_PLATFORM(dev_priv, INTEL_VALLEYVIEW) || IS_CHERRYVIEW(dev_priv)IS_PLATFORM(dev_priv, INTEL_CHERRYVIEW)) |
1009 | reg = VLV_TVIDEO_DIP_GCP(crtc->pipe)((const i915_reg_t){ .reg = ((((const u32 []){ (0x180000 + 0x60210 ), (0x180000 + 0x61178), (0x180000 + 0x611f8) })[(crtc->pipe )])) }); |
1010 | else if (HAS_PCH_SPLIT(dev_priv)(((dev_priv)->pch_type) != PCH_NONE)) |
1011 | reg = TVIDEO_DIP_GCP(crtc->pipe)((const i915_reg_t){ .reg = (((0xe0210) + (crtc->pipe) * ( (0xe1210) - (0xe0210)))) }); |
1012 | else |
1013 | return; |
1014 | |
1015 | crtc_state->infoframes.gcp = intel_de_read(dev_priv, reg); |
1016 | } |
1017 | |
1018 | static void intel_hdmi_compute_gcp_infoframe(struct intel_encoder *encoder, |
1019 | struct intel_crtc_state *crtc_state, |
1020 | struct drm_connector_state *conn_state) |
1021 | { |
1022 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev); |
1023 | |
1024 | if (IS_G4X(dev_priv)(IS_PLATFORM(dev_priv, INTEL_G45) || IS_PLATFORM(dev_priv, INTEL_GM45 )) || !crtc_state->has_infoframe) |
1025 | return; |
1026 | |
1027 | crtc_state->infoframes.enable |= |
1028 | intel_hdmi_infoframe_enable(HDMI_PACKET_TYPE_GENERAL_CONTROL); |
1029 | |
1030 | /* Indicate color indication for deep color mode */ |
1031 | if (crtc_state->pipe_bpp > 24) |
1032 | crtc_state->infoframes.gcp |= GCP_COLOR_INDICATION(1 << 2); |
1033 | |
1034 | /* Enable default_phase whenever the display mode is suitably aligned */ |
1035 | if (gcp_default_phase_possible(crtc_state->pipe_bpp, |
1036 | &crtc_state->hw.adjusted_mode)) |
1037 | crtc_state->infoframes.gcp |= GCP_DEFAULT_PHASE_ENABLE(1 << 1); |
1038 | } |
1039 | |
1040 | static void ibx_set_infoframes(struct intel_encoder *encoder, |
1041 | bool_Bool enable, |
1042 | const struct intel_crtc_state *crtc_state, |
1043 | const struct drm_connector_state *conn_state) |
1044 | { |
1045 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev); |
1046 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc)({ const __typeof( ((struct intel_crtc *)0)->base ) *__mptr = (crtc_state->uapi.crtc); (struct intel_crtc *)( (char * )__mptr - __builtin_offsetof(struct intel_crtc, base) );}); |
1047 | struct intel_digital_port *dig_port = enc_to_dig_port(encoder); |
1048 | struct intel_hdmi *intel_hdmi = &dig_port->hdmi; |
1049 | i915_reg_t reg = TVIDEO_DIP_CTL(crtc->pipe)((const i915_reg_t){ .reg = (((0xe0200) + (crtc->pipe) * ( (0xe1200) - (0xe0200)))) }); |
1050 | u32 val = intel_de_read(dev_priv, reg); |
1051 | u32 port = VIDEO_DIP_PORT(encoder->port)((encoder->port) << 29); |
1052 | |
1053 | assert_hdmi_port_disabled(intel_hdmi); |
1054 | |
1055 | /* See the big comment in g4x_set_infoframes() */ |
1056 | val |= VIDEO_DIP_SELECT_AVI(0 << 19) | VIDEO_DIP_FREQ_VSYNC(1 << 16); |
1057 | |
1058 | if (!enable) { |
1059 | if (!(val & VIDEO_DIP_ENABLE(1 << 31))) |
1060 | return; |
1061 | val &= ~(VIDEO_DIP_ENABLE(1 << 31) | VIDEO_DIP_ENABLE_AVI(1 << 21) | |
1062 | VIDEO_DIP_ENABLE_VENDOR(2 << 21) | VIDEO_DIP_ENABLE_GAMUT(4 << 21) | |
1063 | VIDEO_DIP_ENABLE_SPD(8 << 21) | VIDEO_DIP_ENABLE_GCP(1 << 25)); |
1064 | intel_de_write(dev_priv, reg, val); |
1065 | intel_de_posting_read(dev_priv, reg); |
1066 | return; |
1067 | } |
1068 | |
1069 | if (port != (val & VIDEO_DIP_PORT_MASK(3 << 29))) { |
1070 | drm_WARN(&dev_priv->drm, val & VIDEO_DIP_ENABLE,({ int __ret = !!(val & (1 << 31)); if (__ret) printf ("%s %s: " "DIP already enabled on port %c\n", dev_driver_string ((&dev_priv->drm)->dev), "", (val & (3 << 29)) >> 29); __builtin_expect(!!(__ret), 0); }) |
1071 | "DIP already enabled on port %c\n",({ int __ret = !!(val & (1 << 31)); if (__ret) printf ("%s %s: " "DIP already enabled on port %c\n", dev_driver_string ((&dev_priv->drm)->dev), "", (val & (3 << 29)) >> 29); __builtin_expect(!!(__ret), 0); }) |
1072 | (val & VIDEO_DIP_PORT_MASK) >> 29)({ int __ret = !!(val & (1 << 31)); if (__ret) printf ("%s %s: " "DIP already enabled on port %c\n", dev_driver_string ((&dev_priv->drm)->dev), "", (val & (3 << 29)) >> 29); __builtin_expect(!!(__ret), 0); }); |
1073 | val &= ~VIDEO_DIP_PORT_MASK(3 << 29); |
1074 | val |= port; |
1075 | } |
1076 | |
1077 | val |= VIDEO_DIP_ENABLE(1 << 31); |
1078 | val &= ~(VIDEO_DIP_ENABLE_AVI(1 << 21) | |
1079 | VIDEO_DIP_ENABLE_VENDOR(2 << 21) | VIDEO_DIP_ENABLE_GAMUT(4 << 21) | |
1080 | VIDEO_DIP_ENABLE_SPD(8 << 21) | VIDEO_DIP_ENABLE_GCP(1 << 25)); |
1081 | |
1082 | if (intel_hdmi_set_gcp_infoframe(encoder, crtc_state, conn_state)) |
1083 | val |= VIDEO_DIP_ENABLE_GCP(1 << 25); |
1084 | |
1085 | intel_de_write(dev_priv, reg, val); |
1086 | intel_de_posting_read(dev_priv, reg); |
1087 | |
1088 | intel_write_infoframe(encoder, crtc_state, |
1089 | HDMI_INFOFRAME_TYPE_AVI, |
1090 | &crtc_state->infoframes.avi); |
1091 | intel_write_infoframe(encoder, crtc_state, |
1092 | HDMI_INFOFRAME_TYPE_SPD, |
1093 | &crtc_state->infoframes.spd); |
1094 | intel_write_infoframe(encoder, crtc_state, |
1095 | HDMI_INFOFRAME_TYPE_VENDOR, |
1096 | &crtc_state->infoframes.hdmi); |
1097 | } |
1098 | |
1099 | static void cpt_set_infoframes(struct intel_encoder *encoder, |
1100 | bool_Bool enable, |
1101 | const struct intel_crtc_state *crtc_state, |
1102 | const struct drm_connector_state *conn_state) |
1103 | { |
1104 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev); |
1105 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc)({ const __typeof( ((struct intel_crtc *)0)->base ) *__mptr = (crtc_state->uapi.crtc); (struct intel_crtc *)( (char * )__mptr - __builtin_offsetof(struct intel_crtc, base) );}); |
1106 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
1107 | i915_reg_t reg = TVIDEO_DIP_CTL(crtc->pipe)((const i915_reg_t){ .reg = (((0xe0200) + (crtc->pipe) * ( (0xe1200) - (0xe0200)))) }); |
1108 | u32 val = intel_de_read(dev_priv, reg); |
1109 | |
1110 | assert_hdmi_port_disabled(intel_hdmi); |
1111 | |
1112 | /* See the big comment in g4x_set_infoframes() */ |
1113 | val |= VIDEO_DIP_SELECT_AVI(0 << 19) | VIDEO_DIP_FREQ_VSYNC(1 << 16); |
1114 | |
1115 | if (!enable) { |
1116 | if (!(val & VIDEO_DIP_ENABLE(1 << 31))) |
1117 | return; |
1118 | val &= ~(VIDEO_DIP_ENABLE(1 << 31) | VIDEO_DIP_ENABLE_AVI(1 << 21) | |
1119 | VIDEO_DIP_ENABLE_VENDOR(2 << 21) | VIDEO_DIP_ENABLE_GAMUT(4 << 21) | |
1120 | VIDEO_DIP_ENABLE_SPD(8 << 21) | VIDEO_DIP_ENABLE_GCP(1 << 25)); |
1121 | intel_de_write(dev_priv, reg, val); |
1122 | intel_de_posting_read(dev_priv, reg); |
1123 | return; |
1124 | } |
1125 | |
1126 | /* Set both together, unset both together: see the spec. */ |
1127 | val |= VIDEO_DIP_ENABLE(1 << 31) | VIDEO_DIP_ENABLE_AVI(1 << 21); |
1128 | val &= ~(VIDEO_DIP_ENABLE_VENDOR(2 << 21) | VIDEO_DIP_ENABLE_GAMUT(4 << 21) | |
1129 | VIDEO_DIP_ENABLE_SPD(8 << 21) | VIDEO_DIP_ENABLE_GCP(1 << 25)); |
1130 | |
1131 | if (intel_hdmi_set_gcp_infoframe(encoder, crtc_state, conn_state)) |
1132 | val |= VIDEO_DIP_ENABLE_GCP(1 << 25); |
1133 | |
1134 | intel_de_write(dev_priv, reg, val); |
1135 | intel_de_posting_read(dev_priv, reg); |
1136 | |
1137 | intel_write_infoframe(encoder, crtc_state, |
1138 | HDMI_INFOFRAME_TYPE_AVI, |
1139 | &crtc_state->infoframes.avi); |
1140 | intel_write_infoframe(encoder, crtc_state, |
1141 | HDMI_INFOFRAME_TYPE_SPD, |
1142 | &crtc_state->infoframes.spd); |
1143 | intel_write_infoframe(encoder, crtc_state, |
1144 | HDMI_INFOFRAME_TYPE_VENDOR, |
1145 | &crtc_state->infoframes.hdmi); |
1146 | } |
1147 | |
1148 | static void vlv_set_infoframes(struct intel_encoder *encoder, |
1149 | bool_Bool enable, |
1150 | const struct intel_crtc_state *crtc_state, |
1151 | const struct drm_connector_state *conn_state) |
1152 | { |
1153 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev); |
1154 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc)({ const __typeof( ((struct intel_crtc *)0)->base ) *__mptr = (crtc_state->uapi.crtc); (struct intel_crtc *)( (char * )__mptr - __builtin_offsetof(struct intel_crtc, base) );}); |
1155 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
1156 | i915_reg_t reg = VLV_TVIDEO_DIP_CTL(crtc->pipe)((const i915_reg_t){ .reg = ((((const u32 []){ (0x180000 + 0x60200 ), (0x180000 + 0x61170), (0x180000 + 0x611f0) })[(crtc->pipe )])) }); |
1157 | u32 val = intel_de_read(dev_priv, reg); |
1158 | u32 port = VIDEO_DIP_PORT(encoder->port)((encoder->port) << 29); |
1159 | |
1160 | assert_hdmi_port_disabled(intel_hdmi); |
1161 | |
1162 | /* See the big comment in g4x_set_infoframes() */ |
1163 | val |= VIDEO_DIP_SELECT_AVI(0 << 19) | VIDEO_DIP_FREQ_VSYNC(1 << 16); |
1164 | |
1165 | if (!enable) { |
1166 | if (!(val & VIDEO_DIP_ENABLE(1 << 31))) |
1167 | return; |
1168 | val &= ~(VIDEO_DIP_ENABLE(1 << 31) | VIDEO_DIP_ENABLE_AVI(1 << 21) | |
1169 | VIDEO_DIP_ENABLE_VENDOR(2 << 21) | VIDEO_DIP_ENABLE_GAMUT(4 << 21) | |
1170 | VIDEO_DIP_ENABLE_SPD(8 << 21) | VIDEO_DIP_ENABLE_GCP(1 << 25)); |
1171 | intel_de_write(dev_priv, reg, val); |
1172 | intel_de_posting_read(dev_priv, reg); |
1173 | return; |
1174 | } |
1175 | |
1176 | if (port != (val & VIDEO_DIP_PORT_MASK(3 << 29))) { |
1177 | drm_WARN(&dev_priv->drm, val & VIDEO_DIP_ENABLE,({ int __ret = !!(val & (1 << 31)); if (__ret) printf ("%s %s: " "DIP already enabled on port %c\n", dev_driver_string ((&dev_priv->drm)->dev), "", (val & (3 << 29)) >> 29); __builtin_expect(!!(__ret), 0); }) |
1178 | "DIP already enabled on port %c\n",({ int __ret = !!(val & (1 << 31)); if (__ret) printf ("%s %s: " "DIP already enabled on port %c\n", dev_driver_string ((&dev_priv->drm)->dev), "", (val & (3 << 29)) >> 29); __builtin_expect(!!(__ret), 0); }) |
1179 | (val & VIDEO_DIP_PORT_MASK) >> 29)({ int __ret = !!(val & (1 << 31)); if (__ret) printf ("%s %s: " "DIP already enabled on port %c\n", dev_driver_string ((&dev_priv->drm)->dev), "", (val & (3 << 29)) >> 29); __builtin_expect(!!(__ret), 0); }); |
1180 | val &= ~VIDEO_DIP_PORT_MASK(3 << 29); |
1181 | val |= port; |
1182 | } |
1183 | |
1184 | val |= VIDEO_DIP_ENABLE(1 << 31); |
1185 | val &= ~(VIDEO_DIP_ENABLE_AVI(1 << 21) | |
1186 | VIDEO_DIP_ENABLE_VENDOR(2 << 21) | VIDEO_DIP_ENABLE_GAMUT(4 << 21) | |
1187 | VIDEO_DIP_ENABLE_SPD(8 << 21) | VIDEO_DIP_ENABLE_GCP(1 << 25)); |
1188 | |
1189 | if (intel_hdmi_set_gcp_infoframe(encoder, crtc_state, conn_state)) |
1190 | val |= VIDEO_DIP_ENABLE_GCP(1 << 25); |
1191 | |
1192 | intel_de_write(dev_priv, reg, val); |
1193 | intel_de_posting_read(dev_priv, reg); |
1194 | |
1195 | intel_write_infoframe(encoder, crtc_state, |
1196 | HDMI_INFOFRAME_TYPE_AVI, |
1197 | &crtc_state->infoframes.avi); |
1198 | intel_write_infoframe(encoder, crtc_state, |
1199 | HDMI_INFOFRAME_TYPE_SPD, |
1200 | &crtc_state->infoframes.spd); |
1201 | intel_write_infoframe(encoder, crtc_state, |
1202 | HDMI_INFOFRAME_TYPE_VENDOR, |
1203 | &crtc_state->infoframes.hdmi); |
1204 | } |
1205 | |
1206 | static void hsw_set_infoframes(struct intel_encoder *encoder, |
1207 | bool_Bool enable, |
1208 | const struct intel_crtc_state *crtc_state, |
1209 | const struct drm_connector_state *conn_state) |
1210 | { |
1211 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev); |
1212 | i915_reg_t reg = HSW_TVIDEO_DIP_CTL(crtc_state->cpu_transcoder)((const i915_reg_t){ .reg = ((&(dev_priv)->__info)-> display.trans_offsets[(crtc_state->cpu_transcoder)] - (& (dev_priv)->__info)->display.trans_offsets[TRANSCODER_A ] + ((&(dev_priv)->__info)->display.mmio_offset) + ( 0x60200)) }); |
1213 | u32 val = intel_de_read(dev_priv, reg); |
1214 | |
1215 | assert_hdmi_transcoder_func_disabled(dev_priv, |
1216 | crtc_state->cpu_transcoder); |
1217 | |
1218 | val &= ~(VIDEO_DIP_ENABLE_VSC_HSW(1 << 20) | VIDEO_DIP_ENABLE_AVI_HSW(1 << 12) | |
1219 | VIDEO_DIP_ENABLE_GCP_HSW(1 << 16) | VIDEO_DIP_ENABLE_VS_HSW(1 << 8) | |
1220 | VIDEO_DIP_ENABLE_GMP_HSW(1 << 4) | VIDEO_DIP_ENABLE_SPD_HSW(1 << 0) | |
1221 | VIDEO_DIP_ENABLE_DRM_GLK(1 << 28)); |
1222 | |
1223 | if (!enable) { |
1224 | intel_de_write(dev_priv, reg, val); |
1225 | intel_de_posting_read(dev_priv, reg); |
1226 | return; |
1227 | } |
1228 | |
1229 | if (intel_hdmi_set_gcp_infoframe(encoder, crtc_state, conn_state)) |
1230 | val |= VIDEO_DIP_ENABLE_GCP_HSW(1 << 16); |
1231 | |
1232 | intel_de_write(dev_priv, reg, val); |
1233 | intel_de_posting_read(dev_priv, reg); |
1234 | |
1235 | intel_write_infoframe(encoder, crtc_state, |
1236 | HDMI_INFOFRAME_TYPE_AVI, |
1237 | &crtc_state->infoframes.avi); |
1238 | intel_write_infoframe(encoder, crtc_state, |
1239 | HDMI_INFOFRAME_TYPE_SPD, |
1240 | &crtc_state->infoframes.spd); |
1241 | intel_write_infoframe(encoder, crtc_state, |
1242 | HDMI_INFOFRAME_TYPE_VENDOR, |
1243 | &crtc_state->infoframes.hdmi); |
1244 | intel_write_infoframe(encoder, crtc_state, |
1245 | HDMI_INFOFRAME_TYPE_DRM, |
1246 | &crtc_state->infoframes.drm); |
1247 | } |
1248 | |
1249 | void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool_Bool enable) |
1250 | { |
1251 | struct drm_i915_privateinteldrm_softc *dev_priv = intel_hdmi_to_i915(hdmi); |
1252 | struct i2c_adapter *adapter; |
1253 | |
1254 | if (hdmi->dp_dual_mode.type < DRM_DP_DUAL_MODE_TYPE2_DVI) |
1255 | return; |
1256 | |
1257 | adapter = intel_gmbus_get_adapter(dev_priv, hdmi->ddc_bus); |
1258 | |
1259 | drm_dbg_kms(&dev_priv->drm, "%s DP dual mode adaptor TMDS output\n",__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "%s DP dual mode adaptor TMDS output\n" , enable ? "Enabling" : "Disabling") |
1260 | enable ? "Enabling" : "Disabling")__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "%s DP dual mode adaptor TMDS output\n" , enable ? "Enabling" : "Disabling"); |
1261 | |
1262 | drm_dp_dual_mode_set_tmds_output(&dev_priv->drm, hdmi->dp_dual_mode.type, adapter, enable); |
1263 | } |
1264 | |
1265 | static int intel_hdmi_hdcp_read(struct intel_digital_port *dig_port, |
1266 | unsigned int offset, void *buffer, size_t size) |
1267 | { |
1268 | struct drm_i915_privateinteldrm_softc *i915 = to_i915(dig_port->base.base.dev); |
1269 | struct intel_hdmi *hdmi = &dig_port->hdmi; |
1270 | struct i2c_adapter *adapter = intel_gmbus_get_adapter(i915, |
1271 | hdmi->ddc_bus); |
1272 | int ret; |
1273 | u8 start = offset & 0xff; |
1274 | struct i2c_msg msgs[] = { |
1275 | { |
1276 | .addr = DRM_HDCP_DDC_ADDR0x3A, |
1277 | .flags = 0, |
1278 | .len = 1, |
1279 | .buf = &start, |
1280 | }, |
1281 | { |
1282 | .addr = DRM_HDCP_DDC_ADDR0x3A, |
1283 | .flags = I2C_M_RD0x0001, |
1284 | .len = size, |
1285 | .buf = buffer |
1286 | } |
1287 | }; |
1288 | ret = i2c_transfer(adapter, msgs, ARRAY_SIZE(msgs)(sizeof((msgs)) / sizeof((msgs)[0]))); |
1289 | if (ret == ARRAY_SIZE(msgs)(sizeof((msgs)) / sizeof((msgs)[0]))) |
1290 | return 0; |
1291 | return ret >= 0 ? -EIO5 : ret; |
1292 | } |
1293 | |
1294 | static int intel_hdmi_hdcp_write(struct intel_digital_port *dig_port, |
1295 | unsigned int offset, void *buffer, size_t size) |
1296 | { |
1297 | struct drm_i915_privateinteldrm_softc *i915 = to_i915(dig_port->base.base.dev); |
1298 | struct intel_hdmi *hdmi = &dig_port->hdmi; |
1299 | struct i2c_adapter *adapter = intel_gmbus_get_adapter(i915, |
1300 | hdmi->ddc_bus); |
1301 | int ret; |
1302 | u8 *write_buf; |
1303 | struct i2c_msg msg; |
1304 | |
1305 | write_buf = kzalloc(size + 1, GFP_KERNEL(0x0001 | 0x0004)); |
1306 | if (!write_buf) |
1307 | return -ENOMEM12; |
1308 | |
1309 | write_buf[0] = offset & 0xff; |
1310 | memcpy(&write_buf[1], buffer, size)__builtin_memcpy((&write_buf[1]), (buffer), (size)); |
1311 | |
1312 | msg.addr = DRM_HDCP_DDC_ADDR0x3A; |
1313 | msg.flags = 0, |
1314 | msg.len = size + 1, |
1315 | msg.buf = write_buf; |
1316 | |
1317 | ret = i2c_transfer(adapter, &msg, 1); |
1318 | if (ret == 1) |
1319 | ret = 0; |
1320 | else if (ret >= 0) |
1321 | ret = -EIO5; |
1322 | |
1323 | kfree(write_buf); |
1324 | return ret; |
1325 | } |
1326 | |
1327 | static |
1328 | int intel_hdmi_hdcp_write_an_aksv(struct intel_digital_port *dig_port, |
1329 | u8 *an) |
1330 | { |
1331 | struct drm_i915_privateinteldrm_softc *i915 = to_i915(dig_port->base.base.dev); |
1332 | struct intel_hdmi *hdmi = &dig_port->hdmi; |
1333 | struct i2c_adapter *adapter = intel_gmbus_get_adapter(i915, |
1334 | hdmi->ddc_bus); |
1335 | int ret; |
1336 | |
1337 | ret = intel_hdmi_hdcp_write(dig_port, DRM_HDCP_DDC_AN0x18, an, |
1338 | DRM_HDCP_AN_LEN8); |
1339 | if (ret) { |
1340 | drm_dbg_kms(&i915->drm, "Write An over DDC failed (%d)\n",__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "Write An over DDC failed (%d)\n" , ret) |
1341 | ret)__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "Write An over DDC failed (%d)\n" , ret); |
1342 | return ret; |
1343 | } |
1344 | |
1345 | ret = intel_gmbus_output_aksv(adapter); |
1346 | if (ret < 0) { |
1347 | drm_dbg_kms(&i915->drm, "Failed to output aksv (%d)\n", ret)__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "Failed to output aksv (%d)\n" , ret); |
1348 | return ret; |
1349 | } |
1350 | return 0; |
1351 | } |
1352 | |
1353 | static int intel_hdmi_hdcp_read_bksv(struct intel_digital_port *dig_port, |
1354 | u8 *bksv) |
1355 | { |
1356 | struct drm_i915_privateinteldrm_softc *i915 = to_i915(dig_port->base.base.dev); |
1357 | |
1358 | int ret; |
1359 | ret = intel_hdmi_hdcp_read(dig_port, DRM_HDCP_DDC_BKSV0x00, bksv, |
1360 | DRM_HDCP_KSV_LEN5); |
1361 | if (ret) |
1362 | drm_dbg_kms(&i915->drm, "Read Bksv over DDC failed (%d)\n",__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "Read Bksv over DDC failed (%d)\n" , ret) |
1363 | ret)__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "Read Bksv over DDC failed (%d)\n" , ret); |
1364 | return ret; |
1365 | } |
1366 | |
1367 | static |
1368 | int intel_hdmi_hdcp_read_bstatus(struct intel_digital_port *dig_port, |
1369 | u8 *bstatus) |
1370 | { |
1371 | struct drm_i915_privateinteldrm_softc *i915 = to_i915(dig_port->base.base.dev); |
1372 | |
1373 | int ret; |
1374 | ret = intel_hdmi_hdcp_read(dig_port, DRM_HDCP_DDC_BSTATUS0x41, |
1375 | bstatus, DRM_HDCP_BSTATUS_LEN2); |
1376 | if (ret) |
1377 | drm_dbg_kms(&i915->drm, "Read bstatus over DDC failed (%d)\n",__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "Read bstatus over DDC failed (%d)\n" , ret) |
1378 | ret)__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "Read bstatus over DDC failed (%d)\n" , ret); |
1379 | return ret; |
1380 | } |
1381 | |
1382 | static |
1383 | int intel_hdmi_hdcp_repeater_present(struct intel_digital_port *dig_port, |
1384 | bool_Bool *repeater_present) |
1385 | { |
1386 | struct drm_i915_privateinteldrm_softc *i915 = to_i915(dig_port->base.base.dev); |
1387 | int ret; |
1388 | u8 val; |
1389 | |
1390 | ret = intel_hdmi_hdcp_read(dig_port, DRM_HDCP_DDC_BCAPS0x40, &val, 1); |
1391 | if (ret) { |
1392 | drm_dbg_kms(&i915->drm, "Read bcaps over DDC failed (%d)\n",__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "Read bcaps over DDC failed (%d)\n" , ret) |
1393 | ret)__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "Read bcaps over DDC failed (%d)\n" , ret); |
1394 | return ret; |
1395 | } |
1396 | *repeater_present = val & DRM_HDCP_DDC_BCAPS_REPEATER_PRESENT(1UL << (6)); |
1397 | return 0; |
1398 | } |
1399 | |
1400 | static |
1401 | int intel_hdmi_hdcp_read_ri_prime(struct intel_digital_port *dig_port, |
1402 | u8 *ri_prime) |
1403 | { |
1404 | struct drm_i915_privateinteldrm_softc *i915 = to_i915(dig_port->base.base.dev); |
1405 | |
1406 | int ret; |
1407 | ret = intel_hdmi_hdcp_read(dig_port, DRM_HDCP_DDC_RI_PRIME0x08, |
1408 | ri_prime, DRM_HDCP_RI_LEN2); |
1409 | if (ret) |
1410 | drm_dbg_kms(&i915->drm, "Read Ri' over DDC failed (%d)\n",__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "Read Ri' over DDC failed (%d)\n" , ret) |
1411 | ret)__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "Read Ri' over DDC failed (%d)\n" , ret); |
1412 | return ret; |
1413 | } |
1414 | |
1415 | static |
1416 | int intel_hdmi_hdcp_read_ksv_ready(struct intel_digital_port *dig_port, |
1417 | bool_Bool *ksv_ready) |
1418 | { |
1419 | struct drm_i915_privateinteldrm_softc *i915 = to_i915(dig_port->base.base.dev); |
1420 | int ret; |
1421 | u8 val; |
1422 | |
1423 | ret = intel_hdmi_hdcp_read(dig_port, DRM_HDCP_DDC_BCAPS0x40, &val, 1); |
1424 | if (ret) { |
1425 | drm_dbg_kms(&i915->drm, "Read bcaps over DDC failed (%d)\n",__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "Read bcaps over DDC failed (%d)\n" , ret) |
1426 | ret)__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "Read bcaps over DDC failed (%d)\n" , ret); |
1427 | return ret; |
1428 | } |
1429 | *ksv_ready = val & DRM_HDCP_DDC_BCAPS_KSV_FIFO_READY(1UL << (5)); |
1430 | return 0; |
1431 | } |
1432 | |
1433 | static |
1434 | int intel_hdmi_hdcp_read_ksv_fifo(struct intel_digital_port *dig_port, |
1435 | int num_downstream, u8 *ksv_fifo) |
1436 | { |
1437 | struct drm_i915_privateinteldrm_softc *i915 = to_i915(dig_port->base.base.dev); |
1438 | int ret; |
1439 | ret = intel_hdmi_hdcp_read(dig_port, DRM_HDCP_DDC_KSV_FIFO0x43, |
1440 | ksv_fifo, num_downstream * DRM_HDCP_KSV_LEN5); |
1441 | if (ret) { |
1442 | drm_dbg_kms(&i915->drm,__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "Read ksv fifo over DDC failed (%d)\n" , ret) |
1443 | "Read ksv fifo over DDC failed (%d)\n", ret)__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "Read ksv fifo over DDC failed (%d)\n" , ret); |
1444 | return ret; |
1445 | } |
1446 | return 0; |
1447 | } |
1448 | |
1449 | static |
1450 | int intel_hdmi_hdcp_read_v_prime_part(struct intel_digital_port *dig_port, |
1451 | int i, u32 *part) |
1452 | { |
1453 | struct drm_i915_privateinteldrm_softc *i915 = to_i915(dig_port->base.base.dev); |
1454 | int ret; |
1455 | |
1456 | if (i >= DRM_HDCP_V_PRIME_NUM_PARTS5) |
1457 | return -EINVAL22; |
1458 | |
1459 | ret = intel_hdmi_hdcp_read(dig_port, DRM_HDCP_DDC_V_PRIME(i)(0x20 + i * 4), |
1460 | part, DRM_HDCP_V_PRIME_PART_LEN4); |
1461 | if (ret) |
1462 | drm_dbg_kms(&i915->drm, "Read V'[%d] over DDC failed (%d)\n",__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "Read V'[%d] over DDC failed (%d)\n" , i, ret) |
1463 | i, ret)__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "Read V'[%d] over DDC failed (%d)\n" , i, ret); |
1464 | return ret; |
1465 | } |
1466 | |
1467 | static int kbl_repositioning_enc_en_signal(struct intel_connector *connector, |
1468 | enum transcoder cpu_transcoder) |
1469 | { |
1470 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); |
1471 | struct intel_digital_port *dig_port = intel_attached_dig_port(connector); |
1472 | struct intel_crtc *crtc = to_intel_crtc(connector->base.state->crtc)({ const __typeof( ((struct intel_crtc *)0)->base ) *__mptr = (connector->base.state->crtc); (struct intel_crtc *) ( (char *)__mptr - __builtin_offsetof(struct intel_crtc, base ) );}); |
1473 | u32 scanline; |
1474 | int ret; |
1475 | |
1476 | for (;;) { |
1477 | scanline = intel_de_read(dev_priv, PIPEDSL(crtc->pipe)((const i915_reg_t){ .reg = ((&(dev_priv)->__info)-> display.pipe_offsets[(crtc->pipe)] - (&(dev_priv)-> __info)->display.pipe_offsets[PIPE_A] + ((&(dev_priv)-> __info)->display.mmio_offset) + (0x70000)) })); |
1478 | if (scanline > 100 && scanline < 200) |
1479 | break; |
1480 | usleep_range(25, 50); |
1481 | } |
1482 | |
1483 | ret = intel_ddi_toggle_hdcp_bits(&dig_port->base, cpu_transcoder, |
1484 | false0, TRANS_DDI_HDCP_SIGNALLING(1 << 9)); |
1485 | if (ret) { |
1486 | drm_err(&dev_priv->drm,printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Disable HDCP signalling failed (%d)\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , ret) |
1487 | "Disable HDCP signalling failed (%d)\n", ret)printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Disable HDCP signalling failed (%d)\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , ret); |
1488 | return ret; |
1489 | } |
1490 | |
1491 | ret = intel_ddi_toggle_hdcp_bits(&dig_port->base, cpu_transcoder, |
1492 | true1, TRANS_DDI_HDCP_SIGNALLING(1 << 9)); |
1493 | if (ret) { |
1494 | drm_err(&dev_priv->drm,printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Enable HDCP signalling failed (%d)\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , ret) |
1495 | "Enable HDCP signalling failed (%d)\n", ret)printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Enable HDCP signalling failed (%d)\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , ret); |
1496 | return ret; |
1497 | } |
1498 | |
1499 | return 0; |
1500 | } |
1501 | |
1502 | static |
1503 | int intel_hdmi_hdcp_toggle_signalling(struct intel_digital_port *dig_port, |
1504 | enum transcoder cpu_transcoder, |
1505 | bool_Bool enable) |
1506 | { |
1507 | struct intel_hdmi *hdmi = &dig_port->hdmi; |
1508 | struct intel_connector *connector = hdmi->attached_connector; |
1509 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); |
1510 | int ret; |
1511 | |
1512 | if (!enable) |
1513 | usleep_range(6, 60); /* Bspec says >= 6us */ |
1514 | |
1515 | ret = intel_ddi_toggle_hdcp_bits(&dig_port->base, |
1516 | cpu_transcoder, enable, |
1517 | TRANS_DDI_HDCP_SIGNALLING(1 << 9)); |
1518 | if (ret) { |
1519 | drm_err(&dev_priv->drm, "%s HDCP signalling failed (%d)\n",printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "%s HDCP signalling failed (%d)\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , enable ? "Enable" : "Disable", ret) |
1520 | enable ? "Enable" : "Disable", ret)printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "%s HDCP signalling failed (%d)\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , enable ? "Enable" : "Disable", ret); |
1521 | return ret; |
1522 | } |
1523 | |
1524 | /* |
1525 | * WA: To fix incorrect positioning of the window of |
1526 | * opportunity and enc_en signalling in KABYLAKE. |
1527 | */ |
1528 | if (IS_KABYLAKE(dev_priv)IS_PLATFORM(dev_priv, INTEL_KABYLAKE) && enable) |
1529 | return kbl_repositioning_enc_en_signal(connector, |
1530 | cpu_transcoder); |
1531 | |
1532 | return 0; |
1533 | } |
1534 | |
1535 | static |
1536 | bool_Bool intel_hdmi_hdcp_check_link_once(struct intel_digital_port *dig_port, |
1537 | struct intel_connector *connector) |
1538 | { |
1539 | struct drm_i915_privateinteldrm_softc *i915 = to_i915(dig_port->base.base.dev); |
1540 | enum port port = dig_port->base.port; |
1541 | enum transcoder cpu_transcoder = connector->hdcp.cpu_transcoder; |
1542 | int ret; |
1543 | union { |
1544 | u32 reg; |
1545 | u8 shim[DRM_HDCP_RI_LEN2]; |
1546 | } ri; |
1547 | |
1548 | ret = intel_hdmi_hdcp_read_ri_prime(dig_port, ri.shim); |
1549 | if (ret) |
1550 | return false0; |
1551 | |
1552 | intel_de_write(i915, HDCP_RPRIME(i915, cpu_transcoder, port)(((&(i915)->__runtime)->graphics.ip.ver) >= 12 ? ((const i915_reg_t){ .reg = (((0x66418) + (cpu_transcoder) * ((0x66518) - (0x66418)))) }) : ((const i915_reg_t){ .reg = ( (((const u32 []){ 0x66800, 0x66500, 0x66600, 0x66700, 0x66A00 , 0x66900 })[port]) + (0x18)) })), ri.reg); |
1553 | |
1554 | /* Wait for Ri prime match */ |
1555 | if (wait_for((intel_de_read(i915, HDCP_STATUS(i915, cpu_transcoder, port)) &({ const ktime_t end__ = ktime_add_ns(ktime_get_raw(), 1000ll * (((1) * 1000))); long wait__ = ((10)); int ret__; assertwaitok (); for (;;) { const _Bool expired__ = ktime_after(ktime_get_raw (), end__); ; __asm volatile("" : : : "memory"); if ((((intel_de_read (i915, (((&(i915)->__runtime)->graphics.ip.ver) >= 12 ? ((const i915_reg_t){ .reg = (((0x6641C) + (cpu_transcoder ) * ((0x6651C) - (0x6641C)))) }) : ((const i915_reg_t){ .reg = ((((const u32 []){ 0x66800, 0x66500, 0x66600, 0x66700, 0x66A00 , 0x66900 })[port]) + (0x1C)) }))) & (((u32)((1UL << (19)) + 0)) | ((u32)((1UL << (20)) + 0)))) == (((u32)( (1UL << (19)) + 0)) | ((u32)((1UL << (20)) + 0))) ))) { ret__ = 0; break; } if (expired__) { ret__ = -60; break ; } usleep_range(wait__, wait__ * 2); if (wait__ < ((1000) )) wait__ <<= 1; } ret__; }) |
1556 | (HDCP_STATUS_RI_MATCH | HDCP_STATUS_ENC)) ==({ const ktime_t end__ = ktime_add_ns(ktime_get_raw(), 1000ll * (((1) * 1000))); long wait__ = ((10)); int ret__; assertwaitok (); for (;;) { const _Bool expired__ = ktime_after(ktime_get_raw (), end__); ; __asm volatile("" : : : "memory"); if ((((intel_de_read (i915, (((&(i915)->__runtime)->graphics.ip.ver) >= 12 ? ((const i915_reg_t){ .reg = (((0x6641C) + (cpu_transcoder ) * ((0x6651C) - (0x6641C)))) }) : ((const i915_reg_t){ .reg = ((((const u32 []){ 0x66800, 0x66500, 0x66600, 0x66700, 0x66A00 , 0x66900 })[port]) + (0x1C)) }))) & (((u32)((1UL << (19)) + 0)) | ((u32)((1UL << (20)) + 0)))) == (((u32)( (1UL << (19)) + 0)) | ((u32)((1UL << (20)) + 0))) ))) { ret__ = 0; break; } if (expired__) { ret__ = -60; break ; } usleep_range(wait__, wait__ * 2); if (wait__ < ((1000) )) wait__ <<= 1; } ret__; }) |
1557 | (HDCP_STATUS_RI_MATCH | HDCP_STATUS_ENC), 1)({ const ktime_t end__ = ktime_add_ns(ktime_get_raw(), 1000ll * (((1) * 1000))); long wait__ = ((10)); int ret__; assertwaitok (); for (;;) { const _Bool expired__ = ktime_after(ktime_get_raw (), end__); ; __asm volatile("" : : : "memory"); if ((((intel_de_read (i915, (((&(i915)->__runtime)->graphics.ip.ver) >= 12 ? ((const i915_reg_t){ .reg = (((0x6641C) + (cpu_transcoder ) * ((0x6651C) - (0x6641C)))) }) : ((const i915_reg_t){ .reg = ((((const u32 []){ 0x66800, 0x66500, 0x66600, 0x66700, 0x66A00 , 0x66900 })[port]) + (0x1C)) }))) & (((u32)((1UL << (19)) + 0)) | ((u32)((1UL << (20)) + 0)))) == (((u32)( (1UL << (19)) + 0)) | ((u32)((1UL << (20)) + 0))) ))) { ret__ = 0; break; } if (expired__) { ret__ = -60; break ; } usleep_range(wait__, wait__ * 2); if (wait__ < ((1000) )) wait__ <<= 1; } ret__; })) { |
1558 | drm_dbg_kms(&i915->drm, "Ri' mismatch detected (%x)\n",__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "Ri' mismatch detected (%x)\n" , intel_de_read(i915, (((&(i915)->__runtime)->graphics .ip.ver) >= 12 ? ((const i915_reg_t){ .reg = (((0x6641C) + (cpu_transcoder) * ((0x6651C) - (0x6641C)))) }) : ((const i915_reg_t ){ .reg = ((((const u32 []){ 0x66800, 0x66500, 0x66600, 0x66700 , 0x66A00, 0x66900 })[port]) + (0x1C)) })))) |
1559 | intel_de_read(i915, HDCP_STATUS(i915, cpu_transcoder,__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "Ri' mismatch detected (%x)\n" , intel_de_read(i915, (((&(i915)->__runtime)->graphics .ip.ver) >= 12 ? ((const i915_reg_t){ .reg = (((0x6641C) + (cpu_transcoder) * ((0x6651C) - (0x6641C)))) }) : ((const i915_reg_t ){ .reg = ((((const u32 []){ 0x66800, 0x66500, 0x66600, 0x66700 , 0x66A00, 0x66900 })[port]) + (0x1C)) })))) |
1560 | port)))__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "Ri' mismatch detected (%x)\n" , intel_de_read(i915, (((&(i915)->__runtime)->graphics .ip.ver) >= 12 ? ((const i915_reg_t){ .reg = (((0x6641C) + (cpu_transcoder) * ((0x6651C) - (0x6641C)))) }) : ((const i915_reg_t ){ .reg = ((((const u32 []){ 0x66800, 0x66500, 0x66600, 0x66700 , 0x66A00, 0x66900 })[port]) + (0x1C)) })))); |
1561 | return false0; |
1562 | } |
1563 | return true1; |
1564 | } |
1565 | |
1566 | static |
1567 | bool_Bool intel_hdmi_hdcp_check_link(struct intel_digital_port *dig_port, |
1568 | struct intel_connector *connector) |
1569 | { |
1570 | struct drm_i915_privateinteldrm_softc *i915 = to_i915(dig_port->base.base.dev); |
1571 | int retry; |
1572 | |
1573 | for (retry = 0; retry < 3; retry++) |
1574 | if (intel_hdmi_hdcp_check_link_once(dig_port, connector)) |
1575 | return true1; |
1576 | |
1577 | drm_err(&i915->drm, "Link check failed\n")printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Link check failed\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__); |
1578 | return false0; |
1579 | } |
1580 | |
1581 | struct hdcp2_hdmi_msg_timeout { |
1582 | u8 msg_id; |
1583 | u16 timeout; |
1584 | }; |
1585 | |
1586 | static const struct hdcp2_hdmi_msg_timeout hdcp2_msg_timeout[] = { |
1587 | { HDCP_2_2_AKE_SEND_CERT3, HDCP_2_2_CERT_TIMEOUT_MS100, }, |
1588 | { HDCP_2_2_AKE_SEND_PAIRING_INFO8, HDCP_2_2_PAIRING_TIMEOUT_MS200, }, |
1589 | { HDCP_2_2_LC_SEND_LPRIME10, HDCP_2_2_HDMI_LPRIME_TIMEOUT_MS20, }, |
1590 | { HDCP_2_2_REP_SEND_RECVID_LIST12, HDCP_2_2_RECVID_LIST_TIMEOUT_MS3000, }, |
1591 | { HDCP_2_2_REP_STREAM_READY17, HDCP_2_2_STREAM_READY_TIMEOUT_MS100, }, |
1592 | }; |
1593 | |
1594 | static |
1595 | int intel_hdmi_hdcp2_read_rx_status(struct intel_digital_port *dig_port, |
1596 | u8 *rx_status) |
1597 | { |
1598 | return intel_hdmi_hdcp_read(dig_port, |
1599 | HDCP_2_2_HDMI_REG_RXSTATUS_OFFSET0x70, |
1600 | rx_status, |
1601 | HDCP_2_2_HDMI_RXSTATUS_LEN2); |
1602 | } |
1603 | |
1604 | static int get_hdcp2_msg_timeout(u8 msg_id, bool_Bool is_paired) |
1605 | { |
1606 | int i; |
1607 | |
1608 | if (msg_id == HDCP_2_2_AKE_SEND_HPRIME7) { |
1609 | if (is_paired) |
1610 | return HDCP_2_2_HPRIME_PAIRED_TIMEOUT_MS200; |
1611 | else |
1612 | return HDCP_2_2_HPRIME_NO_PAIRED_TIMEOUT_MS1000; |
1613 | } |
1614 | |
1615 | for (i = 0; i < ARRAY_SIZE(hdcp2_msg_timeout)(sizeof((hdcp2_msg_timeout)) / sizeof((hdcp2_msg_timeout)[0]) ); i++) { |
1616 | if (hdcp2_msg_timeout[i].msg_id == msg_id) |
1617 | return hdcp2_msg_timeout[i].timeout; |
1618 | } |
1619 | |
1620 | return -EINVAL22; |
1621 | } |
1622 | |
1623 | static int |
1624 | hdcp2_detect_msg_availability(struct intel_digital_port *dig_port, |
1625 | u8 msg_id, bool_Bool *msg_ready, |
1626 | ssize_t *msg_sz) |
1627 | { |
1628 | struct drm_i915_privateinteldrm_softc *i915 = to_i915(dig_port->base.base.dev); |
1629 | u8 rx_status[HDCP_2_2_HDMI_RXSTATUS_LEN2]; |
1630 | int ret; |
1631 | |
1632 | ret = intel_hdmi_hdcp2_read_rx_status(dig_port, rx_status); |
1633 | if (ret < 0) { |
1634 | drm_dbg_kms(&i915->drm, "rx_status read failed. Err %d\n",__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "rx_status read failed. Err %d\n" , ret) |
1635 | ret)__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "rx_status read failed. Err %d\n" , ret); |
1636 | return ret; |
1637 | } |
1638 | |
1639 | *msg_sz = ((HDCP_2_2_HDMI_RXSTATUS_MSG_SZ_HI(rx_status[1])((rx_status[1]) & 0x3) << 8) | |
1640 | rx_status[0]); |
1641 | |
1642 | if (msg_id == HDCP_2_2_REP_SEND_RECVID_LIST12) |
1643 | *msg_ready = (HDCP_2_2_HDMI_RXSTATUS_READY(rx_status[1])((rx_status[1]) & (1UL << (2))) && |
1644 | *msg_sz); |
1645 | else |
1646 | *msg_ready = *msg_sz; |
1647 | |
1648 | return 0; |
1649 | } |
1650 | |
1651 | static ssize_t |
1652 | intel_hdmi_hdcp2_wait_for_msg(struct intel_digital_port *dig_port, |
1653 | u8 msg_id, bool_Bool paired) |
1654 | { |
1655 | struct drm_i915_privateinteldrm_softc *i915 = to_i915(dig_port->base.base.dev); |
1656 | bool_Bool msg_ready = false0; |
1657 | int timeout, ret; |
1658 | ssize_t msg_sz = 0; |
1659 | |
1660 | timeout = get_hdcp2_msg_timeout(msg_id, paired); |
1661 | if (timeout < 0) |
1662 | return timeout; |
1663 | |
1664 | ret = __wait_for(ret = hdcp2_detect_msg_availability(dig_port,({ const ktime_t end__ = ktime_add_ns(ktime_get_raw(), 1000ll * (timeout * 1000)); long wait__ = (1000); int ret__; assertwaitok (); for (;;) { const _Bool expired__ = ktime_after(ktime_get_raw (), end__); ret = hdcp2_detect_msg_availability(dig_port, msg_id , &msg_ready, &msg_sz); __asm volatile("" : : : "memory" ); if (!ret && msg_ready && msg_sz) { ret__ = 0; break; } if (expired__) { ret__ = -60; break; } usleep_range (wait__, wait__ * 2); if (wait__ < (5 * 1000)) wait__ <<= 1; } ret__; }) |
1665 | msg_id, &msg_ready,({ const ktime_t end__ = ktime_add_ns(ktime_get_raw(), 1000ll * (timeout * 1000)); long wait__ = (1000); int ret__; assertwaitok (); for (;;) { const _Bool expired__ = ktime_after(ktime_get_raw (), end__); ret = hdcp2_detect_msg_availability(dig_port, msg_id , &msg_ready, &msg_sz); __asm volatile("" : : : "memory" ); if (!ret && msg_ready && msg_sz) { ret__ = 0; break; } if (expired__) { ret__ = -60; break; } usleep_range (wait__, wait__ * 2); if (wait__ < (5 * 1000)) wait__ <<= 1; } ret__; }) |
1666 | &msg_sz),({ const ktime_t end__ = ktime_add_ns(ktime_get_raw(), 1000ll * (timeout * 1000)); long wait__ = (1000); int ret__; assertwaitok (); for (;;) { const _Bool expired__ = ktime_after(ktime_get_raw (), end__); ret = hdcp2_detect_msg_availability(dig_port, msg_id , &msg_ready, &msg_sz); __asm volatile("" : : : "memory" ); if (!ret && msg_ready && msg_sz) { ret__ = 0; break; } if (expired__) { ret__ = -60; break; } usleep_range (wait__, wait__ * 2); if (wait__ < (5 * 1000)) wait__ <<= 1; } ret__; }) |
1667 | !ret && msg_ready && msg_sz, timeout * 1000,({ const ktime_t end__ = ktime_add_ns(ktime_get_raw(), 1000ll * (timeout * 1000)); long wait__ = (1000); int ret__; assertwaitok (); for (;;) { const _Bool expired__ = ktime_after(ktime_get_raw (), end__); ret = hdcp2_detect_msg_availability(dig_port, msg_id , &msg_ready, &msg_sz); __asm volatile("" : : : "memory" ); if (!ret && msg_ready && msg_sz) { ret__ = 0; break; } if (expired__) { ret__ = -60; break; } usleep_range (wait__, wait__ * 2); if (wait__ < (5 * 1000)) wait__ <<= 1; } ret__; }) |
1668 | 1000, 5 * 1000)({ const ktime_t end__ = ktime_add_ns(ktime_get_raw(), 1000ll * (timeout * 1000)); long wait__ = (1000); int ret__; assertwaitok (); for (;;) { const _Bool expired__ = ktime_after(ktime_get_raw (), end__); ret = hdcp2_detect_msg_availability(dig_port, msg_id , &msg_ready, &msg_sz); __asm volatile("" : : : "memory" ); if (!ret && msg_ready && msg_sz) { ret__ = 0; break; } if (expired__) { ret__ = -60; break; } usleep_range (wait__, wait__ * 2); if (wait__ < (5 * 1000)) wait__ <<= 1; } ret__; }); |
1669 | if (ret) |
1670 | drm_dbg_kms(&i915->drm, "msg_id: %d, ret: %d, timeout: %d\n",__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "msg_id: %d, ret: %d, timeout: %d\n" , msg_id, ret, timeout) |
1671 | msg_id, ret, timeout)__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "msg_id: %d, ret: %d, timeout: %d\n" , msg_id, ret, timeout); |
1672 | |
1673 | return ret ? ret : msg_sz; |
1674 | } |
1675 | |
1676 | static |
1677 | int intel_hdmi_hdcp2_write_msg(struct intel_digital_port *dig_port, |
1678 | void *buf, size_t size) |
1679 | { |
1680 | unsigned int offset; |
1681 | |
1682 | offset = HDCP_2_2_HDMI_REG_WR_MSG_OFFSET0x60; |
1683 | return intel_hdmi_hdcp_write(dig_port, offset, buf, size); |
1684 | } |
1685 | |
1686 | static |
1687 | int intel_hdmi_hdcp2_read_msg(struct intel_digital_port *dig_port, |
1688 | u8 msg_id, void *buf, size_t size) |
1689 | { |
1690 | struct drm_i915_privateinteldrm_softc *i915 = to_i915(dig_port->base.base.dev); |
1691 | struct intel_hdmi *hdmi = &dig_port->hdmi; |
1692 | struct intel_hdcp *hdcp = &hdmi->attached_connector->hdcp; |
1693 | unsigned int offset; |
1694 | ssize_t ret; |
1695 | |
1696 | ret = intel_hdmi_hdcp2_wait_for_msg(dig_port, msg_id, |
1697 | hdcp->is_paired); |
1698 | if (ret < 0) |
1699 | return ret; |
1700 | |
1701 | /* |
1702 | * Available msg size should be equal to or lesser than the |
1703 | * available buffer. |
1704 | */ |
1705 | if (ret > size) { |
1706 | drm_dbg_kms(&i915->drm,__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "msg_sz(%zd) is more than exp size(%zu)\n" , ret, size) |
1707 | "msg_sz(%zd) is more than exp size(%zu)\n",__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "msg_sz(%zd) is more than exp size(%zu)\n" , ret, size) |
1708 | ret, size)__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "msg_sz(%zd) is more than exp size(%zu)\n" , ret, size); |
1709 | return -EINVAL22; |
1710 | } |
1711 | |
1712 | offset = HDCP_2_2_HDMI_REG_RD_MSG_OFFSET0x80; |
1713 | ret = intel_hdmi_hdcp_read(dig_port, offset, buf, ret); |
1714 | if (ret) |
1715 | drm_dbg_kms(&i915->drm, "Failed to read msg_id: %d(%zd)\n",__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "Failed to read msg_id: %d(%zd)\n" , msg_id, ret) |
1716 | msg_id, ret)__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "Failed to read msg_id: %d(%zd)\n" , msg_id, ret); |
1717 | |
1718 | return ret; |
1719 | } |
1720 | |
1721 | static |
1722 | int intel_hdmi_hdcp2_check_link(struct intel_digital_port *dig_port, |
1723 | struct intel_connector *connector) |
1724 | { |
1725 | u8 rx_status[HDCP_2_2_HDMI_RXSTATUS_LEN2]; |
1726 | int ret; |
1727 | |
1728 | ret = intel_hdmi_hdcp2_read_rx_status(dig_port, rx_status); |
1729 | if (ret) |
1730 | return ret; |
1731 | |
1732 | /* |
1733 | * Re-auth request and Link Integrity Failures are represented by |
1734 | * same bit. i.e reauth_req. |
1735 | */ |
1736 | if (HDCP_2_2_HDMI_RXSTATUS_REAUTH_REQ(rx_status[1])((rx_status[1]) & (1UL << (3)))) |
1737 | ret = HDCP_REAUTH_REQUEST; |
1738 | else if (HDCP_2_2_HDMI_RXSTATUS_READY(rx_status[1])((rx_status[1]) & (1UL << (2)))) |
1739 | ret = HDCP_TOPOLOGY_CHANGE; |
1740 | |
1741 | return ret; |
1742 | } |
1743 | |
1744 | static |
1745 | int intel_hdmi_hdcp2_capable(struct intel_digital_port *dig_port, |
1746 | bool_Bool *capable) |
1747 | { |
1748 | u8 hdcp2_version; |
1749 | int ret; |
1750 | |
1751 | *capable = false0; |
1752 | ret = intel_hdmi_hdcp_read(dig_port, HDCP_2_2_HDMI_REG_VER_OFFSET0x50, |
1753 | &hdcp2_version, sizeof(hdcp2_version)); |
1754 | if (!ret && hdcp2_version & HDCP_2_2_HDMI_SUPPORT_MASK(1UL << (2))) |
1755 | *capable = true1; |
1756 | |
1757 | return ret; |
1758 | } |
1759 | |
1760 | static const struct intel_hdcp_shim intel_hdmi_hdcp_shim = { |
1761 | .write_an_aksv = intel_hdmi_hdcp_write_an_aksv, |
1762 | .read_bksv = intel_hdmi_hdcp_read_bksv, |
1763 | .read_bstatus = intel_hdmi_hdcp_read_bstatus, |
1764 | .repeater_present = intel_hdmi_hdcp_repeater_present, |
1765 | .read_ri_prime = intel_hdmi_hdcp_read_ri_prime, |
1766 | .read_ksv_ready = intel_hdmi_hdcp_read_ksv_ready, |
1767 | .read_ksv_fifo = intel_hdmi_hdcp_read_ksv_fifo, |
1768 | .read_v_prime_part = intel_hdmi_hdcp_read_v_prime_part, |
1769 | .toggle_signalling = intel_hdmi_hdcp_toggle_signalling, |
1770 | .check_link = intel_hdmi_hdcp_check_link, |
1771 | .write_2_2_msg = intel_hdmi_hdcp2_write_msg, |
1772 | .read_2_2_msg = intel_hdmi_hdcp2_read_msg, |
1773 | .check_2_2_link = intel_hdmi_hdcp2_check_link, |
1774 | .hdcp_2_2_capable = intel_hdmi_hdcp2_capable, |
1775 | .protocol = HDCP_PROTOCOL_HDMI, |
1776 | }; |
1777 | |
1778 | static int intel_hdmi_source_max_tmds_clock(struct intel_encoder *encoder) |
1779 | { |
1780 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev); |
1781 | int max_tmds_clock, vbt_max_tmds_clock; |
1782 | |
1783 | if (DISPLAY_VER(dev_priv)((&(dev_priv)->__runtime)->display.ip.ver) >= 10) |
1784 | max_tmds_clock = 594000; |
1785 | else if (DISPLAY_VER(dev_priv)((&(dev_priv)->__runtime)->display.ip.ver) >= 8 || IS_HASWELL(dev_priv)IS_PLATFORM(dev_priv, INTEL_HASWELL)) |
1786 | max_tmds_clock = 300000; |
1787 | else if (DISPLAY_VER(dev_priv)((&(dev_priv)->__runtime)->display.ip.ver) >= 5) |
1788 | max_tmds_clock = 225000; |
1789 | else |
1790 | max_tmds_clock = 165000; |
1791 | |
1792 | vbt_max_tmds_clock = intel_bios_max_tmds_clock(encoder); |
1793 | if (vbt_max_tmds_clock) |
1794 | max_tmds_clock = min(max_tmds_clock, vbt_max_tmds_clock)(((max_tmds_clock)<(vbt_max_tmds_clock))?(max_tmds_clock): (vbt_max_tmds_clock)); |
1795 | |
1796 | return max_tmds_clock; |
1797 | } |
1798 | |
1799 | static bool_Bool intel_has_hdmi_sink(struct intel_hdmi *hdmi, |
1800 | const struct drm_connector_state *conn_state) |
1801 | { |
1802 | return hdmi->has_hdmi_sink && |
1803 | READ_ONCE(to_intel_digital_connector_state(conn_state)->force_audio)({ typeof(({ const __typeof( ((struct intel_digital_connector_state *)0)->base ) *__mptr = (conn_state); (struct intel_digital_connector_state *)( (char *)__mptr - __builtin_offsetof(struct intel_digital_connector_state , base) );})->force_audio) __tmp = *(volatile typeof(({ const __typeof( ((struct intel_digital_connector_state *)0)->base ) *__mptr = (conn_state); (struct intel_digital_connector_state *)( (char *)__mptr - __builtin_offsetof(struct intel_digital_connector_state , base) );})->force_audio) *)&(({ const __typeof( ((struct intel_digital_connector_state *)0)->base ) *__mptr = (conn_state ); (struct intel_digital_connector_state *)( (char *)__mptr - __builtin_offsetof(struct intel_digital_connector_state, base ) );})->force_audio); membar_datadep_consumer(); __tmp; }) != HDMI_AUDIO_OFF_DVI; |
1804 | } |
1805 | |
1806 | static bool_Bool intel_hdmi_is_ycbcr420(const struct intel_crtc_state *crtc_state) |
1807 | { |
1808 | return crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420; |
1809 | } |
1810 | |
1811 | static int hdmi_port_clock_limit(struct intel_hdmi *hdmi, |
1812 | bool_Bool respect_downstream_limits, |
1813 | bool_Bool has_hdmi_sink) |
1814 | { |
1815 | struct intel_encoder *encoder = &hdmi_to_dig_port(hdmi)->base; |
1816 | int max_tmds_clock = intel_hdmi_source_max_tmds_clock(encoder); |
1817 | |
1818 | if (respect_downstream_limits) { |
1819 | struct intel_connector *connector = hdmi->attached_connector; |
1820 | const struct drm_display_info *info = &connector->base.display_info; |
1821 | |
1822 | if (hdmi->dp_dual_mode.max_tmds_clock) |
1823 | max_tmds_clock = min(max_tmds_clock,(((max_tmds_clock)<(hdmi->dp_dual_mode.max_tmds_clock)) ?(max_tmds_clock):(hdmi->dp_dual_mode.max_tmds_clock)) |
1824 | hdmi->dp_dual_mode.max_tmds_clock)(((max_tmds_clock)<(hdmi->dp_dual_mode.max_tmds_clock)) ?(max_tmds_clock):(hdmi->dp_dual_mode.max_tmds_clock)); |
1825 | |
1826 | if (info->max_tmds_clock) |
1827 | max_tmds_clock = min(max_tmds_clock,(((max_tmds_clock)<(info->max_tmds_clock))?(max_tmds_clock ):(info->max_tmds_clock)) |
1828 | info->max_tmds_clock)(((max_tmds_clock)<(info->max_tmds_clock))?(max_tmds_clock ):(info->max_tmds_clock)); |
1829 | else if (!has_hdmi_sink) |
1830 | max_tmds_clock = min(max_tmds_clock, 165000)(((max_tmds_clock)<(165000))?(max_tmds_clock):(165000)); |
1831 | } |
1832 | |
1833 | return max_tmds_clock; |
1834 | } |
1835 | |
1836 | static enum drm_mode_status |
1837 | hdmi_port_clock_valid(struct intel_hdmi *hdmi, |
1838 | int clock, bool_Bool respect_downstream_limits, |
1839 | bool_Bool has_hdmi_sink) |
1840 | { |
1841 | struct drm_i915_privateinteldrm_softc *dev_priv = intel_hdmi_to_i915(hdmi); |
1842 | enum phy phy = intel_port_to_phy(dev_priv, hdmi_to_dig_port(hdmi)->base.port); |
1843 | |
1844 | if (clock < 25000) |
1845 | return MODE_CLOCK_LOW; |
1846 | if (clock > hdmi_port_clock_limit(hdmi, respect_downstream_limits, |
1847 | has_hdmi_sink)) |
1848 | return MODE_CLOCK_HIGH; |
1849 | |
1850 | /* GLK DPLL can't generate 446-480 MHz */ |
1851 | if (IS_GEMINILAKE(dev_priv)IS_PLATFORM(dev_priv, INTEL_GEMINILAKE) && clock > 446666 && clock < 480000) |
1852 | return MODE_CLOCK_RANGE; |
1853 | |
1854 | /* BXT/GLK DPLL can't generate 223-240 MHz */ |
1855 | if ((IS_GEMINILAKE(dev_priv)IS_PLATFORM(dev_priv, INTEL_GEMINILAKE) || IS_BROXTON(dev_priv)IS_PLATFORM(dev_priv, INTEL_BROXTON)) && |
1856 | clock > 223333 && clock < 240000) |
1857 | return MODE_CLOCK_RANGE; |
1858 | |
1859 | /* CHV DPLL can't generate 216-240 MHz */ |
1860 | if (IS_CHERRYVIEW(dev_priv)IS_PLATFORM(dev_priv, INTEL_CHERRYVIEW) && clock > 216000 && clock < 240000) |
1861 | return MODE_CLOCK_RANGE; |
1862 | |
1863 | /* ICL+ combo PHY PLL can't generate 500-533.2 MHz */ |
1864 | if (intel_phy_is_combo(dev_priv, phy) && clock > 500000 && clock < 533200) |
1865 | return MODE_CLOCK_RANGE; |
1866 | |
1867 | /* ICL+ TC PHY PLL can't generate 500-532.8 MHz */ |
1868 | if (intel_phy_is_tc(dev_priv, phy) && clock > 500000 && clock < 532800) |
1869 | return MODE_CLOCK_RANGE; |
1870 | |
1871 | /* |
1872 | * SNPS PHYs' MPLLB table-based programming can only handle a fixed |
1873 | * set of link rates. |
1874 | * |
1875 | * FIXME: We will hopefully get an algorithmic way of programming |
1876 | * the MPLLB for HDMI in the future. |
1877 | */ |
1878 | if (IS_DG2(dev_priv)IS_PLATFORM(dev_priv, INTEL_DG2)) |
1879 | return intel_snps_phy_check_hdmi_link_rate(clock); |
1880 | |
1881 | return MODE_OK; |
1882 | } |
1883 | |
1884 | int intel_hdmi_tmds_clock(int clock, int bpc, bool_Bool ycbcr420_output) |
1885 | { |
1886 | /* YCBCR420 TMDS rate requirement is half the pixel clock */ |
1887 | if (ycbcr420_output) |
1888 | clock /= 2; |
1889 | |
1890 | /* |
1891 | * Need to adjust the port link by: |
1892 | * 1.5x for 12bpc |
1893 | * 1.25x for 10bpc |
1894 | */ |
1895 | return DIV_ROUND_CLOSEST(clock * bpc, 8)(((clock * bpc) + ((8) / 2)) / (8)); |
1896 | } |
1897 | |
1898 | static bool_Bool intel_hdmi_source_bpc_possible(struct drm_i915_privateinteldrm_softc *i915, int bpc) |
1899 | { |
1900 | switch (bpc) { |
1901 | case 12: |
1902 | return !HAS_GMCH(i915)((&(i915)->__info)->display.has_gmch); |
1903 | case 10: |
1904 | return DISPLAY_VER(i915)((&(i915)->__runtime)->display.ip.ver) >= 11; |
1905 | case 8: |
1906 | return true1; |
1907 | default: |
1908 | MISSING_CASE(bpc)({ int __ret = !!(1); if (__ret) printf("Missing case (%s == %ld)\n" , "bpc", (long)(bpc)); __builtin_expect(!!(__ret), 0); }); |
1909 | return false0; |
1910 | } |
1911 | } |
1912 | |
1913 | static bool_Bool intel_hdmi_sink_bpc_possible(struct drm_connector *connector, |
1914 | int bpc, bool_Bool has_hdmi_sink, bool_Bool ycbcr420_output) |
1915 | { |
1916 | const struct drm_display_info *info = &connector->display_info; |
1917 | const struct drm_hdmi_info *hdmi = &info->hdmi; |
1918 | |
1919 | switch (bpc) { |
1920 | case 12: |
1921 | if (!has_hdmi_sink) |
1922 | return false0; |
1923 | |
1924 | if (ycbcr420_output) |
1925 | return hdmi->y420_dc_modes & DRM_EDID_YCBCR420_DC_36(1 << 1); |
1926 | else |
1927 | return info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_36(1 << 5); |
1928 | case 10: |
1929 | if (!has_hdmi_sink) |
1930 | return false0; |
1931 | |
1932 | if (ycbcr420_output) |
1933 | return hdmi->y420_dc_modes & DRM_EDID_YCBCR420_DC_30(1 << 0); |
1934 | else |
1935 | return info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30(1 << 4); |
1936 | case 8: |
1937 | return true1; |
1938 | default: |
1939 | MISSING_CASE(bpc)({ int __ret = !!(1); if (__ret) printf("Missing case (%s == %ld)\n" , "bpc", (long)(bpc)); __builtin_expect(!!(__ret), 0); }); |
1940 | return false0; |
1941 | } |
1942 | } |
1943 | |
1944 | static enum drm_mode_status |
1945 | intel_hdmi_mode_clock_valid(struct drm_connector *connector, int clock, |
1946 | bool_Bool has_hdmi_sink, bool_Bool ycbcr420_output) |
1947 | { |
1948 | struct drm_i915_privateinteldrm_softc *i915 = to_i915(connector->dev); |
1949 | struct intel_hdmi *hdmi = intel_attached_hdmi(to_intel_connector(connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (connector); (struct intel_connector *)( (char *)__mptr - __builtin_offsetof(struct intel_connector, base) );})); |
1950 | enum drm_mode_status status = MODE_OK; |
1951 | int bpc; |
1952 | |
1953 | /* |
1954 | * Try all color depths since valid port clock range |
1955 | * can have holes. Any mode that can be used with at |
1956 | * least one color depth is accepted. |
1957 | */ |
1958 | for (bpc = 12; bpc >= 8; bpc -= 2) { |
1959 | int tmds_clock = intel_hdmi_tmds_clock(clock, bpc, ycbcr420_output); |
1960 | |
1961 | if (!intel_hdmi_source_bpc_possible(i915, bpc)) |
1962 | continue; |
1963 | |
1964 | if (!intel_hdmi_sink_bpc_possible(connector, bpc, has_hdmi_sink, ycbcr420_output)) |
1965 | continue; |
1966 | |
1967 | status = hdmi_port_clock_valid(hdmi, tmds_clock, true1, has_hdmi_sink); |
1968 | if (status == MODE_OK) |
1969 | return MODE_OK; |
1970 | } |
1971 | |
1972 | /* can never happen */ |
1973 | drm_WARN_ON(&i915->drm, status == MODE_OK)({ int __ret = !!((status == MODE_OK)); if (__ret) printf("%s %s: " "%s", dev_driver_string(((&i915->drm))->dev), "", "drm_WARN_ON(" "status == MODE_OK" ")"); __builtin_expect(!!(__ret), 0); }); |
1974 | |
1975 | return status; |
1976 | } |
1977 | |
1978 | static enum drm_mode_status |
1979 | intel_hdmi_mode_valid(struct drm_connector *connector, |
1980 | struct drm_display_mode *mode) |
1981 | { |
1982 | struct intel_hdmi *hdmi = intel_attached_hdmi(to_intel_connector(connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (connector); (struct intel_connector *)( (char *)__mptr - __builtin_offsetof(struct intel_connector, base) );})); |
1983 | struct drm_i915_privateinteldrm_softc *dev_priv = intel_hdmi_to_i915(hdmi); |
1984 | enum drm_mode_status status; |
1985 | int clock = mode->clock; |
1986 | int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; |
1987 | bool_Bool has_hdmi_sink = intel_has_hdmi_sink(hdmi, connector->state); |
1988 | bool_Bool ycbcr_420_only; |
1989 | |
1990 | status = intel_cpu_transcoder_mode_valid(dev_priv, mode); |
1991 | if (status != MODE_OK) |
1992 | return status; |
1993 | |
1994 | if ((mode->flags & DRM_MODE_FLAG_3D_MASK(0x1f<<14)) == DRM_MODE_FLAG_3D_FRAME_PACKING(1<<14)) |
1995 | clock *= 2; |
1996 | |
1997 | if (clock > max_dotclk) |
1998 | return MODE_CLOCK_HIGH; |
1999 | |
2000 | if (mode->flags & DRM_MODE_FLAG_DBLCLK(1<<12)) { |
2001 | if (!has_hdmi_sink) |
2002 | return MODE_CLOCK_LOW; |
2003 | clock *= 2; |
2004 | } |
2005 | |
2006 | /* |
2007 | * HDMI2.1 requires higher resolution modes like 8k60, 4K120 to be |
2008 | * enumerated only if FRL is supported. Current platforms do not support |
2009 | * FRL so prune the higher resolution modes that require doctclock more |
2010 | * than 600MHz. |
2011 | */ |
2012 | if (clock > 600000) |
2013 | return MODE_CLOCK_HIGH; |
2014 | |
2015 | ycbcr_420_only = drm_mode_is_420_only(&connector->display_info, mode); |
2016 | |
2017 | status = intel_hdmi_mode_clock_valid(connector, clock, has_hdmi_sink, ycbcr_420_only); |
2018 | if (status != MODE_OK) { |
2019 | if (ycbcr_420_only || |
2020 | !connector->ycbcr_420_allowed || |
2021 | !drm_mode_is_420_also(&connector->display_info, mode)) |
2022 | return status; |
2023 | |
2024 | status = intel_hdmi_mode_clock_valid(connector, clock, has_hdmi_sink, true1); |
2025 | if (status != MODE_OK) |
2026 | return status; |
2027 | } |
2028 | |
2029 | return intel_mode_valid_max_plane_size(dev_priv, mode, false0); |
2030 | } |
2031 | |
2032 | bool_Bool intel_hdmi_bpc_possible(const struct intel_crtc_state *crtc_state, |
2033 | int bpc, bool_Bool has_hdmi_sink, bool_Bool ycbcr420_output) |
2034 | { |
2035 | struct drm_atomic_state *state = crtc_state->uapi.state; |
2036 | struct drm_connector_state *connector_state; |
2037 | struct drm_connector *connector; |
2038 | int i; |
2039 | |
2040 | for_each_new_connector_in_state(state, connector, connector_state, i)for ((i) = 0; (i) < (state)->num_connector; (i)++) if ( !((state)->connectors[i].ptr && ((connector) = (state )->connectors[i].ptr, (void)(connector) , (connector_state ) = (state)->connectors[i].new_state, (void)(connector_state ) , 1))) {} else { |
2041 | if (connector_state->crtc != crtc_state->uapi.crtc) |
2042 | continue; |
2043 | |
2044 | if (!intel_hdmi_sink_bpc_possible(connector, bpc, has_hdmi_sink, ycbcr420_output)) |
2045 | return false0; |
2046 | } |
2047 | |
2048 | return true1; |
2049 | } |
2050 | |
2051 | static bool_Bool hdmi_bpc_possible(const struct intel_crtc_state *crtc_state, int bpc) |
2052 | { |
2053 | struct drm_i915_privateinteldrm_softc *dev_priv = |
2054 | to_i915(crtc_state->uapi.crtc->dev); |
2055 | const struct drm_display_mode *adjusted_mode = |
2056 | &crtc_state->hw.adjusted_mode; |
2057 | |
2058 | if (!intel_hdmi_source_bpc_possible(dev_priv, bpc)) |
2059 | return false0; |
2060 | |
2061 | /* |
2062 | * HDMI deep color affects the clocks, so it's only possible |
2063 | * when not cloning with other encoder types. |
2064 | */ |
2065 | if (bpc > 8 && crtc_state->output_types != BIT(INTEL_OUTPUT_HDMI)(1UL << (INTEL_OUTPUT_HDMI))) |
2066 | return false0; |
2067 | |
2068 | /* Display Wa_1405510057:icl,ehl */ |
2069 | if (intel_hdmi_is_ycbcr420(crtc_state) && |
2070 | bpc == 10 && DISPLAY_VER(dev_priv)((&(dev_priv)->__runtime)->display.ip.ver) == 11 && |
2071 | (adjusted_mode->crtc_hblank_end - |
2072 | adjusted_mode->crtc_hblank_start) % 8 == 2) |
2073 | return false0; |
2074 | |
2075 | return intel_hdmi_bpc_possible(crtc_state, bpc, crtc_state->has_hdmi_sink, |
2076 | intel_hdmi_is_ycbcr420(crtc_state)); |
2077 | } |
2078 | |
2079 | static int intel_hdmi_compute_bpc(struct intel_encoder *encoder, |
2080 | struct intel_crtc_state *crtc_state, |
2081 | int clock, bool_Bool respect_downstream_limits) |
2082 | { |
2083 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
2084 | bool_Bool ycbcr420_output = intel_hdmi_is_ycbcr420(crtc_state); |
2085 | int bpc; |
2086 | |
2087 | /* |
2088 | * pipe_bpp could already be below 8bpc due to FDI |
2089 | * bandwidth constraints. HDMI minimum is 8bpc however. |
2090 | */ |
2091 | bpc = max(crtc_state->pipe_bpp / 3, 8)(((crtc_state->pipe_bpp / 3)>(8))?(crtc_state->pipe_bpp / 3):(8)); |
2092 | |
2093 | /* |
2094 | * We will never exceed downstream TMDS clock limits while |
2095 | * attempting deep color. If the user insists on forcing an |
2096 | * out of spec mode they will have to be satisfied with 8bpc. |
2097 | */ |
2098 | if (!respect_downstream_limits) |
2099 | bpc = 8; |
2100 | |
2101 | for (; bpc >= 8; bpc -= 2) { |
2102 | int tmds_clock = intel_hdmi_tmds_clock(clock, bpc, ycbcr420_output); |
2103 | |
2104 | if (hdmi_bpc_possible(crtc_state, bpc) && |
2105 | hdmi_port_clock_valid(intel_hdmi, tmds_clock, |
2106 | respect_downstream_limits, |
2107 | crtc_state->has_hdmi_sink) == MODE_OK) |
2108 | return bpc; |
2109 | } |
2110 | |
2111 | return -EINVAL22; |
2112 | } |
2113 | |
2114 | static int intel_hdmi_compute_clock(struct intel_encoder *encoder, |
2115 | struct intel_crtc_state *crtc_state, |
2116 | bool_Bool respect_downstream_limits) |
2117 | { |
2118 | struct drm_i915_privateinteldrm_softc *i915 = to_i915(encoder->base.dev); |
2119 | const struct drm_display_mode *adjusted_mode = |
2120 | &crtc_state->hw.adjusted_mode; |
2121 | int bpc, clock = adjusted_mode->crtc_clock; |
2122 | |
2123 | if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK(1<<12)) |
2124 | clock *= 2; |
2125 | |
2126 | bpc = intel_hdmi_compute_bpc(encoder, crtc_state, clock, |
2127 | respect_downstream_limits); |
2128 | if (bpc < 0) |
2129 | return bpc; |
2130 | |
2131 | crtc_state->port_clock = |
2132 | intel_hdmi_tmds_clock(clock, bpc, intel_hdmi_is_ycbcr420(crtc_state)); |
2133 | |
2134 | /* |
2135 | * pipe_bpp could already be below 8bpc due to |
2136 | * FDI bandwidth constraints. We shouldn't bump it |
2137 | * back up to the HDMI minimum 8bpc in that case. |
2138 | */ |
2139 | crtc_state->pipe_bpp = min(crtc_state->pipe_bpp, bpc * 3)(((crtc_state->pipe_bpp)<(bpc * 3))?(crtc_state->pipe_bpp ):(bpc * 3)); |
2140 | |
2141 | drm_dbg_kms(&i915->drm,__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "picking %d bpc for HDMI output (pipe bpp: %d)\n" , bpc, crtc_state->pipe_bpp) |
2142 | "picking %d bpc for HDMI output (pipe bpp: %d)\n",__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "picking %d bpc for HDMI output (pipe bpp: %d)\n" , bpc, crtc_state->pipe_bpp) |
2143 | bpc, crtc_state->pipe_bpp)__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "picking %d bpc for HDMI output (pipe bpp: %d)\n" , bpc, crtc_state->pipe_bpp); |
2144 | |
2145 | return 0; |
2146 | } |
2147 | |
2148 | bool_Bool intel_hdmi_limited_color_range(const struct intel_crtc_state *crtc_state, |
2149 | const struct drm_connector_state *conn_state) |
2150 | { |
2151 | const struct intel_digital_connector_state *intel_conn_state = |
2152 | to_intel_digital_connector_state(conn_state)({ const __typeof( ((struct intel_digital_connector_state *)0 )->base ) *__mptr = (conn_state); (struct intel_digital_connector_state *)( (char *)__mptr - __builtin_offsetof(struct intel_digital_connector_state , base) );}); |
2153 | const struct drm_display_mode *adjusted_mode = |
2154 | &crtc_state->hw.adjusted_mode; |
2155 | |
2156 | /* |
2157 | * Our YCbCr output is always limited range. |
2158 | * crtc_state->limited_color_range only applies to RGB, |
2159 | * and it must never be set for YCbCr or we risk setting |
2160 | * some conflicting bits in PIPECONF which will mess up |
2161 | * the colors on the monitor. |
2162 | */ |
2163 | if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB) |
2164 | return false0; |
2165 | |
2166 | if (intel_conn_state->broadcast_rgb == INTEL_BROADCAST_RGB_AUTO) { |
2167 | /* See CEA-861-E - 5.1 Default Encoding Parameters */ |
2168 | return crtc_state->has_hdmi_sink && |
2169 | drm_default_rgb_quant_range(adjusted_mode) == |
2170 | HDMI_QUANTIZATION_RANGE_LIMITED; |
2171 | } else { |
2172 | return intel_conn_state->broadcast_rgb == INTEL_BROADCAST_RGB_LIMITED; |
2173 | } |
2174 | } |
2175 | |
2176 | static bool_Bool intel_hdmi_has_audio(struct intel_encoder *encoder, |
2177 | const struct intel_crtc_state *crtc_state, |
2178 | const struct drm_connector_state *conn_state) |
2179 | { |
2180 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
2181 | const struct intel_digital_connector_state *intel_conn_state = |
2182 | to_intel_digital_connector_state(conn_state)({ const __typeof( ((struct intel_digital_connector_state *)0 )->base ) *__mptr = (conn_state); (struct intel_digital_connector_state *)( (char *)__mptr - __builtin_offsetof(struct intel_digital_connector_state , base) );}); |
2183 | |
2184 | if (!crtc_state->has_hdmi_sink) |
2185 | return false0; |
2186 | |
2187 | if (intel_conn_state->force_audio == HDMI_AUDIO_AUTO) |
2188 | return intel_hdmi->has_audio; |
2189 | else |
2190 | return intel_conn_state->force_audio == HDMI_AUDIO_ON; |
2191 | } |
2192 | |
2193 | static enum intel_output_format |
2194 | intel_hdmi_output_format(struct intel_connector *connector, |
2195 | bool_Bool ycbcr_420_output) |
2196 | { |
2197 | if (connector->base.ycbcr_420_allowed && ycbcr_420_output) |
2198 | return INTEL_OUTPUT_FORMAT_YCBCR420; |
2199 | else |
2200 | return INTEL_OUTPUT_FORMAT_RGB; |
2201 | } |
2202 | |
2203 | static int intel_hdmi_compute_output_format(struct intel_encoder *encoder, |
2204 | struct intel_crtc_state *crtc_state, |
2205 | const struct drm_connector_state *conn_state, |
2206 | bool_Bool respect_downstream_limits) |
2207 | { |
2208 | struct intel_connector *connector = to_intel_connector(conn_state->connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (conn_state->connector); (struct intel_connector * )( (char *)__mptr - __builtin_offsetof(struct intel_connector , base) );}); |
2209 | const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; |
2210 | const struct drm_display_info *info = &connector->base.display_info; |
2211 | struct drm_i915_privateinteldrm_softc *i915 = to_i915(connector->base.dev); |
2212 | bool_Bool ycbcr_420_only = drm_mode_is_420_only(info, adjusted_mode); |
2213 | int ret; |
2214 | |
2215 | crtc_state->output_format = intel_hdmi_output_format(connector, ycbcr_420_only); |
2216 | |
2217 | if (ycbcr_420_only && !intel_hdmi_is_ycbcr420(crtc_state)) { |
2218 | drm_dbg_kms(&i915->drm,__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "YCbCr 4:2:0 mode but YCbCr 4:2:0 output not possible. Falling back to RGB.\n" ) |
2219 | "YCbCr 4:2:0 mode but YCbCr 4:2:0 output not possible. Falling back to RGB.\n")__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "YCbCr 4:2:0 mode but YCbCr 4:2:0 output not possible. Falling back to RGB.\n" ); |
2220 | crtc_state->output_format = INTEL_OUTPUT_FORMAT_RGB; |
2221 | } |
2222 | |
2223 | ret = intel_hdmi_compute_clock(encoder, crtc_state, respect_downstream_limits); |
2224 | if (ret) { |
2225 | if (intel_hdmi_is_ycbcr420(crtc_state) || |
2226 | !connector->base.ycbcr_420_allowed || |
2227 | !drm_mode_is_420_also(info, adjusted_mode)) |
2228 | return ret; |
2229 | |
2230 | crtc_state->output_format = intel_hdmi_output_format(connector, true1); |
2231 | ret = intel_hdmi_compute_clock(encoder, crtc_state, respect_downstream_limits); |
2232 | } |
2233 | |
2234 | return ret; |
2235 | } |
2236 | |
2237 | int intel_hdmi_compute_config(struct intel_encoder *encoder, |
2238 | struct intel_crtc_state *pipe_config, |
2239 | struct drm_connector_state *conn_state) |
2240 | { |
2241 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
2242 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev); |
2243 | struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; |
2244 | struct drm_connector *connector = conn_state->connector; |
2245 | struct drm_scdc *scdc = &connector->display_info.hdmi.scdc; |
2246 | int ret; |
2247 | |
2248 | if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN(1<<5)) |
2249 | return -EINVAL22; |
2250 | |
2251 | pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB; |
2252 | pipe_config->has_hdmi_sink = intel_has_hdmi_sink(intel_hdmi, |
2253 | conn_state); |
2254 | |
2255 | if (pipe_config->has_hdmi_sink) |
2256 | pipe_config->has_infoframe = true1; |
2257 | |
2258 | if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK(1<<12)) |
2259 | pipe_config->pixel_multiplier = 2; |
2260 | |
2261 | if (HAS_PCH_SPLIT(dev_priv)(((dev_priv)->pch_type) != PCH_NONE) && !HAS_DDI(dev_priv)((&(dev_priv)->__info)->display.has_ddi)) |
2262 | pipe_config->has_pch_encoder = true1; |
2263 | |
2264 | pipe_config->has_audio = |
2265 | intel_hdmi_has_audio(encoder, pipe_config, conn_state); |
2266 | |
2267 | /* |
2268 | * Try to respect downstream TMDS clock limits first, if |
2269 | * that fails assume the user might know something we don't. |
2270 | */ |
2271 | ret = intel_hdmi_compute_output_format(encoder, pipe_config, conn_state, true1); |
2272 | if (ret) |
2273 | ret = intel_hdmi_compute_output_format(encoder, pipe_config, conn_state, false0); |
2274 | if (ret) { |
2275 | drm_dbg_kms(&dev_priv->drm,__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "unsupported HDMI clock (%d kHz), rejecting mode\n" , pipe_config->hw.adjusted_mode.crtc_clock) |
2276 | "unsupported HDMI clock (%d kHz), rejecting mode\n",__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "unsupported HDMI clock (%d kHz), rejecting mode\n" , pipe_config->hw.adjusted_mode.crtc_clock) |
2277 | pipe_config->hw.adjusted_mode.crtc_clock)__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "unsupported HDMI clock (%d kHz), rejecting mode\n" , pipe_config->hw.adjusted_mode.crtc_clock); |
2278 | return ret; |
2279 | } |
2280 | |
2281 | if (intel_hdmi_is_ycbcr420(pipe_config)) { |
2282 | ret = intel_panel_fitting(pipe_config, conn_state); |
2283 | if (ret) |
2284 | return ret; |
2285 | } |
2286 | |
2287 | pipe_config->limited_color_range = |
2288 | intel_hdmi_limited_color_range(pipe_config, conn_state); |
2289 | |
2290 | if (conn_state->picture_aspect_ratio) |
2291 | adjusted_mode->picture_aspect_ratio = |
2292 | conn_state->picture_aspect_ratio; |
2293 | |
2294 | pipe_config->lane_count = 4; |
2295 | |
2296 | if (scdc->scrambling.supported && DISPLAY_VER(dev_priv)((&(dev_priv)->__runtime)->display.ip.ver) >= 10) { |
2297 | if (scdc->scrambling.low_rates) |
2298 | pipe_config->hdmi_scrambling = true1; |
2299 | |
2300 | if (pipe_config->port_clock > 340000) { |
2301 | pipe_config->hdmi_scrambling = true1; |
2302 | pipe_config->hdmi_high_tmds_clock_ratio = true1; |
2303 | } |
2304 | } |
2305 | |
2306 | intel_hdmi_compute_gcp_infoframe(encoder, pipe_config, |
2307 | conn_state); |
2308 | |
2309 | if (!intel_hdmi_compute_avi_infoframe(encoder, pipe_config, conn_state)) { |
2310 | drm_dbg_kms(&dev_priv->drm, "bad AVI infoframe\n")__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "bad AVI infoframe\n" ); |
2311 | return -EINVAL22; |
2312 | } |
2313 | |
2314 | if (!intel_hdmi_compute_spd_infoframe(encoder, pipe_config, conn_state)) { |
2315 | drm_dbg_kms(&dev_priv->drm, "bad SPD infoframe\n")__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "bad SPD infoframe\n" ); |
2316 | return -EINVAL22; |
2317 | } |
2318 | |
2319 | if (!intel_hdmi_compute_hdmi_infoframe(encoder, pipe_config, conn_state)) { |
2320 | drm_dbg_kms(&dev_priv->drm, "bad HDMI infoframe\n")__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "bad HDMI infoframe\n" ); |
2321 | return -EINVAL22; |
2322 | } |
2323 | |
2324 | if (!intel_hdmi_compute_drm_infoframe(encoder, pipe_config, conn_state)) { |
2325 | drm_dbg_kms(&dev_priv->drm, "bad DRM infoframe\n")__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "bad DRM infoframe\n" ); |
2326 | return -EINVAL22; |
2327 | } |
2328 | |
2329 | return 0; |
2330 | } |
2331 | |
2332 | void intel_hdmi_encoder_shutdown(struct intel_encoder *encoder) |
2333 | { |
2334 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
2335 | |
2336 | /* |
2337 | * Give a hand to buggy BIOSen which forget to turn |
2338 | * the TMDS output buffers back on after a reboot. |
2339 | */ |
2340 | intel_dp_dual_mode_set_tmds_output(intel_hdmi, true1); |
2341 | } |
2342 | |
2343 | static void |
2344 | intel_hdmi_unset_edid(struct drm_connector *connector) |
2345 | { |
2346 | struct intel_hdmi *intel_hdmi = intel_attached_hdmi(to_intel_connector(connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (connector); (struct intel_connector *)( (char *)__mptr - __builtin_offsetof(struct intel_connector, base) );})); |
2347 | |
2348 | intel_hdmi->has_hdmi_sink = false0; |
2349 | intel_hdmi->has_audio = false0; |
2350 | |
2351 | intel_hdmi->dp_dual_mode.type = DRM_DP_DUAL_MODE_NONE; |
2352 | intel_hdmi->dp_dual_mode.max_tmds_clock = 0; |
2353 | |
2354 | kfree(to_intel_connector(connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (connector); (struct intel_connector *)( (char *)__mptr - __builtin_offsetof(struct intel_connector, base) );})->detect_edid); |
2355 | to_intel_connector(connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (connector); (struct intel_connector *)( (char *)__mptr - __builtin_offsetof(struct intel_connector, base) );})->detect_edid = NULL((void *)0); |
2356 | } |
2357 | |
2358 | static void |
2359 | intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector, bool_Bool has_edid) |
2360 | { |
2361 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->dev); |
2362 | struct intel_hdmi *hdmi = intel_attached_hdmi(to_intel_connector(connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (connector); (struct intel_connector *)( (char *)__mptr - __builtin_offsetof(struct intel_connector, base) );})); |
2363 | enum port port = hdmi_to_dig_port(hdmi)->base.port; |
2364 | struct i2c_adapter *adapter = |
2365 | intel_gmbus_get_adapter(dev_priv, hdmi->ddc_bus); |
2366 | enum drm_dp_dual_mode_type type = drm_dp_dual_mode_detect(&dev_priv->drm, adapter); |
2367 | |
2368 | /* |
2369 | * Type 1 DVI adaptors are not required to implement any |
2370 | * registers, so we can't always detect their presence. |
2371 | * Ideally we should be able to check the state of the |
2372 | * CONFIG1 pin, but no such luck on our hardware. |
2373 | * |
2374 | * The only method left to us is to check the VBT to see |
2375 | * if the port is a dual mode capable DP port. But let's |
2376 | * only do that when we sucesfully read the EDID, to avoid |
2377 | * confusing log messages about DP dual mode adaptors when |
2378 | * there's nothing connected to the port. |
2379 | */ |
2380 | if (type == DRM_DP_DUAL_MODE_UNKNOWN) { |
2381 | /* An overridden EDID imply that we want this port for testing. |
2382 | * Make sure not to set limits for that port. |
2383 | */ |
2384 | if (has_edid && !connector->override_edid && |
2385 | intel_bios_is_port_dp_dual_mode(dev_priv, port)) { |
2386 | drm_dbg_kms(&dev_priv->drm,__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "Assuming DP dual mode adaptor presence based on VBT\n" ) |
2387 | "Assuming DP dual mode adaptor presence based on VBT\n")__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "Assuming DP dual mode adaptor presence based on VBT\n" ); |
2388 | type = DRM_DP_DUAL_MODE_TYPE1_DVI; |
2389 | } else { |
2390 | type = DRM_DP_DUAL_MODE_NONE; |
2391 | } |
2392 | } |
2393 | |
2394 | if (type == DRM_DP_DUAL_MODE_NONE) |
2395 | return; |
2396 | |
2397 | hdmi->dp_dual_mode.type = type; |
2398 | hdmi->dp_dual_mode.max_tmds_clock = |
2399 | drm_dp_dual_mode_max_tmds_clock(&dev_priv->drm, type, adapter); |
2400 | |
2401 | drm_dbg_kms(&dev_priv->drm,__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "DP dual mode adaptor (%s) detected (max TMDS clock: %d kHz)\n" , drm_dp_get_dual_mode_type_name(type), hdmi->dp_dual_mode .max_tmds_clock) |
2402 | "DP dual mode adaptor (%s) detected (max TMDS clock: %d kHz)\n",__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "DP dual mode adaptor (%s) detected (max TMDS clock: %d kHz)\n" , drm_dp_get_dual_mode_type_name(type), hdmi->dp_dual_mode .max_tmds_clock) |
2403 | drm_dp_get_dual_mode_type_name(type),__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "DP dual mode adaptor (%s) detected (max TMDS clock: %d kHz)\n" , drm_dp_get_dual_mode_type_name(type), hdmi->dp_dual_mode .max_tmds_clock) |
2404 | hdmi->dp_dual_mode.max_tmds_clock)__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "DP dual mode adaptor (%s) detected (max TMDS clock: %d kHz)\n" , drm_dp_get_dual_mode_type_name(type), hdmi->dp_dual_mode .max_tmds_clock); |
2405 | |
2406 | /* Older VBTs are often buggy and can't be trusted :( Play it safe. */ |
2407 | if ((DISPLAY_VER(dev_priv)((&(dev_priv)->__runtime)->display.ip.ver) >= 8 || IS_HASWELL(dev_priv)IS_PLATFORM(dev_priv, INTEL_HASWELL)) && |
2408 | !intel_bios_is_port_dp_dual_mode(dev_priv, port)) { |
2409 | drm_dbg_kms(&dev_priv->drm,__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "Ignoring DP dual mode adaptor max TMDS clock for native HDMI port\n" ) |
2410 | "Ignoring DP dual mode adaptor max TMDS clock for native HDMI port\n")__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "Ignoring DP dual mode adaptor max TMDS clock for native HDMI port\n" ); |
2411 | hdmi->dp_dual_mode.max_tmds_clock = 0; |
2412 | } |
2413 | } |
2414 | |
2415 | static bool_Bool |
2416 | intel_hdmi_set_edid(struct drm_connector *connector) |
2417 | { |
2418 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->dev); |
2419 | struct intel_hdmi *intel_hdmi = intel_attached_hdmi(to_intel_connector(connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (connector); (struct intel_connector *)( (char *)__mptr - __builtin_offsetof(struct intel_connector, base) );})); |
2420 | intel_wakeref_t wakeref; |
2421 | struct edid *edid; |
2422 | bool_Bool connected = false0; |
2423 | struct i2c_adapter *i2c; |
2424 | |
2425 | wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS); |
2426 | |
2427 | i2c = intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus); |
2428 | |
2429 | edid = drm_get_edid(connector, i2c); |
2430 | |
2431 | if (!edid && !intel_gmbus_is_forced_bit(i2c)) { |
2432 | drm_dbg_kms(&dev_priv->drm,__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "HDMI GMBUS EDID read failed, retry using GPIO bit-banging\n" ) |
2433 | "HDMI GMBUS EDID read failed, retry using GPIO bit-banging\n")__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "HDMI GMBUS EDID read failed, retry using GPIO bit-banging\n" ); |
2434 | intel_gmbus_force_bit(i2c, true1); |
2435 | edid = drm_get_edid(connector, i2c); |
2436 | intel_gmbus_force_bit(i2c, false0); |
2437 | } |
2438 | |
2439 | intel_hdmi_dp_dual_mode_detect(connector, edid != NULL((void *)0)); |
2440 | |
2441 | intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS, wakeref); |
2442 | |
2443 | to_intel_connector(connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (connector); (struct intel_connector *)( (char *)__mptr - __builtin_offsetof(struct intel_connector, base) );})->detect_edid = edid; |
2444 | if (edid && edid->input & DRM_EDID_INPUT_DIGITAL(1 << 7)) { |
2445 | intel_hdmi->has_audio = drm_detect_monitor_audio(edid); |
2446 | intel_hdmi->has_hdmi_sink = drm_detect_hdmi_monitor(edid); |
2447 | |
2448 | connected = true1; |
2449 | } |
2450 | |
2451 | cec_notifier_set_phys_addr_from_edid(intel_hdmi->cec_notifier, edid); |
2452 | |
2453 | return connected; |
2454 | } |
2455 | |
2456 | static enum drm_connector_status |
2457 | intel_hdmi_detect(struct drm_connector *connector, bool_Bool force) |
2458 | { |
2459 | enum drm_connector_status status = connector_status_disconnected; |
2460 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->dev); |
2461 | struct intel_hdmi *intel_hdmi = intel_attached_hdmi(to_intel_connector(connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (connector); (struct intel_connector *)( (char *)__mptr - __builtin_offsetof(struct intel_connector, base) );})); |
2462 | struct intel_encoder *encoder = &hdmi_to_dig_port(intel_hdmi)->base; |
2463 | intel_wakeref_t wakeref; |
2464 | |
2465 | drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s]\n",__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "[CONNECTOR:%d:%s]\n" , connector->base.id, connector->name) |
2466 | connector->base.id, connector->name)__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "[CONNECTOR:%d:%s]\n" , connector->base.id, connector->name); |
2467 | |
2468 | if (!INTEL_DISPLAY_ENABLED(dev_priv)(({ int __ret = !!((!((&(dev_priv)->__runtime)->pipe_mask != 0))); if (__ret) printf("%s %s: " "%s", dev_driver_string (((&(dev_priv)->drm))->dev), "", "drm_WARN_ON(" "!((&(dev_priv)->__runtime)->pipe_mask != 0)" ")"); __builtin_expect(!!(__ret), 0); }), !(dev_priv)->params .disable_display && !intel_opregion_headless_sku(dev_priv ))) |
2469 | return connector_status_disconnected; |
2470 | |
2471 | wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS); |
2472 | |
2473 | if (DISPLAY_VER(dev_priv)((&(dev_priv)->__runtime)->display.ip.ver) >= 11 && |
2474 | !intel_digital_port_connected(encoder)) |
2475 | goto out; |
2476 | |
2477 | intel_hdmi_unset_edid(connector); |
2478 | |
2479 | if (intel_hdmi_set_edid(connector)) |
2480 | status = connector_status_connected; |
2481 | |
2482 | out: |
2483 | intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS, wakeref); |
2484 | |
2485 | if (status != connector_status_connected) |
2486 | cec_notifier_phys_addr_invalidate(intel_hdmi->cec_notifier); |
2487 | |
2488 | /* |
2489 | * Make sure the refs for power wells enabled during detect are |
2490 | * dropped to avoid a new detect cycle triggered by HPD polling. |
2491 | */ |
2492 | intel_display_power_flush_work(dev_priv); |
2493 | |
2494 | return status; |
2495 | } |
2496 | |
2497 | static void |
2498 | intel_hdmi_force(struct drm_connector *connector) |
2499 | { |
2500 | struct drm_i915_privateinteldrm_softc *i915 = to_i915(connector->dev); |
2501 | |
2502 | drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s]\n",__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "[CONNECTOR:%d:%s]\n" , connector->base.id, connector->name) |
2503 | connector->base.id, connector->name)__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915-> drm)->dev : ((void *)0), DRM_UT_KMS, "[CONNECTOR:%d:%s]\n" , connector->base.id, connector->name); |
2504 | |
2505 | intel_hdmi_unset_edid(connector); |
2506 | |
2507 | if (connector->status != connector_status_connected) |
2508 | return; |
2509 | |
2510 | intel_hdmi_set_edid(connector); |
2511 | } |
2512 | |
2513 | static int intel_hdmi_get_modes(struct drm_connector *connector) |
2514 | { |
2515 | struct edid *edid; |
2516 | |
2517 | edid = to_intel_connector(connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (connector); (struct intel_connector *)( (char *)__mptr - __builtin_offsetof(struct intel_connector, base) );})->detect_edid; |
2518 | if (edid == NULL((void *)0)) |
2519 | return 0; |
2520 | |
2521 | return intel_connector_update_modes(connector, edid); |
2522 | } |
2523 | |
2524 | static struct i2c_adapter * |
2525 | intel_hdmi_get_i2c_adapter(struct drm_connector *connector) |
2526 | { |
2527 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->dev); |
2528 | struct intel_hdmi *intel_hdmi = intel_attached_hdmi(to_intel_connector(connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (connector); (struct intel_connector *)( (char *)__mptr - __builtin_offsetof(struct intel_connector, base) );})); |
2529 | |
2530 | return intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus); |
2531 | } |
2532 | |
2533 | static void intel_hdmi_create_i2c_symlink(struct drm_connector *connector) |
2534 | { |
2535 | #ifdef __linux__ |
2536 | struct drm_i915_privateinteldrm_softc *i915 = to_i915(connector->dev); |
2537 | struct i2c_adapter *adapter = intel_hdmi_get_i2c_adapter(connector); |
2538 | struct kobject *i2c_kobj = &adapter->dev.kobj; |
2539 | struct kobject *connector_kobj = &connector->kdev->kobj; |
2540 | int ret; |
2541 | |
2542 | ret = sysfs_create_link(connector_kobj, i2c_kobj, i2c_kobj->name)0; |
2543 | if (ret) |
2544 | drm_err(&i915->drm, "Failed to create i2c symlink (%d)\n", ret)printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Failed to create i2c symlink (%d)\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , ret); |
2545 | #endif |
2546 | } |
2547 | |
2548 | static void intel_hdmi_remove_i2c_symlink(struct drm_connector *connector) |
2549 | { |
2550 | #ifdef __linux__ |
2551 | struct i2c_adapter *adapter = intel_hdmi_get_i2c_adapter(connector); |
2552 | struct kobject *i2c_kobj = &adapter->dev.kobj; |
2553 | struct kobject *connector_kobj = &connector->kdev->kobj; |
2554 | |
2555 | sysfs_remove_link(connector_kobj, i2c_kobj->name); |
2556 | #endif |
2557 | } |
2558 | |
2559 | static int |
2560 | intel_hdmi_connector_register(struct drm_connector *connector) |
2561 | { |
2562 | int ret; |
2563 | |
2564 | ret = intel_connector_register(connector); |
2565 | if (ret) |
2566 | return ret; |
2567 | |
2568 | intel_hdmi_create_i2c_symlink(connector); |
2569 | |
2570 | return ret; |
2571 | } |
2572 | |
2573 | static void intel_hdmi_connector_unregister(struct drm_connector *connector) |
2574 | { |
2575 | struct cec_notifier *n = intel_attached_hdmi(to_intel_connector(connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (connector); (struct intel_connector *)( (char *)__mptr - __builtin_offsetof(struct intel_connector, base) );}))->cec_notifier; |
2576 | |
2577 | cec_notifier_conn_unregister(n); |
2578 | |
2579 | intel_hdmi_remove_i2c_symlink(connector); |
2580 | intel_connector_unregister(connector); |
2581 | } |
2582 | |
2583 | static const struct drm_connector_funcs intel_hdmi_connector_funcs = { |
2584 | .detect = intel_hdmi_detect, |
2585 | .force = intel_hdmi_force, |
2586 | .fill_modes = drm_helper_probe_single_connector_modes, |
2587 | .atomic_get_property = intel_digital_connector_atomic_get_property, |
2588 | .atomic_set_property = intel_digital_connector_atomic_set_property, |
2589 | .late_register = intel_hdmi_connector_register, |
2590 | .early_unregister = intel_hdmi_connector_unregister, |
2591 | .destroy = intel_connector_destroy, |
2592 | .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, |
2593 | .atomic_duplicate_state = intel_digital_connector_duplicate_state, |
2594 | }; |
2595 | |
2596 | static const struct drm_connector_helper_funcs intel_hdmi_connector_helper_funcs = { |
2597 | .get_modes = intel_hdmi_get_modes, |
2598 | .mode_valid = intel_hdmi_mode_valid, |
2599 | .atomic_check = intel_digital_connector_atomic_check, |
2600 | }; |
2601 | |
2602 | static void |
2603 | intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *connector) |
2604 | { |
2605 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->dev); |
2606 | |
2607 | intel_attach_force_audio_property(connector); |
2608 | intel_attach_broadcast_rgb_property(connector); |
2609 | intel_attach_aspect_ratio_property(connector); |
2610 | |
2611 | intel_attach_hdmi_colorspace_property(connector); |
2612 | drm_connector_attach_content_type_property(connector); |
2613 | |
2614 | if (DISPLAY_VER(dev_priv)((&(dev_priv)->__runtime)->display.ip.ver) >= 10) |
2615 | drm_connector_attach_hdr_output_metadata_property(connector); |
2616 | |
2617 | if (!HAS_GMCH(dev_priv)((&(dev_priv)->__info)->display.has_gmch)) |
2618 | drm_connector_attach_max_bpc_property(connector, 8, 12); |
2619 | } |
2620 | |
2621 | /* |
2622 | * intel_hdmi_handle_sink_scrambling: handle sink scrambling/clock ratio setup |
2623 | * @encoder: intel_encoder |
2624 | * @connector: drm_connector |
2625 | * @high_tmds_clock_ratio = bool to indicate if the function needs to set |
2626 | * or reset the high tmds clock ratio for scrambling |
2627 | * @scrambling: bool to Indicate if the function needs to set or reset |
2628 | * sink scrambling |
2629 | * |
2630 | * This function handles scrambling on HDMI 2.0 capable sinks. |
2631 | * If required clock rate is > 340 Mhz && scrambling is supported by sink |
2632 | * it enables scrambling. This should be called before enabling the HDMI |
2633 | * 2.0 port, as the sink can choose to disable the scrambling if it doesn't |
2634 | * detect a scrambled clock within 100 ms. |
2635 | * |
2636 | * Returns: |
2637 | * True on success, false on failure. |
2638 | */ |
2639 | bool_Bool intel_hdmi_handle_sink_scrambling(struct intel_encoder *encoder, |
2640 | struct drm_connector *connector, |
2641 | bool_Bool high_tmds_clock_ratio, |
2642 | bool_Bool scrambling) |
2643 | { |
2644 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev); |
2645 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
2646 | struct drm_scrambling *sink_scrambling = |
2647 | &connector->display_info.hdmi.scdc.scrambling; |
2648 | struct i2c_adapter *adapter = |
2649 | intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus); |
2650 | |
2651 | if (!sink_scrambling->supported) |
2652 | return true1; |
2653 | |
2654 | drm_dbg_kms(&dev_priv->drm,__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "[CONNECTOR:%d:%s] scrambling=%s, TMDS bit clock ratio=1/%d\n" , connector->base.id, connector->name, str_yes_no(scrambling ), high_tmds_clock_ratio ? 40 : 10) |
2655 | "[CONNECTOR:%d:%s] scrambling=%s, TMDS bit clock ratio=1/%d\n",__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "[CONNECTOR:%d:%s] scrambling=%s, TMDS bit clock ratio=1/%d\n" , connector->base.id, connector->name, str_yes_no(scrambling ), high_tmds_clock_ratio ? 40 : 10) |
2656 | connector->base.id, connector->name,__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "[CONNECTOR:%d:%s] scrambling=%s, TMDS bit clock ratio=1/%d\n" , connector->base.id, connector->name, str_yes_no(scrambling ), high_tmds_clock_ratio ? 40 : 10) |
2657 | str_yes_no(scrambling), high_tmds_clock_ratio ? 40 : 10)__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "[CONNECTOR:%d:%s] scrambling=%s, TMDS bit clock ratio=1/%d\n" , connector->base.id, connector->name, str_yes_no(scrambling ), high_tmds_clock_ratio ? 40 : 10); |
2658 | |
2659 | /* Set TMDS bit clock ratio to 1/40 or 1/10, and enable/disable scrambling */ |
2660 | return drm_scdc_set_high_tmds_clock_ratio(adapter, |
2661 | high_tmds_clock_ratio) && |
2662 | drm_scdc_set_scrambling(adapter, scrambling); |
2663 | } |
2664 | |
2665 | static u8 chv_port_to_ddc_pin(struct drm_i915_privateinteldrm_softc *dev_priv, enum port port) |
2666 | { |
2667 | u8 ddc_pin; |
2668 | |
2669 | switch (port) { |
2670 | case PORT_B: |
2671 | ddc_pin = GMBUS_PIN_DPB5; |
2672 | break; |
2673 | case PORT_C: |
2674 | ddc_pin = GMBUS_PIN_DPC4; |
2675 | break; |
2676 | case PORT_D: |
2677 | ddc_pin = GMBUS_PIN_DPD_CHV3; |
2678 | break; |
2679 | default: |
2680 | MISSING_CASE(port)({ int __ret = !!(1); if (__ret) printf("Missing case (%s == %ld)\n" , "port", (long)(port)); __builtin_expect(!!(__ret), 0); }); |
2681 | ddc_pin = GMBUS_PIN_DPB5; |
2682 | break; |
2683 | } |
2684 | return ddc_pin; |
2685 | } |
2686 | |
2687 | static u8 bxt_port_to_ddc_pin(struct drm_i915_privateinteldrm_softc *dev_priv, enum port port) |
2688 | { |
2689 | u8 ddc_pin; |
2690 | |
2691 | switch (port) { |
2692 | case PORT_B: |
2693 | ddc_pin = GMBUS_PIN_1_BXT1; |
2694 | break; |
2695 | case PORT_C: |
2696 | ddc_pin = GMBUS_PIN_2_BXT2; |
2697 | break; |
2698 | default: |
2699 | MISSING_CASE(port)({ int __ret = !!(1); if (__ret) printf("Missing case (%s == %ld)\n" , "port", (long)(port)); __builtin_expect(!!(__ret), 0); }); |
2700 | ddc_pin = GMBUS_PIN_1_BXT1; |
2701 | break; |
2702 | } |
2703 | return ddc_pin; |
2704 | } |
2705 | |
2706 | static u8 cnp_port_to_ddc_pin(struct drm_i915_privateinteldrm_softc *dev_priv, |
2707 | enum port port) |
2708 | { |
2709 | u8 ddc_pin; |
2710 | |
2711 | switch (port) { |
2712 | case PORT_B: |
2713 | ddc_pin = GMBUS_PIN_1_BXT1; |
2714 | break; |
2715 | case PORT_C: |
2716 | ddc_pin = GMBUS_PIN_2_BXT2; |
2717 | break; |
2718 | case PORT_D: |
2719 | ddc_pin = GMBUS_PIN_4_CNP4; |
2720 | break; |
2721 | case PORT_F: |
2722 | ddc_pin = GMBUS_PIN_3_BXT3; |
2723 | break; |
2724 | default: |
2725 | MISSING_CASE(port)({ int __ret = !!(1); if (__ret) printf("Missing case (%s == %ld)\n" , "port", (long)(port)); __builtin_expect(!!(__ret), 0); }); |
2726 | ddc_pin = GMBUS_PIN_1_BXT1; |
2727 | break; |
2728 | } |
2729 | return ddc_pin; |
2730 | } |
2731 | |
2732 | static u8 icl_port_to_ddc_pin(struct drm_i915_privateinteldrm_softc *dev_priv, enum port port) |
2733 | { |
2734 | enum phy phy = intel_port_to_phy(dev_priv, port); |
2735 | |
2736 | if (intel_phy_is_combo(dev_priv, phy)) |
2737 | return GMBUS_PIN_1_BXT1 + port; |
2738 | else if (intel_phy_is_tc(dev_priv, phy)) |
2739 | return GMBUS_PIN_9_TC1_ICP9 + intel_port_to_tc(dev_priv, port); |
2740 | |
2741 | drm_WARN(&dev_priv->drm, 1, "Unknown port:%c\n", port_name(port))({ int __ret = !!(1); if (__ret) printf("%s %s: " "Unknown port:%c\n" , dev_driver_string((&dev_priv->drm)->dev), "", ((port ) + 'A')); __builtin_expect(!!(__ret), 0); }); |
2742 | return GMBUS_PIN_2_BXT2; |
2743 | } |
2744 | |
2745 | static u8 mcc_port_to_ddc_pin(struct drm_i915_privateinteldrm_softc *dev_priv, enum port port) |
2746 | { |
2747 | enum phy phy = intel_port_to_phy(dev_priv, port); |
2748 | u8 ddc_pin; |
2749 | |
2750 | switch (phy) { |
2751 | case PHY_A: |
2752 | ddc_pin = GMBUS_PIN_1_BXT1; |
2753 | break; |
2754 | case PHY_B: |
2755 | ddc_pin = GMBUS_PIN_2_BXT2; |
2756 | break; |
2757 | case PHY_C: |
2758 | ddc_pin = GMBUS_PIN_9_TC1_ICP9; |
2759 | break; |
2760 | default: |
2761 | MISSING_CASE(phy)({ int __ret = !!(1); if (__ret) printf("Missing case (%s == %ld)\n" , "phy", (long)(phy)); __builtin_expect(!!(__ret), 0); }); |
2762 | ddc_pin = GMBUS_PIN_1_BXT1; |
2763 | break; |
2764 | } |
2765 | return ddc_pin; |
2766 | } |
2767 | |
2768 | static u8 rkl_port_to_ddc_pin(struct drm_i915_privateinteldrm_softc *dev_priv, enum port port) |
2769 | { |
2770 | enum phy phy = intel_port_to_phy(dev_priv, port); |
2771 | |
2772 | WARN_ON(port == PORT_C)({ int __ret = !!(port == PORT_C); if (__ret) printf("WARNING %s failed at %s:%d\n" , "port == PORT_C", "/usr/src/sys/dev/pci/drm/i915/display/intel_hdmi.c" , 2772); __builtin_expect(!!(__ret), 0); }); |
2773 | |
2774 | /* |
2775 | * Pin mapping for RKL depends on which PCH is present. With TGP, the |
2776 | * final two outputs use type-c pins, even though they're actually |
2777 | * combo outputs. With CMP, the traditional DDI A-D pins are used for |
2778 | * all outputs. |
2779 | */ |
2780 | if (INTEL_PCH_TYPE(dev_priv)((dev_priv)->pch_type) >= PCH_TGP && phy >= PHY_C) |
2781 | return GMBUS_PIN_9_TC1_ICP9 + phy - PHY_C; |
2782 | |
2783 | return GMBUS_PIN_1_BXT1 + phy; |
2784 | } |
2785 | |
2786 | static u8 gen9bc_tgp_port_to_ddc_pin(struct drm_i915_privateinteldrm_softc *i915, enum port port) |
2787 | { |
2788 | enum phy phy = intel_port_to_phy(i915, port); |
2789 | |
2790 | drm_WARN_ON(&i915->drm, port == PORT_A)({ int __ret = !!((port == PORT_A)); if (__ret) printf("%s %s: " "%s", dev_driver_string(((&i915->drm))->dev), "", "drm_WARN_ON(" "port == PORT_A" ")"); __builtin_expect(!!(__ret), 0); }); |
2791 | |
2792 | /* |
2793 | * Pin mapping for GEN9 BC depends on which PCH is present. With TGP, |
2794 | * final two outputs use type-c pins, even though they're actually |
2795 | * combo outputs. With CMP, the traditional DDI A-D pins are used for |
2796 | * all outputs. |
2797 | */ |
2798 | if (INTEL_PCH_TYPE(i915)((i915)->pch_type) >= PCH_TGP && phy >= PHY_C) |
2799 | return GMBUS_PIN_9_TC1_ICP9 + phy - PHY_C; |
2800 | |
2801 | return GMBUS_PIN_1_BXT1 + phy; |
2802 | } |
2803 | |
2804 | static u8 dg1_port_to_ddc_pin(struct drm_i915_privateinteldrm_softc *dev_priv, enum port port) |
2805 | { |
2806 | return intel_port_to_phy(dev_priv, port) + 1; |
2807 | } |
2808 | |
2809 | static u8 adls_port_to_ddc_pin(struct drm_i915_privateinteldrm_softc *dev_priv, enum port port) |
2810 | { |
2811 | enum phy phy = intel_port_to_phy(dev_priv, port); |
2812 | |
2813 | WARN_ON(port == PORT_B || port == PORT_C)({ int __ret = !!(port == PORT_B || port == PORT_C); if (__ret ) printf("WARNING %s failed at %s:%d\n", "port == PORT_B || port == PORT_C" , "/usr/src/sys/dev/pci/drm/i915/display/intel_hdmi.c", 2813) ; __builtin_expect(!!(__ret), 0); }); |
2814 | |
2815 | /* |
2816 | * Pin mapping for ADL-S requires TC pins for all combo phy outputs |
2817 | * except first combo output. |
2818 | */ |
2819 | if (phy == PHY_A) |
2820 | return GMBUS_PIN_1_BXT1; |
2821 | |
2822 | return GMBUS_PIN_9_TC1_ICP9 + phy - PHY_B; |
2823 | } |
2824 | |
2825 | static u8 g4x_port_to_ddc_pin(struct drm_i915_privateinteldrm_softc *dev_priv, |
2826 | enum port port) |
2827 | { |
2828 | u8 ddc_pin; |
2829 | |
2830 | switch (port) { |
2831 | case PORT_B: |
2832 | ddc_pin = GMBUS_PIN_DPB5; |
2833 | break; |
2834 | case PORT_C: |
2835 | ddc_pin = GMBUS_PIN_DPC4; |
2836 | break; |
2837 | case PORT_D: |
2838 | ddc_pin = GMBUS_PIN_DPD6; |
2839 | break; |
2840 | default: |
2841 | MISSING_CASE(port)({ int __ret = !!(1); if (__ret) printf("Missing case (%s == %ld)\n" , "port", (long)(port)); __builtin_expect(!!(__ret), 0); }); |
2842 | ddc_pin = GMBUS_PIN_DPB5; |
2843 | break; |
2844 | } |
2845 | return ddc_pin; |
2846 | } |
2847 | |
2848 | static u8 intel_hdmi_ddc_pin(struct intel_encoder *encoder) |
2849 | { |
2850 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev); |
2851 | enum port port = encoder->port; |
2852 | u8 ddc_pin; |
2853 | |
2854 | ddc_pin = intel_bios_alternate_ddc_pin(encoder); |
2855 | if (ddc_pin) { |
2856 | drm_dbg_kms(&dev_priv->drm,__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "Using DDC pin 0x%x for port %c (VBT)\n" , ddc_pin, ((port) + 'A')) |
2857 | "Using DDC pin 0x%x for port %c (VBT)\n",__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "Using DDC pin 0x%x for port %c (VBT)\n" , ddc_pin, ((port) + 'A')) |
2858 | ddc_pin, port_name(port))__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "Using DDC pin 0x%x for port %c (VBT)\n" , ddc_pin, ((port) + 'A')); |
2859 | return ddc_pin; |
2860 | } |
2861 | |
2862 | if (IS_ALDERLAKE_S(dev_priv)IS_PLATFORM(dev_priv, INTEL_ALDERLAKE_S)) |
2863 | ddc_pin = adls_port_to_ddc_pin(dev_priv, port); |
2864 | else if (INTEL_PCH_TYPE(dev_priv)((dev_priv)->pch_type) >= PCH_DG1) |
2865 | ddc_pin = dg1_port_to_ddc_pin(dev_priv, port); |
2866 | else if (IS_ROCKETLAKE(dev_priv)IS_PLATFORM(dev_priv, INTEL_ROCKETLAKE)) |
2867 | ddc_pin = rkl_port_to_ddc_pin(dev_priv, port); |
2868 | else if (DISPLAY_VER(dev_priv)((&(dev_priv)->__runtime)->display.ip.ver) == 9 && HAS_PCH_TGP(dev_priv)(((dev_priv)->pch_type) == PCH_TGP)) |
2869 | ddc_pin = gen9bc_tgp_port_to_ddc_pin(dev_priv, port); |
2870 | else if (IS_JSL_EHL(dev_priv)(IS_PLATFORM(dev_priv, INTEL_JASPERLAKE) || IS_PLATFORM(dev_priv , INTEL_ELKHARTLAKE)) && HAS_PCH_TGP(dev_priv)(((dev_priv)->pch_type) == PCH_TGP)) |
2871 | ddc_pin = mcc_port_to_ddc_pin(dev_priv, port); |
2872 | else if (INTEL_PCH_TYPE(dev_priv)((dev_priv)->pch_type) >= PCH_ICP) |
2873 | ddc_pin = icl_port_to_ddc_pin(dev_priv, port); |
2874 | else if (HAS_PCH_CNP(dev_priv)(((dev_priv)->pch_type) == PCH_CNP)) |
2875 | ddc_pin = cnp_port_to_ddc_pin(dev_priv, port); |
2876 | else if (IS_GEMINILAKE(dev_priv)IS_PLATFORM(dev_priv, INTEL_GEMINILAKE) || IS_BROXTON(dev_priv)IS_PLATFORM(dev_priv, INTEL_BROXTON)) |
2877 | ddc_pin = bxt_port_to_ddc_pin(dev_priv, port); |
2878 | else if (IS_CHERRYVIEW(dev_priv)IS_PLATFORM(dev_priv, INTEL_CHERRYVIEW)) |
2879 | ddc_pin = chv_port_to_ddc_pin(dev_priv, port); |
2880 | else |
2881 | ddc_pin = g4x_port_to_ddc_pin(dev_priv, port); |
2882 | |
2883 | drm_dbg_kms(&dev_priv->drm,__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "Using DDC pin 0x%x for port %c (platform default)\n" , ddc_pin, ((port) + 'A')) |
2884 | "Using DDC pin 0x%x for port %c (platform default)\n",__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "Using DDC pin 0x%x for port %c (platform default)\n" , ddc_pin, ((port) + 'A')) |
2885 | ddc_pin, port_name(port))__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "Using DDC pin 0x%x for port %c (platform default)\n" , ddc_pin, ((port) + 'A')); |
2886 | |
2887 | return ddc_pin; |
2888 | } |
2889 | |
2890 | void intel_infoframe_init(struct intel_digital_port *dig_port) |
2891 | { |
2892 | struct drm_i915_privateinteldrm_softc *dev_priv = |
2893 | to_i915(dig_port->base.base.dev); |
2894 | |
2895 | if (IS_VALLEYVIEW(dev_priv)IS_PLATFORM(dev_priv, INTEL_VALLEYVIEW) || IS_CHERRYVIEW(dev_priv)IS_PLATFORM(dev_priv, INTEL_CHERRYVIEW)) { |
2896 | dig_port->write_infoframe = vlv_write_infoframe; |
2897 | dig_port->read_infoframe = vlv_read_infoframe; |
2898 | dig_port->set_infoframes = vlv_set_infoframes; |
2899 | dig_port->infoframes_enabled = vlv_infoframes_enabled; |
2900 | } else if (IS_G4X(dev_priv)(IS_PLATFORM(dev_priv, INTEL_G45) || IS_PLATFORM(dev_priv, INTEL_GM45 ))) { |
2901 | dig_port->write_infoframe = g4x_write_infoframe; |
2902 | dig_port->read_infoframe = g4x_read_infoframe; |
2903 | dig_port->set_infoframes = g4x_set_infoframes; |
2904 | dig_port->infoframes_enabled = g4x_infoframes_enabled; |
2905 | } else if (HAS_DDI(dev_priv)((&(dev_priv)->__info)->display.has_ddi)) { |
2906 | if (intel_bios_is_lspcon_present(dev_priv, dig_port->base.port)) { |
2907 | dig_port->write_infoframe = lspcon_write_infoframe; |
2908 | dig_port->read_infoframe = lspcon_read_infoframe; |
2909 | dig_port->set_infoframes = lspcon_set_infoframes; |
2910 | dig_port->infoframes_enabled = lspcon_infoframes_enabled; |
2911 | } else { |
2912 | dig_port->write_infoframe = hsw_write_infoframe; |
2913 | dig_port->read_infoframe = hsw_read_infoframe; |
2914 | dig_port->set_infoframes = hsw_set_infoframes; |
2915 | dig_port->infoframes_enabled = hsw_infoframes_enabled; |
2916 | } |
2917 | } else if (HAS_PCH_IBX(dev_priv)(((dev_priv)->pch_type) == PCH_IBX)) { |
2918 | dig_port->write_infoframe = ibx_write_infoframe; |
2919 | dig_port->read_infoframe = ibx_read_infoframe; |
2920 | dig_port->set_infoframes = ibx_set_infoframes; |
2921 | dig_port->infoframes_enabled = ibx_infoframes_enabled; |
2922 | } else { |
2923 | dig_port->write_infoframe = cpt_write_infoframe; |
2924 | dig_port->read_infoframe = cpt_read_infoframe; |
2925 | dig_port->set_infoframes = cpt_set_infoframes; |
2926 | dig_port->infoframes_enabled = cpt_infoframes_enabled; |
2927 | } |
2928 | } |
2929 | |
2930 | void intel_hdmi_init_connector(struct intel_digital_port *dig_port, |
2931 | struct intel_connector *intel_connector) |
2932 | { |
2933 | struct drm_connector *connector = &intel_connector->base; |
2934 | struct intel_hdmi *intel_hdmi = &dig_port->hdmi; |
2935 | struct intel_encoder *intel_encoder = &dig_port->base; |
2936 | struct drm_device *dev = intel_encoder->base.dev; |
2937 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(dev); |
2938 | struct i2c_adapter *ddc; |
2939 | enum port port = intel_encoder->port; |
2940 | struct cec_connector_info conn_info; |
2941 | |
2942 | drm_dbg_kms(&dev_priv->drm,__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "Adding HDMI connector on [ENCODER:%d:%s]\n" , intel_encoder->base.base.id, intel_encoder->base.name ) |
2943 | "Adding HDMI connector on [ENCODER:%d:%s]\n",__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "Adding HDMI connector on [ENCODER:%d:%s]\n" , intel_encoder->base.base.id, intel_encoder->base.name ) |
2944 | intel_encoder->base.base.id, intel_encoder->base.name)__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "Adding HDMI connector on [ENCODER:%d:%s]\n" , intel_encoder->base.base.id, intel_encoder->base.name ); |
2945 | |
2946 | if (DISPLAY_VER(dev_priv)((&(dev_priv)->__runtime)->display.ip.ver) < 12 && drm_WARN_ON(dev, port == PORT_A)({ int __ret = !!((port == PORT_A)); if (__ret) printf("%s %s: " "%s", dev_driver_string(((dev))->dev), "", "drm_WARN_ON(" "port == PORT_A" ")"); __builtin_expect(!!(__ret), 0); })) |
2947 | return; |
2948 | |
2949 | if (drm_WARN(dev, dig_port->max_lanes < 4,({ int __ret = !!(dig_port->max_lanes < 4); if (__ret) printf ("%s %s: " "Not enough lanes (%d) for HDMI on [ENCODER:%d:%s]\n" , dev_driver_string((dev)->dev), "", dig_port->max_lanes , intel_encoder->base.base.id, intel_encoder->base.name ); __builtin_expect(!!(__ret), 0); }) |
2950 | "Not enough lanes (%d) for HDMI on [ENCODER:%d:%s]\n",({ int __ret = !!(dig_port->max_lanes < 4); if (__ret) printf ("%s %s: " "Not enough lanes (%d) for HDMI on [ENCODER:%d:%s]\n" , dev_driver_string((dev)->dev), "", dig_port->max_lanes , intel_encoder->base.base.id, intel_encoder->base.name ); __builtin_expect(!!(__ret), 0); }) |
2951 | dig_port->max_lanes, intel_encoder->base.base.id,({ int __ret = !!(dig_port->max_lanes < 4); if (__ret) printf ("%s %s: " "Not enough lanes (%d) for HDMI on [ENCODER:%d:%s]\n" , dev_driver_string((dev)->dev), "", dig_port->max_lanes , intel_encoder->base.base.id, intel_encoder->base.name ); __builtin_expect(!!(__ret), 0); }) |
2952 | intel_encoder->base.name)({ int __ret = !!(dig_port->max_lanes < 4); if (__ret) printf ("%s %s: " "Not enough lanes (%d) for HDMI on [ENCODER:%d:%s]\n" , dev_driver_string((dev)->dev), "", dig_port->max_lanes , intel_encoder->base.base.id, intel_encoder->base.name ); __builtin_expect(!!(__ret), 0); })) |
2953 | return; |
2954 | |
2955 | intel_hdmi->ddc_bus = intel_hdmi_ddc_pin(intel_encoder); |
2956 | ddc = intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus); |
2957 | |
2958 | drm_connector_init_with_ddc(dev, connector, |
2959 | &intel_hdmi_connector_funcs, |
2960 | DRM_MODE_CONNECTOR_HDMIA11, |
2961 | ddc); |
2962 | drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs); |
2963 | |
2964 | connector->interlace_allowed = 1; |
2965 | connector->doublescan_allowed = 0; |
2966 | connector->stereo_allowed = 1; |
2967 | |
2968 | if (DISPLAY_VER(dev_priv)((&(dev_priv)->__runtime)->display.ip.ver) >= 10) |
2969 | connector->ycbcr_420_allowed = true1; |
2970 | |
2971 | intel_connector->polled = DRM_CONNECTOR_POLL_HPD(1 << 0); |
2972 | |
2973 | if (HAS_DDI(dev_priv)((&(dev_priv)->__info)->display.has_ddi)) |
2974 | intel_connector->get_hw_state = intel_ddi_connector_get_hw_state; |
2975 | else |
2976 | intel_connector->get_hw_state = intel_connector_get_hw_state; |
2977 | |
2978 | intel_hdmi_add_properties(intel_hdmi, connector); |
2979 | |
2980 | intel_connector_attach_encoder(intel_connector, intel_encoder); |
2981 | intel_hdmi->attached_connector = intel_connector; |
2982 | |
2983 | if (is_hdcp_supported(dev_priv, port)) { |
2984 | int ret = intel_hdcp_init(intel_connector, dig_port, |
2985 | &intel_hdmi_hdcp_shim); |
2986 | if (ret) |
2987 | drm_dbg_kms(&dev_priv->drm,__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "HDCP init failed, skipping.\n" ) |
2988 | "HDCP init failed, skipping.\n")__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "HDCP init failed, skipping.\n" ); |
2989 | } |
2990 | |
2991 | /* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written |
2992 | * 0xd. Failure to do so will result in spurious interrupts being |
2993 | * generated on the port when a cable is not attached. |
2994 | */ |
2995 | if (IS_G45(dev_priv)IS_PLATFORM(dev_priv, INTEL_G45)) { |
2996 | u32 temp = intel_de_read(dev_priv, PEG_BAND_GAP_DATA((const i915_reg_t){ .reg = (0x14d68) })); |
2997 | intel_de_write(dev_priv, PEG_BAND_GAP_DATA((const i915_reg_t){ .reg = (0x14d68) }), |
2998 | (temp & ~0xf) | 0xd); |
2999 | } |
3000 | |
3001 | cec_fill_conn_info_from_drm(&conn_info, connector); |
3002 | |
3003 | intel_hdmi->cec_notifier = |
3004 | cec_notifier_conn_register(dev->dev, port_identifier(port), |
3005 | &conn_info); |
3006 | if (!intel_hdmi->cec_notifier) |
3007 | drm_dbg_kms(&dev_priv->drm, "CEC notifier get failed\n")__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv ->drm)->dev : ((void *)0), DRM_UT_KMS, "CEC notifier get failed\n" ); |
3008 | } |
3009 | |
3010 | /* |
3011 | * intel_hdmi_dsc_get_slice_height - get the dsc slice_height |
3012 | * @vactive: Vactive of a display mode |
3013 | * |
3014 | * @return: appropriate dsc slice height for a given mode. |
3015 | */ |
3016 | int intel_hdmi_dsc_get_slice_height(int vactive) |
3017 | { |
3018 | int slice_height; |
3019 | |
3020 | /* |
3021 | * Slice Height determination : HDMI2.1 Section 7.7.5.2 |
3022 | * Select smallest slice height >=96, that results in a valid PPS and |
3023 | * requires minimum padding lines required for final slice. |
3024 | * |
3025 | * Assumption : Vactive is even. |
3026 | */ |
3027 | for (slice_height = 96; slice_height <= vactive; slice_height += 2) |
3028 | if (vactive % slice_height == 0) |
3029 | return slice_height; |
3030 | |
3031 | return 0; |
3032 | } |
3033 | |
3034 | /* |
3035 | * intel_hdmi_dsc_get_num_slices - get no. of dsc slices based on dsc encoder |
3036 | * and dsc decoder capabilities |
3037 | * |
3038 | * @crtc_state: intel crtc_state |
3039 | * @src_max_slices: maximum slices supported by the DSC encoder |
3040 | * @src_max_slice_width: maximum slice width supported by DSC encoder |
3041 | * @hdmi_max_slices: maximum slices supported by sink DSC decoder |
3042 | * @hdmi_throughput: maximum clock per slice (MHz) supported by HDMI sink |
3043 | * |
3044 | * @return: num of dsc slices that can be supported by the dsc encoder |
3045 | * and decoder. |
3046 | */ |
3047 | int |
3048 | intel_hdmi_dsc_get_num_slices(const struct intel_crtc_state *crtc_state, |
3049 | int src_max_slices, int src_max_slice_width, |
3050 | int hdmi_max_slices, int hdmi_throughput) |
3051 | { |
3052 | /* Pixel rates in KPixels/sec */ |
3053 | #define HDMI_DSC_PEAK_PIXEL_RATE2720000 2720000 |
3054 | /* |
3055 | * Rates at which the source and sink are required to process pixels in each |
3056 | * slice, can be two levels: either atleast 340000KHz or atleast 40000KHz. |
3057 | */ |
3058 | #define HDMI_DSC_MAX_ENC_THROUGHPUT_0340000 340000 |
3059 | #define HDMI_DSC_MAX_ENC_THROUGHPUT_1400000 400000 |
3060 | |
3061 | /* Spec limits the slice width to 2720 pixels */ |
3062 | #define MAX_HDMI_SLICE_WIDTH2720 2720 |
3063 | int kslice_adjust; |
3064 | int adjusted_clk_khz; |
3065 | int min_slices; |
3066 | int target_slices; |
3067 | int max_throughput; /* max clock freq. in khz per slice */ |
3068 | int max_slice_width; |
3069 | int slice_width; |
3070 | int pixel_clock = crtc_state->hw.adjusted_mode.crtc_clock; |
3071 | |
3072 | if (!hdmi_throughput) |
3073 | return 0; |
3074 | |
3075 | /* |
3076 | * Slice Width determination : HDMI2.1 Section 7.7.5.1 |
3077 | * kslice_adjust factor for 4:2:0, and 4:2:2 formats is 0.5, where as |
3078 | * for 4:4:4 is 1.0. Multiplying these factors by 10 and later |
3079 | * dividing adjusted clock value by 10. |
3080 | */ |
3081 | if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR444 || |
3082 | crtc_state->output_format == INTEL_OUTPUT_FORMAT_RGB) |
3083 | kslice_adjust = 10; |
3084 | else |
3085 | kslice_adjust = 5; |
3086 | |
3087 | /* |
3088 | * As per spec, the rate at which the source and the sink process |
3089 | * the pixels per slice are at two levels: atleast 340Mhz or 400Mhz. |
3090 | * This depends upon the pixel clock rate and output formats |
3091 | * (kslice adjust). |
3092 | * If pixel clock * kslice adjust >= 2720MHz slices can be processed |
3093 | * at max 340MHz, otherwise they can be processed at max 400MHz. |
3094 | */ |
3095 | |
3096 | adjusted_clk_khz = DIV_ROUND_UP(kslice_adjust * pixel_clock, 10)(((kslice_adjust * pixel_clock) + ((10) - 1)) / (10)); |
3097 | |
3098 | if (adjusted_clk_khz <= HDMI_DSC_PEAK_PIXEL_RATE2720000) |
3099 | max_throughput = HDMI_DSC_MAX_ENC_THROUGHPUT_0340000; |
3100 | else |
3101 | max_throughput = HDMI_DSC_MAX_ENC_THROUGHPUT_1400000; |
3102 | |
3103 | /* |
3104 | * Taking into account the sink's capability for maximum |
3105 | * clock per slice (in MHz) as read from HF-VSDB. |
3106 | */ |
3107 | max_throughput = min(max_throughput, hdmi_throughput * 1000)(((max_throughput)<(hdmi_throughput * 1000))?(max_throughput ):(hdmi_throughput * 1000)); |
3108 | |
3109 | min_slices = DIV_ROUND_UP(adjusted_clk_khz, max_throughput)(((adjusted_clk_khz) + ((max_throughput) - 1)) / (max_throughput )); |
3110 | max_slice_width = min(MAX_HDMI_SLICE_WIDTH, src_max_slice_width)(((2720)<(src_max_slice_width))?(2720):(src_max_slice_width )); |
3111 | |
3112 | /* |
3113 | * Keep on increasing the num of slices/line, starting from min_slices |
3114 | * per line till we get such a number, for which the slice_width is |
3115 | * just less than max_slice_width. The slices/line selected should be |
3116 | * less than or equal to the max horizontal slices that the combination |
3117 | * of PCON encoder and HDMI decoder can support. |
3118 | */ |
3119 | slice_width = max_slice_width; |
Value stored to 'slice_width' is never read | |
3120 | |
3121 | do { |
3122 | if (min_slices <= 1 && src_max_slices >= 1 && hdmi_max_slices >= 1) |
3123 | target_slices = 1; |
3124 | else if (min_slices <= 2 && src_max_slices >= 2 && hdmi_max_slices >= 2) |
3125 | target_slices = 2; |
3126 | else if (min_slices <= 4 && src_max_slices >= 4 && hdmi_max_slices >= 4) |
3127 | target_slices = 4; |
3128 | else if (min_slices <= 8 && src_max_slices >= 8 && hdmi_max_slices >= 8) |
3129 | target_slices = 8; |
3130 | else if (min_slices <= 12 && src_max_slices >= 12 && hdmi_max_slices >= 12) |
3131 | target_slices = 12; |
3132 | else if (min_slices <= 16 && src_max_slices >= 16 && hdmi_max_slices >= 16) |
3133 | target_slices = 16; |
3134 | else |
3135 | return 0; |
3136 | |
3137 | slice_width = DIV_ROUND_UP(crtc_state->hw.adjusted_mode.hdisplay, target_slices)(((crtc_state->hw.adjusted_mode.hdisplay) + ((target_slices ) - 1)) / (target_slices)); |
3138 | if (slice_width >= max_slice_width) |
3139 | min_slices = target_slices + 1; |
3140 | } while (slice_width >= max_slice_width); |
3141 | |
3142 | return target_slices; |
3143 | } |
3144 | |
3145 | /* |
3146 | * intel_hdmi_dsc_get_bpp - get the appropriate compressed bits_per_pixel based on |
3147 | * source and sink capabilities. |
3148 | * |
3149 | * @src_fraction_bpp: fractional bpp supported by the source |
3150 | * @slice_width: dsc slice width supported by the source and sink |
3151 | * @num_slices: num of slices supported by the source and sink |
3152 | * @output_format: video output format |
3153 | * @hdmi_all_bpp: sink supports decoding of 1/16th bpp setting |
3154 | * @hdmi_max_chunk_bytes: max bytes in a line of chunks supported by sink |
3155 | * |
3156 | * @return: compressed bits_per_pixel in step of 1/16 of bits_per_pixel |
3157 | */ |
3158 | int |
3159 | intel_hdmi_dsc_get_bpp(int src_fractional_bpp, int slice_width, int num_slices, |
3160 | int output_format, bool_Bool hdmi_all_bpp, |
3161 | int hdmi_max_chunk_bytes) |
3162 | { |
3163 | int max_dsc_bpp, min_dsc_bpp; |
3164 | int target_bytes; |
3165 | bool_Bool bpp_found = false0; |
3166 | int bpp_decrement_x16; |
3167 | int bpp_target; |
3168 | int bpp_target_x16; |
3169 | |
3170 | /* |
3171 | * Get min bpp and max bpp as per Table 7.23, in HDMI2.1 spec |
3172 | * Start with the max bpp and keep on decrementing with |
3173 | * fractional bpp, if supported by PCON DSC encoder |
3174 | * |
3175 | * for each bpp we check if no of bytes can be supported by HDMI sink |
3176 | */ |
3177 | |
3178 | /* Assuming: bpc as 8*/ |
3179 | if (output_format == INTEL_OUTPUT_FORMAT_YCBCR420) { |
3180 | min_dsc_bpp = 6; |
3181 | max_dsc_bpp = 3 * 4; /* 3*bpc/2 */ |
3182 | } else if (output_format == INTEL_OUTPUT_FORMAT_YCBCR444 || |
3183 | output_format == INTEL_OUTPUT_FORMAT_RGB) { |
3184 | min_dsc_bpp = 8; |
3185 | max_dsc_bpp = 3 * 8; /* 3*bpc */ |
3186 | } else { |
3187 | /* Assuming 4:2:2 encoding */ |
3188 | min_dsc_bpp = 7; |
3189 | max_dsc_bpp = 2 * 8; /* 2*bpc */ |
3190 | } |
3191 | |
3192 | /* |
3193 | * Taking into account if all dsc_all_bpp supported by HDMI2.1 sink |
3194 | * Section 7.7.34 : Source shall not enable compressed Video |
3195 | * Transport with bpp_target settings above 12 bpp unless |
3196 | * DSC_all_bpp is set to 1. |
3197 | */ |
3198 | if (!hdmi_all_bpp) |
3199 | max_dsc_bpp = min(max_dsc_bpp, 12)(((max_dsc_bpp)<(12))?(max_dsc_bpp):(12)); |
3200 | |
3201 | /* |
3202 | * The Sink has a limit of compressed data in bytes for a scanline, |
3203 | * as described in max_chunk_bytes field in HFVSDB block of edid. |
3204 | * The no. of bytes depend on the target bits per pixel that the |
3205 | * source configures. So we start with the max_bpp and calculate |
3206 | * the target_chunk_bytes. We keep on decrementing the target_bpp, |
3207 | * till we get the target_chunk_bytes just less than what the sink's |
3208 | * max_chunk_bytes, or else till we reach the min_dsc_bpp. |
3209 | * |
3210 | * The decrement is according to the fractional support from PCON DSC |
3211 | * encoder. For fractional BPP we use bpp_target as a multiple of 16. |
3212 | * |
3213 | * bpp_target_x16 = bpp_target * 16 |
3214 | * So we need to decrement by {1, 2, 4, 8, 16} for fractional bpps |
3215 | * {1/16, 1/8, 1/4, 1/2, 1} respectively. |
3216 | */ |
3217 | |
3218 | bpp_target = max_dsc_bpp; |
3219 | |
3220 | /* src does not support fractional bpp implies decrement by 16 for bppx16 */ |
3221 | if (!src_fractional_bpp) |
3222 | src_fractional_bpp = 1; |
3223 | bpp_decrement_x16 = DIV_ROUND_UP(16, src_fractional_bpp)(((16) + ((src_fractional_bpp) - 1)) / (src_fractional_bpp)); |
3224 | bpp_target_x16 = (bpp_target * 16) - bpp_decrement_x16; |
3225 | |
3226 | while (bpp_target_x16 > (min_dsc_bpp * 16)) { |
3227 | int bpp; |
3228 | |
3229 | bpp = DIV_ROUND_UP(bpp_target_x16, 16)(((bpp_target_x16) + ((16) - 1)) / (16)); |
3230 | target_bytes = DIV_ROUND_UP((num_slices * slice_width * bpp), 8)((((num_slices * slice_width * bpp)) + ((8) - 1)) / (8)); |
3231 | if (target_bytes <= hdmi_max_chunk_bytes) { |
3232 | bpp_found = true1; |
3233 | break; |
3234 | } |
3235 | bpp_target_x16 -= bpp_decrement_x16; |
3236 | } |
3237 | if (bpp_found) |
3238 | return bpp_target_x16; |
3239 | |
3240 | return 0; |
3241 | } |