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