brintos

brintos / linux-shallow public Read only

0
0
Text · 59.1 KiB · 5fee4be Raw
2030 lines · c
1/*2 * Copyright © 2006-2008 Intel Corporation3 *   Jesse Barnes <jesse.barnes@intel.com>4 *5 * Permission is hereby granted, free of charge, to any person obtaining a6 * copy of this software and associated documentation files (the "Software"),7 * to deal in the Software without restriction, including without limitation8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,9 * and/or sell copies of the Software, and to permit persons to whom the10 * Software is furnished to do so, subject to the following conditions:11 *12 * The above copyright notice and this permission notice (including the next13 * paragraph) shall be included in all copies or substantial portions of the14 * Software.15 *16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER22 * DEALINGS IN THE SOFTWARE.23 *24 * Authors:25 *    Eric Anholt <eric@anholt.net>26 *27 */28 29/** @file30 * 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 "i915_reg.h"39#include "intel_connector.h"40#include "intel_crtc.h"41#include "intel_de.h"42#include "intel_display_irq.h"43#include "intel_display_driver.h"44#include "intel_display_types.h"45#include "intel_dpll.h"46#include "intel_hotplug.h"47#include "intel_load_detect.h"48#include "intel_tv.h"49#include "intel_tv_regs.h"50 51enum tv_margin {52	TV_MARGIN_LEFT, TV_MARGIN_TOP,53	TV_MARGIN_RIGHT, TV_MARGIN_BOTTOM54};55 56struct intel_tv {57	struct intel_encoder base;58 59	int type;60};61 62struct video_levels {63	u16 blank, black;64	u8 burst;65};66 67struct color_conversion {68	u16 ry, gy, by, ay;69	u16 ru, gu, bu, au;70	u16 rv, gv, bv, av;71};72 73static const u32 filter_table[] = {74	0xB1403000, 0x2E203500, 0x35002E20, 0x3000B140,75	0x35A0B160, 0x2DC02E80, 0xB1403480, 0xB1603000,76	0x2EA03640, 0x34002D80, 0x3000B120, 0x36E0B160,77	0x2D202EF0, 0xB1203380, 0xB1603000, 0x2F303780,78	0x33002CC0, 0x3000B100, 0x3820B160, 0x2C802F50,79	0xB10032A0, 0xB1603000, 0x2F9038C0, 0x32202C20,80	0x3000B0E0, 0x3980B160, 0x2BC02FC0, 0xB0E031C0,81	0xB1603000, 0x2FF03A20, 0x31602B60, 0xB020B0C0,82	0x3AE0B160, 0x2B001810, 0xB0C03120, 0xB140B020,83	0x18283BA0, 0x30C02A80, 0xB020B0A0, 0x3C60B140,84	0x2A201838, 0xB0A03080, 0xB120B020, 0x18383D20,85	0x304029C0, 0xB040B080, 0x3DE0B100, 0x29601848,86	0xB0803000, 0xB100B040, 0x18483EC0, 0xB0402900,87	0xB040B060, 0x3F80B0C0, 0x28801858, 0xB060B080,88	0xB0A0B060, 0x18602820, 0xB0A02820, 0x0000B060,89	0xB1403000, 0x2E203500, 0x35002E20, 0x3000B140,90	0x35A0B160, 0x2DC02E80, 0xB1403480, 0xB1603000,91	0x2EA03640, 0x34002D80, 0x3000B120, 0x36E0B160,92	0x2D202EF0, 0xB1203380, 0xB1603000, 0x2F303780,93	0x33002CC0, 0x3000B100, 0x3820B160, 0x2C802F50,94	0xB10032A0, 0xB1603000, 0x2F9038C0, 0x32202C20,95	0x3000B0E0, 0x3980B160, 0x2BC02FC0, 0xB0E031C0,96	0xB1603000, 0x2FF03A20, 0x31602B60, 0xB020B0C0,97	0x3AE0B160, 0x2B001810, 0xB0C03120, 0xB140B020,98	0x18283BA0, 0x30C02A80, 0xB020B0A0, 0x3C60B140,99	0x2A201838, 0xB0A03080, 0xB120B020, 0x18383D20,100	0x304029C0, 0xB040B080, 0x3DE0B100, 0x29601848,101	0xB0803000, 0xB100B040, 0x18483EC0, 0xB0402900,102	0xB040B060, 0x3F80B0C0, 0x28801858, 0xB060B080,103	0xB0A0B060, 0x18602820, 0xB0A02820, 0x0000B060,104	0x36403000, 0x2D002CC0, 0x30003640, 0x2D0036C0,105	0x35C02CC0, 0x37403000, 0x2C802D40, 0x30003540,106	0x2D8037C0, 0x34C02C40, 0x38403000, 0x2BC02E00,107	0x30003440, 0x2E2038C0, 0x34002B80, 0x39803000,108	0x2B402E40, 0x30003380, 0x2E603A00, 0x33402B00,109	0x3A803040, 0x2A802EA0, 0x30403300, 0x2EC03B40,110	0x32802A40, 0x3C003040, 0x2A002EC0, 0x30803240,111	0x2EC03C80, 0x320029C0, 0x3D403080, 0x29402F00,112	0x308031C0, 0x2F203DC0, 0x31802900, 0x3E8030C0,113	0x28802F40, 0x30C03140, 0x2F203F40, 0x31402840,114	0x28003100, 0x28002F00, 0x00003100, 0x36403000,115	0x2D002CC0, 0x30003640, 0x2D0036C0,116	0x35C02CC0, 0x37403000, 0x2C802D40, 0x30003540,117	0x2D8037C0, 0x34C02C40, 0x38403000, 0x2BC02E00,118	0x30003440, 0x2E2038C0, 0x34002B80, 0x39803000,119	0x2B402E40, 0x30003380, 0x2E603A00, 0x33402B00,120	0x3A803040, 0x2A802EA0, 0x30403300, 0x2EC03B40,121	0x32802A40, 0x3C003040, 0x2A002EC0, 0x30803240,122	0x2EC03C80, 0x320029C0, 0x3D403080, 0x29402F00,123	0x308031C0, 0x2F203DC0, 0x31802900, 0x3E8030C0,124	0x28802F40, 0x30C03140, 0x2F203F40, 0x31402840,125	0x28003100, 0x28002F00, 0x00003100,126};127 128/*129 * Color conversion values have 3 separate fixed point formats:130 *131 * 10 bit fields (ay, au)132 *   1.9 fixed point (b.bbbbbbbbb)133 * 11 bit fields (ry, by, ru, gu, gv)134 *   exp.mantissa (ee.mmmmmmmmm)135 *   ee = 00 = 10^-1 (0.mmmmmmmmm)136 *   ee = 01 = 10^-2 (0.0mmmmmmmmm)137 *   ee = 10 = 10^-3 (0.00mmmmmmmmm)138 *   ee = 11 = 10^-4 (0.000mmmmmmmmm)139 * 12 bit fields (gy, rv, bu)140 *   exp.mantissa (eee.mmmmmmmmm)141 *   eee = 000 = 10^-1 (0.mmmmmmmmm)142 *   eee = 001 = 10^-2 (0.0mmmmmmmmm)143 *   eee = 010 = 10^-3 (0.00mmmmmmmmm)144 *   eee = 011 = 10^-4 (0.000mmmmmmmmm)145 *   eee = 100 = reserved146 *   eee = 101 = reserved147 *   eee = 110 = reserved148 *   eee = 111 = 10^0 (m.mmmmmmmm) (only usable for 1.0 representation)149 *150 * Saturation and contrast are 8 bits, with their own representation:151 * 8 bit field (saturation, contrast)152 *   exp.mantissa (ee.mmmmmm)153 *   ee = 00 = 10^-1 (0.mmmmmm)154 *   ee = 01 = 10^0 (m.mmmmm)155 *   ee = 10 = 10^1 (mm.mmmm)156 *   ee = 11 = 10^2 (mmm.mmm)157 *158 * Simple conversion function:159 *160 * static u32161 * float_to_csc_11(float f)162 * {163 *     u32 exp;164 *     u32 mant;165 *     u32 ret;166 *167 *     if (f < 0)168 *         f = -f;169 *170 *     if (f >= 1) {171 *         exp = 0x7;172 *	   mant = 1 << 8;173 *     } else {174 *         for (exp = 0; exp < 3 && f < 0.5; exp++)175 *	   f *= 2.0;176 *         mant = (f * (1 << 9) + 0.5);177 *         if (mant >= (1 << 9))178 *             mant = (1 << 9) - 1;179 *     }180 *     ret = (exp << 9) | mant;181 *     return ret;182 * }183 */184 185/*186 * Behold, magic numbers!  If we plant them they might grow a big187 * s-video cable to the sky... or something.188 *189 * Pre-converted to appropriate hex value.190 */191 192/*193 * PAL & NTSC values for composite & s-video connections194 */195static const struct color_conversion ntsc_m_csc_composite = {196	.ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0104,197	.ru = 0x0733, .gu = 0x052d, .bu = 0x05c7, .au = 0x0200,198	.rv = 0x0340, .gv = 0x030c, .bv = 0x06d0, .av = 0x0200,199};200 201static const struct video_levels ntsc_m_levels_composite = {202	.blank = 225, .black = 267, .burst = 113,203};204 205static const struct color_conversion ntsc_m_csc_svideo = {206	.ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0133,207	.ru = 0x076a, .gu = 0x0564, .bu = 0x030d, .au = 0x0200,208	.rv = 0x037a, .gv = 0x033d, .bv = 0x06f6, .av = 0x0200,209};210 211static const struct video_levels ntsc_m_levels_svideo = {212	.blank = 266, .black = 316, .burst = 133,213};214 215static const struct color_conversion ntsc_j_csc_composite = {216	.ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0119,217	.ru = 0x074c, .gu = 0x0546, .bu = 0x05ec, .au = 0x0200,218	.rv = 0x035a, .gv = 0x0322, .bv = 0x06e1, .av = 0x0200,219};220 221static const struct video_levels ntsc_j_levels_composite = {222	.blank = 225, .black = 225, .burst = 113,223};224 225static const struct color_conversion ntsc_j_csc_svideo = {226	.ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x014c,227	.ru = 0x0788, .gu = 0x0581, .bu = 0x0322, .au = 0x0200,228	.rv = 0x0399, .gv = 0x0356, .bv = 0x070a, .av = 0x0200,229};230 231static const struct video_levels ntsc_j_levels_svideo = {232	.blank = 266, .black = 266, .burst = 133,233};234 235static const struct color_conversion pal_csc_composite = {236	.ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0113,237	.ru = 0x0745, .gu = 0x053f, .bu = 0x05e1, .au = 0x0200,238	.rv = 0x0353, .gv = 0x031c, .bv = 0x06dc, .av = 0x0200,239};240 241static const struct video_levels pal_levels_composite = {242	.blank = 237, .black = 237, .burst = 118,243};244 245static const struct color_conversion pal_csc_svideo = {246	.ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0145,247	.ru = 0x0780, .gu = 0x0579, .bu = 0x031c, .au = 0x0200,248	.rv = 0x0390, .gv = 0x034f, .bv = 0x0705, .av = 0x0200,249};250 251static const struct video_levels pal_levels_svideo = {252	.blank = 280, .black = 280, .burst = 139,253};254 255static const struct color_conversion pal_m_csc_composite = {256	.ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0104,257	.ru = 0x0733, .gu = 0x052d, .bu = 0x05c7, .au = 0x0200,258	.rv = 0x0340, .gv = 0x030c, .bv = 0x06d0, .av = 0x0200,259};260 261static const struct video_levels pal_m_levels_composite = {262	.blank = 225, .black = 267, .burst = 113,263};264 265static const struct color_conversion pal_m_csc_svideo = {266	.ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0133,267	.ru = 0x076a, .gu = 0x0564, .bu = 0x030d, .au = 0x0200,268	.rv = 0x037a, .gv = 0x033d, .bv = 0x06f6, .av = 0x0200,269};270 271static const struct video_levels pal_m_levels_svideo = {272	.blank = 266, .black = 316, .burst = 133,273};274 275static const struct color_conversion pal_n_csc_composite = {276	.ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0104,277	.ru = 0x0733, .gu = 0x052d, .bu = 0x05c7, .au = 0x0200,278	.rv = 0x0340, .gv = 0x030c, .bv = 0x06d0, .av = 0x0200,279};280 281static const struct video_levels pal_n_levels_composite = {282	.blank = 225, .black = 267, .burst = 118,283};284 285static const struct color_conversion pal_n_csc_svideo = {286	.ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0133,287	.ru = 0x076a, .gu = 0x0564, .bu = 0x030d, .au = 0x0200,288	.rv = 0x037a, .gv = 0x033d, .bv = 0x06f6, .av = 0x0200,289};290 291static const struct video_levels pal_n_levels_svideo = {292	.blank = 266, .black = 316, .burst = 139,293};294 295/*296 * Component connections297 */298static const struct color_conversion sdtv_csc_yprpb = {299	.ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0145,300	.ru = 0x0559, .gu = 0x0353, .bu = 0x0100, .au = 0x0200,301	.rv = 0x0100, .gv = 0x03ad, .bv = 0x074d, .av = 0x0200,302};303 304static const struct color_conversion hdtv_csc_yprpb = {305	.ry = 0x05b3, .gy = 0x016e, .by = 0x0728, .ay = 0x0145,306	.ru = 0x07d5, .gu = 0x038b, .bu = 0x0100, .au = 0x0200,307	.rv = 0x0100, .gv = 0x03d1, .bv = 0x06bc, .av = 0x0200,308};309 310static const struct video_levels component_levels = {311	.blank = 279, .black = 279, .burst = 0,312};313 314 315struct tv_mode {316	const char *name;317 318	u32 clock;319	u16 refresh; /* in millihertz (for precision) */320	u8 oversample;321	u8 hsync_end;322	u16 hblank_start, hblank_end, htotal;323	bool progressive : 1, trilevel_sync : 1, component_only : 1;324	u8 vsync_start_f1, vsync_start_f2, vsync_len;325	bool veq_ena : 1;326	u8 veq_start_f1, veq_start_f2, veq_len;327	u8 vi_end_f1, vi_end_f2;328	u16 nbr_end;329	bool burst_ena : 1;330	u8 hburst_start, hburst_len;331	u8 vburst_start_f1;332	u16 vburst_end_f1;333	u8 vburst_start_f2;334	u16 vburst_end_f2;335	u8 vburst_start_f3;336	u16 vburst_end_f3;337	u8 vburst_start_f4;338	u16 vburst_end_f4;339	/*340	 * subcarrier programming341	 */342	u16 dda2_size, dda3_size;343	u8 dda1_inc;344	u16 dda2_inc, dda3_inc;345	u32 sc_reset;346	bool pal_burst : 1;347	/*348	 * blank/black levels349	 */350	const struct video_levels *composite_levels, *svideo_levels;351	const struct color_conversion *composite_color, *svideo_color;352	const u32 *filter_table;353};354 355 356/*357 * Sub carrier DDA358 *359 *  I think this works as follows:360 *361 *  subcarrier freq = pixel_clock * (dda1_inc + dda2_inc / dda2_size) / 4096362 *363 * Presumably, when dda3 is added in, it gets to adjust the dda2_inc value364 *365 * So,366 *  dda1_ideal = subcarrier/pixel * 4096367 *  dda1_inc = floor (dda1_ideal)368 *  dda2 = dda1_ideal - dda1_inc369 *370 *  then pick a ratio for dda2 that gives the closest approximation. If371 *  you can't get close enough, you can play with dda3 as well. This372 *  seems likely to happen when dda2 is small as the jumps would be larger373 *374 * To invert this,375 *376 *  pixel_clock = subcarrier * 4096 / (dda1_inc + dda2_inc / dda2_size)377 *378 * The constants below were all computed using a 107.520MHz clock379 */380 381/*382 * Register programming values for TV modes.383 *384 * These values account for -1s required.385 */386static const struct tv_mode tv_modes[] = {387	{388		.name		= "NTSC-M",389		.clock		= 108000,390		.refresh	= 59940,391		.oversample	= 8,392		.component_only = false,393		/* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.580MHz */394 395		.hsync_end	= 64,		    .hblank_end		= 124,396		.hblank_start	= 836,		    .htotal		= 857,397 398		.progressive	= false,	    .trilevel_sync = false,399 400		.vsync_start_f1	= 6,		    .vsync_start_f2	= 7,401		.vsync_len	= 6,402 403		.veq_ena	= true,		    .veq_start_f1	= 0,404		.veq_start_f2	= 1,		    .veq_len		= 18,405 406		.vi_end_f1	= 20,		    .vi_end_f2		= 21,407		.nbr_end	= 240,408 409		.burst_ena	= true,410		.hburst_start	= 72,		    .hburst_len		= 34,411		.vburst_start_f1 = 9,		    .vburst_end_f1	= 240,412		.vburst_start_f2 = 10,		    .vburst_end_f2	= 240,413		.vburst_start_f3 = 9,		    .vburst_end_f3	= 240,414		.vburst_start_f4 = 10,		    .vburst_end_f4	= 240,415 416		/* desired 3.5800000 actual 3.5800000 clock 107.52 */417		.dda1_inc	=    135,418		.dda2_inc	=  20800,	    .dda2_size		=  27456,419		.dda3_inc	=      0,	    .dda3_size		=      0,420		.sc_reset	= TV_SC_RESET_EVERY_4,421		.pal_burst	= false,422 423		.composite_levels = &ntsc_m_levels_composite,424		.composite_color = &ntsc_m_csc_composite,425		.svideo_levels  = &ntsc_m_levels_svideo,426		.svideo_color = &ntsc_m_csc_svideo,427 428		.filter_table = filter_table,429	},430	{431		.name		= "NTSC-443",432		.clock		= 108000,433		.refresh	= 59940,434		.oversample	= 8,435		.component_only = false,436		/* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 4.43MHz */437		.hsync_end	= 64,		    .hblank_end		= 124,438		.hblank_start	= 836,		    .htotal		= 857,439 440		.progressive	= false,	    .trilevel_sync = false,441 442		.vsync_start_f1 = 6,		    .vsync_start_f2	= 7,443		.vsync_len	= 6,444 445		.veq_ena	= true,		    .veq_start_f1	= 0,446		.veq_start_f2	= 1,		    .veq_len		= 18,447 448		.vi_end_f1	= 20,		    .vi_end_f2		= 21,449		.nbr_end	= 240,450 451		.burst_ena	= true,452		.hburst_start	= 72,		    .hburst_len		= 34,453		.vburst_start_f1 = 9,		    .vburst_end_f1	= 240,454		.vburst_start_f2 = 10,		    .vburst_end_f2	= 240,455		.vburst_start_f3 = 9,		    .vburst_end_f3	= 240,456		.vburst_start_f4 = 10,		    .vburst_end_f4	= 240,457 458		/* desired 4.4336180 actual 4.4336180 clock 107.52 */459		.dda1_inc       =    168,460		.dda2_inc       =   4093,       .dda2_size      =  27456,461		.dda3_inc       =    310,       .dda3_size      =    525,462		.sc_reset   = TV_SC_RESET_NEVER,463		.pal_burst  = false,464 465		.composite_levels = &ntsc_m_levels_composite,466		.composite_color = &ntsc_m_csc_composite,467		.svideo_levels  = &ntsc_m_levels_svideo,468		.svideo_color = &ntsc_m_csc_svideo,469 470		.filter_table = filter_table,471	},472	{473		.name		= "NTSC-J",474		.clock		= 108000,475		.refresh	= 59940,476		.oversample	= 8,477		.component_only = false,478 479		/* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.580MHz */480		.hsync_end	= 64,		    .hblank_end		= 124,481		.hblank_start = 836,	    .htotal		= 857,482 483		.progressive	= false,    .trilevel_sync = false,484 485		.vsync_start_f1	= 6,	    .vsync_start_f2	= 7,486		.vsync_len	= 6,487 488		.veq_ena      = true,	    .veq_start_f1	= 0,489		.veq_start_f2 = 1,	    .veq_len		= 18,490 491		.vi_end_f1	= 20,		    .vi_end_f2		= 21,492		.nbr_end	= 240,493 494		.burst_ena	= true,495		.hburst_start	= 72,		    .hburst_len		= 34,496		.vburst_start_f1 = 9,		    .vburst_end_f1	= 240,497		.vburst_start_f2 = 10,		    .vburst_end_f2	= 240,498		.vburst_start_f3 = 9,		    .vburst_end_f3	= 240,499		.vburst_start_f4 = 10,		    .vburst_end_f4	= 240,500 501		/* desired 3.5800000 actual 3.5800000 clock 107.52 */502		.dda1_inc	=    135,503		.dda2_inc	=  20800,	    .dda2_size		=  27456,504		.dda3_inc	=      0,	    .dda3_size		=      0,505		.sc_reset	= TV_SC_RESET_EVERY_4,506		.pal_burst	= false,507 508		.composite_levels = &ntsc_j_levels_composite,509		.composite_color = &ntsc_j_csc_composite,510		.svideo_levels  = &ntsc_j_levels_svideo,511		.svideo_color = &ntsc_j_csc_svideo,512 513		.filter_table = filter_table,514	},515	{516		.name		= "PAL-M",517		.clock		= 108000,518		.refresh	= 59940,519		.oversample	= 8,520		.component_only = false,521 522		/* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.580MHz */523		.hsync_end	= 64,		  .hblank_end		= 124,524		.hblank_start = 836,	  .htotal		= 857,525 526		.progressive	= false,	    .trilevel_sync = false,527 528		.vsync_start_f1	= 6,		    .vsync_start_f2	= 7,529		.vsync_len	= 6,530 531		.veq_ena	= true,		    .veq_start_f1	= 0,532		.veq_start_f2	= 1,		    .veq_len		= 18,533 534		.vi_end_f1	= 20,		    .vi_end_f2		= 21,535		.nbr_end	= 240,536 537		.burst_ena	= true,538		.hburst_start	= 72,		    .hburst_len		= 34,539		.vburst_start_f1 = 9,		    .vburst_end_f1	= 240,540		.vburst_start_f2 = 10,		    .vburst_end_f2	= 240,541		.vburst_start_f3 = 9,		    .vburst_end_f3	= 240,542		.vburst_start_f4 = 10,		    .vburst_end_f4	= 240,543 544		/* desired 3.5800000 actual 3.5800000 clock 107.52 */545		.dda1_inc	=    135,546		.dda2_inc	=  16704,	    .dda2_size		=  27456,547		.dda3_inc	=      0,	    .dda3_size		=      0,548		.sc_reset	= TV_SC_RESET_EVERY_8,549		.pal_burst  = true,550 551		.composite_levels = &pal_m_levels_composite,552		.composite_color = &pal_m_csc_composite,553		.svideo_levels  = &pal_m_levels_svideo,554		.svideo_color = &pal_m_csc_svideo,555 556		.filter_table = filter_table,557	},558	{559		/* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */560		.name	    = "PAL-N",561		.clock		= 108000,562		.refresh	= 50000,563		.oversample	= 8,564		.component_only = false,565 566		.hsync_end	= 64,		    .hblank_end		= 128,567		.hblank_start = 844,	    .htotal		= 863,568 569		.progressive  = false,    .trilevel_sync = false,570 571 572		.vsync_start_f1	= 6,	   .vsync_start_f2	= 7,573		.vsync_len	= 6,574 575		.veq_ena	= true,		    .veq_start_f1	= 0,576		.veq_start_f2	= 1,		    .veq_len		= 18,577 578		.vi_end_f1	= 24,		    .vi_end_f2		= 25,579		.nbr_end	= 286,580 581		.burst_ena	= true,582		.hburst_start = 73,	    .hburst_len		= 34,583		.vburst_start_f1 = 8,	    .vburst_end_f1	= 285,584		.vburst_start_f2 = 8,	    .vburst_end_f2	= 286,585		.vburst_start_f3 = 9,	    .vburst_end_f3	= 286,586		.vburst_start_f4 = 9,	    .vburst_end_f4	= 285,587 588 589		/* desired 4.4336180 actual 4.4336180 clock 107.52 */590		.dda1_inc       =    135,591		.dda2_inc       =  23578,       .dda2_size      =  27648,592		.dda3_inc       =    134,       .dda3_size      =    625,593		.sc_reset   = TV_SC_RESET_EVERY_8,594		.pal_burst  = true,595 596		.composite_levels = &pal_n_levels_composite,597		.composite_color = &pal_n_csc_composite,598		.svideo_levels  = &pal_n_levels_svideo,599		.svideo_color = &pal_n_csc_svideo,600 601		.filter_table = filter_table,602	},603	{604		/* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */605		.name	    = "PAL",606		.clock		= 108000,607		.refresh	= 50000,608		.oversample	= 8,609		.component_only = false,610 611		.hsync_end	= 64,		    .hblank_end		= 142,612		.hblank_start	= 844,	    .htotal		= 863,613 614		.progressive	= false,    .trilevel_sync = false,615 616		.vsync_start_f1	= 5,	    .vsync_start_f2	= 6,617		.vsync_len	= 5,618 619		.veq_ena	= true,	    .veq_start_f1	= 0,620		.veq_start_f2	= 1,	    .veq_len		= 15,621 622		.vi_end_f1	= 24,		    .vi_end_f2		= 25,623		.nbr_end	= 286,624 625		.burst_ena	= true,626		.hburst_start	= 73,		    .hburst_len		= 32,627		.vburst_start_f1 = 8,		    .vburst_end_f1	= 285,628		.vburst_start_f2 = 8,		    .vburst_end_f2	= 286,629		.vburst_start_f3 = 9,		    .vburst_end_f3	= 286,630		.vburst_start_f4 = 9,		    .vburst_end_f4	= 285,631 632		/* desired 4.4336180 actual 4.4336180 clock 107.52 */633		.dda1_inc       =    168,634		.dda2_inc       =   4122,       .dda2_size      =  27648,635		.dda3_inc       =     67,       .dda3_size      =    625,636		.sc_reset   = TV_SC_RESET_EVERY_8,637		.pal_burst  = true,638 639		.composite_levels = &pal_levels_composite,640		.composite_color = &pal_csc_composite,641		.svideo_levels  = &pal_levels_svideo,642		.svideo_color = &pal_csc_svideo,643 644		.filter_table = filter_table,645	},646	{647		.name       = "480p",648		.clock		= 108000,649		.refresh	= 59940,650		.oversample     = 4,651		.component_only = true,652 653		.hsync_end      = 64,               .hblank_end         = 122,654		.hblank_start   = 842,              .htotal             = 857,655 656		.progressive    = true,		    .trilevel_sync = false,657 658		.vsync_start_f1 = 12,               .vsync_start_f2     = 12,659		.vsync_len      = 12,660 661		.veq_ena        = false,662 663		.vi_end_f1      = 44,               .vi_end_f2          = 44,664		.nbr_end        = 479,665 666		.burst_ena      = false,667 668		.filter_table = filter_table,669	},670	{671		.name       = "576p",672		.clock		= 108000,673		.refresh	= 50000,674		.oversample     = 4,675		.component_only = true,676 677		.hsync_end      = 64,               .hblank_end         = 139,678		.hblank_start   = 859,              .htotal             = 863,679 680		.progressive    = true,		    .trilevel_sync = false,681 682		.vsync_start_f1 = 10,               .vsync_start_f2     = 10,683		.vsync_len      = 10,684 685		.veq_ena        = false,686 687		.vi_end_f1      = 48,               .vi_end_f2          = 48,688		.nbr_end        = 575,689 690		.burst_ena      = false,691 692		.filter_table = filter_table,693	},694	{695		.name       = "720p@60Hz",696		.clock		= 148500,697		.refresh	= 60000,698		.oversample     = 2,699		.component_only = true,700 701		.hsync_end      = 80,               .hblank_end         = 300,702		.hblank_start   = 1580,             .htotal             = 1649,703 704		.progressive	= true,		    .trilevel_sync = true,705 706		.vsync_start_f1 = 10,               .vsync_start_f2     = 10,707		.vsync_len      = 10,708 709		.veq_ena        = false,710 711		.vi_end_f1      = 29,               .vi_end_f2          = 29,712		.nbr_end        = 719,713 714		.burst_ena      = false,715 716		.filter_table = filter_table,717	},718	{719		.name       = "720p@50Hz",720		.clock		= 148500,721		.refresh	= 50000,722		.oversample     = 2,723		.component_only = true,724 725		.hsync_end      = 80,               .hblank_end         = 300,726		.hblank_start   = 1580,             .htotal             = 1979,727 728		.progressive	= true,		    .trilevel_sync = true,729 730		.vsync_start_f1 = 10,               .vsync_start_f2     = 10,731		.vsync_len      = 10,732 733		.veq_ena        = false,734 735		.vi_end_f1      = 29,               .vi_end_f2          = 29,736		.nbr_end        = 719,737 738		.burst_ena      = false,739 740		.filter_table = filter_table,741	},742	{743		.name       = "1080i@50Hz",744		.clock		= 148500,745		.refresh	= 50000,746		.oversample     = 2,747		.component_only = true,748 749		.hsync_end      = 88,               .hblank_end         = 235,750		.hblank_start   = 2155,             .htotal             = 2639,751 752		.progressive	= false,	  .trilevel_sync = true,753 754		.vsync_start_f1 = 4,              .vsync_start_f2     = 5,755		.vsync_len      = 10,756 757		.veq_ena	= true,	    .veq_start_f1	= 4,758		.veq_start_f2   = 4,	    .veq_len		= 10,759 760 761		.vi_end_f1      = 21,           .vi_end_f2          = 22,762		.nbr_end        = 539,763 764		.burst_ena      = false,765 766		.filter_table = filter_table,767	},768	{769		.name       = "1080i@60Hz",770		.clock		= 148500,771		.refresh	= 60000,772		.oversample     = 2,773		.component_only = true,774 775		.hsync_end      = 88,               .hblank_end         = 235,776		.hblank_start   = 2155,             .htotal             = 2199,777 778		.progressive	= false,	    .trilevel_sync = true,779 780		.vsync_start_f1 = 4,               .vsync_start_f2     = 5,781		.vsync_len      = 10,782 783		.veq_ena	= true,		    .veq_start_f1	= 4,784		.veq_start_f2	= 4,		    .veq_len		= 10,785 786 787		.vi_end_f1      = 21,               .vi_end_f2          = 22,788		.nbr_end        = 539,789 790		.burst_ena      = false,791 792		.filter_table = filter_table,793	},794 795	{796		.name       = "1080p@30Hz",797		.clock		= 148500,798		.refresh	= 30000,799		.oversample     = 2,800		.component_only = true,801 802		.hsync_end      = 88,               .hblank_end         = 235,803		.hblank_start   = 2155,             .htotal             = 2199,804 805		.progressive	= true,		    .trilevel_sync = true,806 807		.vsync_start_f1 = 8,               .vsync_start_f2     = 8,808		.vsync_len      = 10,809 810		.veq_ena	= false,	.veq_start_f1	= 0,811		.veq_start_f2	= 0,		    .veq_len		= 0,812 813		.vi_end_f1      = 44,               .vi_end_f2          = 44,814		.nbr_end        = 1079,815 816		.burst_ena      = false,817 818		.filter_table = filter_table,819	},820 821	{822		.name       = "1080p@50Hz",823		.clock		= 148500,824		.refresh	= 50000,825		.oversample     = 1,826		.component_only = true,827 828		.hsync_end      = 88,               .hblank_end         = 235,829		.hblank_start   = 2155,             .htotal             = 2639,830 831		.progressive	= true,		    .trilevel_sync = true,832 833		.vsync_start_f1 = 8,               .vsync_start_f2     = 8,834		.vsync_len      = 10,835 836		.veq_ena	= false,	.veq_start_f1	= 0,837		.veq_start_f2	= 0,		    .veq_len		= 0,838 839		.vi_end_f1      = 44,               .vi_end_f2          = 44,840		.nbr_end        = 1079,841 842		.burst_ena      = false,843 844		.filter_table = filter_table,845	},846 847	{848		.name       = "1080p@60Hz",849		.clock		= 148500,850		.refresh	= 60000,851		.oversample     = 1,852		.component_only = true,853 854		.hsync_end      = 88,               .hblank_end         = 235,855		.hblank_start   = 2155,             .htotal             = 2199,856 857		.progressive	= true,		    .trilevel_sync = true,858 859		.vsync_start_f1 = 8,               .vsync_start_f2     = 8,860		.vsync_len      = 10,861 862		.veq_ena	= false,		    .veq_start_f1	= 0,863		.veq_start_f2	= 0,		    .veq_len		= 0,864 865		.vi_end_f1      = 44,               .vi_end_f2          = 44,866		.nbr_end        = 1079,867 868		.burst_ena      = false,869 870		.filter_table = filter_table,871	},872};873 874struct intel_tv_connector_state {875	struct drm_connector_state base;876 877	/*878	 * May need to override the user margins for879	 * gen3 >1024 wide source vertical centering.880	 */881	struct {882		u16 top, bottom;883	} margins;884 885	bool bypass_vfilter;886};887 888#define to_intel_tv_connector_state(conn_state) \889	container_of_const((conn_state), struct intel_tv_connector_state, base)890 891static struct drm_connector_state *892intel_tv_connector_duplicate_state(struct drm_connector *connector)893{894	struct intel_tv_connector_state *state;895 896	state = kmemdup(connector->state, sizeof(*state), GFP_KERNEL);897	if (!state)898		return NULL;899 900	__drm_atomic_helper_connector_duplicate_state(connector, &state->base);901	return &state->base;902}903 904static struct intel_tv *enc_to_tv(struct intel_encoder *encoder)905{906	return container_of(encoder, struct intel_tv, base);907}908 909static struct intel_tv *intel_attached_tv(struct intel_connector *connector)910{911	return enc_to_tv(intel_attached_encoder(connector));912}913 914static bool915intel_tv_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe)916{917	struct intel_display *display = to_intel_display(encoder);918	u32 tmp = intel_de_read(display, TV_CTL);919 920	*pipe = (tmp & TV_ENC_PIPE_SEL_MASK) >> TV_ENC_PIPE_SEL_SHIFT;921 922	return tmp & TV_ENC_ENABLE;923}924 925static void926intel_enable_tv(struct intel_atomic_state *state,927		struct intel_encoder *encoder,928		const struct intel_crtc_state *pipe_config,929		const struct drm_connector_state *conn_state)930{931	struct intel_display *display = to_intel_display(encoder);932 933	/* Prevents vblank waits from timing out in intel_tv_detect_type() */934	intel_crtc_wait_for_next_vblank(to_intel_crtc(pipe_config->uapi.crtc));935 936	intel_de_rmw(display, TV_CTL, 0, TV_ENC_ENABLE);937}938 939static void940intel_disable_tv(struct intel_atomic_state *state,941		 struct intel_encoder *encoder,942		 const struct intel_crtc_state *old_crtc_state,943		 const struct drm_connector_state *old_conn_state)944{945	struct intel_display *display = to_intel_display(encoder);946 947	intel_de_rmw(display, TV_CTL, TV_ENC_ENABLE, 0);948}949 950static const struct tv_mode *intel_tv_mode_find(const struct drm_connector_state *conn_state)951{952	int format = conn_state->tv.legacy_mode;953 954	return &tv_modes[format];955}956 957static enum drm_mode_status958intel_tv_mode_valid(struct drm_connector *connector,959		    struct drm_display_mode *mode)960{961	struct intel_display *display = to_intel_display(connector->dev);962	struct drm_i915_private *i915 = to_i915(connector->dev);963	const struct tv_mode *tv_mode = intel_tv_mode_find(connector->state);964	int max_dotclk = display->cdclk.max_dotclk_freq;965	enum drm_mode_status status;966 967	status = intel_cpu_transcoder_mode_valid(i915, mode);968	if (status != MODE_OK)969		return status;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 int982intel_tv_mode_vdisplay(const struct tv_mode *tv_mode)983{984	if (tv_mode->progressive)985		return tv_mode->nbr_end + 1;986	else987		return 2 * (tv_mode->nbr_end + 1);988}989 990static void991intel_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_end1001	 *    | hblank_end1002	 *    |    | hblank_start1003	 *    |    |       | htotal1004	 *    |     _______    |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_start1020	 *    | vsync_end1021	 *    |  | vi_end nbr_end1022	 *    |  |    |       |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 void1091intel_tv_get_config(struct intel_encoder *encoder,1092		    struct intel_crtc_state *pipe_config)1093{1094	struct intel_display *display = to_intel_display(encoder);1095	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);1096	struct drm_display_mode *adjusted_mode =1097		&pipe_config->hw.adjusted_mode;1098	struct drm_display_mode mode = {};1099	u32 tv_ctl, hctl1, hctl3, vctl1, vctl2, tmp;1100	struct tv_mode tv_mode = {};1101	int hdisplay = adjusted_mode->crtc_hdisplay;1102	int vdisplay = adjusted_mode->crtc_vdisplay;1103	int xsize, ysize, xpos, ypos;1104 1105	pipe_config->output_types |= BIT(INTEL_OUTPUT_TVOUT);1106 1107	tv_ctl = intel_de_read(display, TV_CTL);1108	hctl1 = intel_de_read(display, TV_H_CTL_1);1109	hctl3 = intel_de_read(display, TV_H_CTL_3);1110	vctl1 = intel_de_read(display, TV_V_CTL_1);1111	vctl2 = intel_de_read(display, TV_V_CTL_2);1112 1113	tv_mode.htotal = (hctl1 & TV_HTOTAL_MASK) >> TV_HTOTAL_SHIFT;1114	tv_mode.hsync_end = (hctl1 & TV_HSYNC_END_MASK) >> TV_HSYNC_END_SHIFT;1115 1116	tv_mode.hblank_start = (hctl3 & TV_HBLANK_START_MASK) >> TV_HBLANK_START_SHIFT;1117	tv_mode.hblank_end = (hctl3 & TV_HSYNC_END_MASK) >> TV_HBLANK_END_SHIFT;1118 1119	tv_mode.nbr_end = (vctl1 & TV_NBR_END_MASK) >> TV_NBR_END_SHIFT;1120	tv_mode.vi_end_f1 = (vctl1 & TV_VI_END_F1_MASK) >> TV_VI_END_F1_SHIFT;1121	tv_mode.vi_end_f2 = (vctl1 & TV_VI_END_F2_MASK) >> TV_VI_END_F2_SHIFT;1122 1123	tv_mode.vsync_len = (vctl2 & TV_VSYNC_LEN_MASK) >> TV_VSYNC_LEN_SHIFT;1124	tv_mode.vsync_start_f1 = (vctl2 & TV_VSYNC_START_F1_MASK) >> TV_VSYNC_START_F1_SHIFT;1125	tv_mode.vsync_start_f2 = (vctl2 & TV_VSYNC_START_F2_MASK) >> TV_VSYNC_START_F2_SHIFT;1126 1127	tv_mode.clock = pipe_config->port_clock;1128 1129	tv_mode.progressive = tv_ctl & TV_PROGRESSIVE;1130 1131	switch (tv_ctl & TV_OVERSAMPLE_MASK) {1132	case TV_OVERSAMPLE_8X:1133		tv_mode.oversample = 8;1134		break;1135	case TV_OVERSAMPLE_4X:1136		tv_mode.oversample = 4;1137		break;1138	case TV_OVERSAMPLE_2X:1139		tv_mode.oversample = 2;1140		break;1141	default:1142		tv_mode.oversample = 1;1143		break;1144	}1145 1146	tmp = intel_de_read(display, TV_WIN_POS);1147	xpos = tmp >> 16;1148	ypos = tmp & 0xffff;1149 1150	tmp = intel_de_read(display, TV_WIN_SIZE);1151	xsize = tmp >> 16;1152	ysize = tmp & 0xffff;1153 1154	intel_tv_mode_to_mode(&mode, &tv_mode, pipe_config->port_clock);1155 1156	drm_dbg_kms(display->drm, "TV mode: " DRM_MODE_FMT "\n",1157		    DRM_MODE_ARG(&mode));1158 1159	intel_tv_scale_mode_horiz(&mode, hdisplay,1160				  xpos, mode.hdisplay - xsize - xpos);1161	intel_tv_scale_mode_vert(&mode, vdisplay,1162				 ypos, mode.vdisplay - ysize - ypos);1163 1164	adjusted_mode->crtc_clock = mode.clock;1165	if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)1166		adjusted_mode->crtc_clock /= 2;1167 1168	/* pixel counter doesn't work on i965gm TV output */1169	if (IS_I965GM(dev_priv))1170		pipe_config->mode_flags |=1171			I915_MODE_FLAG_USE_SCANLINE_COUNTER;1172}1173 1174static bool intel_tv_source_too_wide(struct intel_display *display,1175				     int hdisplay)1176{1177	return DISPLAY_VER(display) == 3 && hdisplay > 1024;1178}1179 1180static bool intel_tv_vert_scaling(const struct drm_display_mode *tv_mode,1181				  const struct drm_connector_state *conn_state,1182				  int vdisplay)1183{1184	return tv_mode->crtc_vdisplay -1185		conn_state->tv.margins.top -1186		conn_state->tv.margins.bottom !=1187		vdisplay;1188}1189 1190static int1191intel_tv_compute_config(struct intel_encoder *encoder,1192			struct intel_crtc_state *pipe_config,1193			struct drm_connector_state *conn_state)1194{1195	struct intel_display *display = to_intel_display(encoder);1196	struct intel_atomic_state *state =1197		to_intel_atomic_state(pipe_config->uapi.state);1198	struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);1199	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);1200	struct intel_tv_connector_state *tv_conn_state =1201		to_intel_tv_connector_state(conn_state);1202	const struct tv_mode *tv_mode = intel_tv_mode_find(conn_state);1203	struct drm_display_mode *adjusted_mode =1204		&pipe_config->hw.adjusted_mode;1205	int hdisplay = adjusted_mode->crtc_hdisplay;1206	int vdisplay = adjusted_mode->crtc_vdisplay;1207	int ret;1208 1209	if (!tv_mode)1210		return -EINVAL;1211 1212	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)1213		return -EINVAL;1214 1215	pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;1216	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;1217 1218	drm_dbg_kms(display->drm, "forcing bpc to 8 for TV\n");1219	pipe_config->pipe_bpp = 8*3;1220 1221	pipe_config->port_clock = tv_mode->clock;1222 1223	ret = intel_dpll_crtc_compute_clock(state, crtc);1224	if (ret)1225		return ret;1226 1227	pipe_config->clock_set = true;1228 1229	intel_tv_mode_to_mode(adjusted_mode, tv_mode, pipe_config->port_clock);1230	drm_mode_set_crtcinfo(adjusted_mode, 0);1231 1232	if (intel_tv_source_too_wide(display, hdisplay) ||1233	    !intel_tv_vert_scaling(adjusted_mode, conn_state, vdisplay)) {1234		int extra, top, bottom;1235 1236		extra = adjusted_mode->crtc_vdisplay - vdisplay;1237 1238		if (extra < 0) {1239			drm_dbg_kms(display->drm,1240				    "No vertical scaling for >1024 pixel wide modes\n");1241			return -EINVAL;1242		}1243 1244		/* Need to turn off the vertical filter and center the image */1245 1246		/* Attempt to maintain the relative sizes of the margins */1247		top = conn_state->tv.margins.top;1248		bottom = conn_state->tv.margins.bottom;1249 1250		if (top + bottom)1251			top = extra * top / (top + bottom);1252		else1253			top = extra / 2;1254		bottom = extra - top;1255 1256		tv_conn_state->margins.top = top;1257		tv_conn_state->margins.bottom = bottom;1258 1259		tv_conn_state->bypass_vfilter = true;1260 1261		if (!tv_mode->progressive) {1262			adjusted_mode->clock /= 2;1263			adjusted_mode->crtc_clock /= 2;1264			adjusted_mode->flags |= DRM_MODE_FLAG_INTERLACE;1265		}1266	} else {1267		tv_conn_state->margins.top = conn_state->tv.margins.top;1268		tv_conn_state->margins.bottom = conn_state->tv.margins.bottom;1269 1270		tv_conn_state->bypass_vfilter = false;1271	}1272 1273	drm_dbg_kms(display->drm, "TV mode: " DRM_MODE_FMT "\n",1274		    DRM_MODE_ARG(adjusted_mode));1275 1276	/*1277	 * The pipe scanline counter behaviour looks as follows when1278	 * using the TV encoder:1279	 *1280	 * time ->1281	 *1282	 * dsl=vtotal-1       |             |1283	 *                   ||            ||1284	 *               ___| |        ___| |1285	 *              /     |       /     |1286	 *             /      |      /      |1287	 * dsl=0   ___/       |_____/       |1288	 *        | | |  |  | |1289	 *         ^ ^ ^   ^ ^1290	 *         | | |   | pipe vblank/first part of tv vblank1291	 *         | | |   bottom margin1292	 *         | | active1293	 *         | top margin1294	 *         remainder of tv vblank1295	 *1296	 * When the TV encoder is used the pipe wants to run faster1297	 * than expected rate. During the active portion the TV1298	 * encoder stalls the pipe every few lines to keep it in1299	 * check. When the TV encoder reaches the bottom margin the1300	 * pipe simply stops. Once we reach the TV vblank the pipe is1301	 * no longer stalled and it runs at the max rate (apparently1302	 * oversample clock on gen3, cdclk on gen4). Once the pipe1303	 * reaches the pipe vtotal the pipe stops for the remainder1304	 * of the TV vblank/top margin. The pipe starts up again when1305	 * the TV encoder exits the top margin.1306	 *1307	 * To avoid huge hassles for vblank timestamping we scale1308	 * the pipe timings as if the pipe always runs at the average1309	 * rate it maintains during the active period. This also1310	 * gives us a reasonable guesstimate as to the pixel rate.1311	 * Due to the variation in the actual pipe speed the scanline1312	 * counter will give us slightly erroneous results during the1313	 * TV vblank/margins. But since vtotal was selected such that1314	 * it matches the average rate of the pipe during the active1315	 * portion the error shouldn't cause any serious grief to1316	 * vblank timestamps.1317	 *1318	 * For posterity here is the empirically derived formula1319	 * that gives us the maximum length of the pipe vblank1320	 * we can use without causing display corruption. Following1321	 * this would allow us to have a ticking scanline counter1322	 * everywhere except during the bottom margin (there the1323	 * pipe always stops). Ie. this would eliminate the second1324	 * flat portion of the above graph. However this would also1325	 * complicate vblank timestamping as the pipe vtotal would1326	 * no longer match the average rate the pipe runs at during1327	 * the active portion. Hence following this formula seems1328	 * more trouble that it's worth.1329	 *1330	 * if (DISPLAY_VER(dev_priv) == 4) {1331	 *	num = cdclk * (tv_mode->oversample >> !tv_mode->progressive);1332	 *	den = tv_mode->clock;1333	 * } else {1334	 *	num = tv_mode->oversample >> !tv_mode->progressive;1335	 *	den = 1;1336	 * }1337	 * max_pipe_vblank_len ~=1338	 *	(num * tv_htotal * (tv_vblank_len + top_margin)) /1339	 *	(den * pipe_htotal);1340	 */1341	intel_tv_scale_mode_horiz(adjusted_mode, hdisplay,1342				  conn_state->tv.margins.left,1343				  conn_state->tv.margins.right);1344	intel_tv_scale_mode_vert(adjusted_mode, vdisplay,1345				 tv_conn_state->margins.top,1346				 tv_conn_state->margins.bottom);1347	drm_mode_set_crtcinfo(adjusted_mode, 0);1348	adjusted_mode->name[0] = '\0';1349 1350	/* pixel counter doesn't work on i965gm TV output */1351	if (IS_I965GM(dev_priv))1352		pipe_config->mode_flags |=1353			I915_MODE_FLAG_USE_SCANLINE_COUNTER;1354 1355	return 0;1356}1357 1358static void1359set_tv_mode_timings(struct intel_display *display,1360		    const struct tv_mode *tv_mode,1361		    bool burst_ena)1362{1363	u32 hctl1, hctl2, hctl3;1364	u32 vctl1, vctl2, vctl3, vctl4, vctl5, vctl6, vctl7;1365 1366	hctl1 = (tv_mode->hsync_end << TV_HSYNC_END_SHIFT) |1367		(tv_mode->htotal << TV_HTOTAL_SHIFT);1368 1369	hctl2 = (tv_mode->hburst_start << 16) |1370		(tv_mode->hburst_len << TV_HBURST_LEN_SHIFT);1371 1372	if (burst_ena)1373		hctl2 |= TV_BURST_ENA;1374 1375	hctl3 = (tv_mode->hblank_start << TV_HBLANK_START_SHIFT) |1376		(tv_mode->hblank_end << TV_HBLANK_END_SHIFT);1377 1378	vctl1 = (tv_mode->nbr_end << TV_NBR_END_SHIFT) |1379		(tv_mode->vi_end_f1 << TV_VI_END_F1_SHIFT) |1380		(tv_mode->vi_end_f2 << TV_VI_END_F2_SHIFT);1381 1382	vctl2 = (tv_mode->vsync_len << TV_VSYNC_LEN_SHIFT) |1383		(tv_mode->vsync_start_f1 << TV_VSYNC_START_F1_SHIFT) |1384		(tv_mode->vsync_start_f2 << TV_VSYNC_START_F2_SHIFT);1385 1386	vctl3 = (tv_mode->veq_len << TV_VEQ_LEN_SHIFT) |1387		(tv_mode->veq_start_f1 << TV_VEQ_START_F1_SHIFT) |1388		(tv_mode->veq_start_f2 << TV_VEQ_START_F2_SHIFT);1389 1390	if (tv_mode->veq_ena)1391		vctl3 |= TV_EQUAL_ENA;1392 1393	vctl4 = (tv_mode->vburst_start_f1 << TV_VBURST_START_F1_SHIFT) |1394		(tv_mode->vburst_end_f1 << TV_VBURST_END_F1_SHIFT);1395 1396	vctl5 = (tv_mode->vburst_start_f2 << TV_VBURST_START_F2_SHIFT) |1397		(tv_mode->vburst_end_f2 << TV_VBURST_END_F2_SHIFT);1398 1399	vctl6 = (tv_mode->vburst_start_f3 << TV_VBURST_START_F3_SHIFT) |1400		(tv_mode->vburst_end_f3 << TV_VBURST_END_F3_SHIFT);1401 1402	vctl7 = (tv_mode->vburst_start_f4 << TV_VBURST_START_F4_SHIFT) |1403		(tv_mode->vburst_end_f4 << TV_VBURST_END_F4_SHIFT);1404 1405	intel_de_write(display, TV_H_CTL_1, hctl1);1406	intel_de_write(display, TV_H_CTL_2, hctl2);1407	intel_de_write(display, TV_H_CTL_3, hctl3);1408	intel_de_write(display, TV_V_CTL_1, vctl1);1409	intel_de_write(display, TV_V_CTL_2, vctl2);1410	intel_de_write(display, TV_V_CTL_3, vctl3);1411	intel_de_write(display, TV_V_CTL_4, vctl4);1412	intel_de_write(display, TV_V_CTL_5, vctl5);1413	intel_de_write(display, TV_V_CTL_6, vctl6);1414	intel_de_write(display, TV_V_CTL_7, vctl7);1415}1416 1417static void set_color_conversion(struct intel_display *display,1418				 const struct color_conversion *color_conversion)1419{1420	intel_de_write(display, TV_CSC_Y,1421		       (color_conversion->ry << 16) | color_conversion->gy);1422	intel_de_write(display, TV_CSC_Y2,1423		       (color_conversion->by << 16) | color_conversion->ay);1424	intel_de_write(display, TV_CSC_U,1425		       (color_conversion->ru << 16) | color_conversion->gu);1426	intel_de_write(display, TV_CSC_U2,1427		       (color_conversion->bu << 16) | color_conversion->au);1428	intel_de_write(display, TV_CSC_V,1429		       (color_conversion->rv << 16) | color_conversion->gv);1430	intel_de_write(display, TV_CSC_V2,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 intel_display *display = to_intel_display(encoder);1440	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);1441	struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);1442	struct intel_tv *intel_tv = enc_to_tv(encoder);1443	const struct intel_tv_connector_state *tv_conn_state =1444		to_intel_tv_connector_state(conn_state);1445	const struct tv_mode *tv_mode = intel_tv_mode_find(conn_state);1446	u32 tv_ctl, tv_filter_ctl;1447	u32 scctl1, scctl2, scctl3;1448	int i, j;1449	const struct video_levels *video_levels;1450	const struct color_conversion *color_conversion;1451	bool burst_ena;1452	int xpos, ypos;1453	unsigned int xsize, ysize;1454 1455	tv_ctl = intel_de_read(display, TV_CTL);1456	tv_ctl &= TV_CTL_SAVE;1457 1458	switch (intel_tv->type) {1459	default:1460	case DRM_MODE_CONNECTOR_Unknown:1461	case DRM_MODE_CONNECTOR_Composite:1462		tv_ctl |= TV_ENC_OUTPUT_COMPOSITE;1463		video_levels = tv_mode->composite_levels;1464		color_conversion = tv_mode->composite_color;1465		burst_ena = tv_mode->burst_ena;1466		break;1467	case DRM_MODE_CONNECTOR_Component:1468		tv_ctl |= TV_ENC_OUTPUT_COMPONENT;1469		video_levels = &component_levels;1470		if (tv_mode->burst_ena)1471			color_conversion = &sdtv_csc_yprpb;1472		else1473			color_conversion = &hdtv_csc_yprpb;1474		burst_ena = false;1475		break;1476	case DRM_MODE_CONNECTOR_SVIDEO:1477		tv_ctl |= TV_ENC_OUTPUT_SVIDEO;1478		video_levels = tv_mode->svideo_levels;1479		color_conversion = tv_mode->svideo_color;1480		burst_ena = tv_mode->burst_ena;1481		break;1482	}1483 1484	tv_ctl |= TV_ENC_PIPE_SEL(crtc->pipe);1485 1486	switch (tv_mode->oversample) {1487	case 8:1488		tv_ctl |= TV_OVERSAMPLE_8X;1489		break;1490	case 4:1491		tv_ctl |= TV_OVERSAMPLE_4X;1492		break;1493	case 2:1494		tv_ctl |= TV_OVERSAMPLE_2X;1495		break;1496	default:1497		tv_ctl |= TV_OVERSAMPLE_NONE;1498		break;1499	}1500 1501	if (tv_mode->progressive)1502		tv_ctl |= TV_PROGRESSIVE;1503	if (tv_mode->trilevel_sync)1504		tv_ctl |= TV_TRILEVEL_SYNC;1505	if (tv_mode->pal_burst)1506		tv_ctl |= TV_PAL_BURST;1507 1508	scctl1 = 0;1509	if (tv_mode->dda1_inc)1510		scctl1 |= TV_SC_DDA1_EN;1511	if (tv_mode->dda2_inc)1512		scctl1 |= TV_SC_DDA2_EN;1513	if (tv_mode->dda3_inc)1514		scctl1 |= TV_SC_DDA3_EN;1515	scctl1 |= tv_mode->sc_reset;1516	if (video_levels)1517		scctl1 |= video_levels->burst << TV_BURST_LEVEL_SHIFT;1518	scctl1 |= tv_mode->dda1_inc << TV_SCDDA1_INC_SHIFT;1519 1520	scctl2 = tv_mode->dda2_size << TV_SCDDA2_SIZE_SHIFT |1521		tv_mode->dda2_inc << TV_SCDDA2_INC_SHIFT;1522 1523	scctl3 = tv_mode->dda3_size << TV_SCDDA3_SIZE_SHIFT |1524		tv_mode->dda3_inc << TV_SCDDA3_INC_SHIFT;1525 1526	/* Enable two fixes for the chips that need them. */1527	if (IS_I915GM(dev_priv))1528		tv_ctl |= TV_ENC_C0_FIX | TV_ENC_SDP_FIX;1529 1530	set_tv_mode_timings(display, tv_mode, burst_ena);1531 1532	intel_de_write(display, TV_SC_CTL_1, scctl1);1533	intel_de_write(display, TV_SC_CTL_2, scctl2);1534	intel_de_write(display, TV_SC_CTL_3, scctl3);1535 1536	set_color_conversion(display, color_conversion);1537 1538	if (DISPLAY_VER(display) >= 4)1539		intel_de_write(display, TV_CLR_KNOBS, 0x00404000);1540	else1541		intel_de_write(display, TV_CLR_KNOBS, 0x00606000);1542 1543	if (video_levels)1544		intel_de_write(display, TV_CLR_LEVEL,1545			       ((video_levels->black << TV_BLACK_LEVEL_SHIFT) | (video_levels->blank << TV_BLANK_LEVEL_SHIFT)));1546 1547	assert_transcoder_disabled(dev_priv, pipe_config->cpu_transcoder);1548 1549	/* Filter ctl must be set before TV_WIN_SIZE */1550	tv_filter_ctl = TV_AUTO_SCALE;1551	if (tv_conn_state->bypass_vfilter)1552		tv_filter_ctl |= TV_V_FILTER_BYPASS;1553	intel_de_write(display, TV_FILTER_CTL_1, tv_filter_ctl);1554 1555	xsize = tv_mode->hblank_start - tv_mode->hblank_end;1556	ysize = intel_tv_mode_vdisplay(tv_mode);1557 1558	xpos = conn_state->tv.margins.left;1559	ypos = tv_conn_state->margins.top;1560	xsize -= (conn_state->tv.margins.left +1561		  conn_state->tv.margins.right);1562	ysize -= (tv_conn_state->margins.top +1563		  tv_conn_state->margins.bottom);1564	intel_de_write(display, TV_WIN_POS, (xpos << 16) | ypos);1565	intel_de_write(display, TV_WIN_SIZE, (xsize << 16) | ysize);1566 1567	j = 0;1568	for (i = 0; i < 60; i++)1569		intel_de_write(display, TV_H_LUMA(i),1570			       tv_mode->filter_table[j++]);1571	for (i = 0; i < 60; i++)1572		intel_de_write(display, TV_H_CHROMA(i),1573			       tv_mode->filter_table[j++]);1574	for (i = 0; i < 43; i++)1575		intel_de_write(display, TV_V_LUMA(i),1576			       tv_mode->filter_table[j++]);1577	for (i = 0; i < 43; i++)1578		intel_de_write(display, TV_V_CHROMA(i),1579			       tv_mode->filter_table[j++]);1580	intel_de_write(display, TV_DAC,1581		       intel_de_read(display, TV_DAC) & TV_DAC_SAVE);1582	intel_de_write(display, TV_CTL, tv_ctl);1583}1584 1585static int1586intel_tv_detect_type(struct intel_tv *intel_tv,1587		      struct drm_connector *connector)1588{1589	struct intel_display *display = to_intel_display(connector->dev);1590	struct intel_crtc *crtc = to_intel_crtc(connector->state->crtc);1591	struct drm_device *dev = connector->dev;1592	struct drm_i915_private *dev_priv = to_i915(dev);1593	u32 tv_ctl, save_tv_ctl;1594	u32 tv_dac, save_tv_dac;1595	int type;1596 1597	/* Disable TV interrupts around load detect or we'll recurse */1598	if (connector->polled & DRM_CONNECTOR_POLL_HPD) {1599		spin_lock_irq(&dev_priv->irq_lock);1600		i915_disable_pipestat(dev_priv, 0,1601				      PIPE_HOTPLUG_INTERRUPT_STATUS |1602				      PIPE_HOTPLUG_TV_INTERRUPT_STATUS);1603		spin_unlock_irq(&dev_priv->irq_lock);1604	}1605 1606	save_tv_dac = tv_dac = intel_de_read(display, TV_DAC);1607	save_tv_ctl = tv_ctl = intel_de_read(display, TV_CTL);1608 1609	/* Poll for TV detection */1610	tv_ctl &= ~(TV_ENC_ENABLE | TV_ENC_PIPE_SEL_MASK | TV_TEST_MODE_MASK);1611	tv_ctl |= TV_TEST_MODE_MONITOR_DETECT;1612	tv_ctl |= TV_ENC_PIPE_SEL(crtc->pipe);1613 1614	tv_dac &= ~(TVDAC_SENSE_MASK | DAC_A_MASK | DAC_B_MASK | DAC_C_MASK);1615	tv_dac |= (TVDAC_STATE_CHG_EN |1616		   TVDAC_A_SENSE_CTL |1617		   TVDAC_B_SENSE_CTL |1618		   TVDAC_C_SENSE_CTL |1619		   DAC_CTL_OVERRIDE |1620		   DAC_A_0_7_V |1621		   DAC_B_0_7_V |1622		   DAC_C_0_7_V);1623 1624 1625	/*1626	 * The TV sense state should be cleared to zero on cantiga platform. Otherwise1627	 * the TV is misdetected. This is hardware requirement.1628	 */1629	if (IS_GM45(dev_priv))1630		tv_dac &= ~(TVDAC_STATE_CHG_EN | TVDAC_A_SENSE_CTL |1631			    TVDAC_B_SENSE_CTL | TVDAC_C_SENSE_CTL);1632 1633	intel_de_write(display, TV_CTL, tv_ctl);1634	intel_de_write(display, TV_DAC, tv_dac);1635	intel_de_posting_read(display, TV_DAC);1636 1637	intel_crtc_wait_for_next_vblank(crtc);1638 1639	type = -1;1640	tv_dac = intel_de_read(display, TV_DAC);1641	drm_dbg_kms(display->drm, "TV detected: %x, %x\n", tv_ctl, tv_dac);1642	/*1643	 *  A B C1644	 *  0 1 1 Composite1645	 *  1 0 X svideo1646	 *  0 0 0 Component1647	 */1648	if ((tv_dac & TVDAC_SENSE_MASK) == (TVDAC_B_SENSE | TVDAC_C_SENSE)) {1649		drm_dbg_kms(display->drm,1650			    "Detected Composite TV connection\n");1651		type = DRM_MODE_CONNECTOR_Composite;1652	} else if ((tv_dac & (TVDAC_A_SENSE|TVDAC_B_SENSE)) == TVDAC_A_SENSE) {1653		drm_dbg_kms(display->drm,1654			    "Detected S-Video TV connection\n");1655		type = DRM_MODE_CONNECTOR_SVIDEO;1656	} else if ((tv_dac & TVDAC_SENSE_MASK) == 0) {1657		drm_dbg_kms(display->drm,1658			    "Detected Component TV connection\n");1659		type = DRM_MODE_CONNECTOR_Component;1660	} else {1661		drm_dbg_kms(display->drm, "Unrecognised TV connection\n");1662		type = -1;1663	}1664 1665	intel_de_write(display, TV_DAC, save_tv_dac & ~TVDAC_STATE_CHG_EN);1666	intel_de_write(display, TV_CTL, save_tv_ctl);1667	intel_de_posting_read(display, TV_CTL);1668 1669	/* For unknown reasons the hw barfs if we don't do this vblank wait. */1670	intel_crtc_wait_for_next_vblank(crtc);1671 1672	/* Restore interrupt config */1673	if (connector->polled & DRM_CONNECTOR_POLL_HPD) {1674		spin_lock_irq(&dev_priv->irq_lock);1675		i915_enable_pipestat(dev_priv, 0,1676				     PIPE_HOTPLUG_INTERRUPT_STATUS |1677				     PIPE_HOTPLUG_TV_INTERRUPT_STATUS);1678		spin_unlock_irq(&dev_priv->irq_lock);1679	}1680 1681	return type;1682}1683 1684/*1685 * Here we set accurate tv format according to connector type1686 * i.e Component TV should not be assigned by NTSC or PAL1687 */1688static void intel_tv_find_better_format(struct drm_connector *connector)1689{1690	struct intel_tv *intel_tv = intel_attached_tv(to_intel_connector(connector));1691	const struct tv_mode *tv_mode = intel_tv_mode_find(connector->state);1692	int i;1693 1694	/* Component supports everything so we can keep the current mode */1695	if (intel_tv->type == DRM_MODE_CONNECTOR_Component)1696		return;1697 1698	/* If the current mode is fine don't change it */1699	if (!tv_mode->component_only)1700		return;1701 1702	for (i = 0; i < ARRAY_SIZE(tv_modes); i++) {1703		tv_mode = &tv_modes[i];1704 1705		if (!tv_mode->component_only)1706			break;1707	}1708 1709	connector->state->tv.legacy_mode = i;1710}1711 1712static int1713intel_tv_detect(struct drm_connector *connector,1714		struct drm_modeset_acquire_ctx *ctx,1715		bool force)1716{1717	struct intel_display *display = to_intel_display(connector->dev);1718	struct drm_i915_private *i915 = to_i915(connector->dev);1719	struct intel_tv *intel_tv = intel_attached_tv(to_intel_connector(connector));1720	enum drm_connector_status status;1721	int type;1722 1723	drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s] force=%d\n",1724		    connector->base.id, connector->name, force);1725 1726	if (!intel_display_device_enabled(i915))1727		return connector_status_disconnected;1728 1729	if (!intel_display_driver_check_access(i915))1730		return connector->status;1731 1732	if (force) {1733		struct drm_atomic_state *state;1734 1735		state = intel_load_detect_get_pipe(connector, ctx);1736		if (IS_ERR(state))1737			return PTR_ERR(state);1738 1739		if (state) {1740			type = intel_tv_detect_type(intel_tv, connector);1741			intel_load_detect_release_pipe(connector, state, ctx);1742			status = type < 0 ?1743				connector_status_disconnected :1744				connector_status_connected;1745		} else {1746			status = connector_status_unknown;1747		}1748 1749		if (status == connector_status_connected) {1750			intel_tv->type = type;1751			intel_tv_find_better_format(connector);1752		}1753 1754		return status;1755	} else1756		return connector->status;1757}1758 1759static const struct input_res {1760	u16 w, h;1761} input_res_table[] = {1762	{ 640, 480 },1763	{ 800, 600 },1764	{ 1024, 768 },1765	{ 1280, 1024 },1766	{ 848, 480 },1767	{ 1280, 720 },1768	{ 1920, 1080 },1769};1770 1771/* Choose preferred mode according to line number of TV format */1772static bool1773intel_tv_is_preferred_mode(const struct drm_display_mode *mode,1774			   const struct tv_mode *tv_mode)1775{1776	int vdisplay = intel_tv_mode_vdisplay(tv_mode);1777 1778	/* prefer 480 line modes for all SD TV modes */1779	if (vdisplay <= 576)1780		vdisplay = 480;1781 1782	return vdisplay == mode->vdisplay;1783}1784 1785static void1786intel_tv_set_mode_type(struct drm_display_mode *mode,1787		       const struct tv_mode *tv_mode)1788{1789	mode->type = DRM_MODE_TYPE_DRIVER;1790 1791	if (intel_tv_is_preferred_mode(mode, tv_mode))1792		mode->type |= DRM_MODE_TYPE_PREFERRED;1793}1794 1795static int1796intel_tv_get_modes(struct drm_connector *connector)1797{1798	struct intel_display *display = to_intel_display(connector->dev);1799	const struct tv_mode *tv_mode = intel_tv_mode_find(connector->state);1800	int i, count = 0;1801 1802	for (i = 0; i < ARRAY_SIZE(input_res_table); i++) {1803		const struct input_res *input = &input_res_table[i];1804		struct drm_display_mode *mode;1805 1806		if (input->w > 1024 &&1807		    !tv_mode->progressive &&1808		    !tv_mode->component_only)1809			continue;1810 1811		/* no vertical scaling with wide sources on gen3 */1812		if (DISPLAY_VER(display) == 3 && input->w > 1024 &&1813		    input->h > intel_tv_mode_vdisplay(tv_mode))1814			continue;1815 1816		mode = drm_mode_create(connector->dev);1817		if (!mode)1818			continue;1819 1820		/*1821		 * We take the TV mode and scale it to look1822		 * like it had the expected h/vdisplay. This1823		 * provides the most information to userspace1824		 * about the actual timings of the mode. We1825		 * do ignore the margins though.1826		 */1827		intel_tv_mode_to_mode(mode, tv_mode, tv_mode->clock);1828		if (count == 0) {1829			drm_dbg_kms(display->drm,1830				    "TV mode: " DRM_MODE_FMT "\n",1831				    DRM_MODE_ARG(mode));1832		}1833		intel_tv_scale_mode_horiz(mode, input->w, 0, 0);1834		intel_tv_scale_mode_vert(mode, input->h, 0, 0);1835		intel_tv_set_mode_type(mode, tv_mode);1836 1837		drm_mode_set_name(mode);1838 1839		drm_mode_probed_add(connector, mode);1840		count++;1841	}1842 1843	return count;1844}1845 1846static const struct drm_connector_funcs intel_tv_connector_funcs = {1847	.late_register = intel_connector_register,1848	.early_unregister = intel_connector_unregister,1849	.destroy = intel_connector_destroy,1850	.fill_modes = drm_helper_probe_single_connector_modes,1851	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,1852	.atomic_duplicate_state = intel_tv_connector_duplicate_state,1853};1854 1855static int intel_tv_atomic_check(struct drm_connector *connector,1856				 struct drm_atomic_state *state)1857{1858	struct drm_connector_state *new_state;1859	struct drm_crtc_state *new_crtc_state;1860	struct drm_connector_state *old_state;1861 1862	new_state = drm_atomic_get_new_connector_state(state, connector);1863	if (!new_state->crtc)1864		return 0;1865 1866	old_state = drm_atomic_get_old_connector_state(state, connector);1867	new_crtc_state = drm_atomic_get_new_crtc_state(state, new_state->crtc);1868 1869	if (old_state->tv.legacy_mode != new_state->tv.legacy_mode ||1870	    old_state->tv.margins.left != new_state->tv.margins.left ||1871	    old_state->tv.margins.right != new_state->tv.margins.right ||1872	    old_state->tv.margins.top != new_state->tv.margins.top ||1873	    old_state->tv.margins.bottom != new_state->tv.margins.bottom) {1874		/* Force a modeset. */1875 1876		new_crtc_state->connectors_changed = true;1877	}1878 1879	return 0;1880}1881 1882static const struct drm_connector_helper_funcs intel_tv_connector_helper_funcs = {1883	.detect_ctx = intel_tv_detect,1884	.mode_valid = intel_tv_mode_valid,1885	.get_modes = intel_tv_get_modes,1886	.atomic_check = intel_tv_atomic_check,1887};1888 1889static const struct drm_encoder_funcs intel_tv_enc_funcs = {1890	.destroy = intel_encoder_destroy,1891};1892 1893static void intel_tv_add_properties(struct drm_connector *connector)1894{1895	struct intel_display *display = to_intel_display(connector->dev);1896	struct drm_connector_state *conn_state = connector->state;1897	const char *tv_format_names[ARRAY_SIZE(tv_modes)];1898	int i;1899 1900	/* BIOS margin values */1901	conn_state->tv.margins.left = 54;1902	conn_state->tv.margins.top = 36;1903	conn_state->tv.margins.right = 46;1904	conn_state->tv.margins.bottom = 37;1905 1906	conn_state->tv.legacy_mode = 0;1907 1908	/* Create TV properties then attach current values */1909	for (i = 0; i < ARRAY_SIZE(tv_modes); i++) {1910		/* 1080p50/1080p60 not supported on gen3 */1911		if (DISPLAY_VER(display) == 3 && tv_modes[i].oversample == 1)1912			break;1913 1914		tv_format_names[i] = tv_modes[i].name;1915	}1916	drm_mode_create_tv_properties_legacy(display->drm, i, tv_format_names);1917 1918	drm_object_attach_property(&connector->base,1919				   display->drm->mode_config.legacy_tv_mode_property,1920				   conn_state->tv.legacy_mode);1921	drm_object_attach_property(&connector->base,1922				   display->drm->mode_config.tv_left_margin_property,1923				   conn_state->tv.margins.left);1924	drm_object_attach_property(&connector->base,1925				   display->drm->mode_config.tv_top_margin_property,1926				   conn_state->tv.margins.top);1927	drm_object_attach_property(&connector->base,1928				   display->drm->mode_config.tv_right_margin_property,1929				   conn_state->tv.margins.right);1930	drm_object_attach_property(&connector->base,1931				   display->drm->mode_config.tv_bottom_margin_property,1932				   conn_state->tv.margins.bottom);1933}1934 1935void1936intel_tv_init(struct intel_display *display)1937{1938	struct drm_connector *connector;1939	struct intel_tv *intel_tv;1940	struct intel_encoder *intel_encoder;1941	struct intel_connector *intel_connector;1942	u32 tv_dac_on, tv_dac_off, save_tv_dac;1943 1944	if ((intel_de_read(display, TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED)1945		return;1946 1947	if (!intel_bios_is_tv_present(display)) {1948		drm_dbg_kms(display->drm, "Integrated TV is not present.\n");1949		return;1950	}1951 1952	/*1953	 * Sanity check the TV output by checking to see if the1954	 * DAC register holds a value1955	 */1956	save_tv_dac = intel_de_read(display, TV_DAC);1957 1958	intel_de_write(display, TV_DAC, save_tv_dac | TVDAC_STATE_CHG_EN);1959	tv_dac_on = intel_de_read(display, TV_DAC);1960 1961	intel_de_write(display, TV_DAC, save_tv_dac & ~TVDAC_STATE_CHG_EN);1962	tv_dac_off = intel_de_read(display, TV_DAC);1963 1964	intel_de_write(display, TV_DAC, save_tv_dac);1965 1966	/*1967	 * If the register does not hold the state change enable1968	 * bit, (either as a 0 or a 1), assume it doesn't really1969	 * exist1970	 */1971	if ((tv_dac_on & TVDAC_STATE_CHG_EN) == 0 ||1972	    (tv_dac_off & TVDAC_STATE_CHG_EN) != 0)1973		return;1974 1975	intel_tv = kzalloc(sizeof(*intel_tv), GFP_KERNEL);1976	if (!intel_tv) {1977		return;1978	}1979 1980	intel_connector = intel_connector_alloc();1981	if (!intel_connector) {1982		kfree(intel_tv);1983		return;1984	}1985 1986	intel_encoder = &intel_tv->base;1987	connector = &intel_connector->base;1988 1989	/*1990	 * The documentation, for the older chipsets at least, recommend1991	 * using a polling method rather than hotplug detection for TVs.1992	 * This is because in order to perform the hotplug detection, the PLLs1993	 * for the TV must be kept alive increasing power drain and starving1994	 * bandwidth from other encoders. Notably for instance, it causes1995	 * pipe underruns on Crestline when this encoder is supposedly idle.1996	 *1997	 * More recent chipsets favour HDMI rather than integrated S-Video.1998	 */1999	intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT;2000	intel_connector->base.polled = intel_connector->polled;2001 2002	drm_connector_init(display->drm, connector, &intel_tv_connector_funcs,2003			   DRM_MODE_CONNECTOR_SVIDEO);2004 2005	drm_encoder_init(display->drm, &intel_encoder->base,2006			 &intel_tv_enc_funcs,2007			 DRM_MODE_ENCODER_TVDAC, "TV");2008 2009	intel_encoder->compute_config = intel_tv_compute_config;2010	intel_encoder->get_config = intel_tv_get_config;2011	intel_encoder->pre_enable = intel_tv_pre_enable;2012	intel_encoder->enable = intel_enable_tv;2013	intel_encoder->disable = intel_disable_tv;2014	intel_encoder->get_hw_state = intel_tv_get_hw_state;2015	intel_connector->get_hw_state = intel_connector_get_hw_state;2016 2017	intel_connector_attach_encoder(intel_connector, intel_encoder);2018 2019	intel_encoder->type = INTEL_OUTPUT_TVOUT;2020	intel_encoder->power_domain = POWER_DOMAIN_PORT_OTHER;2021	intel_encoder->port = PORT_NONE;2022	intel_encoder->pipe_mask = ~0;2023	intel_encoder->cloneable = 0;2024	intel_tv->type = DRM_MODE_CONNECTOR_Unknown;2025 2026	drm_connector_helper_add(connector, &intel_tv_connector_helper_funcs);2027 2028	intel_tv_add_properties(connector);2029}2030