Linux Audio

Check our new training course

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