Bug Summary

File:dev/pci/drm/i915/display/intel_tv.c
Warning:line 1640, column 2
Value stored to 'type' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name intel_tv.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -target-feature +retpoline-external-thunk -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/legacy-dpm -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu13 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/inc -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc/pmfw_if -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D SUSPEND -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /home/ben/Projects/scan/2024-01-11-110808-61670-1 -x c /usr/src/sys/dev/pci/drm/i915/display/intel_tv.c
1/*
2 * Copyright © 2006-2008 Intel Corporation
3 * Jesse Barnes <jesse.barnes@intel.com>
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 *
27 */
28
29/** @file
30 * Integrated TV-out support for the 915GM and 945GM.
31 */
32
33#include <drm/drm_atomic_helper.h>
34#include <drm/drm_crtc.h>
35#include <drm/drm_edid.h>
36
37#include "i915_drv.h"
38#include "intel_connector.h"
39#include "intel_crtc.h"
40#include "intel_de.h"
41#include "intel_display_types.h"
42#include "intel_dpll.h"
43#include "intel_hotplug.h"
44#include "intel_tv.h"
45
46enum tv_margin {
47 TV_MARGIN_LEFT, TV_MARGIN_TOP,
48 TV_MARGIN_RIGHT, TV_MARGIN_BOTTOM
49};
50
51struct intel_tv {
52 struct intel_encoder base;
53
54 int type;
55};
56
57struct video_levels {
58 u16 blank, black;
59 u8 burst;
60};
61
62struct color_conversion {
63 u16 ry, gy, by, ay;
64 u16 ru, gu, bu, au;
65 u16 rv, gv, bv, av;
66};
67
68static const u32 filter_table[] = {
69 0xB1403000, 0x2E203500, 0x35002E20, 0x3000B140,
70 0x35A0B160, 0x2DC02E80, 0xB1403480, 0xB1603000,
71 0x2EA03640, 0x34002D80, 0x3000B120, 0x36E0B160,
72 0x2D202EF0, 0xB1203380, 0xB1603000, 0x2F303780,
73 0x33002CC0, 0x3000B100, 0x3820B160, 0x2C802F50,
74 0xB10032A0, 0xB1603000, 0x2F9038C0, 0x32202C20,
75 0x3000B0E0, 0x3980B160, 0x2BC02FC0, 0xB0E031C0,
76 0xB1603000, 0x2FF03A20, 0x31602B60, 0xB020B0C0,
77 0x3AE0B160, 0x2B001810, 0xB0C03120, 0xB140B020,
78 0x18283BA0, 0x30C02A80, 0xB020B0A0, 0x3C60B140,
79 0x2A201838, 0xB0A03080, 0xB120B020, 0x18383D20,
80 0x304029C0, 0xB040B080, 0x3DE0B100, 0x29601848,
81 0xB0803000, 0xB100B040, 0x18483EC0, 0xB0402900,
82 0xB040B060, 0x3F80B0C0, 0x28801858, 0xB060B080,
83 0xB0A0B060, 0x18602820, 0xB0A02820, 0x0000B060,
84 0xB1403000, 0x2E203500, 0x35002E20, 0x3000B140,
85 0x35A0B160, 0x2DC02E80, 0xB1403480, 0xB1603000,
86 0x2EA03640, 0x34002D80, 0x3000B120, 0x36E0B160,
87 0x2D202EF0, 0xB1203380, 0xB1603000, 0x2F303780,
88 0x33002CC0, 0x3000B100, 0x3820B160, 0x2C802F50,
89 0xB10032A0, 0xB1603000, 0x2F9038C0, 0x32202C20,
90 0x3000B0E0, 0x3980B160, 0x2BC02FC0, 0xB0E031C0,
91 0xB1603000, 0x2FF03A20, 0x31602B60, 0xB020B0C0,
92 0x3AE0B160, 0x2B001810, 0xB0C03120, 0xB140B020,
93 0x18283BA0, 0x30C02A80, 0xB020B0A0, 0x3C60B140,
94 0x2A201838, 0xB0A03080, 0xB120B020, 0x18383D20,
95 0x304029C0, 0xB040B080, 0x3DE0B100, 0x29601848,
96 0xB0803000, 0xB100B040, 0x18483EC0, 0xB0402900,
97 0xB040B060, 0x3F80B0C0, 0x28801858, 0xB060B080,
98 0xB0A0B060, 0x18602820, 0xB0A02820, 0x0000B060,
99 0x36403000, 0x2D002CC0, 0x30003640, 0x2D0036C0,
100 0x35C02CC0, 0x37403000, 0x2C802D40, 0x30003540,
101 0x2D8037C0, 0x34C02C40, 0x38403000, 0x2BC02E00,
102 0x30003440, 0x2E2038C0, 0x34002B80, 0x39803000,
103 0x2B402E40, 0x30003380, 0x2E603A00, 0x33402B00,
104 0x3A803040, 0x2A802EA0, 0x30403300, 0x2EC03B40,
105 0x32802A40, 0x3C003040, 0x2A002EC0, 0x30803240,
106 0x2EC03C80, 0x320029C0, 0x3D403080, 0x29402F00,
107 0x308031C0, 0x2F203DC0, 0x31802900, 0x3E8030C0,
108 0x28802F40, 0x30C03140, 0x2F203F40, 0x31402840,
109 0x28003100, 0x28002F00, 0x00003100, 0x36403000,
110 0x2D002CC0, 0x30003640, 0x2D0036C0,
111 0x35C02CC0, 0x37403000, 0x2C802D40, 0x30003540,
112 0x2D8037C0, 0x34C02C40, 0x38403000, 0x2BC02E00,
113 0x30003440, 0x2E2038C0, 0x34002B80, 0x39803000,
114 0x2B402E40, 0x30003380, 0x2E603A00, 0x33402B00,
115 0x3A803040, 0x2A802EA0, 0x30403300, 0x2EC03B40,
116 0x32802A40, 0x3C003040, 0x2A002EC0, 0x30803240,
117 0x2EC03C80, 0x320029C0, 0x3D403080, 0x29402F00,
118 0x308031C0, 0x2F203DC0, 0x31802900, 0x3E8030C0,
119 0x28802F40, 0x30C03140, 0x2F203F40, 0x31402840,
120 0x28003100, 0x28002F00, 0x00003100,
121};
122
123/*
124 * Color conversion values have 3 separate fixed point formats:
125 *
126 * 10 bit fields (ay, au)
127 * 1.9 fixed point (b.bbbbbbbbb)
128 * 11 bit fields (ry, by, ru, gu, gv)
129 * exp.mantissa (ee.mmmmmmmmm)
130 * ee = 00 = 10^-1 (0.mmmmmmmmm)
131 * ee = 01 = 10^-2 (0.0mmmmmmmmm)
132 * ee = 10 = 10^-3 (0.00mmmmmmmmm)
133 * ee = 11 = 10^-4 (0.000mmmmmmmmm)
134 * 12 bit fields (gy, rv, bu)
135 * exp.mantissa (eee.mmmmmmmmm)
136 * eee = 000 = 10^-1 (0.mmmmmmmmm)
137 * eee = 001 = 10^-2 (0.0mmmmmmmmm)
138 * eee = 010 = 10^-3 (0.00mmmmmmmmm)
139 * eee = 011 = 10^-4 (0.000mmmmmmmmm)
140 * eee = 100 = reserved
141 * eee = 101 = reserved
142 * eee = 110 = reserved
143 * eee = 111 = 10^0 (m.mmmmmmmm) (only usable for 1.0 representation)
144 *
145 * Saturation and contrast are 8 bits, with their own representation:
146 * 8 bit field (saturation, contrast)
147 * exp.mantissa (ee.mmmmmm)
148 * ee = 00 = 10^-1 (0.mmmmmm)
149 * ee = 01 = 10^0 (m.mmmmm)
150 * ee = 10 = 10^1 (mm.mmmm)
151 * ee = 11 = 10^2 (mmm.mmm)
152 *
153 * Simple conversion function:
154 *
155 * static u32
156 * float_to_csc_11(float f)
157 * {
158 * u32 exp;
159 * u32 mant;
160 * u32 ret;
161 *
162 * if (f < 0)
163 * f = -f;
164 *
165 * if (f >= 1) {
166 * exp = 0x7;
167 * mant = 1 << 8;
168 * } else {
169 * for (exp = 0; exp < 3 && f < 0.5; exp++)
170 * f *= 2.0;
171 * mant = (f * (1 << 9) + 0.5);
172 * if (mant >= (1 << 9))
173 * mant = (1 << 9) - 1;
174 * }
175 * ret = (exp << 9) | mant;
176 * return ret;
177 * }
178 */
179
180/*
181 * Behold, magic numbers! If we plant them they might grow a big
182 * s-video cable to the sky... or something.
183 *
184 * Pre-converted to appropriate hex value.
185 */
186
187/*
188 * PAL & NTSC values for composite & s-video connections
189 */
190static const struct color_conversion ntsc_m_csc_composite = {
191 .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0104,
192 .ru = 0x0733, .gu = 0x052d, .bu = 0x05c7, .au = 0x0200,
193 .rv = 0x0340, .gv = 0x030c, .bv = 0x06d0, .av = 0x0200,
194};
195
196static const struct video_levels ntsc_m_levels_composite = {
197 .blank = 225, .black = 267, .burst = 113,
198};
199
200static const struct color_conversion ntsc_m_csc_svideo = {
201 .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0133,
202 .ru = 0x076a, .gu = 0x0564, .bu = 0x030d, .au = 0x0200,
203 .rv = 0x037a, .gv = 0x033d, .bv = 0x06f6, .av = 0x0200,
204};
205
206static const struct video_levels ntsc_m_levels_svideo = {
207 .blank = 266, .black = 316, .burst = 133,
208};
209
210static const struct color_conversion ntsc_j_csc_composite = {
211 .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0119,
212 .ru = 0x074c, .gu = 0x0546, .bu = 0x05ec, .au = 0x0200,
213 .rv = 0x035a, .gv = 0x0322, .bv = 0x06e1, .av = 0x0200,
214};
215
216static const struct video_levels ntsc_j_levels_composite = {
217 .blank = 225, .black = 225, .burst = 113,
218};
219
220static const struct color_conversion ntsc_j_csc_svideo = {
221 .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x014c,
222 .ru = 0x0788, .gu = 0x0581, .bu = 0x0322, .au = 0x0200,
223 .rv = 0x0399, .gv = 0x0356, .bv = 0x070a, .av = 0x0200,
224};
225
226static const struct video_levels ntsc_j_levels_svideo = {
227 .blank = 266, .black = 266, .burst = 133,
228};
229
230static const struct color_conversion pal_csc_composite = {
231 .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0113,
232 .ru = 0x0745, .gu = 0x053f, .bu = 0x05e1, .au = 0x0200,
233 .rv = 0x0353, .gv = 0x031c, .bv = 0x06dc, .av = 0x0200,
234};
235
236static const struct video_levels pal_levels_composite = {
237 .blank = 237, .black = 237, .burst = 118,
238};
239
240static const struct color_conversion pal_csc_svideo = {
241 .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0145,
242 .ru = 0x0780, .gu = 0x0579, .bu = 0x031c, .au = 0x0200,
243 .rv = 0x0390, .gv = 0x034f, .bv = 0x0705, .av = 0x0200,
244};
245
246static const struct video_levels pal_levels_svideo = {
247 .blank = 280, .black = 280, .burst = 139,
248};
249
250static const struct color_conversion pal_m_csc_composite = {
251 .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0104,
252 .ru = 0x0733, .gu = 0x052d, .bu = 0x05c7, .au = 0x0200,
253 .rv = 0x0340, .gv = 0x030c, .bv = 0x06d0, .av = 0x0200,
254};
255
256static const struct video_levels pal_m_levels_composite = {
257 .blank = 225, .black = 267, .burst = 113,
258};
259
260static const struct color_conversion pal_m_csc_svideo = {
261 .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0133,
262 .ru = 0x076a, .gu = 0x0564, .bu = 0x030d, .au = 0x0200,
263 .rv = 0x037a, .gv = 0x033d, .bv = 0x06f6, .av = 0x0200,
264};
265
266static const struct video_levels pal_m_levels_svideo = {
267 .blank = 266, .black = 316, .burst = 133,
268};
269
270static const struct color_conversion pal_n_csc_composite = {
271 .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0104,
272 .ru = 0x0733, .gu = 0x052d, .bu = 0x05c7, .au = 0x0200,
273 .rv = 0x0340, .gv = 0x030c, .bv = 0x06d0, .av = 0x0200,
274};
275
276static const struct video_levels pal_n_levels_composite = {
277 .blank = 225, .black = 267, .burst = 118,
278};
279
280static const struct color_conversion pal_n_csc_svideo = {
281 .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0133,
282 .ru = 0x076a, .gu = 0x0564, .bu = 0x030d, .au = 0x0200,
283 .rv = 0x037a, .gv = 0x033d, .bv = 0x06f6, .av = 0x0200,
284};
285
286static const struct video_levels pal_n_levels_svideo = {
287 .blank = 266, .black = 316, .burst = 139,
288};
289
290/*
291 * Component connections
292 */
293static const struct color_conversion sdtv_csc_yprpb = {
294 .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0145,
295 .ru = 0x0559, .gu = 0x0353, .bu = 0x0100, .au = 0x0200,
296 .rv = 0x0100, .gv = 0x03ad, .bv = 0x074d, .av = 0x0200,
297};
298
299static const struct color_conversion hdtv_csc_yprpb = {
300 .ry = 0x05b3, .gy = 0x016e, .by = 0x0728, .ay = 0x0145,
301 .ru = 0x07d5, .gu = 0x038b, .bu = 0x0100, .au = 0x0200,
302 .rv = 0x0100, .gv = 0x03d1, .bv = 0x06bc, .av = 0x0200,
303};
304
305static const struct video_levels component_levels = {
306 .blank = 279, .black = 279, .burst = 0,
307};
308
309
310struct tv_mode {
311 const char *name;
312
313 u32 clock;
314 u16 refresh; /* in millihertz (for precision) */
315 u8 oversample;
316 u8 hsync_end;
317 u16 hblank_start, hblank_end, htotal;
318 bool_Bool progressive : 1, trilevel_sync : 1, component_only : 1;
319 u8 vsync_start_f1, vsync_start_f2, vsync_len;
320 bool_Bool veq_ena : 1;
321 u8 veq_start_f1, veq_start_f2, veq_len;
322 u8 vi_end_f1, vi_end_f2;
323 u16 nbr_end;
324 bool_Bool burst_ena : 1;
325 u8 hburst_start, hburst_len;
326 u8 vburst_start_f1;
327 u16 vburst_end_f1;
328 u8 vburst_start_f2;
329 u16 vburst_end_f2;
330 u8 vburst_start_f3;
331 u16 vburst_end_f3;
332 u8 vburst_start_f4;
333 u16 vburst_end_f4;
334 /*
335 * subcarrier programming
336 */
337 u16 dda2_size, dda3_size;
338 u8 dda1_inc;
339 u16 dda2_inc, dda3_inc;
340 u32 sc_reset;
341 bool_Bool pal_burst : 1;
342 /*
343 * blank/black levels
344 */
345 const struct video_levels *composite_levels, *svideo_levels;
346 const struct color_conversion *composite_color, *svideo_color;
347 const u32 *filter_table;
348};
349
350
351/*
352 * Sub carrier DDA
353 *
354 * I think this works as follows:
355 *
356 * subcarrier freq = pixel_clock * (dda1_inc + dda2_inc / dda2_size) / 4096
357 *
358 * Presumably, when dda3 is added in, it gets to adjust the dda2_inc value
359 *
360 * So,
361 * dda1_ideal = subcarrier/pixel * 4096
362 * dda1_inc = floor (dda1_ideal)
363 * dda2 = dda1_ideal - dda1_inc
364 *
365 * then pick a ratio for dda2 that gives the closest approximation. If
366 * you can't get close enough, you can play with dda3 as well. This
367 * seems likely to happen when dda2 is small as the jumps would be larger
368 *
369 * To invert this,
370 *
371 * pixel_clock = subcarrier * 4096 / (dda1_inc + dda2_inc / dda2_size)
372 *
373 * The constants below were all computed using a 107.520MHz clock
374 */
375
376/*
377 * Register programming values for TV modes.
378 *
379 * These values account for -1s required.
380 */
381static const struct tv_mode tv_modes[] = {
382 {
383 .name = "NTSC-M",
384 .clock = 108000,
385 .refresh = 59940,
386 .oversample = 8,
387 .component_only = false0,
388 /* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.580MHz */
389
390 .hsync_end = 64, .hblank_end = 124,
391 .hblank_start = 836, .htotal = 857,
392
393 .progressive = false0, .trilevel_sync = false0,
394
395 .vsync_start_f1 = 6, .vsync_start_f2 = 7,
396 .vsync_len = 6,
397
398 .veq_ena = true1, .veq_start_f1 = 0,
399 .veq_start_f2 = 1, .veq_len = 18,
400
401 .vi_end_f1 = 20, .vi_end_f2 = 21,
402 .nbr_end = 240,
403
404 .burst_ena = true1,
405 .hburst_start = 72, .hburst_len = 34,
406 .vburst_start_f1 = 9, .vburst_end_f1 = 240,
407 .vburst_start_f2 = 10, .vburst_end_f2 = 240,
408 .vburst_start_f3 = 9, .vburst_end_f3 = 240,
409 .vburst_start_f4 = 10, .vburst_end_f4 = 240,
410
411 /* desired 3.5800000 actual 3.5800000 clock 107.52 */
412 .dda1_inc = 135,
413 .dda2_inc = 20800, .dda2_size = 27456,
414 .dda3_inc = 0, .dda3_size = 0,
415 .sc_reset = TV_SC_RESET_EVERY_4(1 << 24),
416 .pal_burst = false0,
417
418 .composite_levels = &ntsc_m_levels_composite,
419 .composite_color = &ntsc_m_csc_composite,
420 .svideo_levels = &ntsc_m_levels_svideo,
421 .svideo_color = &ntsc_m_csc_svideo,
422
423 .filter_table = filter_table,
424 },
425 {
426 .name = "NTSC-443",
427 .clock = 108000,
428 .refresh = 59940,
429 .oversample = 8,
430 .component_only = false0,
431 /* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 4.43MHz */
432 .hsync_end = 64, .hblank_end = 124,
433 .hblank_start = 836, .htotal = 857,
434
435 .progressive = false0, .trilevel_sync = false0,
436
437 .vsync_start_f1 = 6, .vsync_start_f2 = 7,
438 .vsync_len = 6,
439
440 .veq_ena = true1, .veq_start_f1 = 0,
441 .veq_start_f2 = 1, .veq_len = 18,
442
443 .vi_end_f1 = 20, .vi_end_f2 = 21,
444 .nbr_end = 240,
445
446 .burst_ena = true1,
447 .hburst_start = 72, .hburst_len = 34,
448 .vburst_start_f1 = 9, .vburst_end_f1 = 240,
449 .vburst_start_f2 = 10, .vburst_end_f2 = 240,
450 .vburst_start_f3 = 9, .vburst_end_f3 = 240,
451 .vburst_start_f4 = 10, .vburst_end_f4 = 240,
452
453 /* desired 4.4336180 actual 4.4336180 clock 107.52 */
454 .dda1_inc = 168,
455 .dda2_inc = 4093, .dda2_size = 27456,
456 .dda3_inc = 310, .dda3_size = 525,
457 .sc_reset = TV_SC_RESET_NEVER(3 << 24),
458 .pal_burst = false0,
459
460 .composite_levels = &ntsc_m_levels_composite,
461 .composite_color = &ntsc_m_csc_composite,
462 .svideo_levels = &ntsc_m_levels_svideo,
463 .svideo_color = &ntsc_m_csc_svideo,
464
465 .filter_table = filter_table,
466 },
467 {
468 .name = "NTSC-J",
469 .clock = 108000,
470 .refresh = 59940,
471 .oversample = 8,
472 .component_only = false0,
473
474 /* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.580MHz */
475 .hsync_end = 64, .hblank_end = 124,
476 .hblank_start = 836, .htotal = 857,
477
478 .progressive = false0, .trilevel_sync = false0,
479
480 .vsync_start_f1 = 6, .vsync_start_f2 = 7,
481 .vsync_len = 6,
482
483 .veq_ena = true1, .veq_start_f1 = 0,
484 .veq_start_f2 = 1, .veq_len = 18,
485
486 .vi_end_f1 = 20, .vi_end_f2 = 21,
487 .nbr_end = 240,
488
489 .burst_ena = true1,
490 .hburst_start = 72, .hburst_len = 34,
491 .vburst_start_f1 = 9, .vburst_end_f1 = 240,
492 .vburst_start_f2 = 10, .vburst_end_f2 = 240,
493 .vburst_start_f3 = 9, .vburst_end_f3 = 240,
494 .vburst_start_f4 = 10, .vburst_end_f4 = 240,
495
496 /* desired 3.5800000 actual 3.5800000 clock 107.52 */
497 .dda1_inc = 135,
498 .dda2_inc = 20800, .dda2_size = 27456,
499 .dda3_inc = 0, .dda3_size = 0,
500 .sc_reset = TV_SC_RESET_EVERY_4(1 << 24),
501 .pal_burst = false0,
502
503 .composite_levels = &ntsc_j_levels_composite,
504 .composite_color = &ntsc_j_csc_composite,
505 .svideo_levels = &ntsc_j_levels_svideo,
506 .svideo_color = &ntsc_j_csc_svideo,
507
508 .filter_table = filter_table,
509 },
510 {
511 .name = "PAL-M",
512 .clock = 108000,
513 .refresh = 59940,
514 .oversample = 8,
515 .component_only = false0,
516
517 /* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.580MHz */
518 .hsync_end = 64, .hblank_end = 124,
519 .hblank_start = 836, .htotal = 857,
520
521 .progressive = false0, .trilevel_sync = false0,
522
523 .vsync_start_f1 = 6, .vsync_start_f2 = 7,
524 .vsync_len = 6,
525
526 .veq_ena = true1, .veq_start_f1 = 0,
527 .veq_start_f2 = 1, .veq_len = 18,
528
529 .vi_end_f1 = 20, .vi_end_f2 = 21,
530 .nbr_end = 240,
531
532 .burst_ena = true1,
533 .hburst_start = 72, .hburst_len = 34,
534 .vburst_start_f1 = 9, .vburst_end_f1 = 240,
535 .vburst_start_f2 = 10, .vburst_end_f2 = 240,
536 .vburst_start_f3 = 9, .vburst_end_f3 = 240,
537 .vburst_start_f4 = 10, .vburst_end_f4 = 240,
538
539 /* desired 3.5800000 actual 3.5800000 clock 107.52 */
540 .dda1_inc = 135,
541 .dda2_inc = 16704, .dda2_size = 27456,
542 .dda3_inc = 0, .dda3_size = 0,
543 .sc_reset = TV_SC_RESET_EVERY_8(2 << 24),
544 .pal_burst = true1,
545
546 .composite_levels = &pal_m_levels_composite,
547 .composite_color = &pal_m_csc_composite,
548 .svideo_levels = &pal_m_levels_svideo,
549 .svideo_color = &pal_m_csc_svideo,
550
551 .filter_table = filter_table,
552 },
553 {
554 /* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */
555 .name = "PAL-N",
556 .clock = 108000,
557 .refresh = 50000,
558 .oversample = 8,
559 .component_only = false0,
560
561 .hsync_end = 64, .hblank_end = 128,
562 .hblank_start = 844, .htotal = 863,
563
564 .progressive = false0, .trilevel_sync = false0,
565
566
567 .vsync_start_f1 = 6, .vsync_start_f2 = 7,
568 .vsync_len = 6,
569
570 .veq_ena = true1, .veq_start_f1 = 0,
571 .veq_start_f2 = 1, .veq_len = 18,
572
573 .vi_end_f1 = 24, .vi_end_f2 = 25,
574 .nbr_end = 286,
575
576 .burst_ena = true1,
577 .hburst_start = 73, .hburst_len = 34,
578 .vburst_start_f1 = 8, .vburst_end_f1 = 285,
579 .vburst_start_f2 = 8, .vburst_end_f2 = 286,
580 .vburst_start_f3 = 9, .vburst_end_f3 = 286,
581 .vburst_start_f4 = 9, .vburst_end_f4 = 285,
582
583
584 /* desired 4.4336180 actual 4.4336180 clock 107.52 */
585 .dda1_inc = 135,
586 .dda2_inc = 23578, .dda2_size = 27648,
587 .dda3_inc = 134, .dda3_size = 625,
588 .sc_reset = TV_SC_RESET_EVERY_8(2 << 24),
589 .pal_burst = true1,
590
591 .composite_levels = &pal_n_levels_composite,
592 .composite_color = &pal_n_csc_composite,
593 .svideo_levels = &pal_n_levels_svideo,
594 .svideo_color = &pal_n_csc_svideo,
595
596 .filter_table = filter_table,
597 },
598 {
599 /* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */
600 .name = "PAL",
601 .clock = 108000,
602 .refresh = 50000,
603 .oversample = 8,
604 .component_only = false0,
605
606 .hsync_end = 64, .hblank_end = 142,
607 .hblank_start = 844, .htotal = 863,
608
609 .progressive = false0, .trilevel_sync = false0,
610
611 .vsync_start_f1 = 5, .vsync_start_f2 = 6,
612 .vsync_len = 5,
613
614 .veq_ena = true1, .veq_start_f1 = 0,
615 .veq_start_f2 = 1, .veq_len = 15,
616
617 .vi_end_f1 = 24, .vi_end_f2 = 25,
618 .nbr_end = 286,
619
620 .burst_ena = true1,
621 .hburst_start = 73, .hburst_len = 32,
622 .vburst_start_f1 = 8, .vburst_end_f1 = 285,
623 .vburst_start_f2 = 8, .vburst_end_f2 = 286,
624 .vburst_start_f3 = 9, .vburst_end_f3 = 286,
625 .vburst_start_f4 = 9, .vburst_end_f4 = 285,
626
627 /* desired 4.4336180 actual 4.4336180 clock 107.52 */
628 .dda1_inc = 168,
629 .dda2_inc = 4122, .dda2_size = 27648,
630 .dda3_inc = 67, .dda3_size = 625,
631 .sc_reset = TV_SC_RESET_EVERY_8(2 << 24),
632 .pal_burst = true1,
633
634 .composite_levels = &pal_levels_composite,
635 .composite_color = &pal_csc_composite,
636 .svideo_levels = &pal_levels_svideo,
637 .svideo_color = &pal_csc_svideo,
638
639 .filter_table = filter_table,
640 },
641 {
642 .name = "480p",
643 .clock = 108000,
644 .refresh = 59940,
645 .oversample = 4,
646 .component_only = true1,
647
648 .hsync_end = 64, .hblank_end = 122,
649 .hblank_start = 842, .htotal = 857,
650
651 .progressive = true1, .trilevel_sync = false0,
652
653 .vsync_start_f1 = 12, .vsync_start_f2 = 12,
654 .vsync_len = 12,
655
656 .veq_ena = false0,
657
658 .vi_end_f1 = 44, .vi_end_f2 = 44,
659 .nbr_end = 479,
660
661 .burst_ena = false0,
662
663 .filter_table = filter_table,
664 },
665 {
666 .name = "576p",
667 .clock = 108000,
668 .refresh = 50000,
669 .oversample = 4,
670 .component_only = true1,
671
672 .hsync_end = 64, .hblank_end = 139,
673 .hblank_start = 859, .htotal = 863,
674
675 .progressive = true1, .trilevel_sync = false0,
676
677 .vsync_start_f1 = 10, .vsync_start_f2 = 10,
678 .vsync_len = 10,
679
680 .veq_ena = false0,
681
682 .vi_end_f1 = 48, .vi_end_f2 = 48,
683 .nbr_end = 575,
684
685 .burst_ena = false0,
686
687 .filter_table = filter_table,
688 },
689 {
690 .name = "720p@60Hz",
691 .clock = 148500,
692 .refresh = 60000,
693 .oversample = 2,
694 .component_only = true1,
695
696 .hsync_end = 80, .hblank_end = 300,
697 .hblank_start = 1580, .htotal = 1649,
698
699 .progressive = true1, .trilevel_sync = true1,
700
701 .vsync_start_f1 = 10, .vsync_start_f2 = 10,
702 .vsync_len = 10,
703
704 .veq_ena = false0,
705
706 .vi_end_f1 = 29, .vi_end_f2 = 29,
707 .nbr_end = 719,
708
709 .burst_ena = false0,
710
711 .filter_table = filter_table,
712 },
713 {
714 .name = "720p@50Hz",
715 .clock = 148500,
716 .refresh = 50000,
717 .oversample = 2,
718 .component_only = true1,
719
720 .hsync_end = 80, .hblank_end = 300,
721 .hblank_start = 1580, .htotal = 1979,
722
723 .progressive = true1, .trilevel_sync = true1,
724
725 .vsync_start_f1 = 10, .vsync_start_f2 = 10,
726 .vsync_len = 10,
727
728 .veq_ena = false0,
729
730 .vi_end_f1 = 29, .vi_end_f2 = 29,
731 .nbr_end = 719,
732
733 .burst_ena = false0,
734
735 .filter_table = filter_table,
736 },
737 {
738 .name = "1080i@50Hz",
739 .clock = 148500,
740 .refresh = 50000,
741 .oversample = 2,
742 .component_only = true1,
743
744 .hsync_end = 88, .hblank_end = 235,
745 .hblank_start = 2155, .htotal = 2639,
746
747 .progressive = false0, .trilevel_sync = true1,
748
749 .vsync_start_f1 = 4, .vsync_start_f2 = 5,
750 .vsync_len = 10,
751
752 .veq_ena = true1, .veq_start_f1 = 4,
753 .veq_start_f2 = 4, .veq_len = 10,
754
755
756 .vi_end_f1 = 21, .vi_end_f2 = 22,
757 .nbr_end = 539,
758
759 .burst_ena = false0,
760
761 .filter_table = filter_table,
762 },
763 {
764 .name = "1080i@60Hz",
765 .clock = 148500,
766 .refresh = 60000,
767 .oversample = 2,
768 .component_only = true1,
769
770 .hsync_end = 88, .hblank_end = 235,
771 .hblank_start = 2155, .htotal = 2199,
772
773 .progressive = false0, .trilevel_sync = true1,
774
775 .vsync_start_f1 = 4, .vsync_start_f2 = 5,
776 .vsync_len = 10,
777
778 .veq_ena = true1, .veq_start_f1 = 4,
779 .veq_start_f2 = 4, .veq_len = 10,
780
781
782 .vi_end_f1 = 21, .vi_end_f2 = 22,
783 .nbr_end = 539,
784
785 .burst_ena = false0,
786
787 .filter_table = filter_table,
788 },
789
790 {
791 .name = "1080p@30Hz",
792 .clock = 148500,
793 .refresh = 30000,
794 .oversample = 2,
795 .component_only = true1,
796
797 .hsync_end = 88, .hblank_end = 235,
798 .hblank_start = 2155, .htotal = 2199,
799
800 .progressive = true1, .trilevel_sync = true1,
801
802 .vsync_start_f1 = 8, .vsync_start_f2 = 8,
803 .vsync_len = 10,
804
805 .veq_ena = false0, .veq_start_f1 = 0,
806 .veq_start_f2 = 0, .veq_len = 0,
807
808 .vi_end_f1 = 44, .vi_end_f2 = 44,
809 .nbr_end = 1079,
810
811 .burst_ena = false0,
812
813 .filter_table = filter_table,
814 },
815
816 {
817 .name = "1080p@50Hz",
818 .clock = 148500,
819 .refresh = 50000,
820 .oversample = 1,
821 .component_only = true1,
822
823 .hsync_end = 88, .hblank_end = 235,
824 .hblank_start = 2155, .htotal = 2639,
825
826 .progressive = true1, .trilevel_sync = true1,
827
828 .vsync_start_f1 = 8, .vsync_start_f2 = 8,
829 .vsync_len = 10,
830
831 .veq_ena = false0, .veq_start_f1 = 0,
832 .veq_start_f2 = 0, .veq_len = 0,
833
834 .vi_end_f1 = 44, .vi_end_f2 = 44,
835 .nbr_end = 1079,
836
837 .burst_ena = false0,
838
839 .filter_table = filter_table,
840 },
841
842 {
843 .name = "1080p@60Hz",
844 .clock = 148500,
845 .refresh = 60000,
846 .oversample = 1,
847 .component_only = true1,
848
849 .hsync_end = 88, .hblank_end = 235,
850 .hblank_start = 2155, .htotal = 2199,
851
852 .progressive = true1, .trilevel_sync = true1,
853
854 .vsync_start_f1 = 8, .vsync_start_f2 = 8,
855 .vsync_len = 10,
856
857 .veq_ena = false0, .veq_start_f1 = 0,
858 .veq_start_f2 = 0, .veq_len = 0,
859
860 .vi_end_f1 = 44, .vi_end_f2 = 44,
861 .nbr_end = 1079,
862
863 .burst_ena = false0,
864
865 .filter_table = filter_table,
866 },
867};
868
869struct intel_tv_connector_state {
870 struct drm_connector_state base;
871
872 /*
873 * May need to override the user margins for
874 * gen3 >1024 wide source vertical centering.
875 */
876 struct {
877 u16 top, bottom;
878 } margins;
879
880 bool_Bool bypass_vfilter;
881};
882
883#define to_intel_tv_connector_state(x)({ const __typeof( ((struct intel_tv_connector_state *)0)->
base ) *__mptr = (x); (struct intel_tv_connector_state *)( (char
*)__mptr - __builtin_offsetof(struct intel_tv_connector_state
, base) );})
container_of(x, struct intel_tv_connector_state, base)({ const __typeof( ((struct intel_tv_connector_state *)0)->
base ) *__mptr = (x); (struct intel_tv_connector_state *)( (char
*)__mptr - __builtin_offsetof(struct intel_tv_connector_state
, base) );})
884
885static struct drm_connector_state *
886intel_tv_connector_duplicate_state(struct drm_connector *connector)
887{
888 struct intel_tv_connector_state *state;
889
890 state = kmemdup(connector->state, sizeof(*state), GFP_KERNEL(0x0001 | 0x0004));
891 if (!state)
892 return NULL((void *)0);
893
894 __drm_atomic_helper_connector_duplicate_state(connector, &state->base);
895 return &state->base;
896}
897
898static struct intel_tv *enc_to_tv(struct intel_encoder *encoder)
899{
900 return container_of(encoder, struct intel_tv, base)({ const __typeof( ((struct intel_tv *)0)->base ) *__mptr =
(encoder); (struct intel_tv *)( (char *)__mptr - __builtin_offsetof
(struct intel_tv, base) );})
;
901}
902
903static struct intel_tv *intel_attached_tv(struct intel_connector *connector)
904{
905 return enc_to_tv(intel_attached_encoder(connector));
906}
907
908static bool_Bool
909intel_tv_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe)
910{
911 struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev);
912 u32 tmp = intel_de_read(dev_priv, TV_CTL((const i915_reg_t){ .reg = (0x68000) }));
913
914 *pipe = (tmp & TV_ENC_PIPE_SEL_MASK(1 << 30)) >> TV_ENC_PIPE_SEL_SHIFT30;
915
916 return tmp & TV_ENC_ENABLE(1 << 31);
917}
918
919static void
920intel_enable_tv(struct intel_atomic_state *state,
921 struct intel_encoder *encoder,
922 const struct intel_crtc_state *pipe_config,
923 const struct drm_connector_state *conn_state)
924{
925 struct drm_device *dev = encoder->base.dev;
926 struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(dev);
927
928 /* Prevents vblank waits from timing out in intel_tv_detect_type() */
929 intel_crtc_wait_for_next_vblank(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) );})
);
930
931 intel_de_write(dev_priv, TV_CTL((const i915_reg_t){ .reg = (0x68000) }),
932 intel_de_read(dev_priv, TV_CTL((const i915_reg_t){ .reg = (0x68000) })) | TV_ENC_ENABLE(1 << 31));
933}
934
935static void
936intel_disable_tv(struct intel_atomic_state *state,
937 struct intel_encoder *encoder,
938 const struct intel_crtc_state *old_crtc_state,
939 const struct drm_connector_state *old_conn_state)
940{
941 struct drm_device *dev = encoder->base.dev;
942 struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(dev);
943
944 intel_de_write(dev_priv, TV_CTL((const i915_reg_t){ .reg = (0x68000) }),
945 intel_de_read(dev_priv, TV_CTL((const i915_reg_t){ .reg = (0x68000) })) & ~TV_ENC_ENABLE(1 << 31));
946}
947
948static const struct tv_mode *intel_tv_mode_find(const struct drm_connector_state *conn_state)
949{
950 int format = conn_state->tv.mode;
951
952 return &tv_modes[format];
953}
954
955static enum drm_mode_status
956intel_tv_mode_valid(struct drm_connector *connector,
957 struct drm_display_mode *mode)
958{
959 struct drm_i915_privateinteldrm_softc *i915 = to_i915(connector->dev);
960 const struct tv_mode *tv_mode = intel_tv_mode_find(connector->state);
961 int max_dotclk = i915->max_dotclk_freq;
962 enum drm_mode_status status;
963
964 status = intel_cpu_transcoder_mode_valid(i915, mode);
965 if (status != MODE_OK)
966 return status;
967
968 if (mode->flags & DRM_MODE_FLAG_DBLSCAN(1<<5))
969 return MODE_NO_DBLESCAN;
970
971 if (mode->clock > max_dotclk)
972 return MODE_CLOCK_HIGH;
973
974 /* Ensure TV refresh is close to desired refresh */
975 if (abs(tv_mode->refresh - drm_mode_vrefresh(mode) * 1000) >= 1000)
976 return MODE_CLOCK_RANGE;
977
978 return MODE_OK;
979}
980
981static int
982intel_tv_mode_vdisplay(const struct tv_mode *tv_mode)
983{
984 if (tv_mode->progressive)
985 return tv_mode->nbr_end + 1;
986 else
987 return 2 * (tv_mode->nbr_end + 1);
988}
989
990static void
991intel_tv_mode_to_mode(struct drm_display_mode *mode,
992 const struct tv_mode *tv_mode,
993 int clock)
994{
995 mode->clock = clock / (tv_mode->oversample >> !tv_mode->progressive);
996
997 /*
998 * tv_mode horizontal timings:
999 *
1000 * hsync_end
1001 * | hblank_end
1002 * | | hblank_start
1003 * | | | htotal
1004 * | _______ |
1005 * ____/ \___
1006 * \__/ \
1007 */
1008 mode->hdisplay =
1009 tv_mode->hblank_start - tv_mode->hblank_end;
1010 mode->hsync_start = mode->hdisplay +
1011 tv_mode->htotal - tv_mode->hblank_start;
1012 mode->hsync_end = mode->hsync_start +
1013 tv_mode->hsync_end;
1014 mode->htotal = tv_mode->htotal + 1;
1015
1016 /*
1017 * tv_mode vertical timings:
1018 *
1019 * vsync_start
1020 * | vsync_end
1021 * | | vi_end nbr_end
1022 * | | | |
1023 * | | _______
1024 * \__ ____/ \
1025 * \__/
1026 */
1027 mode->vdisplay = intel_tv_mode_vdisplay(tv_mode);
1028 if (tv_mode->progressive) {
1029 mode->vsync_start = mode->vdisplay +
1030 tv_mode->vsync_start_f1 + 1;
1031 mode->vsync_end = mode->vsync_start +
1032 tv_mode->vsync_len;
1033 mode->vtotal = mode->vdisplay +
1034 tv_mode->vi_end_f1 + 1;
1035 } else {
1036 mode->vsync_start = mode->vdisplay +
1037 tv_mode->vsync_start_f1 + 1 +
1038 tv_mode->vsync_start_f2 + 1;
1039 mode->vsync_end = mode->vsync_start +
1040 2 * tv_mode->vsync_len;
1041 mode->vtotal = mode->vdisplay +
1042 tv_mode->vi_end_f1 + 1 +
1043 tv_mode->vi_end_f2 + 1;
1044 }
1045
1046 /* TV has it's own notion of sync and other mode flags, so clear them. */
1047 mode->flags = 0;
1048
1049 snprintf(mode->name, sizeof(mode->name),
1050 "%dx%d%c (%s)",
1051 mode->hdisplay, mode->vdisplay,
1052 tv_mode->progressive ? 'p' : 'i',
1053 tv_mode->name);
1054}
1055
1056static void intel_tv_scale_mode_horiz(struct drm_display_mode *mode,
1057 int hdisplay, int left_margin,
1058 int right_margin)
1059{
1060 int hsync_start = mode->hsync_start - mode->hdisplay + right_margin;
1061 int hsync_end = mode->hsync_end - mode->hdisplay + right_margin;
1062 int new_htotal = mode->htotal * hdisplay /
1063 (mode->hdisplay - left_margin - right_margin);
1064
1065 mode->clock = mode->clock * new_htotal / mode->htotal;
1066
1067 mode->hdisplay = hdisplay;
1068 mode->hsync_start = hdisplay + hsync_start * new_htotal / mode->htotal;
1069 mode->hsync_end = hdisplay + hsync_end * new_htotal / mode->htotal;
1070 mode->htotal = new_htotal;
1071}
1072
1073static void intel_tv_scale_mode_vert(struct drm_display_mode *mode,
1074 int vdisplay, int top_margin,
1075 int bottom_margin)
1076{
1077 int vsync_start = mode->vsync_start - mode->vdisplay + bottom_margin;
1078 int vsync_end = mode->vsync_end - mode->vdisplay + bottom_margin;
1079 int new_vtotal = mode->vtotal * vdisplay /
1080 (mode->vdisplay - top_margin - bottom_margin);
1081
1082 mode->clock = mode->clock * new_vtotal / mode->vtotal;
1083
1084 mode->vdisplay = vdisplay;
1085 mode->vsync_start = vdisplay + vsync_start * new_vtotal / mode->vtotal;
1086 mode->vsync_end = vdisplay + vsync_end * new_vtotal / mode->vtotal;
1087 mode->vtotal = new_vtotal;
1088}
1089
1090static void
1091intel_tv_get_config(struct intel_encoder *encoder,
1092 struct intel_crtc_state *pipe_config)
1093{
1094 struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev);
1095 struct drm_display_mode *adjusted_mode =
1096 &pipe_config->hw.adjusted_mode;
1097 struct drm_display_mode mode = {};
1098 u32 tv_ctl, hctl1, hctl3, vctl1, vctl2, tmp;
1099 struct tv_mode tv_mode = {};
1100 int hdisplay = adjusted_mode->crtc_hdisplay;
1101 int vdisplay = adjusted_mode->crtc_vdisplay;
1102 int xsize, ysize, xpos, ypos;
1103
1104 pipe_config->output_types |= BIT(INTEL_OUTPUT_TVOUT)(1UL << (INTEL_OUTPUT_TVOUT));
1105
1106 tv_ctl = intel_de_read(dev_priv, TV_CTL((const i915_reg_t){ .reg = (0x68000) }));
1107 hctl1 = intel_de_read(dev_priv, TV_H_CTL_1((const i915_reg_t){ .reg = (0x68030) }));
1108 hctl3 = intel_de_read(dev_priv, TV_H_CTL_3((const i915_reg_t){ .reg = (0x68038) }));
1109 vctl1 = intel_de_read(dev_priv, TV_V_CTL_1((const i915_reg_t){ .reg = (0x6803c) }));
1110 vctl2 = intel_de_read(dev_priv, TV_V_CTL_2((const i915_reg_t){ .reg = (0x68040) }));
1111
1112 tv_mode.htotal = (hctl1 & TV_HTOTAL_MASK0x00001fff) >> TV_HTOTAL_SHIFT0;
1113 tv_mode.hsync_end = (hctl1 & TV_HSYNC_END_MASK0x1fff0000) >> TV_HSYNC_END_SHIFT16;
1114
1115 tv_mode.hblank_start = (hctl3 & TV_HBLANK_START_MASK0x0001fff) >> TV_HBLANK_START_SHIFT0;
1116 tv_mode.hblank_end = (hctl3 & TV_HSYNC_END_MASK0x1fff0000) >> TV_HBLANK_END_SHIFT16;
1117
1118 tv_mode.nbr_end = (vctl1 & TV_NBR_END_MASK0x07ff0000) >> TV_NBR_END_SHIFT16;
1119 tv_mode.vi_end_f1 = (vctl1 & TV_VI_END_F1_MASK0x00003f00) >> TV_VI_END_F1_SHIFT8;
1120 tv_mode.vi_end_f2 = (vctl1 & TV_VI_END_F2_MASK0x0000003f) >> TV_VI_END_F2_SHIFT0;
1121
1122 tv_mode.vsync_len = (vctl2 & TV_VSYNC_LEN_MASK0x07ff0000) >> TV_VSYNC_LEN_SHIFT16;
1123 tv_mode.vsync_start_f1 = (vctl2 & TV_VSYNC_START_F1_MASK0x00007f00) >> TV_VSYNC_START_F1_SHIFT8;
1124 tv_mode.vsync_start_f2 = (vctl2 & TV_VSYNC_START_F2_MASK0x0000007f) >> TV_VSYNC_START_F2_SHIFT0;
1125
1126 tv_mode.clock = pipe_config->port_clock;
1127
1128 tv_mode.progressive = tv_ctl & TV_PROGRESSIVE(1 << 17);
1129
1130 switch (tv_ctl & TV_OVERSAMPLE_MASK(3 << 18)) {
1131 case TV_OVERSAMPLE_8X(3 << 18):
1132 tv_mode.oversample = 8;
1133 break;
1134 case TV_OVERSAMPLE_4X(0 << 18):
1135 tv_mode.oversample = 4;
1136 break;
1137 case TV_OVERSAMPLE_2X(1 << 18):
1138 tv_mode.oversample = 2;
1139 break;
1140 default:
1141 tv_mode.oversample = 1;
1142 break;
1143 }
1144
1145 tmp = intel_de_read(dev_priv, TV_WIN_POS((const i915_reg_t){ .reg = (0x68070) }));
1146 xpos = tmp >> 16;
1147 ypos = tmp & 0xffff;
1148
1149 tmp = intel_de_read(dev_priv, TV_WIN_SIZE((const i915_reg_t){ .reg = (0x68074) }));
1150 xsize = tmp >> 16;
1151 ysize = tmp & 0xffff;
1152
1153 intel_tv_mode_to_mode(&mode, &tv_mode, pipe_config->port_clock);
1154
1155 drm_dbg_kms(&dev_priv->drm, "TV mode: " DRM_MODE_FMT "\n",__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_KMS, "TV mode: " "\"%s\": %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x"
"\n", (&mode)->name, drm_mode_vrefresh(&mode), (&
mode)->clock, (&mode)->hdisplay, (&mode)->hsync_start
, (&mode)->hsync_end, (&mode)->htotal, (&mode
)->vdisplay, (&mode)->vsync_start, (&mode)->
vsync_end, (&mode)->vtotal, (&mode)->type, (&
mode)->flags)
1156 DRM_MODE_ARG(&mode))__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_KMS, "TV mode: " "\"%s\": %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x"
"\n", (&mode)->name, drm_mode_vrefresh(&mode), (&
mode)->clock, (&mode)->hdisplay, (&mode)->hsync_start
, (&mode)->hsync_end, (&mode)->htotal, (&mode
)->vdisplay, (&mode)->vsync_start, (&mode)->
vsync_end, (&mode)->vtotal, (&mode)->type, (&
mode)->flags)
;
1157
1158 intel_tv_scale_mode_horiz(&mode, hdisplay,
1159 xpos, mode.hdisplay - xsize - xpos);
1160 intel_tv_scale_mode_vert(&mode, vdisplay,
1161 ypos, mode.vdisplay - ysize - ypos);
1162
1163 adjusted_mode->crtc_clock = mode.clock;
1164 if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE(1<<4))
1165 adjusted_mode->crtc_clock /= 2;
1166
1167 /* pixel counter doesn't work on i965gm TV output */
1168 if (IS_I965GM(dev_priv)IS_PLATFORM(dev_priv, INTEL_I965GM))
1169 pipe_config->mode_flags |=
1170 I915_MODE_FLAG_USE_SCANLINE_COUNTER(1<<2);
1171}
1172
1173static bool_Bool intel_tv_source_too_wide(struct drm_i915_privateinteldrm_softc *dev_priv,
1174 int hdisplay)
1175{
1176 return DISPLAY_VER(dev_priv)((&(dev_priv)->__runtime)->display.ip.ver) == 3 && hdisplay > 1024;
1177}
1178
1179static bool_Bool intel_tv_vert_scaling(const struct drm_display_mode *tv_mode,
1180 const struct drm_connector_state *conn_state,
1181 int vdisplay)
1182{
1183 return tv_mode->crtc_vdisplay -
1184 conn_state->tv.margins.top -
1185 conn_state->tv.margins.bottom !=
1186 vdisplay;
1187}
1188
1189static int
1190intel_tv_compute_config(struct intel_encoder *encoder,
1191 struct intel_crtc_state *pipe_config,
1192 struct drm_connector_state *conn_state)
1193{
1194 struct intel_atomic_state *state =
1195 to_intel_atomic_state(pipe_config->uapi.state)({ const __typeof( ((struct intel_atomic_state *)0)->base )
*__mptr = (pipe_config->uapi.state); (struct intel_atomic_state
*)( (char *)__mptr - __builtin_offsetof(struct intel_atomic_state
, base) );})
;
1196 struct intel_crtc *crtc = 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) );})
;
1197 struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev);
1198 struct intel_tv_connector_state *tv_conn_state =
1199 to_intel_tv_connector_state(conn_state)({ const __typeof( ((struct intel_tv_connector_state *)0)->
base ) *__mptr = (conn_state); (struct intel_tv_connector_state
*)( (char *)__mptr - __builtin_offsetof(struct intel_tv_connector_state
, base) );})
;
1200 const struct tv_mode *tv_mode = intel_tv_mode_find(conn_state);
1201 struct drm_display_mode *adjusted_mode =
1202 &pipe_config->hw.adjusted_mode;
1203 int hdisplay = adjusted_mode->crtc_hdisplay;
1204 int vdisplay = adjusted_mode->crtc_vdisplay;
1205 int ret;
1206
1207 if (!tv_mode)
1208 return -EINVAL22;
1209
1210 if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN(1<<5))
1211 return -EINVAL22;
1212
1213 pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
1214
1215 drm_dbg_kms(&dev_priv->drm, "forcing bpc to 8 for TV\n")__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_KMS, "forcing bpc to 8 for TV\n"
)
;
1216 pipe_config->pipe_bpp = 8*3;
1217
1218 pipe_config->port_clock = tv_mode->clock;
1219
1220 ret = intel_dpll_crtc_compute_clock(state, crtc);
1221 if (ret)
1222 return ret;
1223
1224 pipe_config->clock_set = true1;
1225
1226 intel_tv_mode_to_mode(adjusted_mode, tv_mode, pipe_config->port_clock);
1227 drm_mode_set_crtcinfo(adjusted_mode, 0);
1228
1229 if (intel_tv_source_too_wide(dev_priv, hdisplay) ||
1230 !intel_tv_vert_scaling(adjusted_mode, conn_state, vdisplay)) {
1231 int extra, top, bottom;
1232
1233 extra = adjusted_mode->crtc_vdisplay - vdisplay;
1234
1235 if (extra < 0) {
1236 drm_dbg_kms(&dev_priv->drm,__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_KMS, "No vertical scaling for >1024 pixel wide modes\n"
)
1237 "No vertical scaling for >1024 pixel wide modes\n")__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_KMS, "No vertical scaling for >1024 pixel wide modes\n"
)
;
1238 return -EINVAL22;
1239 }
1240
1241 /* Need to turn off the vertical filter and center the image */
1242
1243 /* Attempt to maintain the relative sizes of the margins */
1244 top = conn_state->tv.margins.top;
1245 bottom = conn_state->tv.margins.bottom;
1246
1247 if (top + bottom)
1248 top = extra * top / (top + bottom);
1249 else
1250 top = extra / 2;
1251 bottom = extra - top;
1252
1253 tv_conn_state->margins.top = top;
1254 tv_conn_state->margins.bottom = bottom;
1255
1256 tv_conn_state->bypass_vfilter = true1;
1257
1258 if (!tv_mode->progressive) {
1259 adjusted_mode->clock /= 2;
1260 adjusted_mode->crtc_clock /= 2;
1261 adjusted_mode->flags |= DRM_MODE_FLAG_INTERLACE(1<<4);
1262 }
1263 } else {
1264 tv_conn_state->margins.top = conn_state->tv.margins.top;
1265 tv_conn_state->margins.bottom = conn_state->tv.margins.bottom;
1266
1267 tv_conn_state->bypass_vfilter = false0;
1268 }
1269
1270 drm_dbg_kms(&dev_priv->drm, "TV mode: " DRM_MODE_FMT "\n",__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_KMS, "TV mode: " "\"%s\": %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x"
"\n", (adjusted_mode)->name, drm_mode_vrefresh(adjusted_mode
), (adjusted_mode)->clock, (adjusted_mode)->hdisplay, (
adjusted_mode)->hsync_start, (adjusted_mode)->hsync_end
, (adjusted_mode)->htotal, (adjusted_mode)->vdisplay, (
adjusted_mode)->vsync_start, (adjusted_mode)->vsync_end
, (adjusted_mode)->vtotal, (adjusted_mode)->type, (adjusted_mode
)->flags)
1271 DRM_MODE_ARG(adjusted_mode))__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_KMS, "TV mode: " "\"%s\": %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x"
"\n", (adjusted_mode)->name, drm_mode_vrefresh(adjusted_mode
), (adjusted_mode)->clock, (adjusted_mode)->hdisplay, (
adjusted_mode)->hsync_start, (adjusted_mode)->hsync_end
, (adjusted_mode)->htotal, (adjusted_mode)->vdisplay, (
adjusted_mode)->vsync_start, (adjusted_mode)->vsync_end
, (adjusted_mode)->vtotal, (adjusted_mode)->type, (adjusted_mode
)->flags)
;
1272
1273 /*
1274 * The pipe scanline counter behaviour looks as follows when
1275 * using the TV encoder:
1276 *
1277 * time ->
1278 *
1279 * dsl=vtotal-1 | |
1280 * || ||
1281 * ___| | ___| |
1282 * / | / |
1283 * / | / |
1284 * dsl=0 ___/ |_____/ |
1285 * | | | | | |
1286 * ^ ^ ^ ^ ^
1287 * | | | | pipe vblank/first part of tv vblank
1288 * | | | bottom margin
1289 * | | active
1290 * | top margin
1291 * remainder of tv vblank
1292 *
1293 * When the TV encoder is used the pipe wants to run faster
1294 * than expected rate. During the active portion the TV
1295 * encoder stalls the pipe every few lines to keep it in
1296 * check. When the TV encoder reaches the bottom margin the
1297 * pipe simply stops. Once we reach the TV vblank the pipe is
1298 * no longer stalled and it runs at the max rate (apparently
1299 * oversample clock on gen3, cdclk on gen4). Once the pipe
1300 * reaches the pipe vtotal the pipe stops for the remainder
1301 * of the TV vblank/top margin. The pipe starts up again when
1302 * the TV encoder exits the top margin.
1303 *
1304 * To avoid huge hassles for vblank timestamping we scale
1305 * the pipe timings as if the pipe always runs at the average
1306 * rate it maintains during the active period. This also
1307 * gives us a reasonable guesstimate as to the pixel rate.
1308 * Due to the variation in the actual pipe speed the scanline
1309 * counter will give us slightly erroneous results during the
1310 * TV vblank/margins. But since vtotal was selected such that
1311 * it matches the average rate of the pipe during the active
1312 * portion the error shouldn't cause any serious grief to
1313 * vblank timestamps.
1314 *
1315 * For posterity here is the empirically derived formula
1316 * that gives us the maximum length of the pipe vblank
1317 * we can use without causing display corruption. Following
1318 * this would allow us to have a ticking scanline counter
1319 * everywhere except during the bottom margin (there the
1320 * pipe always stops). Ie. this would eliminate the second
1321 * flat portion of the above graph. However this would also
1322 * complicate vblank timestamping as the pipe vtotal would
1323 * no longer match the average rate the pipe runs at during
1324 * the active portion. Hence following this formula seems
1325 * more trouble that it's worth.
1326 *
1327 * if (GRAPHICS_VER(dev_priv) == 4) {
1328 * num = cdclk * (tv_mode->oversample >> !tv_mode->progressive);
1329 * den = tv_mode->clock;
1330 * } else {
1331 * num = tv_mode->oversample >> !tv_mode->progressive;
1332 * den = 1;
1333 * }
1334 * max_pipe_vblank_len ~=
1335 * (num * tv_htotal * (tv_vblank_len + top_margin)) /
1336 * (den * pipe_htotal);
1337 */
1338 intel_tv_scale_mode_horiz(adjusted_mode, hdisplay,
1339 conn_state->tv.margins.left,
1340 conn_state->tv.margins.right);
1341 intel_tv_scale_mode_vert(adjusted_mode, vdisplay,
1342 tv_conn_state->margins.top,
1343 tv_conn_state->margins.bottom);
1344 drm_mode_set_crtcinfo(adjusted_mode, 0);
1345 adjusted_mode->name[0] = '\0';
1346
1347 /* pixel counter doesn't work on i965gm TV output */
1348 if (IS_I965GM(dev_priv)IS_PLATFORM(dev_priv, INTEL_I965GM))
1349 pipe_config->mode_flags |=
1350 I915_MODE_FLAG_USE_SCANLINE_COUNTER(1<<2);
1351
1352 return 0;
1353}
1354
1355static void
1356set_tv_mode_timings(struct drm_i915_privateinteldrm_softc *dev_priv,
1357 const struct tv_mode *tv_mode,
1358 bool_Bool burst_ena)
1359{
1360 u32 hctl1, hctl2, hctl3;
1361 u32 vctl1, vctl2, vctl3, vctl4, vctl5, vctl6, vctl7;
1362
1363 hctl1 = (tv_mode->hsync_end << TV_HSYNC_END_SHIFT16) |
1364 (tv_mode->htotal << TV_HTOTAL_SHIFT0);
1365
1366 hctl2 = (tv_mode->hburst_start << 16) |
1367 (tv_mode->hburst_len << TV_HBURST_LEN_SHIFT0);
1368
1369 if (burst_ena)
1370 hctl2 |= TV_BURST_ENA(1 << 31);
1371
1372 hctl3 = (tv_mode->hblank_start << TV_HBLANK_START_SHIFT0) |
1373 (tv_mode->hblank_end << TV_HBLANK_END_SHIFT16);
1374
1375 vctl1 = (tv_mode->nbr_end << TV_NBR_END_SHIFT16) |
1376 (tv_mode->vi_end_f1 << TV_VI_END_F1_SHIFT8) |
1377 (tv_mode->vi_end_f2 << TV_VI_END_F2_SHIFT0);
1378
1379 vctl2 = (tv_mode->vsync_len << TV_VSYNC_LEN_SHIFT16) |
1380 (tv_mode->vsync_start_f1 << TV_VSYNC_START_F1_SHIFT8) |
1381 (tv_mode->vsync_start_f2 << TV_VSYNC_START_F2_SHIFT0);
1382
1383 vctl3 = (tv_mode->veq_len << TV_VEQ_LEN_SHIFT16) |
1384 (tv_mode->veq_start_f1 << TV_VEQ_START_F1_SHIFT8) |
1385 (tv_mode->veq_start_f2 << TV_VEQ_START_F2_SHIFT0);
1386
1387 if (tv_mode->veq_ena)
1388 vctl3 |= TV_EQUAL_ENA(1 << 31);
1389
1390 vctl4 = (tv_mode->vburst_start_f1 << TV_VBURST_START_F1_SHIFT16) |
1391 (tv_mode->vburst_end_f1 << TV_VBURST_END_F1_SHIFT0);
1392
1393 vctl5 = (tv_mode->vburst_start_f2 << TV_VBURST_START_F2_SHIFT16) |
1394 (tv_mode->vburst_end_f2 << TV_VBURST_END_F2_SHIFT0);
1395
1396 vctl6 = (tv_mode->vburst_start_f3 << TV_VBURST_START_F3_SHIFT16) |
1397 (tv_mode->vburst_end_f3 << TV_VBURST_END_F3_SHIFT0);
1398
1399 vctl7 = (tv_mode->vburst_start_f4 << TV_VBURST_START_F4_SHIFT16) |
1400 (tv_mode->vburst_end_f4 << TV_VBURST_END_F4_SHIFT0);
1401
1402 intel_de_write(dev_priv, TV_H_CTL_1((const i915_reg_t){ .reg = (0x68030) }), hctl1);
1403 intel_de_write(dev_priv, TV_H_CTL_2((const i915_reg_t){ .reg = (0x68034) }), hctl2);
1404 intel_de_write(dev_priv, TV_H_CTL_3((const i915_reg_t){ .reg = (0x68038) }), hctl3);
1405 intel_de_write(dev_priv, TV_V_CTL_1((const i915_reg_t){ .reg = (0x6803c) }), vctl1);
1406 intel_de_write(dev_priv, TV_V_CTL_2((const i915_reg_t){ .reg = (0x68040) }), vctl2);
1407 intel_de_write(dev_priv, TV_V_CTL_3((const i915_reg_t){ .reg = (0x68044) }), vctl3);
1408 intel_de_write(dev_priv, TV_V_CTL_4((const i915_reg_t){ .reg = (0x68048) }), vctl4);
1409 intel_de_write(dev_priv, TV_V_CTL_5((const i915_reg_t){ .reg = (0x6804c) }), vctl5);
1410 intel_de_write(dev_priv, TV_V_CTL_6((const i915_reg_t){ .reg = (0x68050) }), vctl6);
1411 intel_de_write(dev_priv, TV_V_CTL_7((const i915_reg_t){ .reg = (0x68054) }), vctl7);
1412}
1413
1414static void set_color_conversion(struct drm_i915_privateinteldrm_softc *dev_priv,
1415 const struct color_conversion *color_conversion)
1416{
1417 if (!color_conversion)
1418 return;
1419
1420 intel_de_write(dev_priv, TV_CSC_Y((const i915_reg_t){ .reg = (0x68010) }),
1421 (color_conversion->ry << 16) | color_conversion->gy);
1422 intel_de_write(dev_priv, TV_CSC_Y2((const i915_reg_t){ .reg = (0x68014) }),
1423 (color_conversion->by << 16) | color_conversion->ay);
1424 intel_de_write(dev_priv, TV_CSC_U((const i915_reg_t){ .reg = (0x68018) }),
1425 (color_conversion->ru << 16) | color_conversion->gu);
1426 intel_de_write(dev_priv, TV_CSC_U2((const i915_reg_t){ .reg = (0x6801c) }),
1427 (color_conversion->bu << 16) | color_conversion->au);
1428 intel_de_write(dev_priv, TV_CSC_V((const i915_reg_t){ .reg = (0x68020) }),
1429 (color_conversion->rv << 16) | color_conversion->gv);
1430 intel_de_write(dev_priv, TV_CSC_V2((const i915_reg_t){ .reg = (0x68024) }),
1431 (color_conversion->bv << 16) | color_conversion->av);
1432}
1433
1434static void intel_tv_pre_enable(struct intel_atomic_state *state,
1435 struct intel_encoder *encoder,
1436 const struct intel_crtc_state *pipe_config,
1437 const struct drm_connector_state *conn_state)
1438{
1439 struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev);
1440 struct intel_crtc *crtc = 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) );})
;
1441 struct intel_tv *intel_tv = enc_to_tv(encoder);
1442 const struct intel_tv_connector_state *tv_conn_state =
1443 to_intel_tv_connector_state(conn_state)({ const __typeof( ((struct intel_tv_connector_state *)0)->
base ) *__mptr = (conn_state); (struct intel_tv_connector_state
*)( (char *)__mptr - __builtin_offsetof(struct intel_tv_connector_state
, base) );})
;
1444 const struct tv_mode *tv_mode = intel_tv_mode_find(conn_state);
1445 u32 tv_ctl, tv_filter_ctl;
1446 u32 scctl1, scctl2, scctl3;
1447 int i, j;
1448 const struct video_levels *video_levels;
1449 const struct color_conversion *color_conversion;
1450 bool_Bool burst_ena;
1451 int xpos, ypos;
1452 unsigned int xsize, ysize;
1453
1454 if (!tv_mode)
1455 return; /* can't happen (mode_prepare prevents this) */
1456
1457 tv_ctl = intel_de_read(dev_priv, TV_CTL((const i915_reg_t){ .reg = (0x68000) }));
1458 tv_ctl &= TV_CTL_SAVE((1 << 11) | (3 << 9) | (7 << 6) | 0xf);
1459
1460 switch (intel_tv->type) {
1461 default:
1462 case DRM_MODE_CONNECTOR_Unknown0:
1463 case DRM_MODE_CONNECTOR_Composite5:
1464 tv_ctl |= TV_ENC_OUTPUT_COMPOSITE(0 << 28);
1465 video_levels = tv_mode->composite_levels;
1466 color_conversion = tv_mode->composite_color;
1467 burst_ena = tv_mode->burst_ena;
1468 break;
1469 case DRM_MODE_CONNECTOR_Component8:
1470 tv_ctl |= TV_ENC_OUTPUT_COMPONENT(2 << 28);
1471 video_levels = &component_levels;
1472 if (tv_mode->burst_ena)
1473 color_conversion = &sdtv_csc_yprpb;
1474 else
1475 color_conversion = &hdtv_csc_yprpb;
1476 burst_ena = false0;
1477 break;
1478 case DRM_MODE_CONNECTOR_SVIDEO6:
1479 tv_ctl |= TV_ENC_OUTPUT_SVIDEO(1 << 28);
1480 video_levels = tv_mode->svideo_levels;
1481 color_conversion = tv_mode->svideo_color;
1482 burst_ena = tv_mode->burst_ena;
1483 break;
1484 }
1485
1486 tv_ctl |= TV_ENC_PIPE_SEL(crtc->pipe)((crtc->pipe) << 30);
1487
1488 switch (tv_mode->oversample) {
1489 case 8:
1490 tv_ctl |= TV_OVERSAMPLE_8X(3 << 18);
1491 break;
1492 case 4:
1493 tv_ctl |= TV_OVERSAMPLE_4X(0 << 18);
1494 break;
1495 case 2:
1496 tv_ctl |= TV_OVERSAMPLE_2X(1 << 18);
1497 break;
1498 default:
1499 tv_ctl |= TV_OVERSAMPLE_NONE(2 << 18);
1500 break;
1501 }
1502
1503 if (tv_mode->progressive)
1504 tv_ctl |= TV_PROGRESSIVE(1 << 17);
1505 if (tv_mode->trilevel_sync)
1506 tv_ctl |= TV_TRILEVEL_SYNC(1 << 21);
1507 if (tv_mode->pal_burst)
1508 tv_ctl |= TV_PAL_BURST(1 << 16);
1509
1510 scctl1 = 0;
1511 if (tv_mode->dda1_inc)
1512 scctl1 |= TV_SC_DDA1_EN(1 << 31);
1513 if (tv_mode->dda2_inc)
1514 scctl1 |= TV_SC_DDA2_EN(1 << 30);
1515 if (tv_mode->dda3_inc)
1516 scctl1 |= TV_SC_DDA3_EN(1 << 29);
1517 scctl1 |= tv_mode->sc_reset;
1518 if (video_levels)
1519 scctl1 |= video_levels->burst << TV_BURST_LEVEL_SHIFT16;
1520 scctl1 |= tv_mode->dda1_inc << TV_SCDDA1_INC_SHIFT0;
1521
1522 scctl2 = tv_mode->dda2_size << TV_SCDDA2_SIZE_SHIFT16 |
1523 tv_mode->dda2_inc << TV_SCDDA2_INC_SHIFT0;
1524
1525 scctl3 = tv_mode->dda3_size << TV_SCDDA3_SIZE_SHIFT16 |
1526 tv_mode->dda3_inc << TV_SCDDA3_INC_SHIFT0;
1527
1528 /* Enable two fixes for the chips that need them. */
1529 if (IS_I915GM(dev_priv)IS_PLATFORM(dev_priv, INTEL_I915GM))
1530 tv_ctl |= TV_ENC_C0_FIX(1 << 10) | TV_ENC_SDP_FIX(1 << 11);
1531
1532 set_tv_mode_timings(dev_priv, tv_mode, burst_ena);
1533
1534 intel_de_write(dev_priv, TV_SC_CTL_1((const i915_reg_t){ .reg = (0x68060) }), scctl1);
1535 intel_de_write(dev_priv, TV_SC_CTL_2((const i915_reg_t){ .reg = (0x68064) }), scctl2);
1536 intel_de_write(dev_priv, TV_SC_CTL_3((const i915_reg_t){ .reg = (0x68068) }), scctl3);
1537
1538 set_color_conversion(dev_priv, color_conversion);
1539
1540 if (DISPLAY_VER(dev_priv)((&(dev_priv)->__runtime)->display.ip.ver) >= 4)
1541 intel_de_write(dev_priv, TV_CLR_KNOBS((const i915_reg_t){ .reg = (0x68028) }), 0x00404000);
1542 else
1543 intel_de_write(dev_priv, TV_CLR_KNOBS((const i915_reg_t){ .reg = (0x68028) }), 0x00606000);
1544
1545 if (video_levels)
1546 intel_de_write(dev_priv, TV_CLR_LEVEL((const i915_reg_t){ .reg = (0x6802c) }),
1547 ((video_levels->black << TV_BLACK_LEVEL_SHIFT16) | (video_levels->blank << TV_BLANK_LEVEL_SHIFT0)));
1548
1549 assert_transcoder_disabled(dev_priv, pipe_config->cpu_transcoder)assert_transcoder(dev_priv, pipe_config->cpu_transcoder, 0
)
;
1550
1551 /* Filter ctl must be set before TV_WIN_SIZE */
1552 tv_filter_ctl = TV_AUTO_SCALE(1 << 31);
1553 if (tv_conn_state->bypass_vfilter)
1554 tv_filter_ctl |= TV_V_FILTER_BYPASS(1 << 29);
1555 intel_de_write(dev_priv, TV_FILTER_CTL_1((const i915_reg_t){ .reg = (0x68080) }), tv_filter_ctl);
1556
1557 xsize = tv_mode->hblank_start - tv_mode->hblank_end;
1558 ysize = intel_tv_mode_vdisplay(tv_mode);
1559
1560 xpos = conn_state->tv.margins.left;
1561 ypos = tv_conn_state->margins.top;
1562 xsize -= (conn_state->tv.margins.left +
1563 conn_state->tv.margins.right);
1564 ysize -= (tv_conn_state->margins.top +
1565 tv_conn_state->margins.bottom);
1566 intel_de_write(dev_priv, TV_WIN_POS((const i915_reg_t){ .reg = (0x68070) }), (xpos << 16) | ypos);
1567 intel_de_write(dev_priv, TV_WIN_SIZE((const i915_reg_t){ .reg = (0x68074) }), (xsize << 16) | ysize);
1568
1569 j = 0;
1570 for (i = 0; i < 60; i++)
1571 intel_de_write(dev_priv, TV_H_LUMA(i)((const i915_reg_t){ .reg = (0x68100 + (i) * 4) }),
1572 tv_mode->filter_table[j++]);
1573 for (i = 0; i < 60; i++)
1574 intel_de_write(dev_priv, TV_H_CHROMA(i)((const i915_reg_t){ .reg = (0x68200 + (i) * 4) }),
1575 tv_mode->filter_table[j++]);
1576 for (i = 0; i < 43; i++)
1577 intel_de_write(dev_priv, TV_V_LUMA(i)((const i915_reg_t){ .reg = (0x68300 + (i) * 4) }),
1578 tv_mode->filter_table[j++]);
1579 for (i = 0; i < 43; i++)
1580 intel_de_write(dev_priv, TV_V_CHROMA(i)((const i915_reg_t){ .reg = (0x68400 + (i) * 4) }),
1581 tv_mode->filter_table[j++]);
1582 intel_de_write(dev_priv, TV_DAC((const i915_reg_t){ .reg = (0x68004) }),
1583 intel_de_read(dev_priv, TV_DAC((const i915_reg_t){ .reg = (0x68004) })) & TV_DAC_SAVE0x00ffff00);
1584 intel_de_write(dev_priv, TV_CTL((const i915_reg_t){ .reg = (0x68000) }), tv_ctl);
1585}
1586
1587static int
1588intel_tv_detect_type(struct intel_tv *intel_tv,
1589 struct drm_connector *connector)
1590{
1591 struct intel_crtc *crtc = to_intel_crtc(connector->state->crtc)({ const __typeof( ((struct intel_crtc *)0)->base ) *__mptr
= (connector->state->crtc); (struct intel_crtc *)( (char
*)__mptr - __builtin_offsetof(struct intel_crtc, base) );})
;
1592 struct drm_device *dev = connector->dev;
1593 struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(dev);
1594 u32 tv_ctl, save_tv_ctl;
1595 u32 tv_dac, save_tv_dac;
1596 int type;
1597
1598 /* Disable TV interrupts around load detect or we'll recurse */
1599 if (connector->polled & DRM_CONNECTOR_POLL_HPD(1 << 0)) {
1600 spin_lock_irq(&dev_priv->irq_lock)mtx_enter(&dev_priv->irq_lock);
1601 i915_disable_pipestat(dev_priv, 0,
1602 PIPE_HOTPLUG_INTERRUPT_STATUS(1UL << 10) |
1603 PIPE_HOTPLUG_TV_INTERRUPT_STATUS(1UL << 2));
1604 spin_unlock_irq(&dev_priv->irq_lock)mtx_leave(&dev_priv->irq_lock);
1605 }
1606
1607 save_tv_dac = tv_dac = intel_de_read(dev_priv, TV_DAC((const i915_reg_t){ .reg = (0x68004) }));
1608 save_tv_ctl = tv_ctl = intel_de_read(dev_priv, TV_CTL((const i915_reg_t){ .reg = (0x68000) }));
1609
1610 /* Poll for TV detection */
1611 tv_ctl &= ~(TV_ENC_ENABLE(1 << 31) | TV_ENC_PIPE_SEL_MASK(1 << 30) | TV_TEST_MODE_MASK(7 << 0));
1612 tv_ctl |= TV_TEST_MODE_MONITOR_DETECT(7 << 0);
1613 tv_ctl |= TV_ENC_PIPE_SEL(crtc->pipe)((crtc->pipe) << 30);
1614
1615 tv_dac &= ~(TVDAC_SENSE_MASK(7 << 28) | DAC_A_MASK(3 << 4) | DAC_B_MASK(3 << 2) | DAC_C_MASK(3 << 0));
1616 tv_dac |= (TVDAC_STATE_CHG_EN(1 << 27) |
1617 TVDAC_A_SENSE_CTL(1 << 26) |
1618 TVDAC_B_SENSE_CTL(1 << 25) |
1619 TVDAC_C_SENSE_CTL(1 << 24) |
1620 DAC_CTL_OVERRIDE(1 << 7) |
1621 DAC_A_0_7_V(2 << 4) |
1622 DAC_B_0_7_V(2 << 2) |
1623 DAC_C_0_7_V(2 << 0));
1624
1625
1626 /*
1627 * The TV sense state should be cleared to zero on cantiga platform. Otherwise
1628 * the TV is misdetected. This is hardware requirement.
1629 */
1630 if (IS_GM45(dev_priv)IS_PLATFORM(dev_priv, INTEL_GM45))
1631 tv_dac &= ~(TVDAC_STATE_CHG_EN(1 << 27) | TVDAC_A_SENSE_CTL(1 << 26) |
1632 TVDAC_B_SENSE_CTL(1 << 25) | TVDAC_C_SENSE_CTL(1 << 24));
1633
1634 intel_de_write(dev_priv, TV_CTL((const i915_reg_t){ .reg = (0x68000) }), tv_ctl);
1635 intel_de_write(dev_priv, TV_DAC((const i915_reg_t){ .reg = (0x68004) }), tv_dac);
1636 intel_de_posting_read(dev_priv, TV_DAC((const i915_reg_t){ .reg = (0x68004) }));
1637
1638 intel_crtc_wait_for_next_vblank(crtc);
1639
1640 type = -1;
Value stored to 'type' is never read
1641 tv_dac = intel_de_read(dev_priv, TV_DAC((const i915_reg_t){ .reg = (0x68004) }));
1642 drm_dbg_kms(&dev_priv->drm, "TV detected: %x, %x\n", tv_ctl, tv_dac)__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_KMS, "TV detected: %x, %x\n"
, tv_ctl, tv_dac)
;
1643 /*
1644 * A B C
1645 * 0 1 1 Composite
1646 * 1 0 X svideo
1647 * 0 0 0 Component
1648 */
1649 if ((tv_dac & TVDAC_SENSE_MASK(7 << 28)) == (TVDAC_B_SENSE(1 << 29) | TVDAC_C_SENSE(1 << 28))) {
1650 drm_dbg_kms(&dev_priv->drm,__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_KMS, "Detected Composite TV connection\n"
)
1651 "Detected Composite TV connection\n")__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_KMS, "Detected Composite TV connection\n"
)
;
1652 type = DRM_MODE_CONNECTOR_Composite5;
1653 } else if ((tv_dac & (TVDAC_A_SENSE(1 << 30)|TVDAC_B_SENSE(1 << 29))) == TVDAC_A_SENSE(1 << 30)) {
1654 drm_dbg_kms(&dev_priv->drm,__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_KMS, "Detected S-Video TV connection\n"
)
1655 "Detected S-Video TV connection\n")__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_KMS, "Detected S-Video TV connection\n"
)
;
1656 type = DRM_MODE_CONNECTOR_SVIDEO6;
1657 } else if ((tv_dac & TVDAC_SENSE_MASK(7 << 28)) == 0) {
1658 drm_dbg_kms(&dev_priv->drm,__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_KMS, "Detected Component TV connection\n"
)
1659 "Detected Component TV connection\n")__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_KMS, "Detected Component TV connection\n"
)
;
1660 type = DRM_MODE_CONNECTOR_Component8;
1661 } else {
1662 drm_dbg_kms(&dev_priv->drm, "Unrecognised TV connection\n")__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_KMS, "Unrecognised TV connection\n"
)
;
1663 type = -1;
1664 }
1665
1666 intel_de_write(dev_priv, TV_DAC((const i915_reg_t){ .reg = (0x68004) }), save_tv_dac & ~TVDAC_STATE_CHG_EN(1 << 27));
1667 intel_de_write(dev_priv, TV_CTL((const i915_reg_t){ .reg = (0x68000) }), save_tv_ctl);
1668 intel_de_posting_read(dev_priv, TV_CTL((const i915_reg_t){ .reg = (0x68000) }));
1669
1670 /* For unknown reasons the hw barfs if we don't do this vblank wait. */
1671 intel_crtc_wait_for_next_vblank(crtc);
1672
1673 /* Restore interrupt config */
1674 if (connector->polled & DRM_CONNECTOR_POLL_HPD(1 << 0)) {
1675 spin_lock_irq(&dev_priv->irq_lock)mtx_enter(&dev_priv->irq_lock);
1676 i915_enable_pipestat(dev_priv, 0,
1677 PIPE_HOTPLUG_INTERRUPT_STATUS(1UL << 10) |
1678 PIPE_HOTPLUG_TV_INTERRUPT_STATUS(1UL << 2));
1679 spin_unlock_irq(&dev_priv->irq_lock)mtx_leave(&dev_priv->irq_lock);
1680 }
1681
1682 return type;
1683}
1684
1685/*
1686 * Here we set accurate tv format according to connector type
1687 * i.e Component TV should not be assigned by NTSC or PAL
1688 */
1689static void intel_tv_find_better_format(struct drm_connector *connector)
1690{
1691 struct intel_tv *intel_tv = intel_attached_tv(to_intel_connector(connector)({ const __typeof( ((struct intel_connector *)0)->base ) *
__mptr = (connector); (struct intel_connector *)( (char *)__mptr
- __builtin_offsetof(struct intel_connector, base) );})
);
1692 const struct tv_mode *tv_mode = intel_tv_mode_find(connector->state);
1693 int i;
1694
1695 /* Component supports everything so we can keep the current mode */
1696 if (intel_tv->type == DRM_MODE_CONNECTOR_Component8)
1697 return;
1698
1699 /* If the current mode is fine don't change it */
1700 if (!tv_mode->component_only)
1701 return;
1702
1703 for (i = 0; i < ARRAY_SIZE(tv_modes)(sizeof((tv_modes)) / sizeof((tv_modes)[0])); i++) {
1704 tv_mode = &tv_modes[i];
1705
1706 if (!tv_mode->component_only)
1707 break;
1708 }
1709
1710 connector->state->tv.mode = i;
1711}
1712
1713static int
1714intel_tv_detect(struct drm_connector *connector,
1715 struct drm_modeset_acquire_ctx *ctx,
1716 bool_Bool force)
1717{
1718 struct drm_i915_privateinteldrm_softc *i915 = to_i915(connector->dev);
1719 struct intel_tv *intel_tv = intel_attached_tv(to_intel_connector(connector)({ const __typeof( ((struct intel_connector *)0)->base ) *
__mptr = (connector); (struct intel_connector *)( (char *)__mptr
- __builtin_offsetof(struct intel_connector, base) );})
);
1720 enum drm_connector_status status;
1721 int type;
1722
1723 drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] force=%d\n",__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "[CONNECTOR:%d:%s] force=%d\n"
, connector->base.id, connector->name, force)
1724 connector->base.id, connector->name, force)__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "[CONNECTOR:%d:%s] force=%d\n"
, connector->base.id, connector->name, force)
;
1725
1726 if (!INTEL_DISPLAY_ENABLED(i915)(({ int __ret = !!((!((&(i915)->__runtime)->pipe_mask
!= 0))); if (__ret) printf("%s %s: " "%s", dev_driver_string
(((&(i915)->drm))->dev), "", "drm_WARN_ON(" "!((&(i915)->__runtime)->pipe_mask != 0)"
")"); __builtin_expect(!!(__ret), 0); }), !(i915)->params
.disable_display && !intel_opregion_headless_sku(i915
))
)
1727 return connector_status_disconnected;
1728
1729 if (force) {
1730 struct intel_load_detect_pipe tmp;
1731 int ret;
1732
1733 ret = intel_get_load_detect_pipe(connector, &tmp, ctx);
1734 if (ret < 0)
1735 return ret;
1736
1737 if (ret > 0) {
1738 type = intel_tv_detect_type(intel_tv, connector);
1739 intel_release_load_detect_pipe(connector, &tmp, ctx);
1740 status = type < 0 ?
1741 connector_status_disconnected :
1742 connector_status_connected;
1743 } else
1744 status = connector_status_unknown;
1745
1746 if (status == connector_status_connected) {
1747 intel_tv->type = type;
1748 intel_tv_find_better_format(connector);
1749 }
1750
1751 return status;
1752 } else
1753 return connector->status;
1754}
1755
1756static const struct input_res {
1757 u16 w, h;
1758} input_res_table[] = {
1759 { 640, 480 },
1760 { 800, 600 },
1761 { 1024, 768 },
1762 { 1280, 1024 },
1763 { 848, 480 },
1764 { 1280, 720 },
1765 { 1920, 1080 },
1766};
1767
1768/* Choose preferred mode according to line number of TV format */
1769static bool_Bool
1770intel_tv_is_preferred_mode(const struct drm_display_mode *mode,
1771 const struct tv_mode *tv_mode)
1772{
1773 int vdisplay = intel_tv_mode_vdisplay(tv_mode);
1774
1775 /* prefer 480 line modes for all SD TV modes */
1776 if (vdisplay <= 576)
1777 vdisplay = 480;
1778
1779 return vdisplay == mode->vdisplay;
1780}
1781
1782static void
1783intel_tv_set_mode_type(struct drm_display_mode *mode,
1784 const struct tv_mode *tv_mode)
1785{
1786 mode->type = DRM_MODE_TYPE_DRIVER(1<<6);
1787
1788 if (intel_tv_is_preferred_mode(mode, tv_mode))
1789 mode->type |= DRM_MODE_TYPE_PREFERRED(1<<3);
1790}
1791
1792static int
1793intel_tv_get_modes(struct drm_connector *connector)
1794{
1795 struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->dev);
1796 const struct tv_mode *tv_mode = intel_tv_mode_find(connector->state);
1797 int i, count = 0;
1798
1799 for (i = 0; i < ARRAY_SIZE(input_res_table)(sizeof((input_res_table)) / sizeof((input_res_table)[0])); i++) {
1800 const struct input_res *input = &input_res_table[i];
1801 struct drm_display_mode *mode;
1802
1803 if (input->w > 1024 &&
1804 !tv_mode->progressive &&
1805 !tv_mode->component_only)
1806 continue;
1807
1808 /* no vertical scaling with wide sources on gen3 */
1809 if (DISPLAY_VER(dev_priv)((&(dev_priv)->__runtime)->display.ip.ver) == 3 && input->w > 1024 &&
1810 input->h > intel_tv_mode_vdisplay(tv_mode))
1811 continue;
1812
1813 mode = drm_mode_create(connector->dev);
1814 if (!mode)
1815 continue;
1816
1817 /*
1818 * We take the TV mode and scale it to look
1819 * like it had the expected h/vdisplay. This
1820 * provides the most information to userspace
1821 * about the actual timings of the mode. We
1822 * do ignore the margins though.
1823 */
1824 intel_tv_mode_to_mode(mode, tv_mode, tv_mode->clock);
1825 if (count == 0) {
1826 drm_dbg_kms(&dev_priv->drm, "TV mode: " DRM_MODE_FMT "\n",__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_KMS, "TV mode: " "\"%s\": %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x"
"\n", (mode)->name, drm_mode_vrefresh(mode), (mode)->clock
, (mode)->hdisplay, (mode)->hsync_start, (mode)->hsync_end
, (mode)->htotal, (mode)->vdisplay, (mode)->vsync_start
, (mode)->vsync_end, (mode)->vtotal, (mode)->type, (
mode)->flags)
1827 DRM_MODE_ARG(mode))__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_KMS, "TV mode: " "\"%s\": %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x"
"\n", (mode)->name, drm_mode_vrefresh(mode), (mode)->clock
, (mode)->hdisplay, (mode)->hsync_start, (mode)->hsync_end
, (mode)->htotal, (mode)->vdisplay, (mode)->vsync_start
, (mode)->vsync_end, (mode)->vtotal, (mode)->type, (
mode)->flags)
;
1828 }
1829 intel_tv_scale_mode_horiz(mode, input->w, 0, 0);
1830 intel_tv_scale_mode_vert(mode, input->h, 0, 0);
1831 intel_tv_set_mode_type(mode, tv_mode);
1832
1833 drm_mode_set_name(mode);
1834
1835 drm_mode_probed_add(connector, mode);
1836 count++;
1837 }
1838
1839 return count;
1840}
1841
1842static const struct drm_connector_funcs intel_tv_connector_funcs = {
1843 .late_register = intel_connector_register,
1844 .early_unregister = intel_connector_unregister,
1845 .destroy = intel_connector_destroy,
1846 .fill_modes = drm_helper_probe_single_connector_modes,
1847 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
1848 .atomic_duplicate_state = intel_tv_connector_duplicate_state,
1849};
1850
1851static int intel_tv_atomic_check(struct drm_connector *connector,
1852 struct drm_atomic_state *state)
1853{
1854 struct drm_connector_state *new_state;
1855 struct drm_crtc_state *new_crtc_state;
1856 struct drm_connector_state *old_state;
1857
1858 new_state = drm_atomic_get_new_connector_state(state, connector);
1859 if (!new_state->crtc)
1860 return 0;
1861
1862 old_state = drm_atomic_get_old_connector_state(state, connector);
1863 new_crtc_state = drm_atomic_get_new_crtc_state(state, new_state->crtc);
1864
1865 if (old_state->tv.mode != new_state->tv.mode ||
1866 old_state->tv.margins.left != new_state->tv.margins.left ||
1867 old_state->tv.margins.right != new_state->tv.margins.right ||
1868 old_state->tv.margins.top != new_state->tv.margins.top ||
1869 old_state->tv.margins.bottom != new_state->tv.margins.bottom) {
1870 /* Force a modeset. */
1871
1872 new_crtc_state->connectors_changed = true1;
1873 }
1874
1875 return 0;
1876}
1877
1878static const struct drm_connector_helper_funcs intel_tv_connector_helper_funcs = {
1879 .detect_ctx = intel_tv_detect,
1880 .mode_valid = intel_tv_mode_valid,
1881 .get_modes = intel_tv_get_modes,
1882 .atomic_check = intel_tv_atomic_check,
1883};
1884
1885static const struct drm_encoder_funcs intel_tv_enc_funcs = {
1886 .destroy = intel_encoder_destroy,
1887};
1888
1889void
1890intel_tv_init(struct drm_i915_privateinteldrm_softc *dev_priv)
1891{
1892 struct drm_device *dev = &dev_priv->drm;
1893 struct drm_connector *connector;
1894 struct intel_tv *intel_tv;
1895 struct intel_encoder *intel_encoder;
1896 struct intel_connector *intel_connector;
1897 u32 tv_dac_on, tv_dac_off, save_tv_dac;
1898 const char *tv_format_names[ARRAY_SIZE(tv_modes)(sizeof((tv_modes)) / sizeof((tv_modes)[0]))];
1899 int i, initial_mode = 0;
1900 struct drm_connector_state *state;
1901
1902 if ((intel_de_read(dev_priv, TV_CTL((const i915_reg_t){ .reg = (0x68000) })) & TV_FUSE_STATE_MASK(3 << 4)) == TV_FUSE_STATE_DISABLED(2 << 4))
1903 return;
1904
1905 if (!intel_bios_is_tv_present(dev_priv)) {
1906 drm_dbg_kms(&dev_priv->drm, "Integrated TV is not present.\n")__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_KMS, "Integrated TV is not present.\n"
)
;
1907 return;
1908 }
1909
1910 /*
1911 * Sanity check the TV output by checking to see if the
1912 * DAC register holds a value
1913 */
1914 save_tv_dac = intel_de_read(dev_priv, TV_DAC((const i915_reg_t){ .reg = (0x68004) }));
1915
1916 intel_de_write(dev_priv, TV_DAC((const i915_reg_t){ .reg = (0x68004) }), save_tv_dac | TVDAC_STATE_CHG_EN(1 << 27));
1917 tv_dac_on = intel_de_read(dev_priv, TV_DAC((const i915_reg_t){ .reg = (0x68004) }));
1918
1919 intel_de_write(dev_priv, TV_DAC((const i915_reg_t){ .reg = (0x68004) }), save_tv_dac & ~TVDAC_STATE_CHG_EN(1 << 27));
1920 tv_dac_off = intel_de_read(dev_priv, TV_DAC((const i915_reg_t){ .reg = (0x68004) }));
1921
1922 intel_de_write(dev_priv, TV_DAC((const i915_reg_t){ .reg = (0x68004) }), save_tv_dac);
1923
1924 /*
1925 * If the register does not hold the state change enable
1926 * bit, (either as a 0 or a 1), assume it doesn't really
1927 * exist
1928 */
1929 if ((tv_dac_on & TVDAC_STATE_CHG_EN(1 << 27)) == 0 ||
1930 (tv_dac_off & TVDAC_STATE_CHG_EN(1 << 27)) != 0)
1931 return;
1932
1933 intel_tv = kzalloc(sizeof(*intel_tv), GFP_KERNEL(0x0001 | 0x0004));
1934 if (!intel_tv) {
1935 return;
1936 }
1937
1938 intel_connector = intel_connector_alloc();
1939 if (!intel_connector) {
1940 kfree(intel_tv);
1941 return;
1942 }
1943
1944 intel_encoder = &intel_tv->base;
1945 connector = &intel_connector->base;
1946 state = connector->state;
1947
1948 /*
1949 * The documentation, for the older chipsets at least, recommend
1950 * using a polling method rather than hotplug detection for TVs.
1951 * This is because in order to perform the hotplug detection, the PLLs
1952 * for the TV must be kept alive increasing power drain and starving
1953 * bandwidth from other encoders. Notably for instance, it causes
1954 * pipe underruns on Crestline when this encoder is supposedly idle.
1955 *
1956 * More recent chipsets favour HDMI rather than integrated S-Video.
1957 */
1958 intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT(1 << 1);
1959
1960 drm_connector_init(dev, connector, &intel_tv_connector_funcs,
1961 DRM_MODE_CONNECTOR_SVIDEO6);
1962
1963 drm_encoder_init(dev, &intel_encoder->base, &intel_tv_enc_funcs,
1964 DRM_MODE_ENCODER_TVDAC4, "TV");
1965
1966 intel_encoder->compute_config = intel_tv_compute_config;
1967 intel_encoder->get_config = intel_tv_get_config;
1968 intel_encoder->pre_enable = intel_tv_pre_enable;
1969 intel_encoder->enable = intel_enable_tv;
1970 intel_encoder->disable = intel_disable_tv;
1971 intel_encoder->get_hw_state = intel_tv_get_hw_state;
1972 intel_connector->get_hw_state = intel_connector_get_hw_state;
1973
1974 intel_connector_attach_encoder(intel_connector, intel_encoder);
1975
1976 intel_encoder->type = INTEL_OUTPUT_TVOUT;
1977 intel_encoder->power_domain = POWER_DOMAIN_PORT_OTHER;
1978 intel_encoder->port = PORT_NONE;
1979 intel_encoder->pipe_mask = ~0;
1980 intel_encoder->cloneable = 0;
1981 intel_tv->type = DRM_MODE_CONNECTOR_Unknown0;
1982
1983 /* BIOS margin values */
1984 state->tv.margins.left = 54;
1985 state->tv.margins.top = 36;
1986 state->tv.margins.right = 46;
1987 state->tv.margins.bottom = 37;
1988
1989 state->tv.mode = initial_mode;
1990
1991 drm_connector_helper_add(connector, &intel_tv_connector_helper_funcs);
1992 connector->interlace_allowed = false0;
1993 connector->doublescan_allowed = false0;
1994
1995 /* Create TV properties then attach current values */
1996 for (i = 0; i < ARRAY_SIZE(tv_modes)(sizeof((tv_modes)) / sizeof((tv_modes)[0])); i++) {
1997 /* 1080p50/1080p60 not supported on gen3 */
1998 if (DISPLAY_VER(dev_priv)((&(dev_priv)->__runtime)->display.ip.ver) == 3 &&
1999 tv_modes[i].oversample == 1)
2000 break;
2001
2002 tv_format_names[i] = tv_modes[i].name;
2003 }
2004 drm_mode_create_tv_properties(dev, i, tv_format_names);
2005
2006 drm_object_attach_property(&connector->base, dev->mode_config.tv_mode_property,
2007 state->tv.mode);
2008 drm_object_attach_property(&connector->base,
2009 dev->mode_config.tv_left_margin_property,
2010 state->tv.margins.left);
2011 drm_object_attach_property(&connector->base,
2012 dev->mode_config.tv_top_margin_property,
2013 state->tv.margins.top);
2014 drm_object_attach_property(&connector->base,
2015 dev->mode_config.tv_right_margin_property,
2016 state->tv.margins.right);
2017 drm_object_attach_property(&connector->base,
2018 dev->mode_config.tv_bottom_margin_property,
2019 state->tv.margins.bottom);
2020}