blob: 31dc275bf1157aa21a54f00e04dfaa55178974b6 [file] [log] [blame]
Neil Armstrongbbbe7752016-11-10 15:29:37 +01001/*
2 * Copyright (C) 2016 BayLibre, SAS
3 * Author: Neil Armstrong <narmstrong@baylibre.com>
4 * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <linux/kernel.h>
21#include <linux/module.h>
22#include <drm/drmP.h>
23#include "meson_drv.h"
24#include "meson_venc.h"
25#include "meson_vpp.h"
26#include "meson_vclk.h"
27#include "meson_registers.h"
28
29/*
30 * VENC Handle the pixels encoding to the output formats.
31 * We handle the following encodings :
32 * - CVBS Encoding via the ENCI encoder and VDAC digital to analog converter
Neil Armstrongbbbe7752016-11-10 15:29:37 +010033 * - TMDS/HDMI Encoding via ENCI_DIV and ENCP
34 * - Setup of more clock rates for HDMI modes
Neil Armstrong335e3712017-04-04 14:15:26 +020035 *
36 * What is missing :
Neil Armstrongbbbe7752016-11-10 15:29:37 +010037 * - LCD Panel encoding via ENCL
38 * - TV Panel encoding via ENCT
Neil Armstrong335e3712017-04-04 14:15:26 +020039 *
40 * VENC paths :
41 * _____ _____ ____________________
42 * vd1---| |-| | | VENC /---------|----VDAC
43 * vd2---| VIU |-| VPP |-|-----ENCI/-ENCI_DVI-|\
44 * osd1--| |-| | | \ | X--HDMI-TX
45 * osd2--|_____|-|_____| | |\-ENCP--ENCP_DVI-|/
46 * | | |
47 * | \--ENCL-----------|----LVDS
48 * |____________________|
49 *
50 * The ENCI is designed for PAl or NTSC encoding and can go through the VDAC
51 * directly for CVBS encoding or through the ENCI_DVI encoder for HDMI.
52 * The ENCP is designed for Progressive encoding but can also generate
53 * 1080i interlaced pixels, and was initialy desined to encode pixels for
54 * VDAC to output RGB ou YUV analog outputs.
55 * It's output is only used through the ENCP_DVI encoder for HDMI.
56 * The ENCL LVDS encoder is not implemented.
57 *
58 * The ENCI and ENCP encoders needs specially defined parameters for each
59 * supported mode and thus cannot be determined from standard video timings.
60 *
61 * The ENCI end ENCP DVI encoders are more generic and can generate any timings
62 * from the pixel data generated by ENCI or ENCP, so can use the standard video
63 * timings are source for HW parameters.
Neil Armstrongbbbe7752016-11-10 15:29:37 +010064 */
65
Neil Armstrong0c931a22017-01-02 16:14:15 +010066/* HHI Registers */
67#define HHI_VDAC_CNTL0 0x2F4 /* 0xbd offset in data sheet */
68#define HHI_VDAC_CNTL1 0x2F8 /* 0xbe offset in data sheet */
69#define HHI_HDMI_PHY_CNTL0 0x3a0 /* 0xe8 offset in data sheet */
70
Neil Armstrongbbbe7752016-11-10 15:29:37 +010071struct meson_cvbs_enci_mode meson_cvbs_enci_pal = {
72 .mode_tag = MESON_VENC_MODE_CVBS_PAL,
73 .hso_begin = 3,
74 .hso_end = 129,
75 .vso_even = 3,
76 .vso_odd = 260,
77 .macv_max_amp = 7,
78 .video_prog_mode = 0xff,
79 .video_mode = 0x13,
80 .sch_adjust = 0x28,
81 .yc_delay = 0x343,
82 .pixel_start = 251,
83 .pixel_end = 1691,
84 .top_field_line_start = 22,
85 .top_field_line_end = 310,
86 .bottom_field_line_start = 23,
87 .bottom_field_line_end = 311,
88 .video_saturation = 9,
89 .video_contrast = 0,
90 .video_brightness = 0,
91 .video_hue = 0,
92 .analog_sync_adj = 0x8080,
93};
94
95struct meson_cvbs_enci_mode meson_cvbs_enci_ntsc = {
96 .mode_tag = MESON_VENC_MODE_CVBS_NTSC,
97 .hso_begin = 5,
98 .hso_end = 129,
99 .vso_even = 3,
100 .vso_odd = 260,
101 .macv_max_amp = 0xb,
102 .video_prog_mode = 0xf0,
103 .video_mode = 0x8,
104 .sch_adjust = 0x20,
105 .yc_delay = 0x333,
106 .pixel_start = 227,
107 .pixel_end = 1667,
108 .top_field_line_start = 18,
109 .top_field_line_end = 258,
110 .bottom_field_line_start = 19,
111 .bottom_field_line_end = 259,
112 .video_saturation = 18,
113 .video_contrast = 3,
114 .video_brightness = 0,
115 .video_hue = 0,
116 .analog_sync_adj = 0x9c00,
117};
118
Neil Armstrong335e3712017-04-04 14:15:26 +0200119union meson_hdmi_venc_mode {
120 struct {
121 unsigned int mode_tag;
122 unsigned int hso_begin;
123 unsigned int hso_end;
124 unsigned int vso_even;
125 unsigned int vso_odd;
126 unsigned int macv_max_amp;
127 unsigned int video_prog_mode;
128 unsigned int video_mode;
129 unsigned int sch_adjust;
130 unsigned int yc_delay;
131 unsigned int pixel_start;
132 unsigned int pixel_end;
133 unsigned int top_field_line_start;
134 unsigned int top_field_line_end;
135 unsigned int bottom_field_line_start;
136 unsigned int bottom_field_line_end;
137 } enci;
138 struct {
139 unsigned int dvi_settings;
140 unsigned int video_mode;
141 unsigned int video_mode_adv;
142 unsigned int video_prog_mode;
143 bool video_prog_mode_present;
144 unsigned int video_sync_mode;
145 bool video_sync_mode_present;
146 unsigned int video_yc_dly;
147 bool video_yc_dly_present;
148 unsigned int video_rgb_ctrl;
149 bool video_rgb_ctrl_present;
150 unsigned int video_filt_ctrl;
151 bool video_filt_ctrl_present;
152 unsigned int video_ofld_voav_ofst;
153 bool video_ofld_voav_ofst_present;
154 unsigned int yfp1_htime;
155 unsigned int yfp2_htime;
156 unsigned int max_pxcnt;
157 unsigned int hspuls_begin;
158 unsigned int hspuls_end;
159 unsigned int hspuls_switch;
160 unsigned int vspuls_begin;
161 unsigned int vspuls_end;
162 unsigned int vspuls_bline;
163 unsigned int vspuls_eline;
164 unsigned int eqpuls_begin;
165 bool eqpuls_begin_present;
166 unsigned int eqpuls_end;
167 bool eqpuls_end_present;
168 unsigned int eqpuls_bline;
169 bool eqpuls_bline_present;
170 unsigned int eqpuls_eline;
171 bool eqpuls_eline_present;
172 unsigned int havon_begin;
173 unsigned int havon_end;
174 unsigned int vavon_bline;
175 unsigned int vavon_eline;
176 unsigned int hso_begin;
177 unsigned int hso_end;
178 unsigned int vso_begin;
179 unsigned int vso_end;
180 unsigned int vso_bline;
181 unsigned int vso_eline;
182 bool vso_eline_present;
183 unsigned int sy_val;
184 bool sy_val_present;
185 unsigned int sy2_val;
186 bool sy2_val_present;
187 unsigned int max_lncnt;
188 } encp;
189};
190
191union meson_hdmi_venc_mode meson_hdmi_enci_mode_480i = {
192 .enci = {
193 .hso_begin = 5,
194 .hso_end = 129,
195 .vso_even = 3,
196 .vso_odd = 260,
197 .macv_max_amp = 0x810b,
198 .video_prog_mode = 0xf0,
199 .video_mode = 0x8,
200 .sch_adjust = 0x20,
201 .yc_delay = 0,
202 .pixel_start = 227,
203 .pixel_end = 1667,
204 .top_field_line_start = 18,
205 .top_field_line_end = 258,
206 .bottom_field_line_start = 19,
207 .bottom_field_line_end = 259,
208 },
209};
210
211union meson_hdmi_venc_mode meson_hdmi_enci_mode_576i = {
212 .enci = {
213 .hso_begin = 3,
214 .hso_end = 129,
215 .vso_even = 3,
216 .vso_odd = 260,
217 .macv_max_amp = 8107,
218 .video_prog_mode = 0xff,
219 .video_mode = 0x13,
220 .sch_adjust = 0x28,
221 .yc_delay = 0x333,
222 .pixel_start = 251,
223 .pixel_end = 1691,
224 .top_field_line_start = 22,
225 .top_field_line_end = 310,
226 .bottom_field_line_start = 23,
227 .bottom_field_line_end = 311,
228 },
229};
230
231union meson_hdmi_venc_mode meson_hdmi_encp_mode_480p = {
232 .encp = {
233 .dvi_settings = 0x21,
234 .video_mode = 0x4000,
235 .video_mode_adv = 0x9,
236 .video_prog_mode = 0,
237 .video_prog_mode_present = true,
238 .video_sync_mode = 7,
239 .video_sync_mode_present = true,
240 /* video_yc_dly */
241 /* video_rgb_ctrl */
242 .video_filt_ctrl = 0x2052,
243 .video_filt_ctrl_present = true,
244 /* video_ofld_voav_ofst */
245 .yfp1_htime = 244,
246 .yfp2_htime = 1630,
247 .max_pxcnt = 1715,
248 .hspuls_begin = 0x22,
249 .hspuls_end = 0xa0,
250 .hspuls_switch = 88,
251 .vspuls_begin = 0,
252 .vspuls_end = 1589,
253 .vspuls_bline = 0,
254 .vspuls_eline = 5,
255 .havon_begin = 249,
256 .havon_end = 1689,
257 .vavon_bline = 42,
258 .vavon_eline = 521,
259 /* eqpuls_begin */
260 /* eqpuls_end */
261 /* eqpuls_bline */
262 /* eqpuls_eline */
263 .hso_begin = 3,
264 .hso_end = 5,
265 .vso_begin = 3,
266 .vso_end = 5,
267 .vso_bline = 0,
268 /* vso_eline */
269 .sy_val = 8,
270 .sy_val_present = true,
271 .sy2_val = 0x1d8,
272 .sy2_val_present = true,
273 .max_lncnt = 524,
274 },
275};
276
277union meson_hdmi_venc_mode meson_hdmi_encp_mode_576p = {
278 .encp = {
279 .dvi_settings = 0x21,
280 .video_mode = 0x4000,
281 .video_mode_adv = 0x9,
282 .video_prog_mode = 0,
283 .video_prog_mode_present = true,
284 .video_sync_mode = 7,
285 .video_sync_mode_present = true,
286 /* video_yc_dly */
287 /* video_rgb_ctrl */
288 .video_filt_ctrl = 0x52,
289 .video_filt_ctrl_present = true,
290 /* video_ofld_voav_ofst */
291 .yfp1_htime = 235,
292 .yfp2_htime = 1674,
293 .max_pxcnt = 1727,
294 .hspuls_begin = 0,
295 .hspuls_end = 0x80,
296 .hspuls_switch = 88,
297 .vspuls_begin = 0,
298 .vspuls_end = 1599,
299 .vspuls_bline = 0,
300 .vspuls_eline = 4,
301 .havon_begin = 235,
302 .havon_end = 1674,
303 .vavon_bline = 44,
304 .vavon_eline = 619,
305 /* eqpuls_begin */
306 /* eqpuls_end */
307 /* eqpuls_bline */
308 /* eqpuls_eline */
309 .hso_begin = 0x80,
310 .hso_end = 0,
311 .vso_begin = 0,
312 .vso_end = 5,
313 .vso_bline = 0,
314 /* vso_eline */
315 .sy_val = 8,
316 .sy_val_present = true,
317 .sy2_val = 0x1d8,
318 .sy2_val_present = true,
319 .max_lncnt = 624,
320 },
321};
322
323union meson_hdmi_venc_mode meson_hdmi_encp_mode_720p60 = {
324 .encp = {
325 .dvi_settings = 0x2029,
326 .video_mode = 0x4040,
327 .video_mode_adv = 0x19,
328 /* video_prog_mode */
329 /* video_sync_mode */
330 /* video_yc_dly */
331 /* video_rgb_ctrl */
332 /* video_filt_ctrl */
333 /* video_ofld_voav_ofst */
334 .yfp1_htime = 648,
335 .yfp2_htime = 3207,
336 .max_pxcnt = 3299,
337 .hspuls_begin = 80,
338 .hspuls_end = 240,
339 .hspuls_switch = 80,
340 .vspuls_begin = 688,
341 .vspuls_end = 3248,
342 .vspuls_bline = 4,
343 .vspuls_eline = 8,
344 .havon_begin = 648,
345 .havon_end = 3207,
346 .vavon_bline = 29,
347 .vavon_eline = 748,
348 /* eqpuls_begin */
349 /* eqpuls_end */
350 /* eqpuls_bline */
351 /* eqpuls_eline */
352 .hso_begin = 256,
353 .hso_end = 168,
354 .vso_begin = 168,
355 .vso_end = 256,
356 .vso_bline = 0,
357 .vso_eline = 5,
358 .vso_eline_present = true,
359 /* sy_val */
360 /* sy2_val */
361 .max_lncnt = 749,
362 },
363};
364
365union meson_hdmi_venc_mode meson_hdmi_encp_mode_720p50 = {
366 .encp = {
367 .dvi_settings = 0x202d,
368 .video_mode = 0x4040,
369 .video_mode_adv = 0x19,
370 .video_prog_mode = 0x100,
371 .video_prog_mode_present = true,
372 .video_sync_mode = 0x407,
373 .video_sync_mode_present = true,
374 .video_yc_dly = 0,
375 .video_yc_dly_present = true,
376 /* video_rgb_ctrl */
377 /* video_filt_ctrl */
378 /* video_ofld_voav_ofst */
379 .yfp1_htime = 648,
380 .yfp2_htime = 3207,
381 .max_pxcnt = 3959,
382 .hspuls_begin = 80,
383 .hspuls_end = 240,
384 .hspuls_switch = 80,
385 .vspuls_begin = 688,
386 .vspuls_end = 3248,
387 .vspuls_bline = 4,
388 .vspuls_eline = 8,
389 .havon_begin = 648,
390 .havon_end = 3207,
391 .vavon_bline = 29,
392 .vavon_eline = 748,
393 /* eqpuls_begin */
394 /* eqpuls_end */
395 /* eqpuls_bline */
396 /* eqpuls_eline */
397 .hso_begin = 128,
398 .hso_end = 208,
399 .vso_begin = 128,
400 .vso_end = 128,
401 .vso_bline = 0,
402 .vso_eline = 5,
403 .vso_eline_present = true,
404 /* sy_val */
405 /* sy2_val */
406 .max_lncnt = 749,
407 },
408};
409
410union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080i60 = {
411 .encp = {
412 .dvi_settings = 0x2029,
413 .video_mode = 0x5ffc,
414 .video_mode_adv = 0x19,
415 .video_prog_mode = 0x100,
416 .video_prog_mode_present = true,
417 .video_sync_mode = 0x207,
418 .video_sync_mode_present = true,
419 /* video_yc_dly */
420 /* video_rgb_ctrl */
421 /* video_filt_ctrl */
422 .video_ofld_voav_ofst = 0x11,
423 .video_ofld_voav_ofst_present = true,
424 .yfp1_htime = 516,
425 .yfp2_htime = 4355,
426 .max_pxcnt = 4399,
427 .hspuls_begin = 88,
428 .hspuls_end = 264,
429 .hspuls_switch = 88,
430 .vspuls_begin = 440,
431 .vspuls_end = 2200,
432 .vspuls_bline = 0,
433 .vspuls_eline = 4,
434 .havon_begin = 516,
435 .havon_end = 4355,
436 .vavon_bline = 20,
437 .vavon_eline = 559,
438 .eqpuls_begin = 2288,
439 .eqpuls_begin_present = true,
440 .eqpuls_end = 2464,
441 .eqpuls_end_present = true,
442 .eqpuls_bline = 0,
443 .eqpuls_bline_present = true,
444 .eqpuls_eline = 4,
445 .eqpuls_eline_present = true,
446 .hso_begin = 264,
447 .hso_end = 176,
448 .vso_begin = 88,
449 .vso_end = 88,
450 .vso_bline = 0,
451 .vso_eline = 5,
452 .vso_eline_present = true,
453 /* sy_val */
454 /* sy2_val */
455 .max_lncnt = 1124,
456 },
457};
458
459union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080i50 = {
460 .encp = {
461 .dvi_settings = 0x202d,
462 .video_mode = 0x5ffc,
463 .video_mode_adv = 0x19,
464 .video_prog_mode = 0x100,
465 .video_prog_mode_present = true,
466 .video_sync_mode = 0x7,
467 .video_sync_mode_present = true,
468 /* video_yc_dly */
469 /* video_rgb_ctrl */
470 /* video_filt_ctrl */
471 .video_ofld_voav_ofst = 0x11,
472 .video_ofld_voav_ofst_present = true,
473 .yfp1_htime = 526,
474 .yfp2_htime = 4365,
475 .max_pxcnt = 5279,
476 .hspuls_begin = 88,
477 .hspuls_end = 264,
478 .hspuls_switch = 88,
479 .vspuls_begin = 440,
480 .vspuls_end = 2200,
481 .vspuls_bline = 0,
482 .vspuls_eline = 4,
483 .havon_begin = 526,
484 .havon_end = 4365,
485 .vavon_bline = 20,
486 .vavon_eline = 559,
487 .eqpuls_begin = 2288,
488 .eqpuls_begin_present = true,
489 .eqpuls_end = 2464,
490 .eqpuls_end_present = true,
491 .eqpuls_bline = 0,
492 .eqpuls_bline_present = true,
493 .eqpuls_eline = 4,
494 .eqpuls_eline_present = true,
495 .hso_begin = 142,
496 .hso_end = 230,
497 .vso_begin = 142,
498 .vso_end = 142,
499 .vso_bline = 0,
500 .vso_eline = 5,
501 .vso_eline_present = true,
502 /* sy_val */
503 /* sy2_val */
504 .max_lncnt = 1124,
505 },
506};
507
508union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p24 = {
509 .encp = {
510 .dvi_settings = 0xd,
511 .video_mode = 0x4040,
512 .video_mode_adv = 0x18,
513 .video_prog_mode = 0x100,
514 .video_prog_mode_present = true,
515 .video_sync_mode = 0x7,
516 .video_sync_mode_present = true,
517 .video_yc_dly = 0,
518 .video_yc_dly_present = true,
519 .video_rgb_ctrl = 2,
520 .video_rgb_ctrl_present = true,
521 .video_filt_ctrl = 0x1052,
522 .video_filt_ctrl_present = true,
523 /* video_ofld_voav_ofst */
524 .yfp1_htime = 271,
525 .yfp2_htime = 2190,
526 .max_pxcnt = 2749,
527 .hspuls_begin = 44,
528 .hspuls_end = 132,
529 .hspuls_switch = 44,
530 .vspuls_begin = 220,
531 .vspuls_end = 2140,
532 .vspuls_bline = 0,
533 .vspuls_eline = 4,
534 .havon_begin = 271,
535 .havon_end = 2190,
536 .vavon_bline = 41,
537 .vavon_eline = 1120,
538 /* eqpuls_begin */
539 /* eqpuls_end */
540 .eqpuls_bline = 0,
541 .eqpuls_bline_present = true,
542 .eqpuls_eline = 4,
543 .eqpuls_eline_present = true,
544 .hso_begin = 79,
545 .hso_end = 123,
546 .vso_begin = 79,
547 .vso_end = 79,
548 .vso_bline = 0,
549 .vso_eline = 5,
550 .vso_eline_present = true,
551 /* sy_val */
552 /* sy2_val */
553 .max_lncnt = 1124,
554 },
555};
556
557union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p30 = {
558 .encp = {
559 .dvi_settings = 0x1,
560 .video_mode = 0x4040,
561 .video_mode_adv = 0x18,
562 .video_prog_mode = 0x100,
563 .video_prog_mode_present = true,
564 /* video_sync_mode */
565 /* video_yc_dly */
566 /* video_rgb_ctrl */
567 .video_filt_ctrl = 0x1052,
568 .video_filt_ctrl_present = true,
569 /* video_ofld_voav_ofst */
570 .yfp1_htime = 140,
571 .yfp2_htime = 2060,
572 .max_pxcnt = 2199,
573 .hspuls_begin = 2156,
574 .hspuls_end = 44,
575 .hspuls_switch = 44,
576 .vspuls_begin = 140,
577 .vspuls_end = 2059,
578 .vspuls_bline = 0,
579 .vspuls_eline = 4,
580 .havon_begin = 148,
581 .havon_end = 2067,
582 .vavon_bline = 41,
583 .vavon_eline = 1120,
584 /* eqpuls_begin */
585 /* eqpuls_end */
586 /* eqpuls_bline */
587 /* eqpuls_eline */
588 .hso_begin = 44,
589 .hso_end = 2156,
590 .vso_begin = 2100,
591 .vso_end = 2164,
592 .vso_bline = 0,
593 .vso_eline = 5,
594 .vso_eline_present = true,
595 /* sy_val */
596 /* sy2_val */
597 .max_lncnt = 1124,
598 },
599};
600
601union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p50 = {
602 .encp = {
603 .dvi_settings = 0xd,
604 .video_mode = 0x4040,
605 .video_mode_adv = 0x18,
606 .video_prog_mode = 0x100,
607 .video_prog_mode_present = true,
608 .video_sync_mode = 0x7,
609 .video_sync_mode_present = true,
610 .video_yc_dly = 0,
611 .video_yc_dly_present = true,
612 .video_rgb_ctrl = 2,
613 .video_rgb_ctrl_present = true,
614 /* video_filt_ctrl */
615 /* video_ofld_voav_ofst */
616 .yfp1_htime = 271,
617 .yfp2_htime = 2190,
618 .max_pxcnt = 2639,
619 .hspuls_begin = 44,
620 .hspuls_end = 132,
621 .hspuls_switch = 44,
622 .vspuls_begin = 220,
623 .vspuls_end = 2140,
624 .vspuls_bline = 0,
625 .vspuls_eline = 4,
626 .havon_begin = 271,
627 .havon_end = 2190,
628 .vavon_bline = 41,
629 .vavon_eline = 1120,
630 /* eqpuls_begin */
631 /* eqpuls_end */
632 .eqpuls_bline = 0,
633 .eqpuls_bline_present = true,
634 .eqpuls_eline = 4,
635 .eqpuls_eline_present = true,
636 .hso_begin = 79,
637 .hso_end = 123,
638 .vso_begin = 79,
639 .vso_end = 79,
640 .vso_bline = 0,
641 .vso_eline = 5,
642 .vso_eline_present = true,
643 /* sy_val */
644 /* sy2_val */
645 .max_lncnt = 1124,
646 },
647};
648
649union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p60 = {
650 .encp = {
651 .dvi_settings = 0x1,
652 .video_mode = 0x4040,
653 .video_mode_adv = 0x18,
654 .video_prog_mode = 0x100,
655 .video_prog_mode_present = true,
656 /* video_sync_mode */
657 /* video_yc_dly */
658 /* video_rgb_ctrl */
659 .video_filt_ctrl = 0x1052,
660 .video_filt_ctrl_present = true,
661 /* video_ofld_voav_ofst */
662 .yfp1_htime = 140,
663 .yfp2_htime = 2060,
664 .max_pxcnt = 2199,
665 .hspuls_begin = 2156,
666 .hspuls_end = 44,
667 .hspuls_switch = 44,
668 .vspuls_begin = 140,
669 .vspuls_end = 2059,
670 .vspuls_bline = 0,
671 .vspuls_eline = 4,
672 .havon_begin = 148,
673 .havon_end = 2067,
674 .vavon_bline = 41,
675 .vavon_eline = 1120,
676 /* eqpuls_begin */
677 /* eqpuls_end */
678 /* eqpuls_bline */
679 /* eqpuls_eline */
680 .hso_begin = 44,
681 .hso_end = 2156,
682 .vso_begin = 2100,
683 .vso_end = 2164,
684 .vso_bline = 0,
685 .vso_eline = 5,
686 .vso_eline_present = true,
687 /* sy_val */
688 /* sy2_val */
689 .max_lncnt = 1124,
690 },
691};
692
693struct meson_hdmi_venc_vic_mode {
694 unsigned int vic;
695 union meson_hdmi_venc_mode *mode;
696} meson_hdmi_venc_vic_modes[] = {
697 { 6, &meson_hdmi_enci_mode_480i },
698 { 7, &meson_hdmi_enci_mode_480i },
699 { 21, &meson_hdmi_enci_mode_576i },
700 { 22, &meson_hdmi_enci_mode_576i },
701 { 2, &meson_hdmi_encp_mode_480p },
702 { 3, &meson_hdmi_encp_mode_480p },
703 { 17, &meson_hdmi_encp_mode_576p },
704 { 18, &meson_hdmi_encp_mode_576p },
705 { 4, &meson_hdmi_encp_mode_720p60 },
706 { 19, &meson_hdmi_encp_mode_720p50 },
707 { 5, &meson_hdmi_encp_mode_1080i60 },
708 { 20, &meson_hdmi_encp_mode_1080i50 },
709 { 32, &meson_hdmi_encp_mode_1080p24 },
710 { 34, &meson_hdmi_encp_mode_1080p30 },
711 { 31, &meson_hdmi_encp_mode_1080p50 },
712 { 16, &meson_hdmi_encp_mode_1080p60 },
713 { 0, NULL}, /* sentinel */
714};
715
716static signed int to_signed(unsigned int a)
717{
718 if (a <= 7)
719 return a;
720 else
721 return a - 16;
722}
723
724static unsigned long modulo(unsigned long a, unsigned long b)
725{
726 if (a >= b)
727 return a - b;
728 else
729 return a;
730}
731
732bool meson_venc_hdmi_supported_vic(int vic)
733{
734 struct meson_hdmi_venc_vic_mode *vmode = meson_hdmi_venc_vic_modes;
735
736 while (vmode->vic && vmode->mode) {
737 if (vmode->vic == vic)
738 return true;
739 vmode++;
740 }
741
742 return false;
743}
744EXPORT_SYMBOL_GPL(meson_venc_hdmi_supported_vic);
745
746static union meson_hdmi_venc_mode *meson_venc_hdmi_get_vic_vmode(int vic)
747{
748 struct meson_hdmi_venc_vic_mode *vmode = meson_hdmi_venc_vic_modes;
749
750 while (vmode->vic && vmode->mode) {
751 if (vmode->vic == vic)
752 return vmode->mode;
753 vmode++;
754 }
755
756 return NULL;
757}
758
759bool meson_venc_hdmi_venc_repeat(int vic)
760{
761 /* Repeat VENC pixels for 480/576i/p, 720p50/60 and 1080p50/60 */
762 if (vic == 6 || vic == 7 || /* 480i */
763 vic == 21 || vic == 22 || /* 576i */
764 vic == 17 || vic == 18 || /* 576p */
765 vic == 2 || vic == 3 || /* 480p */
766 vic == 4 || /* 720p60 */
767 vic == 19 || /* 720p50 */
768 vic == 5 || /* 1080i60 */
769 vic == 20) /* 1080i50 */
770 return true;
771
772 return false;
773}
774EXPORT_SYMBOL_GPL(meson_venc_hdmi_venc_repeat);
775
776void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic,
777 struct drm_display_mode *mode)
778{
779 union meson_hdmi_venc_mode *vmode = NULL;
780 bool use_enci = false;
781 bool venc_repeat = false;
782 bool hdmi_repeat = false;
783 unsigned int venc_hdmi_latency = 2;
784 unsigned long total_pixels_venc = 0;
785 unsigned long active_pixels_venc = 0;
786 unsigned long front_porch_venc = 0;
787 unsigned long hsync_pixels_venc = 0;
788 unsigned long de_h_begin = 0;
789 unsigned long de_h_end = 0;
790 unsigned long de_v_begin_even = 0;
791 unsigned long de_v_end_even = 0;
792 unsigned long de_v_begin_odd = 0;
793 unsigned long de_v_end_odd = 0;
794 unsigned long hs_begin = 0;
795 unsigned long hs_end = 0;
796 unsigned long vs_adjust = 0;
797 unsigned long vs_bline_evn = 0;
798 unsigned long vs_eline_evn = 0;
799 unsigned long vs_bline_odd = 0;
800 unsigned long vs_eline_odd = 0;
801 unsigned long vso_begin_evn = 0;
802 unsigned long vso_begin_odd = 0;
803 unsigned int eof_lines;
804 unsigned int sof_lines;
805 unsigned int vsync_lines;
806
807 vmode = meson_venc_hdmi_get_vic_vmode(vic);
808 if (!vmode) {
809 dev_err(priv->dev, "%s: Fatal Error, unsupported vic %d\n",
810 __func__, vic);
811 return;
812 }
813
814 /* Use VENCI for 480i and 576i and double HDMI pixels */
815 if (mode->flags & DRM_MODE_FLAG_DBLCLK) {
816 hdmi_repeat = true;
817 use_enci = true;
818 venc_hdmi_latency = 1;
819 }
820
821 /* Repeat VENC pixels for 480/576i/p, 720p50/60 and 1080p50/60 */
822 if (meson_venc_hdmi_venc_repeat(vic))
823 venc_repeat = true;
824
825 eof_lines = mode->vsync_start - mode->vdisplay;
826 if (mode->flags & DRM_MODE_FLAG_INTERLACE)
827 eof_lines /= 2;
828 sof_lines = mode->vtotal - mode->vsync_end;
829 if (mode->flags & DRM_MODE_FLAG_INTERLACE)
830 sof_lines /= 2;
831 vsync_lines = mode->vsync_end - mode->vsync_start;
832 if (mode->flags & DRM_MODE_FLAG_INTERLACE)
833 vsync_lines /= 2;
834
835 total_pixels_venc = mode->htotal;
836 if (hdmi_repeat)
837 total_pixels_venc /= 2;
838 if (venc_repeat)
839 total_pixels_venc *= 2;
840
841 active_pixels_venc = mode->hdisplay;
842 if (hdmi_repeat)
843 active_pixels_venc /= 2;
844 if (venc_repeat)
845 active_pixels_venc *= 2;
846
847 front_porch_venc = (mode->hsync_start - mode->hdisplay);
848 if (hdmi_repeat)
849 front_porch_venc /= 2;
850 if (venc_repeat)
851 front_porch_venc *= 2;
852
853 hsync_pixels_venc = (mode->hsync_end - mode->hsync_start);
854 if (hdmi_repeat)
855 hsync_pixels_venc /= 2;
856 if (venc_repeat)
857 hsync_pixels_venc *= 2;
858
859 /* Disable VDACs */
860 writel_bits_relaxed(0x1f, 0x1f,
861 priv->io_base + _REG(VENC_VDAC_SETTING));
862
863 writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN));
864 writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN));
865
866 if (use_enci) {
867 unsigned int lines_f0;
868 unsigned int lines_f1;
869
870 /* CVBS Filter settings */
871 writel_relaxed(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL));
872 writel_relaxed(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL2));
873
874 /* Digital Video Select : Interlace, clk27 clk, external */
875 writel_relaxed(0, priv->io_base + _REG(VENC_DVI_SETTING));
876
877 /* Reset Video Mode */
878 writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_MODE));
879 writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
880
881 /* Horizontal sync signal output */
882 writel_relaxed(vmode->enci.hso_begin,
883 priv->io_base + _REG(ENCI_SYNC_HSO_BEGIN));
884 writel_relaxed(vmode->enci.hso_end,
885 priv->io_base + _REG(ENCI_SYNC_HSO_END));
886
887 /* Vertical Sync lines */
888 writel_relaxed(vmode->enci.vso_even,
889 priv->io_base + _REG(ENCI_SYNC_VSO_EVNLN));
890 writel_relaxed(vmode->enci.vso_odd,
891 priv->io_base + _REG(ENCI_SYNC_VSO_ODDLN));
892
893 /* Macrovision max amplitude change */
894 writel_relaxed(vmode->enci.macv_max_amp,
895 priv->io_base + _REG(ENCI_MACV_MAX_AMP));
896
897 /* Video mode */
898 writel_relaxed(vmode->enci.video_prog_mode,
899 priv->io_base + _REG(VENC_VIDEO_PROG_MODE));
900 writel_relaxed(vmode->enci.video_mode,
901 priv->io_base + _REG(ENCI_VIDEO_MODE));
902
903 /* Advanced Video Mode :
904 * Demux shifting 0x2
905 * Blank line end at line17/22
906 * High bandwidth Luma Filter
907 * Low bandwidth Chroma Filter
908 * Bypass luma low pass filter
909 * No macrovision on CSYNC
910 */
911 writel_relaxed(0x26, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
912
913 writel(vmode->enci.sch_adjust,
914 priv->io_base + _REG(ENCI_VIDEO_SCH));
915
916 /* Sync mode : MASTER Master mode, free run, send HSO/VSO out */
917 writel_relaxed(0x07, priv->io_base + _REG(ENCI_SYNC_MODE));
918
919 if (vmode->enci.yc_delay)
920 writel_relaxed(vmode->enci.yc_delay,
921 priv->io_base + _REG(ENCI_YC_DELAY));
922
923
924 /* UNreset Interlaced TV Encoder */
925 writel_relaxed(0, priv->io_base + _REG(ENCI_DBG_PX_RST));
926
927 /* Enable Vfifo2vd, Y_Cb_Y_Cr select */
928 writel_relaxed(0x4e01, priv->io_base + _REG(ENCI_VFIFO2VD_CTL));
929
930 /* Timings */
931 writel_relaxed(vmode->enci.pixel_start,
932 priv->io_base + _REG(ENCI_VFIFO2VD_PIXEL_START));
933 writel_relaxed(vmode->enci.pixel_end,
934 priv->io_base + _REG(ENCI_VFIFO2VD_PIXEL_END));
935
936 writel_relaxed(vmode->enci.top_field_line_start,
937 priv->io_base + _REG(ENCI_VFIFO2VD_LINE_TOP_START));
938 writel_relaxed(vmode->enci.top_field_line_end,
939 priv->io_base + _REG(ENCI_VFIFO2VD_LINE_TOP_END));
940
941 writel_relaxed(vmode->enci.bottom_field_line_start,
942 priv->io_base + _REG(ENCI_VFIFO2VD_LINE_BOT_START));
943 writel_relaxed(vmode->enci.bottom_field_line_end,
944 priv->io_base + _REG(ENCI_VFIFO2VD_LINE_BOT_END));
945
946 /* Select ENCI for VIU */
947 meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCI);
948
949 /* Interlace video enable */
950 writel_relaxed(1, priv->io_base + _REG(ENCI_VIDEO_EN));
951
952 lines_f0 = mode->vtotal >> 1;
953 lines_f1 = lines_f0 + 1;
954
955 de_h_begin = modulo(readl_relaxed(priv->io_base +
956 _REG(ENCI_VFIFO2VD_PIXEL_START))
957 + venc_hdmi_latency,
958 total_pixels_venc);
959 de_h_end = modulo(de_h_begin + active_pixels_venc,
960 total_pixels_venc);
961
962 writel_relaxed(de_h_begin,
963 priv->io_base + _REG(ENCI_DE_H_BEGIN));
964 writel_relaxed(de_h_end,
965 priv->io_base + _REG(ENCI_DE_H_END));
966
967 de_v_begin_even = readl_relaxed(priv->io_base +
968 _REG(ENCI_VFIFO2VD_LINE_TOP_START));
969 de_v_end_even = de_v_begin_even + mode->vdisplay;
970 de_v_begin_odd = readl_relaxed(priv->io_base +
971 _REG(ENCI_VFIFO2VD_LINE_BOT_START));
972 de_v_end_odd = de_v_begin_odd + mode->vdisplay;
973
974 writel_relaxed(de_v_begin_even,
975 priv->io_base + _REG(ENCI_DE_V_BEGIN_EVEN));
976 writel_relaxed(de_v_end_even,
977 priv->io_base + _REG(ENCI_DE_V_END_EVEN));
978 writel_relaxed(de_v_begin_odd,
979 priv->io_base + _REG(ENCI_DE_V_BEGIN_ODD));
980 writel_relaxed(de_v_end_odd,
981 priv->io_base + _REG(ENCI_DE_V_END_ODD));
982
983 /* Program Hsync timing */
984 hs_begin = de_h_end + front_porch_venc;
985 if (de_h_end + front_porch_venc >= total_pixels_venc) {
986 hs_begin -= total_pixels_venc;
987 vs_adjust = 1;
988 } else {
989 hs_begin = de_h_end + front_porch_venc;
990 vs_adjust = 0;
991 }
992
993 hs_end = modulo(hs_begin + hsync_pixels_venc,
994 total_pixels_venc);
995 writel_relaxed(hs_begin,
996 priv->io_base + _REG(ENCI_DVI_HSO_BEGIN));
997 writel_relaxed(hs_end,
998 priv->io_base + _REG(ENCI_DVI_HSO_END));
999
1000 /* Program Vsync timing for even field */
1001 if (((de_v_end_odd - 1) + eof_lines + vs_adjust) >= lines_f1) {
1002 vs_bline_evn = (de_v_end_odd - 1)
1003 + eof_lines
1004 + vs_adjust
1005 - lines_f1;
1006 vs_eline_evn = vs_bline_evn + vsync_lines;
1007
1008 writel_relaxed(vs_bline_evn,
1009 priv->io_base + _REG(ENCI_DVI_VSO_BLINE_EVN));
1010
1011 writel_relaxed(vs_eline_evn,
1012 priv->io_base + _REG(ENCI_DVI_VSO_ELINE_EVN));
1013
1014 writel_relaxed(hs_begin,
1015 priv->io_base + _REG(ENCI_DVI_VSO_BEGIN_EVN));
1016 writel_relaxed(hs_begin,
1017 priv->io_base + _REG(ENCI_DVI_VSO_END_EVN));
1018 } else {
1019 vs_bline_odd = (de_v_end_odd - 1)
1020 + eof_lines
1021 + vs_adjust;
1022
1023 writel_relaxed(vs_bline_odd,
1024 priv->io_base + _REG(ENCI_DVI_VSO_BLINE_ODD));
1025
1026 writel_relaxed(hs_begin,
1027 priv->io_base + _REG(ENCI_DVI_VSO_BEGIN_ODD));
1028
1029 if ((vs_bline_odd + vsync_lines) >= lines_f1) {
1030 vs_eline_evn = vs_bline_odd
1031 + vsync_lines
1032 - lines_f1;
1033
1034 writel_relaxed(vs_eline_evn, priv->io_base
1035 + _REG(ENCI_DVI_VSO_ELINE_EVN));
1036
1037 writel_relaxed(hs_begin, priv->io_base
1038 + _REG(ENCI_DVI_VSO_END_EVN));
1039 } else {
1040 vs_eline_odd = vs_bline_odd
1041 + vsync_lines;
1042
1043 writel_relaxed(vs_eline_odd, priv->io_base
1044 + _REG(ENCI_DVI_VSO_ELINE_ODD));
1045
1046 writel_relaxed(hs_begin, priv->io_base
1047 + _REG(ENCI_DVI_VSO_END_ODD));
1048 }
1049 }
1050
1051 /* Program Vsync timing for odd field */
1052 if (((de_v_end_even - 1) + (eof_lines + 1)) >= lines_f0) {
1053 vs_bline_odd = (de_v_end_even - 1)
1054 + (eof_lines + 1)
1055 - lines_f0;
1056 vs_eline_odd = vs_bline_odd + vsync_lines;
1057
1058 writel_relaxed(vs_bline_odd,
1059 priv->io_base + _REG(ENCI_DVI_VSO_BLINE_ODD));
1060
1061 writel_relaxed(vs_eline_odd,
1062 priv->io_base + _REG(ENCI_DVI_VSO_ELINE_ODD));
1063
1064 vso_begin_odd = modulo(hs_begin
1065 + (total_pixels_venc >> 1),
1066 total_pixels_venc);
1067
1068 writel_relaxed(vso_begin_odd,
1069 priv->io_base + _REG(ENCI_DVI_VSO_BEGIN_ODD));
1070 writel_relaxed(vso_begin_odd,
1071 priv->io_base + _REG(ENCI_DVI_VSO_END_ODD));
1072 } else {
1073 vs_bline_evn = (de_v_end_even - 1)
1074 + (eof_lines + 1);
1075
1076 writel_relaxed(vs_bline_evn,
1077 priv->io_base + _REG(ENCI_DVI_VSO_BLINE_EVN));
1078
1079 vso_begin_evn = modulo(hs_begin
1080 + (total_pixels_venc >> 1),
1081 total_pixels_venc);
1082
1083 writel_relaxed(vso_begin_evn, priv->io_base
1084 + _REG(ENCI_DVI_VSO_BEGIN_EVN));
1085
1086 if (vs_bline_evn + vsync_lines >= lines_f0) {
1087 vs_eline_odd = vs_bline_evn
1088 + vsync_lines
1089 - lines_f0;
1090
1091 writel_relaxed(vs_eline_odd, priv->io_base
1092 + _REG(ENCI_DVI_VSO_ELINE_ODD));
1093
1094 writel_relaxed(vso_begin_evn, priv->io_base
1095 + _REG(ENCI_DVI_VSO_END_ODD));
1096 } else {
1097 vs_eline_evn = vs_bline_evn + vsync_lines;
1098
1099 writel_relaxed(vs_eline_evn, priv->io_base
1100 + _REG(ENCI_DVI_VSO_ELINE_EVN));
1101
1102 writel_relaxed(vso_begin_evn, priv->io_base
1103 + _REG(ENCI_DVI_VSO_END_EVN));
1104 }
1105 }
1106 } else {
1107 writel_relaxed(vmode->encp.dvi_settings,
1108 priv->io_base + _REG(VENC_DVI_SETTING));
1109 writel_relaxed(vmode->encp.video_mode,
1110 priv->io_base + _REG(ENCP_VIDEO_MODE));
1111 writel_relaxed(vmode->encp.video_mode_adv,
1112 priv->io_base + _REG(ENCP_VIDEO_MODE_ADV));
1113 if (vmode->encp.video_prog_mode_present)
1114 writel_relaxed(vmode->encp.video_prog_mode,
1115 priv->io_base + _REG(VENC_VIDEO_PROG_MODE));
1116 if (vmode->encp.video_sync_mode_present)
1117 writel_relaxed(vmode->encp.video_sync_mode,
1118 priv->io_base + _REG(ENCP_VIDEO_SYNC_MODE));
1119 if (vmode->encp.video_yc_dly_present)
1120 writel_relaxed(vmode->encp.video_yc_dly,
1121 priv->io_base + _REG(ENCP_VIDEO_YC_DLY));
1122 if (vmode->encp.video_rgb_ctrl_present)
1123 writel_relaxed(vmode->encp.video_rgb_ctrl,
1124 priv->io_base + _REG(ENCP_VIDEO_RGB_CTRL));
1125 if (vmode->encp.video_filt_ctrl_present)
1126 writel_relaxed(vmode->encp.video_filt_ctrl,
1127 priv->io_base + _REG(ENCP_VIDEO_FILT_CTRL));
1128 if (vmode->encp.video_ofld_voav_ofst_present)
1129 writel_relaxed(vmode->encp.video_ofld_voav_ofst,
1130 priv->io_base
1131 + _REG(ENCP_VIDEO_OFLD_VOAV_OFST));
1132 writel_relaxed(vmode->encp.yfp1_htime,
1133 priv->io_base + _REG(ENCP_VIDEO_YFP1_HTIME));
1134 writel_relaxed(vmode->encp.yfp2_htime,
1135 priv->io_base + _REG(ENCP_VIDEO_YFP2_HTIME));
1136 writel_relaxed(vmode->encp.max_pxcnt,
1137 priv->io_base + _REG(ENCP_VIDEO_MAX_PXCNT));
1138 writel_relaxed(vmode->encp.hspuls_begin,
1139 priv->io_base + _REG(ENCP_VIDEO_HSPULS_BEGIN));
1140 writel_relaxed(vmode->encp.hspuls_end,
1141 priv->io_base + _REG(ENCP_VIDEO_HSPULS_END));
1142 writel_relaxed(vmode->encp.hspuls_switch,
1143 priv->io_base + _REG(ENCP_VIDEO_HSPULS_SWITCH));
1144 writel_relaxed(vmode->encp.vspuls_begin,
1145 priv->io_base + _REG(ENCP_VIDEO_VSPULS_BEGIN));
1146 writel_relaxed(vmode->encp.vspuls_end,
1147 priv->io_base + _REG(ENCP_VIDEO_VSPULS_END));
1148 writel_relaxed(vmode->encp.vspuls_bline,
1149 priv->io_base + _REG(ENCP_VIDEO_VSPULS_BLINE));
1150 writel_relaxed(vmode->encp.vspuls_eline,
1151 priv->io_base + _REG(ENCP_VIDEO_VSPULS_ELINE));
1152 if (vmode->encp.eqpuls_begin_present)
1153 writel_relaxed(vmode->encp.eqpuls_begin,
1154 priv->io_base + _REG(ENCP_VIDEO_EQPULS_BEGIN));
1155 if (vmode->encp.eqpuls_end_present)
1156 writel_relaxed(vmode->encp.eqpuls_end,
1157 priv->io_base + _REG(ENCP_VIDEO_EQPULS_END));
1158 if (vmode->encp.eqpuls_bline_present)
1159 writel_relaxed(vmode->encp.eqpuls_bline,
1160 priv->io_base + _REG(ENCP_VIDEO_EQPULS_BLINE));
1161 if (vmode->encp.eqpuls_eline_present)
1162 writel_relaxed(vmode->encp.eqpuls_eline,
1163 priv->io_base + _REG(ENCP_VIDEO_EQPULS_ELINE));
1164 writel_relaxed(vmode->encp.havon_begin,
1165 priv->io_base + _REG(ENCP_VIDEO_HAVON_BEGIN));
1166 writel_relaxed(vmode->encp.havon_end,
1167 priv->io_base + _REG(ENCP_VIDEO_HAVON_END));
1168 writel_relaxed(vmode->encp.vavon_bline,
1169 priv->io_base + _REG(ENCP_VIDEO_VAVON_BLINE));
1170 writel_relaxed(vmode->encp.vavon_eline,
1171 priv->io_base + _REG(ENCP_VIDEO_VAVON_ELINE));
1172 writel_relaxed(vmode->encp.hso_begin,
1173 priv->io_base + _REG(ENCP_VIDEO_HSO_BEGIN));
1174 writel_relaxed(vmode->encp.hso_end,
1175 priv->io_base + _REG(ENCP_VIDEO_HSO_END));
1176 writel_relaxed(vmode->encp.vso_begin,
1177 priv->io_base + _REG(ENCP_VIDEO_VSO_BEGIN));
1178 writel_relaxed(vmode->encp.vso_end,
1179 priv->io_base + _REG(ENCP_VIDEO_VSO_END));
1180 writel_relaxed(vmode->encp.vso_bline,
1181 priv->io_base + _REG(ENCP_VIDEO_VSO_BLINE));
1182 if (vmode->encp.vso_eline_present)
1183 writel_relaxed(vmode->encp.vso_eline,
1184 priv->io_base + _REG(ENCP_VIDEO_VSO_ELINE));
1185 if (vmode->encp.sy_val_present)
1186 writel_relaxed(vmode->encp.sy_val,
1187 priv->io_base + _REG(ENCP_VIDEO_SY_VAL));
1188 if (vmode->encp.sy2_val_present)
1189 writel_relaxed(vmode->encp.sy2_val,
1190 priv->io_base + _REG(ENCP_VIDEO_SY2_VAL));
1191 writel_relaxed(vmode->encp.max_lncnt,
1192 priv->io_base + _REG(ENCP_VIDEO_MAX_LNCNT));
1193
1194 writel_relaxed(1, priv->io_base + _REG(ENCP_VIDEO_EN));
1195
1196 /* Set DE signal’s polarity is active high */
1197 writel_bits_relaxed(BIT(14), BIT(14),
1198 priv->io_base + _REG(ENCP_VIDEO_MODE));
1199
1200 /* Program DE timing */
1201 de_h_begin = modulo(readl_relaxed(priv->io_base +
1202 _REG(ENCP_VIDEO_HAVON_BEGIN))
1203 + venc_hdmi_latency,
1204 total_pixels_venc);
1205 de_h_end = modulo(de_h_begin + active_pixels_venc,
1206 total_pixels_venc);
1207
1208 writel_relaxed(de_h_begin,
1209 priv->io_base + _REG(ENCP_DE_H_BEGIN));
1210 writel_relaxed(de_h_end,
1211 priv->io_base + _REG(ENCP_DE_H_END));
1212
1213 /* Program DE timing for even field */
1214 de_v_begin_even = readl_relaxed(priv->io_base
1215 + _REG(ENCP_VIDEO_VAVON_BLINE));
1216 if (mode->flags & DRM_MODE_FLAG_INTERLACE)
1217 de_v_end_even = de_v_begin_even +
1218 (mode->vdisplay / 2);
1219 else
1220 de_v_end_even = de_v_begin_even + mode->vdisplay;
1221
1222 writel_relaxed(de_v_begin_even,
1223 priv->io_base + _REG(ENCP_DE_V_BEGIN_EVEN));
1224 writel_relaxed(de_v_end_even,
1225 priv->io_base + _REG(ENCP_DE_V_END_EVEN));
1226
1227 /* Program DE timing for odd field if needed */
1228 if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
1229 unsigned int ofld_voav_ofst =
1230 readl_relaxed(priv->io_base +
1231 _REG(ENCP_VIDEO_OFLD_VOAV_OFST));
1232 de_v_begin_odd = to_signed((ofld_voav_ofst & 0xf0) >> 4)
1233 + de_v_begin_even
1234 + ((mode->vtotal - 1) / 2);
1235 de_v_end_odd = de_v_begin_odd + (mode->vdisplay / 2);
1236
1237 writel_relaxed(de_v_begin_odd,
1238 priv->io_base + _REG(ENCP_DE_V_BEGIN_ODD));
1239 writel_relaxed(de_v_end_odd,
1240 priv->io_base + _REG(ENCP_DE_V_END_ODD));
1241 }
1242
1243 /* Program Hsync timing */
1244 if ((de_h_end + front_porch_venc) >= total_pixels_venc) {
1245 hs_begin = de_h_end
1246 + front_porch_venc
1247 - total_pixels_venc;
1248 vs_adjust = 1;
1249 } else {
1250 hs_begin = de_h_end
1251 + front_porch_venc;
1252 vs_adjust = 0;
1253 }
1254
1255 hs_end = modulo(hs_begin + hsync_pixels_venc,
1256 total_pixels_venc);
1257
1258 writel_relaxed(hs_begin,
1259 priv->io_base + _REG(ENCP_DVI_HSO_BEGIN));
1260 writel_relaxed(hs_end,
1261 priv->io_base + _REG(ENCP_DVI_HSO_END));
1262
1263 /* Program Vsync timing for even field */
1264 if (de_v_begin_even >=
1265 (sof_lines + vsync_lines + (1 - vs_adjust)))
1266 vs_bline_evn = de_v_begin_even
1267 - sof_lines
1268 - vsync_lines
1269 - (1 - vs_adjust);
1270 else
1271 vs_bline_evn = mode->vtotal
1272 + de_v_begin_even
1273 - sof_lines
1274 - vsync_lines
1275 - (1 - vs_adjust);
1276
1277 vs_eline_evn = modulo(vs_bline_evn + vsync_lines,
1278 mode->vtotal);
1279
1280 writel_relaxed(vs_bline_evn,
1281 priv->io_base + _REG(ENCP_DVI_VSO_BLINE_EVN));
1282 writel_relaxed(vs_eline_evn,
1283 priv->io_base + _REG(ENCP_DVI_VSO_ELINE_EVN));
1284
1285 vso_begin_evn = hs_begin;
1286 writel_relaxed(vso_begin_evn,
1287 priv->io_base + _REG(ENCP_DVI_VSO_BEGIN_EVN));
1288 writel_relaxed(vso_begin_evn,
1289 priv->io_base + _REG(ENCP_DVI_VSO_END_EVN));
1290
1291 /* Program Vsync timing for odd field if needed */
1292 if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
1293 vs_bline_odd = (de_v_begin_odd - 1)
1294 - sof_lines
1295 - vsync_lines;
1296 vs_eline_odd = (de_v_begin_odd - 1)
1297 - vsync_lines;
1298 vso_begin_odd = modulo(hs_begin
1299 + (total_pixels_venc >> 1),
1300 total_pixels_venc);
1301
1302 writel_relaxed(vs_bline_odd,
1303 priv->io_base + _REG(ENCP_DVI_VSO_BLINE_ODD));
1304 writel_relaxed(vs_eline_odd,
1305 priv->io_base + _REG(ENCP_DVI_VSO_ELINE_ODD));
1306 writel_relaxed(vso_begin_odd,
1307 priv->io_base + _REG(ENCP_DVI_VSO_BEGIN_ODD));
1308 writel_relaxed(vso_begin_odd,
1309 priv->io_base + _REG(ENCP_DVI_VSO_END_ODD));
1310 }
1311
1312 /* Select ENCP for VIU */
1313 meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCP);
1314 }
1315
1316 writel_relaxed((use_enci ? 1 : 2) |
1317 (mode->flags & DRM_MODE_FLAG_PHSYNC ? 1 << 2 : 0) |
1318 (mode->flags & DRM_MODE_FLAG_PVSYNC ? 1 << 3 : 0) |
1319 4 << 5 |
1320 (venc_repeat ? 1 << 8 : 0) |
1321 (hdmi_repeat ? 1 << 12 : 0),
1322 priv->io_base + _REG(VPU_HDMI_SETTING));
1323
1324 priv->venc.hdmi_repeat = hdmi_repeat;
1325 priv->venc.venc_repeat = venc_repeat;
1326 priv->venc.hdmi_use_enci = use_enci;
1327
1328 priv->venc.current_mode = MESON_VENC_MODE_HDMI;
1329}
1330EXPORT_SYMBOL_GPL(meson_venc_hdmi_mode_set);
1331
Neil Armstrongbbbe7752016-11-10 15:29:37 +01001332void meson_venci_cvbs_mode_set(struct meson_drm *priv,
1333 struct meson_cvbs_enci_mode *mode)
1334{
1335 if (mode->mode_tag == priv->venc.current_mode)
1336 return;
1337
1338 /* CVBS Filter settings */
1339 writel_relaxed(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL));
1340 writel_relaxed(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL2));
1341
1342 /* Digital Video Select : Interlace, clk27 clk, external */
1343 writel_relaxed(0, priv->io_base + _REG(VENC_DVI_SETTING));
1344
1345 /* Reset Video Mode */
1346 writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_MODE));
1347 writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
1348
1349 /* Horizontal sync signal output */
1350 writel_relaxed(mode->hso_begin,
1351 priv->io_base + _REG(ENCI_SYNC_HSO_BEGIN));
1352 writel_relaxed(mode->hso_end,
1353 priv->io_base + _REG(ENCI_SYNC_HSO_END));
1354
1355 /* Vertical Sync lines */
1356 writel_relaxed(mode->vso_even,
1357 priv->io_base + _REG(ENCI_SYNC_VSO_EVNLN));
1358 writel_relaxed(mode->vso_odd,
1359 priv->io_base + _REG(ENCI_SYNC_VSO_ODDLN));
1360
1361 /* Macrovision max amplitude change */
1362 writel_relaxed(0x8100 + mode->macv_max_amp,
1363 priv->io_base + _REG(ENCI_MACV_MAX_AMP));
1364
1365 /* Video mode */
1366 writel_relaxed(mode->video_prog_mode,
1367 priv->io_base + _REG(VENC_VIDEO_PROG_MODE));
1368 writel_relaxed(mode->video_mode,
1369 priv->io_base + _REG(ENCI_VIDEO_MODE));
1370
1371 /* Advanced Video Mode :
1372 * Demux shifting 0x2
1373 * Blank line end at line17/22
1374 * High bandwidth Luma Filter
1375 * Low bandwidth Chroma Filter
1376 * Bypass luma low pass filter
1377 * No macrovision on CSYNC
1378 */
1379 writel_relaxed(0x26, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
1380
1381 writel(mode->sch_adjust, priv->io_base + _REG(ENCI_VIDEO_SCH));
1382
1383 /* Sync mode : MASTER Master mode, free run, send HSO/VSO out */
1384 writel_relaxed(0x07, priv->io_base + _REG(ENCI_SYNC_MODE));
1385
1386 /* 0x3 Y, C, and Component Y delay */
1387 writel_relaxed(mode->yc_delay, priv->io_base + _REG(ENCI_YC_DELAY));
1388
1389 /* Timings */
1390 writel_relaxed(mode->pixel_start,
1391 priv->io_base + _REG(ENCI_VFIFO2VD_PIXEL_START));
1392 writel_relaxed(mode->pixel_end,
1393 priv->io_base + _REG(ENCI_VFIFO2VD_PIXEL_END));
1394
1395 writel_relaxed(mode->top_field_line_start,
1396 priv->io_base + _REG(ENCI_VFIFO2VD_LINE_TOP_START));
1397 writel_relaxed(mode->top_field_line_end,
1398 priv->io_base + _REG(ENCI_VFIFO2VD_LINE_TOP_END));
1399
1400 writel_relaxed(mode->bottom_field_line_start,
1401 priv->io_base + _REG(ENCI_VFIFO2VD_LINE_BOT_START));
1402 writel_relaxed(mode->bottom_field_line_end,
1403 priv->io_base + _REG(ENCI_VFIFO2VD_LINE_BOT_END));
1404
1405 /* Internal Venc, Internal VIU Sync, Internal Vencoder */
1406 writel_relaxed(0, priv->io_base + _REG(VENC_SYNC_ROUTE));
1407
1408 /* UNreset Interlaced TV Encoder */
1409 writel_relaxed(0, priv->io_base + _REG(ENCI_DBG_PX_RST));
1410
1411 /* Enable Vfifo2vd, Y_Cb_Y_Cr select */
1412 writel_relaxed(0x4e01, priv->io_base + _REG(ENCI_VFIFO2VD_CTL));
1413
1414 /* Power UP Dacs */
1415 writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_SETTING));
1416
1417 /* Video Upsampling */
1418 writel_relaxed(0x0061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL0));
1419 writel_relaxed(0x4061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL1));
1420 writel_relaxed(0x5061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL2));
1421
1422 /* Select Interlace Y DACs */
1423 writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL0));
1424 writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL1));
1425 writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL2));
1426 writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL3));
1427 writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL4));
1428 writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL5));
1429
1430 /* Select ENCI for VIU */
1431 meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCI);
1432
1433 /* Enable ENCI FIFO */
1434 writel_relaxed(0x2000, priv->io_base + _REG(VENC_VDAC_FIFO_CTRL));
1435
1436 /* Select ENCI DACs 0, 1, 4, and 5 */
1437 writel_relaxed(0x11, priv->io_base + _REG(ENCI_DACSEL_0));
1438 writel_relaxed(0x11, priv->io_base + _REG(ENCI_DACSEL_1));
1439
1440 /* Interlace video enable */
1441 writel_relaxed(1, priv->io_base + _REG(ENCI_VIDEO_EN));
1442
1443 /* Configure Video Saturation / Contrast / Brightness / Hue */
1444 writel_relaxed(mode->video_saturation,
1445 priv->io_base + _REG(ENCI_VIDEO_SAT));
1446 writel_relaxed(mode->video_contrast,
1447 priv->io_base + _REG(ENCI_VIDEO_CONT));
1448 writel_relaxed(mode->video_brightness,
1449 priv->io_base + _REG(ENCI_VIDEO_BRIGHT));
1450 writel_relaxed(mode->video_hue,
1451 priv->io_base + _REG(ENCI_VIDEO_HUE));
1452
1453 /* Enable DAC0 Filter */
1454 writel_relaxed(0x1, priv->io_base + _REG(VENC_VDAC_DAC0_FILT_CTRL0));
1455 writel_relaxed(0xfc48, priv->io_base + _REG(VENC_VDAC_DAC0_FILT_CTRL1));
1456
1457 /* 0 in Macrovision register 0 */
1458 writel_relaxed(0, priv->io_base + _REG(ENCI_MACV_N0));
1459
1460 /* Analog Synchronization and color burst value adjust */
1461 writel_relaxed(mode->analog_sync_adj,
1462 priv->io_base + _REG(ENCI_SYNC_ADJ));
1463
Neil Armstrongbbbe7752016-11-10 15:29:37 +01001464 priv->venc.current_mode = mode->mode_tag;
1465}
1466
1467/* Returns the current ENCI field polarity */
1468unsigned int meson_venci_get_field(struct meson_drm *priv)
1469{
1470 return readl_relaxed(priv->io_base + _REG(ENCI_INFO_READ)) & BIT(29);
1471}
1472
1473void meson_venc_enable_vsync(struct meson_drm *priv)
1474{
1475 writel_relaxed(2, priv->io_base + _REG(VENC_INTCTRL));
1476}
1477
1478void meson_venc_disable_vsync(struct meson_drm *priv)
1479{
1480 writel_relaxed(0, priv->io_base + _REG(VENC_INTCTRL));
1481}
1482
1483void meson_venc_init(struct meson_drm *priv)
1484{
Neil Armstrong0c931a22017-01-02 16:14:15 +01001485 /* Disable CVBS VDAC */
1486 regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0);
1487 regmap_write(priv->hhi, HHI_VDAC_CNTL1, 8);
1488
1489 /* Power Down Dacs */
1490 writel_relaxed(0xff, priv->io_base + _REG(VENC_VDAC_SETTING));
1491
1492 /* Disable HDMI PHY */
1493 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0);
1494
1495 /* Disable HDMI */
1496 writel_bits_relaxed(0x3, 0,
1497 priv->io_base + _REG(VPU_HDMI_SETTING));
1498
Neil Armstrongbbbe7752016-11-10 15:29:37 +01001499 /* Disable all encoders */
1500 writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN));
1501 writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN));
1502 writel_relaxed(0, priv->io_base + _REG(ENCL_VIDEO_EN));
1503
1504 /* Disable VSync IRQ */
1505 meson_venc_disable_vsync(priv);
1506
1507 priv->venc.current_mode = MESON_VENC_MODE_NONE;
1508}