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