LCOV - code coverage report
Current view: top level - dev/pci/drm/i915 - intel_tv.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 432 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 22 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright © 2006-2008 Intel Corporation
       3             :  *   Jesse Barnes <jesse.barnes@intel.com>
       4             :  *
       5             :  * Permission is hereby granted, free of charge, to any person obtaining a
       6             :  * copy of this software and associated documentation files (the "Software"),
       7             :  * to deal in the Software without restriction, including without limitation
       8             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
       9             :  * and/or sell copies of the Software, and to permit persons to whom the
      10             :  * Software is furnished to do so, subject to the following conditions:
      11             :  *
      12             :  * The above copyright notice and this permission notice (including the next
      13             :  * paragraph) shall be included in all copies or substantial portions of the
      14             :  * Software.
      15             :  *
      16             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      17             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      18             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      19             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      20             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      21             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      22             :  * DEALINGS IN THE SOFTWARE.
      23             :  *
      24             :  * Authors:
      25             :  *    Eric Anholt <eric@anholt.net>
      26             :  *
      27             :  */
      28             : 
      29             : /** @file
      30             :  * Integrated TV-out support for the 915GM and 945GM.
      31             :  */
      32             : 
      33             : #include <dev/pci/drm/drmP.h>
      34             : #include <dev/pci/drm/drm_atomic_helper.h>
      35             : #include <dev/pci/drm/drm_crtc.h>
      36             : #include <dev/pci/drm/drm_edid.h>
      37             : #include "intel_drv.h"
      38             : #include <dev/pci/drm/i915_drm.h>
      39             : #include "i915_drv.h"
      40             : 
      41             : enum tv_margin {
      42             :         TV_MARGIN_LEFT, TV_MARGIN_TOP,
      43             :         TV_MARGIN_RIGHT, TV_MARGIN_BOTTOM
      44             : };
      45             : 
      46             : /** Private structure for the integrated TV support */
      47             : struct intel_tv {
      48             :         struct intel_encoder base;
      49             : 
      50             :         int type;
      51             :         const char *tv_format;
      52             :         int margin[4];
      53             :         u32 save_TV_H_CTL_1;
      54             :         u32 save_TV_H_CTL_2;
      55             :         u32 save_TV_H_CTL_3;
      56             :         u32 save_TV_V_CTL_1;
      57             :         u32 save_TV_V_CTL_2;
      58             :         u32 save_TV_V_CTL_3;
      59             :         u32 save_TV_V_CTL_4;
      60             :         u32 save_TV_V_CTL_5;
      61             :         u32 save_TV_V_CTL_6;
      62             :         u32 save_TV_V_CTL_7;
      63             :         u32 save_TV_SC_CTL_1, save_TV_SC_CTL_2, save_TV_SC_CTL_3;
      64             : 
      65             :         u32 save_TV_CSC_Y;
      66             :         u32 save_TV_CSC_Y2;
      67             :         u32 save_TV_CSC_U;
      68             :         u32 save_TV_CSC_U2;
      69             :         u32 save_TV_CSC_V;
      70             :         u32 save_TV_CSC_V2;
      71             :         u32 save_TV_CLR_KNOBS;
      72             :         u32 save_TV_CLR_LEVEL;
      73             :         u32 save_TV_WIN_POS;
      74             :         u32 save_TV_WIN_SIZE;
      75             :         u32 save_TV_FILTER_CTL_1;
      76             :         u32 save_TV_FILTER_CTL_2;
      77             :         u32 save_TV_FILTER_CTL_3;
      78             : 
      79             :         u32 save_TV_H_LUMA[60];
      80             :         u32 save_TV_H_CHROMA[60];
      81             :         u32 save_TV_V_LUMA[43];
      82             :         u32 save_TV_V_CHROMA[43];
      83             : 
      84             :         u32 save_TV_DAC;
      85             :         u32 save_TV_CTL;
      86             : };
      87             : 
      88             : struct video_levels {
      89             :         int blank, black, burst;
      90             : };
      91             : 
      92             : struct color_conversion {
      93             :         u16 ry, gy, by, ay;
      94             :         u16 ru, gu, bu, au;
      95             :         u16 rv, gv, bv, av;
      96             : };
      97             : 
      98             : static const u32 filter_table[] = {
      99             :         0xB1403000, 0x2E203500, 0x35002E20, 0x3000B140,
     100             :         0x35A0B160, 0x2DC02E80, 0xB1403480, 0xB1603000,
     101             :         0x2EA03640, 0x34002D80, 0x3000B120, 0x36E0B160,
     102             :         0x2D202EF0, 0xB1203380, 0xB1603000, 0x2F303780,
     103             :         0x33002CC0, 0x3000B100, 0x3820B160, 0x2C802F50,
     104             :         0xB10032A0, 0xB1603000, 0x2F9038C0, 0x32202C20,
     105             :         0x3000B0E0, 0x3980B160, 0x2BC02FC0, 0xB0E031C0,
     106             :         0xB1603000, 0x2FF03A20, 0x31602B60, 0xB020B0C0,
     107             :         0x3AE0B160, 0x2B001810, 0xB0C03120, 0xB140B020,
     108             :         0x18283BA0, 0x30C02A80, 0xB020B0A0, 0x3C60B140,
     109             :         0x2A201838, 0xB0A03080, 0xB120B020, 0x18383D20,
     110             :         0x304029C0, 0xB040B080, 0x3DE0B100, 0x29601848,
     111             :         0xB0803000, 0xB100B040, 0x18483EC0, 0xB0402900,
     112             :         0xB040B060, 0x3F80B0C0, 0x28801858, 0xB060B080,
     113             :         0xB0A0B060, 0x18602820, 0xB0A02820, 0x0000B060,
     114             :         0xB1403000, 0x2E203500, 0x35002E20, 0x3000B140,
     115             :         0x35A0B160, 0x2DC02E80, 0xB1403480, 0xB1603000,
     116             :         0x2EA03640, 0x34002D80, 0x3000B120, 0x36E0B160,
     117             :         0x2D202EF0, 0xB1203380, 0xB1603000, 0x2F303780,
     118             :         0x33002CC0, 0x3000B100, 0x3820B160, 0x2C802F50,
     119             :         0xB10032A0, 0xB1603000, 0x2F9038C0, 0x32202C20,
     120             :         0x3000B0E0, 0x3980B160, 0x2BC02FC0, 0xB0E031C0,
     121             :         0xB1603000, 0x2FF03A20, 0x31602B60, 0xB020B0C0,
     122             :         0x3AE0B160, 0x2B001810, 0xB0C03120, 0xB140B020,
     123             :         0x18283BA0, 0x30C02A80, 0xB020B0A0, 0x3C60B140,
     124             :         0x2A201838, 0xB0A03080, 0xB120B020, 0x18383D20,
     125             :         0x304029C0, 0xB040B080, 0x3DE0B100, 0x29601848,
     126             :         0xB0803000, 0xB100B040, 0x18483EC0, 0xB0402900,
     127             :         0xB040B060, 0x3F80B0C0, 0x28801858, 0xB060B080,
     128             :         0xB0A0B060, 0x18602820, 0xB0A02820, 0x0000B060,
     129             :         0x36403000, 0x2D002CC0, 0x30003640, 0x2D0036C0,
     130             :         0x35C02CC0, 0x37403000, 0x2C802D40, 0x30003540,
     131             :         0x2D8037C0, 0x34C02C40, 0x38403000, 0x2BC02E00,
     132             :         0x30003440, 0x2E2038C0, 0x34002B80, 0x39803000,
     133             :         0x2B402E40, 0x30003380, 0x2E603A00, 0x33402B00,
     134             :         0x3A803040, 0x2A802EA0, 0x30403300, 0x2EC03B40,
     135             :         0x32802A40, 0x3C003040, 0x2A002EC0, 0x30803240,
     136             :         0x2EC03C80, 0x320029C0, 0x3D403080, 0x29402F00,
     137             :         0x308031C0, 0x2F203DC0, 0x31802900, 0x3E8030C0,
     138             :         0x28802F40, 0x30C03140, 0x2F203F40, 0x31402840,
     139             :         0x28003100, 0x28002F00, 0x00003100, 0x36403000,
     140             :         0x2D002CC0, 0x30003640, 0x2D0036C0,
     141             :         0x35C02CC0, 0x37403000, 0x2C802D40, 0x30003540,
     142             :         0x2D8037C0, 0x34C02C40, 0x38403000, 0x2BC02E00,
     143             :         0x30003440, 0x2E2038C0, 0x34002B80, 0x39803000,
     144             :         0x2B402E40, 0x30003380, 0x2E603A00, 0x33402B00,
     145             :         0x3A803040, 0x2A802EA0, 0x30403300, 0x2EC03B40,
     146             :         0x32802A40, 0x3C003040, 0x2A002EC0, 0x30803240,
     147             :         0x2EC03C80, 0x320029C0, 0x3D403080, 0x29402F00,
     148             :         0x308031C0, 0x2F203DC0, 0x31802900, 0x3E8030C0,
     149             :         0x28802F40, 0x30C03140, 0x2F203F40, 0x31402840,
     150             :         0x28003100, 0x28002F00, 0x00003100,
     151             : };
     152             : 
     153             : /*
     154             :  * Color conversion values have 3 separate fixed point formats:
     155             :  *
     156             :  * 10 bit fields (ay, au)
     157             :  *   1.9 fixed point (b.bbbbbbbbb)
     158             :  * 11 bit fields (ry, by, ru, gu, gv)
     159             :  *   exp.mantissa (ee.mmmmmmmmm)
     160             :  *   ee = 00 = 10^-1 (0.mmmmmmmmm)
     161             :  *   ee = 01 = 10^-2 (0.0mmmmmmmmm)
     162             :  *   ee = 10 = 10^-3 (0.00mmmmmmmmm)
     163             :  *   ee = 11 = 10^-4 (0.000mmmmmmmmm)
     164             :  * 12 bit fields (gy, rv, bu)
     165             :  *   exp.mantissa (eee.mmmmmmmmm)
     166             :  *   eee = 000 = 10^-1 (0.mmmmmmmmm)
     167             :  *   eee = 001 = 10^-2 (0.0mmmmmmmmm)
     168             :  *   eee = 010 = 10^-3 (0.00mmmmmmmmm)
     169             :  *   eee = 011 = 10^-4 (0.000mmmmmmmmm)
     170             :  *   eee = 100 = reserved
     171             :  *   eee = 101 = reserved
     172             :  *   eee = 110 = reserved
     173             :  *   eee = 111 = 10^0 (m.mmmmmmmm) (only usable for 1.0 representation)
     174             :  *
     175             :  * Saturation and contrast are 8 bits, with their own representation:
     176             :  * 8 bit field (saturation, contrast)
     177             :  *   exp.mantissa (ee.mmmmmm)
     178             :  *   ee = 00 = 10^-1 (0.mmmmmm)
     179             :  *   ee = 01 = 10^0 (m.mmmmm)
     180             :  *   ee = 10 = 10^1 (mm.mmmm)
     181             :  *   ee = 11 = 10^2 (mmm.mmm)
     182             :  *
     183             :  * Simple conversion function:
     184             :  *
     185             :  * static u32
     186             :  * float_to_csc_11(float f)
     187             :  * {
     188             :  *     u32 exp;
     189             :  *     u32 mant;
     190             :  *     u32 ret;
     191             :  *
     192             :  *     if (f < 0)
     193             :  *         f = -f;
     194             :  *
     195             :  *     if (f >= 1) {
     196             :  *         exp = 0x7;
     197             :  *         mant = 1 << 8;
     198             :  *     } else {
     199             :  *         for (exp = 0; exp < 3 && f < 0.5; exp++)
     200             :  *         f *= 2.0;
     201             :  *         mant = (f * (1 << 9) + 0.5);
     202             :  *         if (mant >= (1 << 9))
     203             :  *             mant = (1 << 9) - 1;
     204             :  *     }
     205             :  *     ret = (exp << 9) | mant;
     206             :  *     return ret;
     207             :  * }
     208             :  */
     209             : 
     210             : /*
     211             :  * Behold, magic numbers!  If we plant them they might grow a big
     212             :  * s-video cable to the sky... or something.
     213             :  *
     214             :  * Pre-converted to appropriate hex value.
     215             :  */
     216             : 
     217             : /*
     218             :  * PAL & NTSC values for composite & s-video connections
     219             :  */
     220             : static const struct color_conversion ntsc_m_csc_composite = {
     221             :         .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0104,
     222             :         .ru = 0x0733, .gu = 0x052d, .bu = 0x05c7, .au = 0x0200,
     223             :         .rv = 0x0340, .gv = 0x030c, .bv = 0x06d0, .av = 0x0200,
     224             : };
     225             : 
     226             : static const struct video_levels ntsc_m_levels_composite = {
     227             :         .blank = 225, .black = 267, .burst = 113,
     228             : };
     229             : 
     230             : static const struct color_conversion ntsc_m_csc_svideo = {
     231             :         .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0133,
     232             :         .ru = 0x076a, .gu = 0x0564, .bu = 0x030d, .au = 0x0200,
     233             :         .rv = 0x037a, .gv = 0x033d, .bv = 0x06f6, .av = 0x0200,
     234             : };
     235             : 
     236             : static const struct video_levels ntsc_m_levels_svideo = {
     237             :         .blank = 266, .black = 316, .burst = 133,
     238             : };
     239             : 
     240             : static const struct color_conversion ntsc_j_csc_composite = {
     241             :         .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0119,
     242             :         .ru = 0x074c, .gu = 0x0546, .bu = 0x05ec, .au = 0x0200,
     243             :         .rv = 0x035a, .gv = 0x0322, .bv = 0x06e1, .av = 0x0200,
     244             : };
     245             : 
     246             : static const struct video_levels ntsc_j_levels_composite = {
     247             :         .blank = 225, .black = 225, .burst = 113,
     248             : };
     249             : 
     250             : static const struct color_conversion ntsc_j_csc_svideo = {
     251             :         .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x014c,
     252             :         .ru = 0x0788, .gu = 0x0581, .bu = 0x0322, .au = 0x0200,
     253             :         .rv = 0x0399, .gv = 0x0356, .bv = 0x070a, .av = 0x0200,
     254             : };
     255             : 
     256             : static const struct video_levels ntsc_j_levels_svideo = {
     257             :         .blank = 266, .black = 266, .burst = 133,
     258             : };
     259             : 
     260             : static const struct color_conversion pal_csc_composite = {
     261             :         .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0113,
     262             :         .ru = 0x0745, .gu = 0x053f, .bu = 0x05e1, .au = 0x0200,
     263             :         .rv = 0x0353, .gv = 0x031c, .bv = 0x06dc, .av = 0x0200,
     264             : };
     265             : 
     266             : static const struct video_levels pal_levels_composite = {
     267             :         .blank = 237, .black = 237, .burst = 118,
     268             : };
     269             : 
     270             : static const struct color_conversion pal_csc_svideo = {
     271             :         .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0145,
     272             :         .ru = 0x0780, .gu = 0x0579, .bu = 0x031c, .au = 0x0200,
     273             :         .rv = 0x0390, .gv = 0x034f, .bv = 0x0705, .av = 0x0200,
     274             : };
     275             : 
     276             : static const struct video_levels pal_levels_svideo = {
     277             :         .blank = 280, .black = 280, .burst = 139,
     278             : };
     279             : 
     280             : static const struct color_conversion pal_m_csc_composite = {
     281             :         .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0104,
     282             :         .ru = 0x0733, .gu = 0x052d, .bu = 0x05c7, .au = 0x0200,
     283             :         .rv = 0x0340, .gv = 0x030c, .bv = 0x06d0, .av = 0x0200,
     284             : };
     285             : 
     286             : static const struct video_levels pal_m_levels_composite = {
     287             :         .blank = 225, .black = 267, .burst = 113,
     288             : };
     289             : 
     290             : static const struct color_conversion pal_m_csc_svideo = {
     291             :         .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0133,
     292             :         .ru = 0x076a, .gu = 0x0564, .bu = 0x030d, .au = 0x0200,
     293             :         .rv = 0x037a, .gv = 0x033d, .bv = 0x06f6, .av = 0x0200,
     294             : };
     295             : 
     296             : static const struct video_levels pal_m_levels_svideo = {
     297             :         .blank = 266, .black = 316, .burst = 133,
     298             : };
     299             : 
     300             : static const struct color_conversion pal_n_csc_composite = {
     301             :         .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0104,
     302             :         .ru = 0x0733, .gu = 0x052d, .bu = 0x05c7, .au = 0x0200,
     303             :         .rv = 0x0340, .gv = 0x030c, .bv = 0x06d0, .av = 0x0200,
     304             : };
     305             : 
     306             : static const struct video_levels pal_n_levels_composite = {
     307             :         .blank = 225, .black = 267, .burst = 118,
     308             : };
     309             : 
     310             : static const struct color_conversion pal_n_csc_svideo = {
     311             :         .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0133,
     312             :         .ru = 0x076a, .gu = 0x0564, .bu = 0x030d, .au = 0x0200,
     313             :         .rv = 0x037a, .gv = 0x033d, .bv = 0x06f6, .av = 0x0200,
     314             : };
     315             : 
     316             : static const struct video_levels pal_n_levels_svideo = {
     317             :         .blank = 266, .black = 316, .burst = 139,
     318             : };
     319             : 
     320             : /*
     321             :  * Component connections
     322             :  */
     323             : static const struct color_conversion sdtv_csc_yprpb = {
     324             :         .ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0145,
     325             :         .ru = 0x0559, .gu = 0x0353, .bu = 0x0100, .au = 0x0200,
     326             :         .rv = 0x0100, .gv = 0x03ad, .bv = 0x074d, .av = 0x0200,
     327             : };
     328             : 
     329             : static const struct color_conversion hdtv_csc_yprpb = {
     330             :         .ry = 0x05b3, .gy = 0x016e, .by = 0x0728, .ay = 0x0145,
     331             :         .ru = 0x07d5, .gu = 0x038b, .bu = 0x0100, .au = 0x0200,
     332             :         .rv = 0x0100, .gv = 0x03d1, .bv = 0x06bc, .av = 0x0200,
     333             : };
     334             : 
     335             : static const struct video_levels component_levels = {
     336             :         .blank = 279, .black = 279, .burst = 0,
     337             : };
     338             : 
     339             : 
     340             : struct tv_mode {
     341             :         const char *name;
     342             :         int clock;
     343             :         int refresh; /* in millihertz (for precision) */
     344             :         u32 oversample;
     345             :         int hsync_end, hblank_start, hblank_end, htotal;
     346             :         bool progressive, trilevel_sync, component_only;
     347             :         int vsync_start_f1, vsync_start_f2, vsync_len;
     348             :         bool veq_ena;
     349             :         int veq_start_f1, veq_start_f2, veq_len;
     350             :         int vi_end_f1, vi_end_f2, nbr_end;
     351             :         bool burst_ena;
     352             :         int hburst_start, hburst_len;
     353             :         int vburst_start_f1, vburst_end_f1;
     354             :         int vburst_start_f2, vburst_end_f2;
     355             :         int vburst_start_f3, vburst_end_f3;
     356             :         int vburst_start_f4, vburst_end_f4;
     357             :         /*
     358             :          * subcarrier programming
     359             :          */
     360             :         int dda2_size, dda3_size, dda1_inc, dda2_inc, dda3_inc;
     361             :         u32 sc_reset;
     362             :         bool pal_burst;
     363             :         /*
     364             :          * blank/black levels
     365             :          */
     366             :         const struct video_levels *composite_levels, *svideo_levels;
     367             :         const struct color_conversion *composite_color, *svideo_color;
     368             :         const u32 *filter_table;
     369             :         int max_srcw;
     370             : };
     371             : 
     372             : 
     373             : /*
     374             :  * Sub carrier DDA
     375             :  *
     376             :  *  I think this works as follows:
     377             :  *
     378             :  *  subcarrier freq = pixel_clock * (dda1_inc + dda2_inc / dda2_size) / 4096
     379             :  *
     380             :  * Presumably, when dda3 is added in, it gets to adjust the dda2_inc value
     381             :  *
     382             :  * So,
     383             :  *  dda1_ideal = subcarrier/pixel * 4096
     384             :  *  dda1_inc = floor (dda1_ideal)
     385             :  *  dda2 = dda1_ideal - dda1_inc
     386             :  *
     387             :  *  then pick a ratio for dda2 that gives the closest approximation. If
     388             :  *  you can't get close enough, you can play with dda3 as well. This
     389             :  *  seems likely to happen when dda2 is small as the jumps would be larger
     390             :  *
     391             :  * To invert this,
     392             :  *
     393             :  *  pixel_clock = subcarrier * 4096 / (dda1_inc + dda2_inc / dda2_size)
     394             :  *
     395             :  * The constants below were all computed using a 107.520MHz clock
     396             :  */
     397             : 
     398             : /**
     399             :  * Register programming values for TV modes.
     400             :  *
     401             :  * These values account for -1s required.
     402             :  */
     403             : 
     404             : static const struct tv_mode tv_modes[] = {
     405             :         {
     406             :                 .name           = "NTSC-M",
     407             :                 .clock          = 108000,
     408             :                 .refresh        = 59940,
     409             :                 .oversample     = TV_OVERSAMPLE_8X,
     410             :                 .component_only = 0,
     411             :                 /* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.580MHz */
     412             : 
     413             :                 .hsync_end      = 64,               .hblank_end         = 124,
     414             :                 .hblank_start   = 836,              .htotal             = 857,
     415             : 
     416             :                 .progressive    = false,            .trilevel_sync = false,
     417             : 
     418             :                 .vsync_start_f1 = 6,                .vsync_start_f2     = 7,
     419             :                 .vsync_len      = 6,
     420             : 
     421             :                 .veq_ena        = true,             .veq_start_f1       = 0,
     422             :                 .veq_start_f2   = 1,                .veq_len            = 18,
     423             : 
     424             :                 .vi_end_f1      = 20,               .vi_end_f2          = 21,
     425             :                 .nbr_end        = 240,
     426             : 
     427             :                 .burst_ena      = true,
     428             :                 .hburst_start   = 72,               .hburst_len         = 34,
     429             :                 .vburst_start_f1 = 9,               .vburst_end_f1      = 240,
     430             :                 .vburst_start_f2 = 10,              .vburst_end_f2      = 240,
     431             :                 .vburst_start_f3 = 9,               .vburst_end_f3      = 240,
     432             :                 .vburst_start_f4 = 10,              .vburst_end_f4      = 240,
     433             : 
     434             :                 /* desired 3.5800000 actual 3.5800000 clock 107.52 */
     435             :                 .dda1_inc       =    135,
     436             :                 .dda2_inc       =  20800,           .dda2_size          =  27456,
     437             :                 .dda3_inc       =      0,           .dda3_size          =      0,
     438             :                 .sc_reset       = TV_SC_RESET_EVERY_4,
     439             :                 .pal_burst      = false,
     440             : 
     441             :                 .composite_levels = &ntsc_m_levels_composite,
     442             :                 .composite_color = &ntsc_m_csc_composite,
     443             :                 .svideo_levels  = &ntsc_m_levels_svideo,
     444             :                 .svideo_color = &ntsc_m_csc_svideo,
     445             : 
     446             :                 .filter_table = filter_table,
     447             :         },
     448             :         {
     449             :                 .name           = "NTSC-443",
     450             :                 .clock          = 108000,
     451             :                 .refresh        = 59940,
     452             :                 .oversample     = TV_OVERSAMPLE_8X,
     453             :                 .component_only = 0,
     454             :                 /* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 4.43MHz */
     455             :                 .hsync_end      = 64,               .hblank_end         = 124,
     456             :                 .hblank_start   = 836,              .htotal             = 857,
     457             : 
     458             :                 .progressive    = false,            .trilevel_sync = false,
     459             : 
     460             :                 .vsync_start_f1 = 6,                .vsync_start_f2     = 7,
     461             :                 .vsync_len      = 6,
     462             : 
     463             :                 .veq_ena        = true,             .veq_start_f1       = 0,
     464             :                 .veq_start_f2   = 1,                .veq_len            = 18,
     465             : 
     466             :                 .vi_end_f1      = 20,               .vi_end_f2          = 21,
     467             :                 .nbr_end        = 240,
     468             : 
     469             :                 .burst_ena      = true,
     470             :                 .hburst_start   = 72,               .hburst_len         = 34,
     471             :                 .vburst_start_f1 = 9,               .vburst_end_f1      = 240,
     472             :                 .vburst_start_f2 = 10,              .vburst_end_f2      = 240,
     473             :                 .vburst_start_f3 = 9,               .vburst_end_f3      = 240,
     474             :                 .vburst_start_f4 = 10,              .vburst_end_f4      = 240,
     475             : 
     476             :                 /* desired 4.4336180 actual 4.4336180 clock 107.52 */
     477             :                 .dda1_inc       =    168,
     478             :                 .dda2_inc       =   4093,       .dda2_size      =  27456,
     479             :                 .dda3_inc       =    310,       .dda3_size      =    525,
     480             :                 .sc_reset   = TV_SC_RESET_NEVER,
     481             :                 .pal_burst  = false,
     482             : 
     483             :                 .composite_levels = &ntsc_m_levels_composite,
     484             :                 .composite_color = &ntsc_m_csc_composite,
     485             :                 .svideo_levels  = &ntsc_m_levels_svideo,
     486             :                 .svideo_color = &ntsc_m_csc_svideo,
     487             : 
     488             :                 .filter_table = filter_table,
     489             :         },
     490             :         {
     491             :                 .name           = "NTSC-J",
     492             :                 .clock          = 108000,
     493             :                 .refresh        = 59940,
     494             :                 .oversample     = TV_OVERSAMPLE_8X,
     495             :                 .component_only = 0,
     496             : 
     497             :                 /* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.580MHz */
     498             :                 .hsync_end      = 64,               .hblank_end         = 124,
     499             :                 .hblank_start = 836,        .htotal             = 857,
     500             : 
     501             :                 .progressive    = false,    .trilevel_sync = false,
     502             : 
     503             :                 .vsync_start_f1 = 6,        .vsync_start_f2     = 7,
     504             :                 .vsync_len      = 6,
     505             : 
     506             :                 .veq_ena      = true,       .veq_start_f1       = 0,
     507             :                 .veq_start_f2 = 1,          .veq_len            = 18,
     508             : 
     509             :                 .vi_end_f1      = 20,               .vi_end_f2          = 21,
     510             :                 .nbr_end        = 240,
     511             : 
     512             :                 .burst_ena      = true,
     513             :                 .hburst_start   = 72,               .hburst_len         = 34,
     514             :                 .vburst_start_f1 = 9,               .vburst_end_f1      = 240,
     515             :                 .vburst_start_f2 = 10,              .vburst_end_f2      = 240,
     516             :                 .vburst_start_f3 = 9,               .vburst_end_f3      = 240,
     517             :                 .vburst_start_f4 = 10,              .vburst_end_f4      = 240,
     518             : 
     519             :                 /* desired 3.5800000 actual 3.5800000 clock 107.52 */
     520             :                 .dda1_inc       =    135,
     521             :                 .dda2_inc       =  20800,           .dda2_size          =  27456,
     522             :                 .dda3_inc       =      0,           .dda3_size          =      0,
     523             :                 .sc_reset       = TV_SC_RESET_EVERY_4,
     524             :                 .pal_burst      = false,
     525             : 
     526             :                 .composite_levels = &ntsc_j_levels_composite,
     527             :                 .composite_color = &ntsc_j_csc_composite,
     528             :                 .svideo_levels  = &ntsc_j_levels_svideo,
     529             :                 .svideo_color = &ntsc_j_csc_svideo,
     530             : 
     531             :                 .filter_table = filter_table,
     532             :         },
     533             :         {
     534             :                 .name           = "PAL-M",
     535             :                 .clock          = 108000,
     536             :                 .refresh        = 59940,
     537             :                 .oversample     = TV_OVERSAMPLE_8X,
     538             :                 .component_only = 0,
     539             : 
     540             :                 /* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.580MHz */
     541             :                 .hsync_end      = 64,             .hblank_end           = 124,
     542             :                 .hblank_start = 836,      .htotal               = 857,
     543             : 
     544             :                 .progressive    = false,            .trilevel_sync = false,
     545             : 
     546             :                 .vsync_start_f1 = 6,                .vsync_start_f2     = 7,
     547             :                 .vsync_len      = 6,
     548             : 
     549             :                 .veq_ena        = true,             .veq_start_f1       = 0,
     550             :                 .veq_start_f2   = 1,                .veq_len            = 18,
     551             : 
     552             :                 .vi_end_f1      = 20,               .vi_end_f2          = 21,
     553             :                 .nbr_end        = 240,
     554             : 
     555             :                 .burst_ena      = true,
     556             :                 .hburst_start   = 72,               .hburst_len         = 34,
     557             :                 .vburst_start_f1 = 9,               .vburst_end_f1      = 240,
     558             :                 .vburst_start_f2 = 10,              .vburst_end_f2      = 240,
     559             :                 .vburst_start_f3 = 9,               .vburst_end_f3      = 240,
     560             :                 .vburst_start_f4 = 10,              .vburst_end_f4      = 240,
     561             : 
     562             :                 /* desired 3.5800000 actual 3.5800000 clock 107.52 */
     563             :                 .dda1_inc       =    135,
     564             :                 .dda2_inc       =  16704,           .dda2_size          =  27456,
     565             :                 .dda3_inc       =      0,           .dda3_size          =      0,
     566             :                 .sc_reset       = TV_SC_RESET_EVERY_8,
     567             :                 .pal_burst  = true,
     568             : 
     569             :                 .composite_levels = &pal_m_levels_composite,
     570             :                 .composite_color = &pal_m_csc_composite,
     571             :                 .svideo_levels  = &pal_m_levels_svideo,
     572             :                 .svideo_color = &pal_m_csc_svideo,
     573             : 
     574             :                 .filter_table = filter_table,
     575             :         },
     576             :         {
     577             :                 /* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */
     578             :                 .name       = "PAL-N",
     579             :                 .clock          = 108000,
     580             :                 .refresh        = 50000,
     581             :                 .oversample     = TV_OVERSAMPLE_8X,
     582             :                 .component_only = 0,
     583             : 
     584             :                 .hsync_end      = 64,               .hblank_end         = 128,
     585             :                 .hblank_start = 844,        .htotal             = 863,
     586             : 
     587             :                 .progressive  = false,    .trilevel_sync = false,
     588             : 
     589             : 
     590             :                 .vsync_start_f1 = 6,       .vsync_start_f2      = 7,
     591             :                 .vsync_len      = 6,
     592             : 
     593             :                 .veq_ena        = true,             .veq_start_f1       = 0,
     594             :                 .veq_start_f2   = 1,                .veq_len            = 18,
     595             : 
     596             :                 .vi_end_f1      = 24,               .vi_end_f2          = 25,
     597             :                 .nbr_end        = 286,
     598             : 
     599             :                 .burst_ena      = true,
     600             :                 .hburst_start = 73,         .hburst_len         = 34,
     601             :                 .vburst_start_f1 = 8,       .vburst_end_f1      = 285,
     602             :                 .vburst_start_f2 = 8,       .vburst_end_f2      = 286,
     603             :                 .vburst_start_f3 = 9,       .vburst_end_f3      = 286,
     604             :                 .vburst_start_f4 = 9,       .vburst_end_f4      = 285,
     605             : 
     606             : 
     607             :                 /* desired 4.4336180 actual 4.4336180 clock 107.52 */
     608             :                 .dda1_inc       =    135,
     609             :                 .dda2_inc       =  23578,       .dda2_size      =  27648,
     610             :                 .dda3_inc       =    134,       .dda3_size      =    625,
     611             :                 .sc_reset   = TV_SC_RESET_EVERY_8,
     612             :                 .pal_burst  = true,
     613             : 
     614             :                 .composite_levels = &pal_n_levels_composite,
     615             :                 .composite_color = &pal_n_csc_composite,
     616             :                 .svideo_levels  = &pal_n_levels_svideo,
     617             :                 .svideo_color = &pal_n_csc_svideo,
     618             : 
     619             :                 .filter_table = filter_table,
     620             :         },
     621             :         {
     622             :                 /* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */
     623             :                 .name       = "PAL",
     624             :                 .clock          = 108000,
     625             :                 .refresh        = 50000,
     626             :                 .oversample     = TV_OVERSAMPLE_8X,
     627             :                 .component_only = 0,
     628             : 
     629             :                 .hsync_end      = 64,               .hblank_end         = 142,
     630             :                 .hblank_start   = 844,      .htotal             = 863,
     631             : 
     632             :                 .progressive    = false,    .trilevel_sync = false,
     633             : 
     634             :                 .vsync_start_f1 = 5,        .vsync_start_f2     = 6,
     635             :                 .vsync_len      = 5,
     636             : 
     637             :                 .veq_ena        = true,     .veq_start_f1       = 0,
     638             :                 .veq_start_f2   = 1,        .veq_len            = 15,
     639             : 
     640             :                 .vi_end_f1      = 24,               .vi_end_f2          = 25,
     641             :                 .nbr_end        = 286,
     642             : 
     643             :                 .burst_ena      = true,
     644             :                 .hburst_start   = 73,               .hburst_len         = 32,
     645             :                 .vburst_start_f1 = 8,               .vburst_end_f1      = 285,
     646             :                 .vburst_start_f2 = 8,               .vburst_end_f2      = 286,
     647             :                 .vburst_start_f3 = 9,               .vburst_end_f3      = 286,
     648             :                 .vburst_start_f4 = 9,               .vburst_end_f4      = 285,
     649             : 
     650             :                 /* desired 4.4336180 actual 4.4336180 clock 107.52 */
     651             :                 .dda1_inc       =    168,
     652             :                 .dda2_inc       =   4122,       .dda2_size      =  27648,
     653             :                 .dda3_inc       =     67,       .dda3_size      =    625,
     654             :                 .sc_reset   = TV_SC_RESET_EVERY_8,
     655             :                 .pal_burst  = true,
     656             : 
     657             :                 .composite_levels = &pal_levels_composite,
     658             :                 .composite_color = &pal_csc_composite,
     659             :                 .svideo_levels  = &pal_levels_svideo,
     660             :                 .svideo_color = &pal_csc_svideo,
     661             : 
     662             :                 .filter_table = filter_table,
     663             :         },
     664             :         {
     665             :                 .name       = "480p",
     666             :                 .clock          = 107520,
     667             :                 .refresh        = 59940,
     668             :                 .oversample     = TV_OVERSAMPLE_4X,
     669             :                 .component_only = 1,
     670             : 
     671             :                 .hsync_end      = 64,               .hblank_end         = 122,
     672             :                 .hblank_start   = 842,              .htotal             = 857,
     673             : 
     674             :                 .progressive    = true,             .trilevel_sync = false,
     675             : 
     676             :                 .vsync_start_f1 = 12,               .vsync_start_f2     = 12,
     677             :                 .vsync_len      = 12,
     678             : 
     679             :                 .veq_ena        = false,
     680             : 
     681             :                 .vi_end_f1      = 44,               .vi_end_f2          = 44,
     682             :                 .nbr_end        = 479,
     683             : 
     684             :                 .burst_ena      = false,
     685             : 
     686             :                 .filter_table = filter_table,
     687             :         },
     688             :         {
     689             :                 .name       = "576p",
     690             :                 .clock          = 107520,
     691             :                 .refresh        = 50000,
     692             :                 .oversample     = TV_OVERSAMPLE_4X,
     693             :                 .component_only = 1,
     694             : 
     695             :                 .hsync_end      = 64,               .hblank_end         = 139,
     696             :                 .hblank_start   = 859,              .htotal             = 863,
     697             : 
     698             :                 .progressive    = true,             .trilevel_sync = false,
     699             : 
     700             :                 .vsync_start_f1 = 10,               .vsync_start_f2     = 10,
     701             :                 .vsync_len      = 10,
     702             : 
     703             :                 .veq_ena        = false,
     704             : 
     705             :                 .vi_end_f1      = 48,               .vi_end_f2          = 48,
     706             :                 .nbr_end        = 575,
     707             : 
     708             :                 .burst_ena      = false,
     709             : 
     710             :                 .filter_table = filter_table,
     711             :         },
     712             :         {
     713             :                 .name       = "720p@60Hz",
     714             :                 .clock          = 148800,
     715             :                 .refresh        = 60000,
     716             :                 .oversample     = TV_OVERSAMPLE_2X,
     717             :                 .component_only = 1,
     718             : 
     719             :                 .hsync_end      = 80,               .hblank_end         = 300,
     720             :                 .hblank_start   = 1580,             .htotal             = 1649,
     721             : 
     722             :                 .progressive    = true,             .trilevel_sync = true,
     723             : 
     724             :                 .vsync_start_f1 = 10,               .vsync_start_f2     = 10,
     725             :                 .vsync_len      = 10,
     726             : 
     727             :                 .veq_ena        = false,
     728             : 
     729             :                 .vi_end_f1      = 29,               .vi_end_f2          = 29,
     730             :                 .nbr_end        = 719,
     731             : 
     732             :                 .burst_ena      = false,
     733             : 
     734             :                 .filter_table = filter_table,
     735             :         },
     736             :         {
     737             :                 .name       = "720p@50Hz",
     738             :                 .clock          = 148800,
     739             :                 .refresh        = 50000,
     740             :                 .oversample     = TV_OVERSAMPLE_2X,
     741             :                 .component_only = 1,
     742             : 
     743             :                 .hsync_end      = 80,               .hblank_end         = 300,
     744             :                 .hblank_start   = 1580,             .htotal             = 1979,
     745             : 
     746             :                 .progressive    = true,             .trilevel_sync = true,
     747             : 
     748             :                 .vsync_start_f1 = 10,               .vsync_start_f2     = 10,
     749             :                 .vsync_len      = 10,
     750             : 
     751             :                 .veq_ena        = false,
     752             : 
     753             :                 .vi_end_f1      = 29,               .vi_end_f2          = 29,
     754             :                 .nbr_end        = 719,
     755             : 
     756             :                 .burst_ena      = false,
     757             : 
     758             :                 .filter_table = filter_table,
     759             :                 .max_srcw = 800
     760             :         },
     761             :         {
     762             :                 .name       = "1080i@50Hz",
     763             :                 .clock          = 148800,
     764             :                 .refresh        = 50000,
     765             :                 .oversample     = TV_OVERSAMPLE_2X,
     766             :                 .component_only = 1,
     767             : 
     768             :                 .hsync_end      = 88,               .hblank_end         = 235,
     769             :                 .hblank_start   = 2155,             .htotal             = 2639,
     770             : 
     771             :                 .progressive    = false,          .trilevel_sync = true,
     772             : 
     773             :                 .vsync_start_f1 = 4,              .vsync_start_f2     = 5,
     774             :                 .vsync_len      = 10,
     775             : 
     776             :                 .veq_ena        = true,     .veq_start_f1       = 4,
     777             :                 .veq_start_f2   = 4,        .veq_len            = 10,
     778             : 
     779             : 
     780             :                 .vi_end_f1      = 21,           .vi_end_f2          = 22,
     781             :                 .nbr_end        = 539,
     782             : 
     783             :                 .burst_ena      = false,
     784             : 
     785             :                 .filter_table = filter_table,
     786             :         },
     787             :         {
     788             :                 .name       = "1080i@60Hz",
     789             :                 .clock          = 148800,
     790             :                 .refresh        = 60000,
     791             :                 .oversample     = TV_OVERSAMPLE_2X,
     792             :                 .component_only = 1,
     793             : 
     794             :                 .hsync_end      = 88,               .hblank_end         = 235,
     795             :                 .hblank_start   = 2155,             .htotal             = 2199,
     796             : 
     797             :                 .progressive    = false,            .trilevel_sync = true,
     798             : 
     799             :                 .vsync_start_f1 = 4,               .vsync_start_f2     = 5,
     800             :                 .vsync_len      = 10,
     801             : 
     802             :                 .veq_ena        = true,             .veq_start_f1       = 4,
     803             :                 .veq_start_f2   = 4,                .veq_len            = 10,
     804             : 
     805             : 
     806             :                 .vi_end_f1      = 21,               .vi_end_f2          = 22,
     807             :                 .nbr_end        = 539,
     808             : 
     809             :                 .burst_ena      = false,
     810             : 
     811             :                 .filter_table = filter_table,
     812             :         },
     813             : };
     814             : 
     815           0 : static struct intel_tv *enc_to_tv(struct intel_encoder *encoder)
     816             : {
     817           0 :         return container_of(encoder, struct intel_tv, base);
     818             : }
     819             : 
     820           0 : static struct intel_tv *intel_attached_tv(struct drm_connector *connector)
     821             : {
     822           0 :         return enc_to_tv(intel_attached_encoder(connector));
     823             : }
     824             : 
     825             : static bool
     826           0 : intel_tv_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe)
     827             : {
     828           0 :         struct drm_device *dev = encoder->base.dev;
     829           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
     830           0 :         u32 tmp = I915_READ(TV_CTL);
     831             : 
     832           0 :         if (!(tmp & TV_ENC_ENABLE))
     833           0 :                 return false;
     834             : 
     835           0 :         *pipe = PORT_TO_PIPE(tmp);
     836             : 
     837           0 :         return true;
     838           0 : }
     839             : 
     840             : static void
     841           0 : intel_enable_tv(struct intel_encoder *encoder)
     842             : {
     843           0 :         struct drm_device *dev = encoder->base.dev;
     844           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
     845             : 
     846             :         /* Prevents vblank waits from timing out in intel_tv_detect_type() */
     847           0 :         intel_wait_for_vblank(encoder->base.dev,
     848           0 :                               to_intel_crtc(encoder->base.crtc)->pipe);
     849             : 
     850           0 :         I915_WRITE(TV_CTL, I915_READ(TV_CTL) | TV_ENC_ENABLE);
     851           0 : }
     852             : 
     853             : static void
     854           0 : intel_disable_tv(struct intel_encoder *encoder)
     855             : {
     856           0 :         struct drm_device *dev = encoder->base.dev;
     857           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
     858             : 
     859           0 :         I915_WRITE(TV_CTL, I915_READ(TV_CTL) & ~TV_ENC_ENABLE);
     860           0 : }
     861             : 
     862             : static const struct tv_mode *
     863           0 : intel_tv_mode_lookup(const char *tv_format)
     864             : {
     865             :         int i;
     866             : 
     867           0 :         for (i = 0; i < ARRAY_SIZE(tv_modes); i++) {
     868           0 :                 const struct tv_mode *tv_mode = &tv_modes[i];
     869             : 
     870           0 :                 if (!strcmp(tv_format, tv_mode->name))
     871           0 :                         return tv_mode;
     872           0 :         }
     873           0 :         return NULL;
     874           0 : }
     875             : 
     876             : static const struct tv_mode *
     877           0 : intel_tv_mode_find(struct intel_tv *intel_tv)
     878             : {
     879           0 :         return intel_tv_mode_lookup(intel_tv->tv_format);
     880             : }
     881             : 
     882             : static enum drm_mode_status
     883           0 : intel_tv_mode_valid(struct drm_connector *connector,
     884             :                     struct drm_display_mode *mode)
     885             : {
     886           0 :         struct intel_tv *intel_tv = intel_attached_tv(connector);
     887           0 :         const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
     888             : 
     889             :         /* Ensure TV refresh is close to desired refresh */
     890           0 :         if (tv_mode && abs(tv_mode->refresh - drm_mode_vrefresh(mode) * 1000)
     891           0 :                                 < 1000)
     892           0 :                 return MODE_OK;
     893             : 
     894           0 :         return MODE_CLOCK_RANGE;
     895           0 : }
     896             : 
     897             : 
     898             : static void
     899           0 : intel_tv_get_config(struct intel_encoder *encoder,
     900             :                     struct intel_crtc_state *pipe_config)
     901             : {
     902           0 :         pipe_config->base.adjusted_mode.crtc_clock = pipe_config->port_clock;
     903           0 : }
     904             : 
     905             : static bool
     906           0 : intel_tv_compute_config(struct intel_encoder *encoder,
     907             :                         struct intel_crtc_state *pipe_config)
     908             : {
     909           0 :         struct intel_tv *intel_tv = enc_to_tv(encoder);
     910           0 :         const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
     911             : 
     912           0 :         if (!tv_mode)
     913           0 :                 return false;
     914             : 
     915           0 :         pipe_config->base.adjusted_mode.crtc_clock = tv_mode->clock;
     916             :         DRM_DEBUG_KMS("forcing bpc to 8 for TV\n");
     917           0 :         pipe_config->pipe_bpp = 8*3;
     918             : 
     919             :         /* TV has it's own notion of sync and other mode flags, so clear them. */
     920           0 :         pipe_config->base.adjusted_mode.flags = 0;
     921             : 
     922             :         /*
     923             :          * FIXME: We don't check whether the input mode is actually what we want
     924             :          * or whether userspace is doing something stupid.
     925             :          */
     926             : 
     927           0 :         return true;
     928           0 : }
     929             : 
     930             : static void
     931           0 : set_tv_mode_timings(struct drm_i915_private *dev_priv,
     932             :                     const struct tv_mode *tv_mode,
     933             :                     bool burst_ena)
     934             : {
     935             :         u32 hctl1, hctl2, hctl3;
     936             :         u32 vctl1, vctl2, vctl3, vctl4, vctl5, vctl6, vctl7;
     937             : 
     938           0 :         hctl1 = (tv_mode->hsync_end << TV_HSYNC_END_SHIFT) |
     939           0 :                 (tv_mode->htotal << TV_HTOTAL_SHIFT);
     940             : 
     941           0 :         hctl2 = (tv_mode->hburst_start << 16) |
     942           0 :                 (tv_mode->hburst_len << TV_HBURST_LEN_SHIFT);
     943             : 
     944           0 :         if (burst_ena)
     945           0 :                 hctl2 |= TV_BURST_ENA;
     946             : 
     947           0 :         hctl3 = (tv_mode->hblank_start << TV_HBLANK_START_SHIFT) |
     948           0 :                 (tv_mode->hblank_end << TV_HBLANK_END_SHIFT);
     949             : 
     950           0 :         vctl1 = (tv_mode->nbr_end << TV_NBR_END_SHIFT) |
     951           0 :                 (tv_mode->vi_end_f1 << TV_VI_END_F1_SHIFT) |
     952           0 :                 (tv_mode->vi_end_f2 << TV_VI_END_F2_SHIFT);
     953             : 
     954           0 :         vctl2 = (tv_mode->vsync_len << TV_VSYNC_LEN_SHIFT) |
     955           0 :                 (tv_mode->vsync_start_f1 << TV_VSYNC_START_F1_SHIFT) |
     956           0 :                 (tv_mode->vsync_start_f2 << TV_VSYNC_START_F2_SHIFT);
     957             : 
     958           0 :         vctl3 = (tv_mode->veq_len << TV_VEQ_LEN_SHIFT) |
     959           0 :                 (tv_mode->veq_start_f1 << TV_VEQ_START_F1_SHIFT) |
     960           0 :                 (tv_mode->veq_start_f2 << TV_VEQ_START_F2_SHIFT);
     961             : 
     962           0 :         if (tv_mode->veq_ena)
     963           0 :                 vctl3 |= TV_EQUAL_ENA;
     964             : 
     965           0 :         vctl4 = (tv_mode->vburst_start_f1 << TV_VBURST_START_F1_SHIFT) |
     966           0 :                 (tv_mode->vburst_end_f1 << TV_VBURST_END_F1_SHIFT);
     967             : 
     968           0 :         vctl5 = (tv_mode->vburst_start_f2 << TV_VBURST_START_F2_SHIFT) |
     969           0 :                 (tv_mode->vburst_end_f2 << TV_VBURST_END_F2_SHIFT);
     970             : 
     971           0 :         vctl6 = (tv_mode->vburst_start_f3 << TV_VBURST_START_F3_SHIFT) |
     972           0 :                 (tv_mode->vburst_end_f3 << TV_VBURST_END_F3_SHIFT);
     973             : 
     974           0 :         vctl7 = (tv_mode->vburst_start_f4 << TV_VBURST_START_F4_SHIFT) |
     975           0 :                 (tv_mode->vburst_end_f4 << TV_VBURST_END_F4_SHIFT);
     976             : 
     977           0 :         I915_WRITE(TV_H_CTL_1, hctl1);
     978           0 :         I915_WRITE(TV_H_CTL_2, hctl2);
     979           0 :         I915_WRITE(TV_H_CTL_3, hctl3);
     980           0 :         I915_WRITE(TV_V_CTL_1, vctl1);
     981           0 :         I915_WRITE(TV_V_CTL_2, vctl2);
     982           0 :         I915_WRITE(TV_V_CTL_3, vctl3);
     983           0 :         I915_WRITE(TV_V_CTL_4, vctl4);
     984           0 :         I915_WRITE(TV_V_CTL_5, vctl5);
     985           0 :         I915_WRITE(TV_V_CTL_6, vctl6);
     986           0 :         I915_WRITE(TV_V_CTL_7, vctl7);
     987           0 : }
     988             : 
     989           0 : static void set_color_conversion(struct drm_i915_private *dev_priv,
     990             :                                  const struct color_conversion *color_conversion)
     991             : {
     992           0 :         if (!color_conversion)
     993             :                 return;
     994             : 
     995           0 :         I915_WRITE(TV_CSC_Y, (color_conversion->ry << 16) |
     996             :                    color_conversion->gy);
     997           0 :         I915_WRITE(TV_CSC_Y2, (color_conversion->by << 16) |
     998             :                    color_conversion->ay);
     999           0 :         I915_WRITE(TV_CSC_U, (color_conversion->ru << 16) |
    1000             :                    color_conversion->gu);
    1001           0 :         I915_WRITE(TV_CSC_U2, (color_conversion->bu << 16) |
    1002             :                    color_conversion->au);
    1003           0 :         I915_WRITE(TV_CSC_V, (color_conversion->rv << 16) |
    1004             :                    color_conversion->gv);
    1005           0 :         I915_WRITE(TV_CSC_V2, (color_conversion->bv << 16) |
    1006             :                    color_conversion->av);
    1007           0 : }
    1008             : 
    1009           0 : static void intel_tv_pre_enable(struct intel_encoder *encoder)
    1010             : {
    1011           0 :         struct drm_device *dev = encoder->base.dev;
    1012           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
    1013           0 :         struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
    1014           0 :         struct intel_tv *intel_tv = enc_to_tv(encoder);
    1015           0 :         const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
    1016             :         u32 tv_ctl;
    1017             :         u32 scctl1, scctl2, scctl3;
    1018             :         int i, j;
    1019             :         const struct video_levels *video_levels;
    1020             :         const struct color_conversion *color_conversion;
    1021             :         bool burst_ena;
    1022             :         int xpos = 0x0, ypos = 0x0;
    1023             :         unsigned int xsize, ysize;
    1024             : 
    1025           0 :         if (!tv_mode)
    1026           0 :                 return; /* can't happen (mode_prepare prevents this) */
    1027             : 
    1028           0 :         tv_ctl = I915_READ(TV_CTL);
    1029           0 :         tv_ctl &= TV_CTL_SAVE;
    1030             : 
    1031           0 :         switch (intel_tv->type) {
    1032             :         default:
    1033             :         case DRM_MODE_CONNECTOR_Unknown:
    1034             :         case DRM_MODE_CONNECTOR_Composite:
    1035             :                 tv_ctl |= TV_ENC_OUTPUT_COMPOSITE;
    1036           0 :                 video_levels = tv_mode->composite_levels;
    1037           0 :                 color_conversion = tv_mode->composite_color;
    1038           0 :                 burst_ena = tv_mode->burst_ena;
    1039           0 :                 break;
    1040             :         case DRM_MODE_CONNECTOR_Component:
    1041           0 :                 tv_ctl |= TV_ENC_OUTPUT_COMPONENT;
    1042             :                 video_levels = &component_levels;
    1043           0 :                 if (tv_mode->burst_ena)
    1044           0 :                         color_conversion = &sdtv_csc_yprpb;
    1045             :                 else
    1046             :                         color_conversion = &hdtv_csc_yprpb;
    1047             :                 burst_ena = false;
    1048           0 :                 break;
    1049             :         case DRM_MODE_CONNECTOR_SVIDEO:
    1050           0 :                 tv_ctl |= TV_ENC_OUTPUT_SVIDEO;
    1051           0 :                 video_levels = tv_mode->svideo_levels;
    1052           0 :                 color_conversion = tv_mode->svideo_color;
    1053           0 :                 burst_ena = tv_mode->burst_ena;
    1054           0 :                 break;
    1055             :         }
    1056             : 
    1057           0 :         if (intel_crtc->pipe == 1)
    1058           0 :                 tv_ctl |= TV_ENC_PIPEB_SELECT;
    1059           0 :         tv_ctl |= tv_mode->oversample;
    1060             : 
    1061           0 :         if (tv_mode->progressive)
    1062           0 :                 tv_ctl |= TV_PROGRESSIVE;
    1063           0 :         if (tv_mode->trilevel_sync)
    1064           0 :                 tv_ctl |= TV_TRILEVEL_SYNC;
    1065           0 :         if (tv_mode->pal_burst)
    1066           0 :                 tv_ctl |= TV_PAL_BURST;
    1067             : 
    1068             :         scctl1 = 0;
    1069           0 :         if (tv_mode->dda1_inc)
    1070           0 :                 scctl1 |= TV_SC_DDA1_EN;
    1071           0 :         if (tv_mode->dda2_inc)
    1072           0 :                 scctl1 |= TV_SC_DDA2_EN;
    1073           0 :         if (tv_mode->dda3_inc)
    1074           0 :                 scctl1 |= TV_SC_DDA3_EN;
    1075           0 :         scctl1 |= tv_mode->sc_reset;
    1076           0 :         if (video_levels)
    1077           0 :                 scctl1 |= video_levels->burst << TV_BURST_LEVEL_SHIFT;
    1078           0 :         scctl1 |= tv_mode->dda1_inc << TV_SCDDA1_INC_SHIFT;
    1079             : 
    1080           0 :         scctl2 = tv_mode->dda2_size << TV_SCDDA2_SIZE_SHIFT |
    1081           0 :                 tv_mode->dda2_inc << TV_SCDDA2_INC_SHIFT;
    1082             : 
    1083           0 :         scctl3 = tv_mode->dda3_size << TV_SCDDA3_SIZE_SHIFT |
    1084           0 :                 tv_mode->dda3_inc << TV_SCDDA3_INC_SHIFT;
    1085             : 
    1086             :         /* Enable two fixes for the chips that need them. */
    1087           0 :         if (IS_I915GM(dev))
    1088           0 :                 tv_ctl |= TV_ENC_C0_FIX | TV_ENC_SDP_FIX;
    1089             : 
    1090           0 :         set_tv_mode_timings(dev_priv, tv_mode, burst_ena);
    1091             : 
    1092           0 :         I915_WRITE(TV_SC_CTL_1, scctl1);
    1093           0 :         I915_WRITE(TV_SC_CTL_2, scctl2);
    1094           0 :         I915_WRITE(TV_SC_CTL_3, scctl3);
    1095             : 
    1096           0 :         set_color_conversion(dev_priv, color_conversion);
    1097             : 
    1098           0 :         if (INTEL_INFO(dev)->gen >= 4)
    1099           0 :                 I915_WRITE(TV_CLR_KNOBS, 0x00404000);
    1100             :         else
    1101           0 :                 I915_WRITE(TV_CLR_KNOBS, 0x00606000);
    1102             : 
    1103           0 :         if (video_levels)
    1104           0 :                 I915_WRITE(TV_CLR_LEVEL,
    1105             :                            ((video_levels->black << TV_BLACK_LEVEL_SHIFT) |
    1106             :                             (video_levels->blank << TV_BLANK_LEVEL_SHIFT)));
    1107             : 
    1108           0 :         assert_pipe_disabled(dev_priv, intel_crtc->pipe);
    1109             : 
    1110             :         /* Filter ctl must be set before TV_WIN_SIZE */
    1111           0 :         I915_WRITE(TV_FILTER_CTL_1, TV_AUTO_SCALE);
    1112           0 :         xsize = tv_mode->hblank_start - tv_mode->hblank_end;
    1113           0 :         if (tv_mode->progressive)
    1114           0 :                 ysize = tv_mode->nbr_end + 1;
    1115             :         else
    1116           0 :                 ysize = 2*tv_mode->nbr_end + 1;
    1117             : 
    1118           0 :         xpos += intel_tv->margin[TV_MARGIN_LEFT];
    1119           0 :         ypos += intel_tv->margin[TV_MARGIN_TOP];
    1120           0 :         xsize -= (intel_tv->margin[TV_MARGIN_LEFT] +
    1121           0 :                   intel_tv->margin[TV_MARGIN_RIGHT]);
    1122           0 :         ysize -= (intel_tv->margin[TV_MARGIN_TOP] +
    1123           0 :                   intel_tv->margin[TV_MARGIN_BOTTOM]);
    1124           0 :         I915_WRITE(TV_WIN_POS, (xpos<<16)|ypos);
    1125           0 :         I915_WRITE(TV_WIN_SIZE, (xsize<<16)|ysize);
    1126             : 
    1127             :         j = 0;
    1128           0 :         for (i = 0; i < 60; i++)
    1129           0 :                 I915_WRITE(TV_H_LUMA(i), tv_mode->filter_table[j++]);
    1130           0 :         for (i = 0; i < 60; i++)
    1131           0 :                 I915_WRITE(TV_H_CHROMA(i), tv_mode->filter_table[j++]);
    1132           0 :         for (i = 0; i < 43; i++)
    1133           0 :                 I915_WRITE(TV_V_LUMA(i), tv_mode->filter_table[j++]);
    1134           0 :         for (i = 0; i < 43; i++)
    1135           0 :                 I915_WRITE(TV_V_CHROMA(i), tv_mode->filter_table[j++]);
    1136           0 :         I915_WRITE(TV_DAC, I915_READ(TV_DAC) & TV_DAC_SAVE);
    1137           0 :         I915_WRITE(TV_CTL, tv_ctl);
    1138           0 : }
    1139             : 
    1140             : static const struct drm_display_mode reported_modes[] = {
    1141             :         {
    1142             :                 .name = "NTSC 480i",
    1143             :                 .clock = 107520,
    1144             :                 .hdisplay = 1280,
    1145             :                 .hsync_start = 1368,
    1146             :                 .hsync_end = 1496,
    1147             :                 .htotal = 1712,
    1148             : 
    1149             :                 .vdisplay = 1024,
    1150             :                 .vsync_start = 1027,
    1151             :                 .vsync_end = 1034,
    1152             :                 .vtotal = 1104,
    1153             :                 .type = DRM_MODE_TYPE_DRIVER,
    1154             :         },
    1155             : };
    1156             : 
    1157             : /**
    1158             :  * Detects TV presence by checking for load.
    1159             :  *
    1160             :  * Requires that the current pipe's DPLL is active.
    1161             : 
    1162             :  * \return true if TV is connected.
    1163             :  * \return false if TV is disconnected.
    1164             :  */
    1165             : static int
    1166           0 : intel_tv_detect_type(struct intel_tv *intel_tv,
    1167             :                       struct drm_connector *connector)
    1168             : {
    1169           0 :         struct drm_encoder *encoder = &intel_tv->base.base;
    1170           0 :         struct drm_crtc *crtc = encoder->crtc;
    1171           0 :         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
    1172           0 :         struct drm_device *dev = encoder->dev;
    1173           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
    1174             :         u32 tv_ctl, save_tv_ctl;
    1175             :         u32 tv_dac, save_tv_dac;
    1176             :         int type;
    1177             : 
    1178             :         /* Disable TV interrupts around load detect or we'll recurse */
    1179           0 :         if (connector->polled & DRM_CONNECTOR_POLL_HPD) {
    1180           0 :                 spin_lock_irq(&dev_priv->irq_lock);
    1181           0 :                 i915_disable_pipestat(dev_priv, 0,
    1182             :                                       PIPE_HOTPLUG_INTERRUPT_STATUS |
    1183             :                                       PIPE_HOTPLUG_TV_INTERRUPT_STATUS);
    1184           0 :                 spin_unlock_irq(&dev_priv->irq_lock);
    1185           0 :         }
    1186             : 
    1187           0 :         save_tv_dac = tv_dac = I915_READ(TV_DAC);
    1188           0 :         save_tv_ctl = tv_ctl = I915_READ(TV_CTL);
    1189             : 
    1190             :         /* Poll for TV detection */
    1191           0 :         tv_ctl &= ~(TV_ENC_ENABLE | TV_TEST_MODE_MASK);
    1192           0 :         tv_ctl |= TV_TEST_MODE_MONITOR_DETECT;
    1193           0 :         if (intel_crtc->pipe == 1)
    1194           0 :                 tv_ctl |= TV_ENC_PIPEB_SELECT;
    1195             :         else
    1196           0 :                 tv_ctl &= ~TV_ENC_PIPEB_SELECT;
    1197             : 
    1198           0 :         tv_dac &= ~(TVDAC_SENSE_MASK | DAC_A_MASK | DAC_B_MASK | DAC_C_MASK);
    1199           0 :         tv_dac |= (TVDAC_STATE_CHG_EN |
    1200             :                    TVDAC_A_SENSE_CTL |
    1201             :                    TVDAC_B_SENSE_CTL |
    1202             :                    TVDAC_C_SENSE_CTL |
    1203             :                    DAC_CTL_OVERRIDE |
    1204             :                    DAC_A_0_7_V |
    1205             :                    DAC_B_0_7_V |
    1206             :                    DAC_C_0_7_V);
    1207             : 
    1208             : 
    1209             :         /*
    1210             :          * The TV sense state should be cleared to zero on cantiga platform. Otherwise
    1211             :          * the TV is misdetected. This is hardware requirement.
    1212             :          */
    1213           0 :         if (IS_GM45(dev))
    1214           0 :                 tv_dac &= ~(TVDAC_STATE_CHG_EN | TVDAC_A_SENSE_CTL |
    1215             :                             TVDAC_B_SENSE_CTL | TVDAC_C_SENSE_CTL);
    1216             : 
    1217           0 :         I915_WRITE(TV_CTL, tv_ctl);
    1218           0 :         I915_WRITE(TV_DAC, tv_dac);
    1219           0 :         POSTING_READ(TV_DAC);
    1220             : 
    1221           0 :         intel_wait_for_vblank(intel_tv->base.base.dev,
    1222           0 :                               to_intel_crtc(intel_tv->base.base.crtc)->pipe);
    1223             : 
    1224             :         type = -1;
    1225           0 :         tv_dac = I915_READ(TV_DAC);
    1226             :         DRM_DEBUG_KMS("TV detected: %x, %x\n", tv_ctl, tv_dac);
    1227             :         /*
    1228             :          *  A B C
    1229             :          *  0 1 1 Composite
    1230             :          *  1 0 X svideo
    1231             :          *  0 0 0 Component
    1232             :          */
    1233           0 :         if ((tv_dac & TVDAC_SENSE_MASK) == (TVDAC_B_SENSE | TVDAC_C_SENSE)) {
    1234             :                 DRM_DEBUG_KMS("Detected Composite TV connection\n");
    1235             :                 type = DRM_MODE_CONNECTOR_Composite;
    1236           0 :         } else if ((tv_dac & (TVDAC_A_SENSE|TVDAC_B_SENSE)) == TVDAC_A_SENSE) {
    1237             :                 DRM_DEBUG_KMS("Detected S-Video TV connection\n");
    1238             :                 type = DRM_MODE_CONNECTOR_SVIDEO;
    1239           0 :         } else if ((tv_dac & TVDAC_SENSE_MASK) == 0) {
    1240             :                 DRM_DEBUG_KMS("Detected Component TV connection\n");
    1241             :                 type = DRM_MODE_CONNECTOR_Component;
    1242           0 :         } else {
    1243             :                 DRM_DEBUG_KMS("Unrecognised TV connection\n");
    1244             :                 type = -1;
    1245             :         }
    1246             : 
    1247           0 :         I915_WRITE(TV_DAC, save_tv_dac & ~TVDAC_STATE_CHG_EN);
    1248           0 :         I915_WRITE(TV_CTL, save_tv_ctl);
    1249           0 :         POSTING_READ(TV_CTL);
    1250             : 
    1251             :         /* For unknown reasons the hw barfs if we don't do this vblank wait. */
    1252           0 :         intel_wait_for_vblank(intel_tv->base.base.dev,
    1253           0 :                               to_intel_crtc(intel_tv->base.base.crtc)->pipe);
    1254             : 
    1255             :         /* Restore interrupt config */
    1256           0 :         if (connector->polled & DRM_CONNECTOR_POLL_HPD) {
    1257           0 :                 spin_lock_irq(&dev_priv->irq_lock);
    1258           0 :                 i915_enable_pipestat(dev_priv, 0,
    1259             :                                      PIPE_HOTPLUG_INTERRUPT_STATUS |
    1260             :                                      PIPE_HOTPLUG_TV_INTERRUPT_STATUS);
    1261           0 :                 spin_unlock_irq(&dev_priv->irq_lock);
    1262           0 :         }
    1263             : 
    1264           0 :         return type;
    1265             : }
    1266             : 
    1267             : /*
    1268             :  * Here we set accurate tv format according to connector type
    1269             :  * i.e Component TV should not be assigned by NTSC or PAL
    1270             :  */
    1271           0 : static void intel_tv_find_better_format(struct drm_connector *connector)
    1272             : {
    1273           0 :         struct intel_tv *intel_tv = intel_attached_tv(connector);
    1274           0 :         const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
    1275             :         int i;
    1276             : 
    1277           0 :         if ((intel_tv->type == DRM_MODE_CONNECTOR_Component) ==
    1278           0 :                 tv_mode->component_only)
    1279           0 :                 return;
    1280             : 
    1281             : 
    1282           0 :         for (i = 0; i < ARRAY_SIZE(tv_modes); i++) {
    1283           0 :                 tv_mode = tv_modes + i;
    1284             : 
    1285           0 :                 if ((intel_tv->type == DRM_MODE_CONNECTOR_Component) ==
    1286           0 :                         tv_mode->component_only)
    1287             :                         break;
    1288             :         }
    1289             : 
    1290           0 :         intel_tv->tv_format = tv_mode->name;
    1291           0 :         drm_object_property_set_value(&connector->base,
    1292           0 :                 connector->dev->mode_config.tv_mode_property, i);
    1293           0 : }
    1294             : 
    1295             : /**
    1296             :  * Detect the TV connection.
    1297             :  *
    1298             :  * Currently this always returns CONNECTOR_STATUS_UNKNOWN, as we need to be sure
    1299             :  * we have a pipe programmed in order to probe the TV.
    1300             :  */
    1301             : static enum drm_connector_status
    1302           0 : intel_tv_detect(struct drm_connector *connector, bool force)
    1303             : {
    1304           0 :         struct drm_display_mode mode;
    1305           0 :         struct intel_tv *intel_tv = intel_attached_tv(connector);
    1306             :         enum drm_connector_status status;
    1307             :         int type;
    1308             : 
    1309             :         DRM_DEBUG_KMS("[CONNECTOR:%d:%s] force=%d\n",
    1310             :                       connector->base.id, connector->name,
    1311             :                       force);
    1312             : 
    1313           0 :         mode = reported_modes[0];
    1314             : 
    1315           0 :         if (force) {
    1316           0 :                 struct intel_load_detect_pipe tmp;
    1317           0 :                 struct drm_modeset_acquire_ctx ctx;
    1318             : 
    1319           0 :                 drm_modeset_acquire_init(&ctx, 0);
    1320             : 
    1321           0 :                 if (intel_get_load_detect_pipe(connector, &mode, &tmp, &ctx)) {
    1322           0 :                         type = intel_tv_detect_type(intel_tv, connector);
    1323           0 :                         intel_release_load_detect_pipe(connector, &tmp, &ctx);
    1324           0 :                         status = type < 0 ?
    1325             :                                 connector_status_disconnected :
    1326             :                                 connector_status_connected;
    1327           0 :                 } else
    1328             :                         status = connector_status_unknown;
    1329             : 
    1330           0 :                 drm_modeset_drop_locks(&ctx);
    1331           0 :                 drm_modeset_acquire_fini(&ctx);
    1332           0 :         } else
    1333           0 :                 return connector->status;
    1334             : 
    1335           0 :         if (status != connector_status_connected)
    1336           0 :                 return status;
    1337             : 
    1338           0 :         intel_tv->type = type;
    1339           0 :         intel_tv_find_better_format(connector);
    1340             : 
    1341           0 :         return connector_status_connected;
    1342           0 : }
    1343             : 
    1344             : static const struct input_res {
    1345             :         const char *name;
    1346             :         int w, h;
    1347             : } input_res_table[] = {
    1348             :         {"640x480", 640, 480},
    1349             :         {"800x600", 800, 600},
    1350             :         {"1024x768", 1024, 768},
    1351             :         {"1280x1024", 1280, 1024},
    1352             :         {"848x480", 848, 480},
    1353             :         {"1280x720", 1280, 720},
    1354             :         {"1920x1080", 1920, 1080},
    1355             : };
    1356             : 
    1357             : /*
    1358             :  * Chose preferred mode  according to line number of TV format
    1359             :  */
    1360             : static void
    1361           0 : intel_tv_chose_preferred_modes(struct drm_connector *connector,
    1362             :                                struct drm_display_mode *mode_ptr)
    1363             : {
    1364           0 :         struct intel_tv *intel_tv = intel_attached_tv(connector);
    1365           0 :         const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
    1366             : 
    1367           0 :         if (tv_mode->nbr_end < 480 && mode_ptr->vdisplay == 480)
    1368           0 :                 mode_ptr->type |= DRM_MODE_TYPE_PREFERRED;
    1369           0 :         else if (tv_mode->nbr_end > 480) {
    1370           0 :                 if (tv_mode->progressive == true && tv_mode->nbr_end < 720) {
    1371           0 :                         if (mode_ptr->vdisplay == 720)
    1372           0 :                                 mode_ptr->type |= DRM_MODE_TYPE_PREFERRED;
    1373           0 :                 } else if (mode_ptr->vdisplay == 1080)
    1374           0 :                                 mode_ptr->type |= DRM_MODE_TYPE_PREFERRED;
    1375             :         }
    1376           0 : }
    1377             : 
    1378             : /**
    1379             :  * Stub get_modes function.
    1380             :  *
    1381             :  * This should probably return a set of fixed modes, unless we can figure out
    1382             :  * how to probe modes off of TV connections.
    1383             :  */
    1384             : 
    1385             : static int
    1386           0 : intel_tv_get_modes(struct drm_connector *connector)
    1387             : {
    1388             :         struct drm_display_mode *mode_ptr;
    1389           0 :         struct intel_tv *intel_tv = intel_attached_tv(connector);
    1390           0 :         const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
    1391             :         int j, count = 0;
    1392             :         u64 tmp;
    1393             : 
    1394           0 :         for (j = 0; j < ARRAY_SIZE(input_res_table);
    1395           0 :              j++) {
    1396           0 :                 const struct input_res *input = &input_res_table[j];
    1397           0 :                 unsigned int hactive_s = input->w;
    1398           0 :                 unsigned int vactive_s = input->h;
    1399             : 
    1400           0 :                 if (tv_mode->max_srcw && input->w > tv_mode->max_srcw)
    1401           0 :                         continue;
    1402             : 
    1403           0 :                 if (input->w > 1024 && (!tv_mode->progressive
    1404           0 :                                         && !tv_mode->component_only))
    1405           0 :                         continue;
    1406             : 
    1407           0 :                 mode_ptr = drm_mode_create(connector->dev);
    1408           0 :                 if (!mode_ptr)
    1409           0 :                         continue;
    1410           0 :                 strncpy(mode_ptr->name, input->name, DRM_DISPLAY_MODE_LEN);
    1411             : 
    1412           0 :                 mode_ptr->hdisplay = hactive_s;
    1413           0 :                 mode_ptr->hsync_start = hactive_s + 1;
    1414           0 :                 mode_ptr->hsync_end = hactive_s + 64;
    1415           0 :                 if (mode_ptr->hsync_end <= mode_ptr->hsync_start)
    1416           0 :                         mode_ptr->hsync_end = mode_ptr->hsync_start + 1;
    1417           0 :                 mode_ptr->htotal = hactive_s + 96;
    1418             : 
    1419           0 :                 mode_ptr->vdisplay = vactive_s;
    1420           0 :                 mode_ptr->vsync_start = vactive_s + 1;
    1421           0 :                 mode_ptr->vsync_end = vactive_s + 32;
    1422           0 :                 if (mode_ptr->vsync_end <= mode_ptr->vsync_start)
    1423           0 :                         mode_ptr->vsync_end = mode_ptr->vsync_start  + 1;
    1424           0 :                 mode_ptr->vtotal = vactive_s + 33;
    1425             : 
    1426           0 :                 tmp = (u64) tv_mode->refresh * mode_ptr->vtotal;
    1427           0 :                 tmp *= mode_ptr->htotal;
    1428           0 :                 tmp = div_u64(tmp, 1000000);
    1429           0 :                 mode_ptr->clock = (int) tmp;
    1430             : 
    1431           0 :                 mode_ptr->type = DRM_MODE_TYPE_DRIVER;
    1432           0 :                 intel_tv_chose_preferred_modes(connector, mode_ptr);
    1433           0 :                 drm_mode_probed_add(connector, mode_ptr);
    1434           0 :                 count++;
    1435           0 :         }
    1436             : 
    1437           0 :         return count;
    1438             : }
    1439             : 
    1440             : static void
    1441           0 : intel_tv_destroy(struct drm_connector *connector)
    1442             : {
    1443           0 :         drm_connector_cleanup(connector);
    1444           0 :         kfree(connector);
    1445           0 : }
    1446             : 
    1447             : 
    1448             : static int
    1449           0 : intel_tv_set_property(struct drm_connector *connector, struct drm_property *property,
    1450             :                       uint64_t val)
    1451             : {
    1452           0 :         struct drm_device *dev = connector->dev;
    1453           0 :         struct intel_tv *intel_tv = intel_attached_tv(connector);
    1454           0 :         struct drm_crtc *crtc = intel_tv->base.base.crtc;
    1455             :         int ret = 0;
    1456             :         bool changed = false;
    1457             : 
    1458           0 :         ret = drm_object_property_set_value(&connector->base, property, val);
    1459           0 :         if (ret < 0)
    1460             :                 goto out;
    1461             : 
    1462           0 :         if (property == dev->mode_config.tv_left_margin_property &&
    1463           0 :                 intel_tv->margin[TV_MARGIN_LEFT] != val) {
    1464           0 :                 intel_tv->margin[TV_MARGIN_LEFT] = val;
    1465             :                 changed = true;
    1466           0 :         } else if (property == dev->mode_config.tv_right_margin_property &&
    1467           0 :                 intel_tv->margin[TV_MARGIN_RIGHT] != val) {
    1468           0 :                 intel_tv->margin[TV_MARGIN_RIGHT] = val;
    1469             :                 changed = true;
    1470           0 :         } else if (property == dev->mode_config.tv_top_margin_property &&
    1471           0 :                 intel_tv->margin[TV_MARGIN_TOP] != val) {
    1472           0 :                 intel_tv->margin[TV_MARGIN_TOP] = val;
    1473             :                 changed = true;
    1474           0 :         } else if (property == dev->mode_config.tv_bottom_margin_property &&
    1475           0 :                 intel_tv->margin[TV_MARGIN_BOTTOM] != val) {
    1476           0 :                 intel_tv->margin[TV_MARGIN_BOTTOM] = val;
    1477             :                 changed = true;
    1478           0 :         } else if (property == dev->mode_config.tv_mode_property) {
    1479           0 :                 if (val >= ARRAY_SIZE(tv_modes)) {
    1480             :                         ret = -EINVAL;
    1481           0 :                         goto out;
    1482             :                 }
    1483           0 :                 if (!strcmp(intel_tv->tv_format, tv_modes[val].name))
    1484             :                         goto out;
    1485             : 
    1486           0 :                 intel_tv->tv_format = tv_modes[val].name;
    1487             :                 changed = true;
    1488             :         } else {
    1489             :                 ret = -EINVAL;
    1490           0 :                 goto out;
    1491             :         }
    1492             : 
    1493           0 :         if (changed && crtc)
    1494           0 :                 intel_crtc_restore_mode(crtc);
    1495             : out:
    1496           0 :         return ret;
    1497             : }
    1498             : 
    1499             : static const struct drm_connector_funcs intel_tv_connector_funcs = {
    1500             :         .dpms = drm_atomic_helper_connector_dpms,
    1501             :         .detect = intel_tv_detect,
    1502             :         .destroy = intel_tv_destroy,
    1503             :         .set_property = intel_tv_set_property,
    1504             :         .atomic_get_property = intel_connector_atomic_get_property,
    1505             :         .fill_modes = drm_helper_probe_single_connector_modes,
    1506             :         .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
    1507             :         .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
    1508             : };
    1509             : 
    1510             : static const struct drm_connector_helper_funcs intel_tv_connector_helper_funcs = {
    1511             :         .mode_valid = intel_tv_mode_valid,
    1512             :         .get_modes = intel_tv_get_modes,
    1513             :         .best_encoder = intel_best_encoder,
    1514             : };
    1515             : 
    1516             : static const struct drm_encoder_funcs intel_tv_enc_funcs = {
    1517             :         .destroy = intel_encoder_destroy,
    1518             : };
    1519             : 
    1520             : /*
    1521             :  * Enumerate the child dev array parsed from VBT to check whether
    1522             :  * the integrated TV is present.
    1523             :  * If it is present, return 1.
    1524             :  * If it is not present, return false.
    1525             :  * If no child dev is parsed from VBT, it assumes that the TV is present.
    1526             :  */
    1527           0 : static int tv_is_present_in_vbt(struct drm_device *dev)
    1528             : {
    1529           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
    1530             :         union child_device_config *p_child;
    1531             :         int i, ret;
    1532             : 
    1533           0 :         if (!dev_priv->vbt.child_dev_num)
    1534           0 :                 return 1;
    1535             : 
    1536             :         ret = 0;
    1537           0 :         for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
    1538           0 :                 p_child = dev_priv->vbt.child_dev + i;
    1539             :                 /*
    1540             :                  * If the device type is not TV, continue.
    1541             :                  */
    1542           0 :                 switch (p_child->old.device_type) {
    1543             :                 case DEVICE_TYPE_INT_TV:
    1544             :                 case DEVICE_TYPE_TV:
    1545             :                 case DEVICE_TYPE_TV_SVIDEO_COMPOSITE:
    1546             :                         break;
    1547             :                 default:
    1548             :                         continue;
    1549             :                 }
    1550             :                 /* Only when the addin_offset is non-zero, it is regarded
    1551             :                  * as present.
    1552             :                  */
    1553           0 :                 if (p_child->old.addin_offset) {
    1554             :                         ret = 1;
    1555           0 :                         break;
    1556             :                 }
    1557             :         }
    1558           0 :         return ret;
    1559           0 : }
    1560             : 
    1561             : void
    1562           0 : intel_tv_init(struct drm_device *dev)
    1563             : {
    1564           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
    1565             :         struct drm_connector *connector;
    1566             :         struct intel_tv *intel_tv;
    1567             :         struct intel_encoder *intel_encoder;
    1568             :         struct intel_connector *intel_connector;
    1569             :         u32 tv_dac_on, tv_dac_off, save_tv_dac;
    1570           0 :         const char *tv_format_names[ARRAY_SIZE(tv_modes)];
    1571             :         int i, initial_mode = 0;
    1572             : 
    1573           0 :         if ((I915_READ(TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED)
    1574           0 :                 return;
    1575             : 
    1576           0 :         if (!tv_is_present_in_vbt(dev)) {
    1577             :                 DRM_DEBUG_KMS("Integrated TV is not present.\n");
    1578           0 :                 return;
    1579             :         }
    1580             :         /* Even if we have an encoder we may not have a connector */
    1581           0 :         if (!dev_priv->vbt.int_tv_support)
    1582           0 :                 return;
    1583             : 
    1584             :         /*
    1585             :          * Sanity check the TV output by checking to see if the
    1586             :          * DAC register holds a value
    1587             :          */
    1588           0 :         save_tv_dac = I915_READ(TV_DAC);
    1589             : 
    1590           0 :         I915_WRITE(TV_DAC, save_tv_dac | TVDAC_STATE_CHG_EN);
    1591           0 :         tv_dac_on = I915_READ(TV_DAC);
    1592             : 
    1593           0 :         I915_WRITE(TV_DAC, save_tv_dac & ~TVDAC_STATE_CHG_EN);
    1594           0 :         tv_dac_off = I915_READ(TV_DAC);
    1595             : 
    1596           0 :         I915_WRITE(TV_DAC, save_tv_dac);
    1597             : 
    1598             :         /*
    1599             :          * If the register does not hold the state change enable
    1600             :          * bit, (either as a 0 or a 1), assume it doesn't really
    1601             :          * exist
    1602             :          */
    1603           0 :         if ((tv_dac_on & TVDAC_STATE_CHG_EN) == 0 ||
    1604           0 :             (tv_dac_off & TVDAC_STATE_CHG_EN) != 0)
    1605           0 :                 return;
    1606             : 
    1607           0 :         intel_tv = kzalloc(sizeof(*intel_tv), GFP_KERNEL);
    1608           0 :         if (!intel_tv) {
    1609           0 :                 return;
    1610             :         }
    1611             : 
    1612           0 :         intel_connector = intel_connector_alloc();
    1613           0 :         if (!intel_connector) {
    1614           0 :                 kfree(intel_tv);
    1615           0 :                 return;
    1616             :         }
    1617             : 
    1618           0 :         intel_encoder = &intel_tv->base;
    1619           0 :         connector = &intel_connector->base;
    1620             : 
    1621             :         /* The documentation, for the older chipsets at least, recommend
    1622             :          * using a polling method rather than hotplug detection for TVs.
    1623             :          * This is because in order to perform the hotplug detection, the PLLs
    1624             :          * for the TV must be kept alive increasing power drain and starving
    1625             :          * bandwidth from other encoders. Notably for instance, it causes
    1626             :          * pipe underruns on Crestline when this encoder is supposedly idle.
    1627             :          *
    1628             :          * More recent chipsets favour HDMI rather than integrated S-Video.
    1629             :          */
    1630           0 :         intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT;
    1631             : 
    1632           0 :         drm_connector_init(dev, connector, &intel_tv_connector_funcs,
    1633             :                            DRM_MODE_CONNECTOR_SVIDEO);
    1634             : 
    1635           0 :         drm_encoder_init(dev, &intel_encoder->base, &intel_tv_enc_funcs,
    1636             :                          DRM_MODE_ENCODER_TVDAC);
    1637             : 
    1638           0 :         intel_encoder->compute_config = intel_tv_compute_config;
    1639           0 :         intel_encoder->get_config = intel_tv_get_config;
    1640           0 :         intel_encoder->pre_enable = intel_tv_pre_enable;
    1641           0 :         intel_encoder->enable = intel_enable_tv;
    1642           0 :         intel_encoder->disable = intel_disable_tv;
    1643           0 :         intel_encoder->get_hw_state = intel_tv_get_hw_state;
    1644           0 :         intel_connector->get_hw_state = intel_connector_get_hw_state;
    1645           0 :         intel_connector->unregister = intel_connector_unregister;
    1646             : 
    1647           0 :         intel_connector_attach_encoder(intel_connector, intel_encoder);
    1648           0 :         intel_encoder->type = INTEL_OUTPUT_TVOUT;
    1649           0 :         intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
    1650           0 :         intel_encoder->cloneable = 0;
    1651           0 :         intel_encoder->base.possible_crtcs = ((1 << 0) | (1 << 1));
    1652           0 :         intel_tv->type = DRM_MODE_CONNECTOR_Unknown;
    1653             : 
    1654             :         /* BIOS margin values */
    1655           0 :         intel_tv->margin[TV_MARGIN_LEFT] = 54;
    1656           0 :         intel_tv->margin[TV_MARGIN_TOP] = 36;
    1657           0 :         intel_tv->margin[TV_MARGIN_RIGHT] = 46;
    1658           0 :         intel_tv->margin[TV_MARGIN_BOTTOM] = 37;
    1659             : 
    1660           0 :         intel_tv->tv_format = tv_modes[initial_mode].name;
    1661             : 
    1662           0 :         drm_connector_helper_add(connector, &intel_tv_connector_helper_funcs);
    1663           0 :         connector->interlace_allowed = false;
    1664           0 :         connector->doublescan_allowed = false;
    1665             : 
    1666             :         /* Create TV properties then attach current values */
    1667           0 :         for (i = 0; i < ARRAY_SIZE(tv_modes); i++)
    1668           0 :                 tv_format_names[i] = tv_modes[i].name;
    1669           0 :         drm_mode_create_tv_properties(dev,
    1670             :                                       ARRAY_SIZE(tv_modes),
    1671           0 :                                       tv_format_names);
    1672             : 
    1673           0 :         drm_object_attach_property(&connector->base, dev->mode_config.tv_mode_property,
    1674             :                                    initial_mode);
    1675           0 :         drm_object_attach_property(&connector->base,
    1676           0 :                                    dev->mode_config.tv_left_margin_property,
    1677           0 :                                    intel_tv->margin[TV_MARGIN_LEFT]);
    1678           0 :         drm_object_attach_property(&connector->base,
    1679           0 :                                    dev->mode_config.tv_top_margin_property,
    1680           0 :                                    intel_tv->margin[TV_MARGIN_TOP]);
    1681           0 :         drm_object_attach_property(&connector->base,
    1682           0 :                                    dev->mode_config.tv_right_margin_property,
    1683           0 :                                    intel_tv->margin[TV_MARGIN_RIGHT]);
    1684           0 :         drm_object_attach_property(&connector->base,
    1685           0 :                                    dev->mode_config.tv_bottom_margin_property,
    1686           0 :                                    intel_tv->margin[TV_MARGIN_BOTTOM]);
    1687           0 :         drm_connector_register(connector);
    1688           0 : }

Generated by: LCOV version 1.13