root/drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tv_setup_filter
  2. tv_save_filter
  3. tv_load_filter
  4. nv17_tv_state_save
  5. nv17_tv_state_load
  6. nv17_tv_update_properties
  7. nv17_tv_update_rescaler
  8. nv17_ctv_update_rescaler

   1 /*
   2  * Copyright (C) 2009 Francisco Jerez.
   3  * All Rights Reserved.
   4  *
   5  * Permission is hereby granted, free of charge, to any person obtaining
   6  * a copy of this software and associated documentation files (the
   7  * "Software"), to deal in the Software without restriction, including
   8  * without limitation the rights to use, copy, modify, merge, publish,
   9  * distribute, sublicense, and/or sell copies of the Software, and to
  10  * permit persons to whom the Software is furnished to do so, subject to
  11  * the following conditions:
  12  *
  13  * The above copyright notice and this permission notice (including the
  14  * next paragraph) shall be included in all copies or substantial
  15  * portions of the Software.
  16  *
  17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  20  * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
  21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  24  *
  25  */
  26 
  27 #include <drm/drm_crtc_helper.h>
  28 #include "nouveau_drv.h"
  29 #include "nouveau_encoder.h"
  30 #include "nouveau_crtc.h"
  31 #include "hw.h"
  32 #include "tvnv17.h"
  33 
  34 const char * const nv17_tv_norm_names[NUM_TV_NORMS] = {
  35         [TV_NORM_PAL] = "PAL",
  36         [TV_NORM_PAL_M] = "PAL-M",
  37         [TV_NORM_PAL_N] = "PAL-N",
  38         [TV_NORM_PAL_NC] = "PAL-Nc",
  39         [TV_NORM_NTSC_M] = "NTSC-M",
  40         [TV_NORM_NTSC_J] = "NTSC-J",
  41         [TV_NORM_HD480I] = "hd480i",
  42         [TV_NORM_HD480P] = "hd480p",
  43         [TV_NORM_HD576I] = "hd576i",
  44         [TV_NORM_HD576P] = "hd576p",
  45         [TV_NORM_HD720P] = "hd720p",
  46         [TV_NORM_HD1080I] = "hd1080i"
  47 };
  48 
  49 /* TV standard specific parameters */
  50 
  51 struct nv17_tv_norm_params nv17_tv_norms[NUM_TV_NORMS] = {
  52         [TV_NORM_PAL] = { TV_ENC_MODE, {
  53                         .tv_enc_mode = { 720, 576, 50000, {
  54                                         0x2a, 0x9, 0x8a, 0xcb, 0x0, 0x0, 0xb, 0x18,
  55                                         0x7e, 0x40, 0x8a, 0x35, 0x27, 0x0, 0x34, 0x3,
  56                                         0x3e, 0x3, 0x17, 0x21, 0x1b, 0x1b, 0x24, 0x9c,
  57                                         0x1, 0x0, 0xf, 0xf, 0x60, 0x5, 0xd3, 0x3,
  58                                         0xd3, 0x4, 0xd4, 0x1, 0x2, 0x0, 0xa, 0x5,
  59                                         0x0, 0x1a, 0xff, 0x3, 0x18, 0xf, 0x78, 0x0,
  60                                         0x0, 0xb4, 0x0, 0x15, 0x49, 0x10, 0x0, 0x9b,
  61                                         0xbd, 0x15, 0x5, 0x15, 0x3e, 0x3, 0x0, 0x0
  62                                 } } } },
  63 
  64         [TV_NORM_PAL_M] = { TV_ENC_MODE, {
  65                         .tv_enc_mode = { 720, 480, 59940, {
  66                                         0x21, 0xe6, 0xef, 0xe3, 0x0, 0x0, 0xb, 0x18,
  67                                         0x7e, 0x44, 0x76, 0x32, 0x25, 0x0, 0x3c, 0x0,
  68                                         0x3c, 0x0, 0x17, 0x21, 0x1b, 0x1b, 0x24, 0x83,
  69                                         0x1, 0x0, 0xf, 0xf, 0x60, 0x5, 0xd3, 0x1,
  70                                         0xc5, 0x4, 0xc5, 0x1, 0x2, 0x0, 0xa, 0x5,
  71                                         0x0, 0x18, 0xff, 0x3, 0x20, 0xf, 0x78, 0x0,
  72                                         0x0, 0xb4, 0x0, 0x15, 0x40, 0x10, 0x0, 0x9c,
  73                                         0xc8, 0x15, 0x5, 0x15, 0x3c, 0x0, 0x0, 0x0
  74                                 } } } },
  75 
  76         [TV_NORM_PAL_N] = { TV_ENC_MODE, {
  77                         .tv_enc_mode = { 720, 576, 50000, {
  78                                         0x2a, 0x9, 0x8a, 0xcb, 0x0, 0x0, 0xb, 0x18,
  79                                         0x7e, 0x40, 0x8a, 0x32, 0x25, 0x0, 0x3c, 0x0,
  80                                         0x3c, 0x0, 0x17, 0x21, 0x1b, 0x1b, 0x24, 0x9c,
  81                                         0x1, 0x0, 0xf, 0xf, 0x60, 0x5, 0xd3, 0x1,
  82                                         0xc5, 0x4, 0xc5, 0x1, 0x2, 0x0, 0xa, 0x5,
  83                                         0x0, 0x1a, 0xff, 0x3, 0x18, 0xf, 0x78, 0x0,
  84                                         0x0, 0xb4, 0x0, 0x15, 0x49, 0x10, 0x0, 0x9b,
  85                                         0xbd, 0x15, 0x5, 0x15, 0x3c, 0x0, 0x0, 0x0
  86                                 } } } },
  87 
  88         [TV_NORM_PAL_NC] = { TV_ENC_MODE, {
  89                         .tv_enc_mode = { 720, 576, 50000, {
  90                                         0x21, 0xf6, 0x94, 0x46, 0x0, 0x0, 0xb, 0x18,
  91                                         0x7e, 0x44, 0x8a, 0x35, 0x27, 0x0, 0x34, 0x3,
  92                                         0x3e, 0x3, 0x17, 0x21, 0x1b, 0x1b, 0x24, 0x9c,
  93                                         0x1, 0x0, 0xf, 0xf, 0x60, 0x5, 0xd3, 0x3,
  94                                         0xd3, 0x4, 0xd4, 0x1, 0x2, 0x0, 0xa, 0x5,
  95                                         0x0, 0x1a, 0xff, 0x3, 0x18, 0xf, 0x78, 0x0,
  96                                         0x0, 0xb4, 0x0, 0x15, 0x49, 0x10, 0x0, 0x9b,
  97                                         0xbd, 0x15, 0x5, 0x15, 0x3e, 0x3, 0x0, 0x0
  98                                 } } } },
  99 
 100         [TV_NORM_NTSC_M] = { TV_ENC_MODE, {
 101                         .tv_enc_mode = { 720, 480, 59940, {
 102                                         0x21, 0xf0, 0x7c, 0x1f, 0x0, 0x0, 0xb, 0x18,
 103                                         0x7e, 0x44, 0x76, 0x48, 0x0, 0x0, 0x3c, 0x0,
 104                                         0x3c, 0x0, 0x17, 0x21, 0x1b, 0x1b, 0x24, 0x83,
 105                                         0x1, 0x0, 0xf, 0xf, 0x60, 0x5, 0xd3, 0x1,
 106                                         0xc5, 0x4, 0xc5, 0x1, 0x2, 0x0, 0xa, 0x5,
 107                                         0x0, 0x16, 0xff, 0x3, 0x20, 0xf, 0x78, 0x0,
 108                                         0x0, 0xb4, 0x0, 0x15, 0x4, 0x10, 0x0, 0x9c,
 109                                         0xc8, 0x15, 0x5, 0x15, 0x3c, 0x0, 0x0, 0x0
 110                                 } } } },
 111 
 112         [TV_NORM_NTSC_J] = { TV_ENC_MODE, {
 113                         .tv_enc_mode = { 720, 480, 59940, {
 114                                         0x21, 0xf0, 0x7c, 0x1f, 0x0, 0x0, 0xb, 0x18,
 115                                         0x7e, 0x44, 0x76, 0x48, 0x0, 0x0, 0x32, 0x0,
 116                                         0x3c, 0x0, 0x17, 0x21, 0x1b, 0x1b, 0x24, 0x83,
 117                                         0x1, 0x0, 0xf, 0xf, 0x60, 0x5, 0xd3, 0x1,
 118                                         0xcf, 0x4, 0xcf, 0x1, 0x2, 0x0, 0xa, 0x5,
 119                                         0x0, 0x16, 0xff, 0x3, 0x20, 0xf, 0x78, 0x0,
 120                                         0x0, 0xb4, 0x0, 0x15, 0x4, 0x10, 0x0, 0xa4,
 121                                         0xc8, 0x15, 0x5, 0x15, 0x3c, 0x0, 0x0, 0x0
 122                                 } } } },
 123 
 124         [TV_NORM_HD480I] = { TV_ENC_MODE, {
 125                         .tv_enc_mode = { 720, 480, 59940, {
 126                                         0x21, 0xf0, 0x7c, 0x1f, 0x0, 0x0, 0xb, 0x18,
 127                                         0x7e, 0x44, 0x76, 0x48, 0x0, 0x0, 0x32, 0x0,
 128                                         0x3c, 0x0, 0x17, 0x21, 0x1b, 0x1b, 0x24, 0x83,
 129                                         0x1, 0x0, 0xf, 0xf, 0x60, 0x5, 0xd3, 0x1,
 130                                         0xcf, 0x4, 0xcf, 0x1, 0x2, 0x0, 0xa, 0x5,
 131                                         0x0, 0x16, 0xff, 0x3, 0x20, 0xf, 0x78, 0x0,
 132                                         0x0, 0xb4, 0x0, 0x15, 0x4, 0x10, 0x0, 0xa4,
 133                                         0xc8, 0x15, 0x5, 0x15, 0x3c, 0x0, 0x0, 0x0
 134                                 } } } },
 135 
 136         [TV_NORM_HD576I] = { TV_ENC_MODE, {
 137                         .tv_enc_mode = { 720, 576, 50000, {
 138                                         0x2a, 0x9, 0x8a, 0xcb, 0x0, 0x0, 0xb, 0x18,
 139                                         0x7e, 0x40, 0x8a, 0x35, 0x27, 0x0, 0x34, 0x3,
 140                                         0x3e, 0x3, 0x17, 0x21, 0x1b, 0x1b, 0x24, 0x9c,
 141                                         0x1, 0x0, 0xf, 0xf, 0x60, 0x5, 0xd3, 0x3,
 142                                         0xd3, 0x4, 0xd4, 0x1, 0x2, 0x0, 0xa, 0x5,
 143                                         0x0, 0x1a, 0xff, 0x3, 0x18, 0xf, 0x78, 0x0,
 144                                         0x0, 0xb4, 0x0, 0x15, 0x49, 0x10, 0x0, 0x9b,
 145                                         0xbd, 0x15, 0x5, 0x15, 0x3e, 0x3, 0x0, 0x0
 146                                 } } } },
 147 
 148 
 149         [TV_NORM_HD480P] = { CTV_ENC_MODE, {
 150                         .ctv_enc_mode = {
 151                                 .mode = { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 27000,
 152                                                    720, 735, 743, 858, 0, 480, 490, 494, 525, 0,
 153                                                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
 154                                 .ctv_regs = { 0x3540000, 0x0, 0x0, 0x314,
 155                                               0x354003a, 0x40000, 0x6f0344, 0x18100000,
 156                                               0x10160004, 0x10060005, 0x1006000c, 0x10060020,
 157                                               0x10060021, 0x140e0022, 0x10060202, 0x1802020a,
 158                                               0x1810020b, 0x10000fff, 0x10000fff, 0x10000fff,
 159                                               0x10000fff, 0x10000fff, 0x10000fff, 0x70,
 160                                               0x3ff0000, 0x57, 0x2e001e, 0x258012c,
 161                                               0xa0aa04ec, 0x30, 0x80960019, 0x12c0300,
 162                                               0x2019, 0x600, 0x32060019, 0x0, 0x0, 0x400
 163                                 } } } },
 164 
 165         [TV_NORM_HD576P] = { CTV_ENC_MODE, {
 166                         .ctv_enc_mode = {
 167                                 .mode = { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 27000,
 168                                                    720, 730, 738, 864, 0, 576, 581, 585, 625, 0,
 169                                                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
 170                                 .ctv_regs = { 0x3540000, 0x0, 0x0, 0x314,
 171                                               0x354003a, 0x40000, 0x6f0344, 0x18100000,
 172                                               0x10060001, 0x10060009, 0x10060026, 0x10060027,
 173                                               0x140e0028, 0x10060268, 0x1810026d, 0x10000fff,
 174                                               0x10000fff, 0x10000fff, 0x10000fff, 0x10000fff,
 175                                               0x10000fff, 0x10000fff, 0x10000fff, 0x69,
 176                                               0x3ff0000, 0x57, 0x2e001e, 0x258012c,
 177                                               0xa0aa04ec, 0x30, 0x80960019, 0x12c0300,
 178                                               0x2019, 0x600, 0x32060019, 0x0, 0x0, 0x400
 179                                 } } } },
 180 
 181         [TV_NORM_HD720P] = { CTV_ENC_MODE, {
 182                         .ctv_enc_mode = {
 183                                 .mode = { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250,
 184                                                    1280, 1349, 1357, 1650, 0, 720, 725, 730, 750, 0,
 185                                                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
 186                                 .ctv_regs = { 0x1260394, 0x0, 0x0, 0x622,
 187                                               0x66b0021, 0x6004a, 0x1210626, 0x8170000,
 188                                               0x70004, 0x70016, 0x70017, 0x40f0018,
 189                                               0x702e8, 0x81702ed, 0xfff, 0xfff,
 190                                               0xfff, 0xfff, 0xfff, 0xfff,
 191                                               0xfff, 0xfff, 0xfff, 0x0,
 192                                               0x2e40001, 0x58, 0x2e001e, 0x258012c,
 193                                               0xa0aa04ec, 0x30, 0x810c0039, 0x12c0300,
 194                                               0xc0002039, 0x600, 0x32060039, 0x0, 0x0, 0x0
 195                                 } } } },
 196 
 197         [TV_NORM_HD1080I] = { CTV_ENC_MODE, {
 198                         .ctv_enc_mode = {
 199                                 .mode = { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250,
 200                                                    1920, 1961, 2049, 2200, 0, 1080, 1084, 1088, 1125, 0,
 201                                                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC
 202                                                    | DRM_MODE_FLAG_INTERLACE) },
 203                                 .ctv_regs = { 0xac0420, 0x44c0478, 0x4a4, 0x4fc0868,
 204                                               0x8940028, 0x60054, 0xe80870, 0xbf70000,
 205                                               0xbc70004, 0x70005, 0x70012, 0x70013,
 206                                               0x40f0014, 0x70230, 0xbf70232, 0xbf70233,
 207                                               0x1c70237, 0x70238, 0x70244, 0x70245,
 208                                               0x40f0246, 0x70462, 0x1f70464, 0x0,
 209                                               0x2e40001, 0x58, 0x2e001e, 0x258012c,
 210                                               0xa0aa04ec, 0x30, 0x815f004c, 0x12c0300,
 211                                               0xc000204c, 0x600, 0x3206004c, 0x0, 0x0, 0x0
 212                                 } } } }
 213 };
 214 
 215 /*
 216  * The following is some guesswork on how the TV encoder flicker
 217  * filter/rescaler works:
 218  *
 219  * It seems to use some sort of resampling filter, it is controlled
 220  * through the registers at NV_PTV_HFILTER and NV_PTV_VFILTER, they
 221  * control the horizontal and vertical stage respectively, there is
 222  * also NV_PTV_HFILTER2 the blob fills identically to NV_PTV_HFILTER,
 223  * but they seem to do nothing. A rough guess might be that they could
 224  * be used to independently control the filtering of each interlaced
 225  * field, but I don't know how they are enabled. The whole filtering
 226  * process seems to be disabled with bits 26:27 of PTV_200, but we
 227  * aren't doing that.
 228  *
 229  * The layout of both register sets is the same:
 230  *
 231  * A: [BASE+0x18]...[BASE+0x0] [BASE+0x58]..[BASE+0x40]
 232  * B: [BASE+0x34]...[BASE+0x1c] [BASE+0x74]..[BASE+0x5c]
 233  *
 234  * Each coefficient is stored in bits [31],[15:9] in two's complement
 235  * format. They seem to be some kind of weights used in a low-pass
 236  * filter. Both A and B coefficients are applied to the 14 nearest
 237  * samples on each side (Listed from nearest to furthermost.  They
 238  * roughly cover 2 framebuffer pixels on each side).  They are
 239  * probably multiplied with some more hardwired weights before being
 240  * used: B-coefficients are applied the same on both sides,
 241  * A-coefficients are inverted before being applied to the opposite
 242  * side.
 243  *
 244  * After all the hassle, I got the following formula by empirical
 245  * means...
 246  */
 247 
 248 #define calc_overscan(o) interpolate(0x100, 0xe1, 0xc1, o)
 249 
 250 #define id1 (1LL << 8)
 251 #define id2 (1LL << 16)
 252 #define id3 (1LL << 24)
 253 #define id4 (1LL << 32)
 254 #define id5 (1LL << 48)
 255 
 256 static struct filter_params{
 257         int64_t k1;
 258         int64_t ki;
 259         int64_t ki2;
 260         int64_t ki3;
 261         int64_t kr;
 262         int64_t kir;
 263         int64_t ki2r;
 264         int64_t ki3r;
 265         int64_t kf;
 266         int64_t kif;
 267         int64_t ki2f;
 268         int64_t ki3f;
 269         int64_t krf;
 270         int64_t kirf;
 271         int64_t ki2rf;
 272         int64_t ki3rf;
 273 } fparams[2][4] = {
 274         /* Horizontal filter parameters */
 275         {
 276                 {64.311690 * id5, -39.516924 * id5, 6.586143 * id5, 0.000002 * id5,
 277                  0.051285 * id4, 26.168746 * id4, -4.361449 * id4, -0.000001 * id4,
 278                  9.308169 * id3, 78.180965 * id3, -13.030158 * id3, -0.000001 * id3,
 279                  -8.801540 * id1, -46.572890 * id1, 7.762145 * id1, -0.000000 * id1},
 280                 {-44.565569 * id5, -68.081246 * id5, 39.812074 * id5, -4.009316 * id5,
 281                  29.832207 * id4, 50.047322 * id4, -25.380017 * id4, 2.546422 * id4,
 282                  104.605622 * id3, 141.908641 * id3, -74.322319 * id3, 7.484316 * id3,
 283                  -37.081621 * id1, -90.397510 * id1, 42.784229 * id1, -4.289952 * id1},
 284                 {-56.793244 * id5, 31.153584 * id5, -5.192247 * id5, -0.000003 * id5,
 285                  33.541131 * id4, -34.149302 * id4, 5.691537 * id4, 0.000002 * id4,
 286                  87.196610 * id3, -88.995169 * id3, 14.832456 * id3, 0.000012 * id3,
 287                  17.288138 * id1, 71.864786 * id1, -11.977408 * id1, -0.000009 * id1},
 288                 {51.787796 * id5, 21.211771 * id5, -18.993730 * id5, 1.853310 * id5,
 289                  -41.470726 * id4, -17.775823 * id4, 13.057821 * id4, -1.15823 * id4,
 290                  -154.235673 * id3, -44.878641 * id3, 40.656077 * id3, -3.695595 * id3,
 291                  112.201065 * id1, 39.992155 * id1, -25.155714 * id1, 2.113984 * id1},
 292         },
 293 
 294         /* Vertical filter parameters */
 295         {
 296                 {67.601979 * id5, 0.428319 * id5, -0.071318 * id5, -0.000012 * id5,
 297                  -3.402339 * id4, 0.000209 * id4, -0.000092 * id4, 0.000010 * id4,
 298                  -9.180996 * id3, 6.111270 * id3, -1.024457 * id3, 0.001043 * id3,
 299                  6.060315 * id1, -0.017425 * id1, 0.007830 * id1, -0.000869 * id1},
 300                 {6.755647 * id5, 5.841348 * id5, 1.469734 * id5, -0.149656 * id5,
 301                  8.293120 * id4, -1.192888 * id4, -0.947652 * id4, 0.094507 * id4,
 302                  37.526655 * id3, 10.257875 * id3, -10.823275 * id3, 1.081497 * id3,
 303                  -2.361928 * id1, -2.059432 * id1, 1.840671 * id1, -0.168100 * id1},
 304                 {-14.780391 * id5, -16.042148 * id5, 2.673692 * id5, -0.000000 * id5,
 305                  39.541978 * id4, 5.680053 * id4, -0.946676 * id4, 0.000000 * id4,
 306                  152.994486 * id3, 12.625439 * id3, -2.119579 * id3, 0.002708 * id3,
 307                  -38.125089 * id1, -0.855880 * id1, 0.155359 * id1, -0.002245 * id1},
 308                 {-27.476193 * id5, -1.454976 * id5, 1.286557 * id5, 0.025346 * id5,
 309                  20.687300 * id4, 3.014003 * id4, -0.557786 * id4, -0.01311 * id4,
 310                  60.008737 * id3, -0.738273 * id3, 5.408217 * id3, -0.796798 * id3,
 311                  -17.296835 * id1, 4.438577 * id1, -2.809420 * id1, 0.385491 * id1},
 312         }
 313 };
 314 
 315 static void tv_setup_filter(struct drm_encoder *encoder)
 316 {
 317         struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder);
 318         struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder);
 319         struct drm_display_mode *mode = &encoder->crtc->mode;
 320         uint32_t (*filters[])[4][7] = {&tv_enc->state.hfilter,
 321                                        &tv_enc->state.vfilter};
 322         int i, j, k;
 323         int32_t overscan = calc_overscan(tv_enc->overscan);
 324         int64_t flicker = (tv_enc->flicker - 50) * (id3 / 100);
 325         uint64_t rs[] = {mode->hdisplay * id3,
 326                          mode->vdisplay * id3};
 327 
 328         do_div(rs[0], overscan * tv_norm->tv_enc_mode.hdisplay);
 329         do_div(rs[1], overscan * tv_norm->tv_enc_mode.vdisplay);
 330 
 331         for (k = 0; k < 2; k++) {
 332                 rs[k] = max((int64_t)rs[k], id2);
 333 
 334                 for (j = 0; j < 4; j++) {
 335                         struct filter_params *p = &fparams[k][j];
 336 
 337                         for (i = 0; i < 7; i++) {
 338                                 int64_t c = (p->k1 + p->ki*i + p->ki2*i*i +
 339                                              p->ki3*i*i*i)
 340                                         + (p->kr + p->kir*i + p->ki2r*i*i +
 341                                            p->ki3r*i*i*i) * rs[k]
 342                                         + (p->kf + p->kif*i + p->ki2f*i*i +
 343                                            p->ki3f*i*i*i) * flicker
 344                                         + (p->krf + p->kirf*i + p->ki2rf*i*i +
 345                                            p->ki3rf*i*i*i) * flicker * rs[k];
 346 
 347                                 (*filters[k])[j][i] = (c + id5/2) >> 39
 348                                         & (0x1 << 31 | 0x7f << 9);
 349                         }
 350                 }
 351         }
 352 }
 353 
 354 /* Hardware state saving/restoring */
 355 
 356 static void tv_save_filter(struct drm_device *dev, uint32_t base,
 357                            uint32_t regs[4][7])
 358 {
 359         int i, j;
 360         uint32_t offsets[] = { base, base + 0x1c, base + 0x40, base + 0x5c };
 361 
 362         for (i = 0; i < 4; i++) {
 363                 for (j = 0; j < 7; j++)
 364                         regs[i][j] = nv_read_ptv(dev, offsets[i]+4*j);
 365         }
 366 }
 367 
 368 static void tv_load_filter(struct drm_device *dev, uint32_t base,
 369                            uint32_t regs[4][7])
 370 {
 371         int i, j;
 372         uint32_t offsets[] = { base, base + 0x1c, base + 0x40, base + 0x5c };
 373 
 374         for (i = 0; i < 4; i++) {
 375                 for (j = 0; j < 7; j++)
 376                         nv_write_ptv(dev, offsets[i]+4*j, regs[i][j]);
 377         }
 378 }
 379 
 380 void nv17_tv_state_save(struct drm_device *dev, struct nv17_tv_state *state)
 381 {
 382         int i;
 383 
 384         for (i = 0; i < 0x40; i++)
 385                 state->tv_enc[i] = nv_read_tv_enc(dev, i);
 386 
 387         tv_save_filter(dev, NV_PTV_HFILTER, state->hfilter);
 388         tv_save_filter(dev, NV_PTV_HFILTER2, state->hfilter2);
 389         tv_save_filter(dev, NV_PTV_VFILTER, state->vfilter);
 390 
 391         nv_save_ptv(dev, state, 200);
 392         nv_save_ptv(dev, state, 204);
 393         nv_save_ptv(dev, state, 208);
 394         nv_save_ptv(dev, state, 20c);
 395         nv_save_ptv(dev, state, 304);
 396         nv_save_ptv(dev, state, 500);
 397         nv_save_ptv(dev, state, 504);
 398         nv_save_ptv(dev, state, 508);
 399         nv_save_ptv(dev, state, 600);
 400         nv_save_ptv(dev, state, 604);
 401         nv_save_ptv(dev, state, 608);
 402         nv_save_ptv(dev, state, 60c);
 403         nv_save_ptv(dev, state, 610);
 404         nv_save_ptv(dev, state, 614);
 405 }
 406 
 407 void nv17_tv_state_load(struct drm_device *dev, struct nv17_tv_state *state)
 408 {
 409         int i;
 410 
 411         for (i = 0; i < 0x40; i++)
 412                 nv_write_tv_enc(dev, i, state->tv_enc[i]);
 413 
 414         tv_load_filter(dev, NV_PTV_HFILTER, state->hfilter);
 415         tv_load_filter(dev, NV_PTV_HFILTER2, state->hfilter2);
 416         tv_load_filter(dev, NV_PTV_VFILTER, state->vfilter);
 417 
 418         nv_load_ptv(dev, state, 200);
 419         nv_load_ptv(dev, state, 204);
 420         nv_load_ptv(dev, state, 208);
 421         nv_load_ptv(dev, state, 20c);
 422         nv_load_ptv(dev, state, 304);
 423         nv_load_ptv(dev, state, 500);
 424         nv_load_ptv(dev, state, 504);
 425         nv_load_ptv(dev, state, 508);
 426         nv_load_ptv(dev, state, 600);
 427         nv_load_ptv(dev, state, 604);
 428         nv_load_ptv(dev, state, 608);
 429         nv_load_ptv(dev, state, 60c);
 430         nv_load_ptv(dev, state, 610);
 431         nv_load_ptv(dev, state, 614);
 432 
 433         /* This is required for some settings to kick in. */
 434         nv_write_tv_enc(dev, 0x3e, 1);
 435         nv_write_tv_enc(dev, 0x3e, 0);
 436 }
 437 
 438 /* Timings similar to the ones the blob sets */
 439 
 440 const struct drm_display_mode nv17_tv_modes[] = {
 441         { DRM_MODE("320x200", DRM_MODE_TYPE_DRIVER, 0,
 442                    320, 344, 392, 560, 0, 200, 200, 202, 220, 0,
 443                    DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC
 444                    | DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_CLKDIV2) },
 445         { DRM_MODE("320x240", DRM_MODE_TYPE_DRIVER, 0,
 446                    320, 344, 392, 560, 0, 240, 240, 246, 263, 0,
 447                    DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC
 448                    | DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_CLKDIV2) },
 449         { DRM_MODE("400x300", DRM_MODE_TYPE_DRIVER, 0,
 450                    400, 432, 496, 640, 0, 300, 300, 303, 314, 0,
 451                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC
 452                    | DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_CLKDIV2) },
 453         { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 0,
 454                    640, 672, 768, 880, 0, 480, 480, 492, 525, 0,
 455                    DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
 456         { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 0,
 457                    720, 752, 872, 960, 0, 480, 480, 493, 525, 0,
 458                    DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
 459         { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 0,
 460                    720, 776, 856, 960, 0, 576, 576, 588, 597, 0,
 461                    DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
 462         { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 0,
 463                    800, 840, 920, 1040, 0, 600, 600, 604, 618, 0,
 464                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
 465         { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 0,
 466                    1024, 1064, 1200, 1344, 0, 768, 768, 777, 806, 0,
 467                    DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
 468         {}
 469 };
 470 
 471 void nv17_tv_update_properties(struct drm_encoder *encoder)
 472 {
 473         struct drm_device *dev = encoder->dev;
 474         struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder);
 475         struct nv17_tv_state *regs = &tv_enc->state;
 476         struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder);
 477         int subconnector = tv_enc->select_subconnector ?
 478                                                 tv_enc->select_subconnector :
 479                                                 tv_enc->subconnector;
 480 
 481         switch (subconnector) {
 482         case DRM_MODE_SUBCONNECTOR_Composite:
 483         {
 484                 regs->ptv_204 = 0x2;
 485 
 486                 /* The composite connector may be found on either pin. */
 487                 if (tv_enc->pin_mask & 0x4)
 488                         regs->ptv_204 |= 0x010000;
 489                 else if (tv_enc->pin_mask & 0x2)
 490                         regs->ptv_204 |= 0x100000;
 491                 else
 492                         regs->ptv_204 |= 0x110000;
 493 
 494                 regs->tv_enc[0x7] = 0x10;
 495                 break;
 496         }
 497         case DRM_MODE_SUBCONNECTOR_SVIDEO:
 498                 regs->ptv_204 = 0x11012;
 499                 regs->tv_enc[0x7] = 0x18;
 500                 break;
 501 
 502         case DRM_MODE_SUBCONNECTOR_Component:
 503                 regs->ptv_204 = 0x111333;
 504                 regs->tv_enc[0x7] = 0x14;
 505                 break;
 506 
 507         case DRM_MODE_SUBCONNECTOR_SCART:
 508                 regs->ptv_204 = 0x111012;
 509                 regs->tv_enc[0x7] = 0x18;
 510                 break;
 511         }
 512 
 513         regs->tv_enc[0x20] = interpolate(0, tv_norm->tv_enc_mode.tv_enc[0x20],
 514                                          255, tv_enc->saturation);
 515         regs->tv_enc[0x22] = interpolate(0, tv_norm->tv_enc_mode.tv_enc[0x22],
 516                                          255, tv_enc->saturation);
 517         regs->tv_enc[0x25] = tv_enc->hue * 255 / 100;
 518 
 519         nv_load_ptv(dev, regs, 204);
 520         nv_load_tv_enc(dev, regs, 7);
 521         nv_load_tv_enc(dev, regs, 20);
 522         nv_load_tv_enc(dev, regs, 22);
 523         nv_load_tv_enc(dev, regs, 25);
 524 }
 525 
 526 void nv17_tv_update_rescaler(struct drm_encoder *encoder)
 527 {
 528         struct drm_device *dev = encoder->dev;
 529         struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder);
 530         struct nv17_tv_state *regs = &tv_enc->state;
 531 
 532         regs->ptv_208 = 0x40 | (calc_overscan(tv_enc->overscan) << 8);
 533 
 534         tv_setup_filter(encoder);
 535 
 536         nv_load_ptv(dev, regs, 208);
 537         tv_load_filter(dev, NV_PTV_HFILTER, regs->hfilter);
 538         tv_load_filter(dev, NV_PTV_HFILTER2, regs->hfilter2);
 539         tv_load_filter(dev, NV_PTV_VFILTER, regs->vfilter);
 540 }
 541 
 542 void nv17_ctv_update_rescaler(struct drm_encoder *encoder)
 543 {
 544         struct drm_device *dev = encoder->dev;
 545         struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder);
 546         int head = nouveau_crtc(encoder->crtc)->index;
 547         struct nv04_crtc_reg *regs = &nv04_display(dev)->mode_reg.crtc_reg[head];
 548         struct drm_display_mode *crtc_mode = &encoder->crtc->mode;
 549         struct drm_display_mode *output_mode =
 550                 &get_tv_norm(encoder)->ctv_enc_mode.mode;
 551         int overscan, hmargin, vmargin, hratio, vratio;
 552 
 553         /* The rescaler doesn't do the right thing for interlaced modes. */
 554         if (output_mode->flags & DRM_MODE_FLAG_INTERLACE)
 555                 overscan = 100;
 556         else
 557                 overscan = tv_enc->overscan;
 558 
 559         hmargin = (output_mode->hdisplay - crtc_mode->hdisplay) / 2;
 560         vmargin = (output_mode->vdisplay - crtc_mode->vdisplay) / 2;
 561 
 562         hmargin = interpolate(0, min(hmargin, output_mode->hdisplay/20),
 563                               hmargin, overscan);
 564         vmargin = interpolate(0, min(vmargin, output_mode->vdisplay/20),
 565                               vmargin, overscan);
 566 
 567         hratio = crtc_mode->hdisplay * 0x800 /
 568                 (output_mode->hdisplay - 2*hmargin);
 569         vratio = crtc_mode->vdisplay * 0x800 /
 570                 (output_mode->vdisplay - 2*vmargin) & ~3;
 571 
 572         regs->fp_horiz_regs[FP_VALID_START] = hmargin;
 573         regs->fp_horiz_regs[FP_VALID_END] = output_mode->hdisplay - hmargin - 1;
 574         regs->fp_vert_regs[FP_VALID_START] = vmargin;
 575         regs->fp_vert_regs[FP_VALID_END] = output_mode->vdisplay - vmargin - 1;
 576 
 577         regs->fp_debug_1 = NV_PRAMDAC_FP_DEBUG_1_YSCALE_TESTMODE_ENABLE |
 578                 XLATE(vratio, 0, NV_PRAMDAC_FP_DEBUG_1_YSCALE_VALUE) |
 579                 NV_PRAMDAC_FP_DEBUG_1_XSCALE_TESTMODE_ENABLE |
 580                 XLATE(hratio, 0, NV_PRAMDAC_FP_DEBUG_1_XSCALE_VALUE);
 581 
 582         NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HVALID_START,
 583                       regs->fp_horiz_regs[FP_VALID_START]);
 584         NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HVALID_END,
 585                       regs->fp_horiz_regs[FP_VALID_END]);
 586         NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_VVALID_START,
 587                       regs->fp_vert_regs[FP_VALID_START]);
 588         NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_VVALID_END,
 589                       regs->fp_vert_regs[FP_VALID_END]);
 590         NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_DEBUG_1, regs->fp_debug_1);
 591 }

/* [<][>][^][v][top][bottom][index][help] */