1
0
mirror of https://xff.cz/git/u-boot/ synced 2025-10-10 12:36:34 +02:00
Files
u-boot-megous/drivers/video/meson/meson_venc.c
Tom Rini d678a59d2d Revert "Merge patch series "arm: dts: am62-beagleplay: Fix Beagleplay Ethernet""
When bringing in the series 'arm: dts: am62-beagleplay: Fix Beagleplay
Ethernet"' I failed to notice that b4 noticed it was based on next and
so took that as the base commit and merged that part of next to master.

This reverts commit c8ffd1356d, reversing
changes made to 2ee6f3a5f7.

Reported-by: Jonas Karlman <jonas@kwiboo.se>
Signed-off-by: Tom Rini <trini@konsulko.com>
2024-05-19 08:16:36 -06:00

1571 lines
42 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Amlogic Meson Video Processing Unit driver
*
* Copyright (c) 2018 BayLibre, SAS.
* Author: Neil Armstrong <narmstrong@baylibre.com>
*/
#include <common.h>
#include <dm.h>
#include <edid.h>
#include <fdtdec.h>
#include <log.h>
#include <asm/io.h>
#include "meson_vpu.h"
enum {
MESON_VENC_MODE_NONE = 0,
MESON_VENC_MODE_CVBS_PAL,
MESON_VENC_MODE_CVBS_NTSC,
MESON_VENC_MODE_HDMI,
};
enum meson_venc_source {
MESON_VENC_SOURCE_NONE = 0,
MESON_VENC_SOURCE_ENCI = 1,
MESON_VENC_SOURCE_ENCP = 2,
};
#define HHI_VDAC_CNTL0 0x2F4 /* 0xbd offset in data sheet */
#define HHI_VDAC_CNTL0_G12A 0x2EC /* 0xbb offset in data sheet */
#define HHI_VDAC_CNTL1 0x2F8 /* 0xbe offset in data sheet */
#define HHI_VDAC_CNTL1_G12A 0x2F0 /* 0xbc offset in data sheet */
struct meson_cvbs_enci_mode {
unsigned int mode_tag;
unsigned int hso_begin; /* HSO begin position */
unsigned int hso_end; /* HSO end position */
unsigned int vso_even; /* VSO even line */
unsigned int vso_odd; /* VSO odd line */
unsigned int macv_max_amp; /* Macrovision max amplitude */
unsigned int video_prog_mode;
unsigned int video_mode;
unsigned int sch_adjust;
unsigned int yc_delay;
unsigned int pixel_start;
unsigned int pixel_end;
unsigned int top_field_line_start;
unsigned int top_field_line_end;
unsigned int bottom_field_line_start;
unsigned int bottom_field_line_end;
unsigned int video_saturation;
unsigned int video_contrast;
unsigned int video_brightness;
unsigned int video_hue;
unsigned int analog_sync_adj;
};
struct meson_cvbs_enci_mode meson_cvbs_enci_pal = {
.mode_tag = MESON_VENC_MODE_CVBS_PAL,
.hso_begin = 3,
.hso_end = 129,
.vso_even = 3,
.vso_odd = 260,
.macv_max_amp = 7,
.video_prog_mode = 0xff,
.video_mode = 0x13,
.sch_adjust = 0x28,
.yc_delay = 0x343,
.pixel_start = 251,
.pixel_end = 1691,
.top_field_line_start = 22,
.top_field_line_end = 310,
.bottom_field_line_start = 23,
.bottom_field_line_end = 311,
.video_saturation = 9,
.video_contrast = 0,
.video_brightness = 0,
.video_hue = 0,
.analog_sync_adj = 0x8080,
};
struct meson_cvbs_enci_mode meson_cvbs_enci_ntsc = {
.mode_tag = MESON_VENC_MODE_CVBS_NTSC,
.hso_begin = 5,
.hso_end = 129,
.vso_even = 3,
.vso_odd = 260,
.macv_max_amp = 0xb,
.video_prog_mode = 0xf0,
.video_mode = 0x8,
.sch_adjust = 0x20,
.yc_delay = 0x333,
.pixel_start = 227,
.pixel_end = 1667,
.top_field_line_start = 18,
.top_field_line_end = 258,
.bottom_field_line_start = 19,
.bottom_field_line_end = 259,
.video_saturation = 18,
.video_contrast = 3,
.video_brightness = 0,
.video_hue = 0,
.analog_sync_adj = 0x9c00,
};
union meson_hdmi_venc_mode {
struct {
unsigned int mode_tag;
unsigned int hso_begin;
unsigned int hso_end;
unsigned int vso_even;
unsigned int vso_odd;
unsigned int macv_max_amp;
unsigned int video_prog_mode;
unsigned int video_mode;
unsigned int sch_adjust;
unsigned int yc_delay;
unsigned int pixel_start;
unsigned int pixel_end;
unsigned int top_field_line_start;
unsigned int top_field_line_end;
unsigned int bottom_field_line_start;
unsigned int bottom_field_line_end;
} enci;
struct {
unsigned int dvi_settings;
unsigned int video_mode;
unsigned int video_mode_adv;
unsigned int video_prog_mode;
bool video_prog_mode_present;
unsigned int video_sync_mode;
bool video_sync_mode_present;
unsigned int video_yc_dly;
bool video_yc_dly_present;
unsigned int video_rgb_ctrl;
bool video_rgb_ctrl_present;
unsigned int video_filt_ctrl;
bool video_filt_ctrl_present;
unsigned int video_ofld_voav_ofst;
bool video_ofld_voav_ofst_present;
unsigned int yfp1_htime;
unsigned int yfp2_htime;
unsigned int max_pxcnt;
unsigned int hspuls_begin;
unsigned int hspuls_end;
unsigned int hspuls_switch;
unsigned int vspuls_begin;
unsigned int vspuls_end;
unsigned int vspuls_bline;
unsigned int vspuls_eline;
unsigned int eqpuls_begin;
bool eqpuls_begin_present;
unsigned int eqpuls_end;
bool eqpuls_end_present;
unsigned int eqpuls_bline;
bool eqpuls_bline_present;
unsigned int eqpuls_eline;
bool eqpuls_eline_present;
unsigned int havon_begin;
unsigned int havon_end;
unsigned int vavon_bline;
unsigned int vavon_eline;
unsigned int hso_begin;
unsigned int hso_end;
unsigned int vso_begin;
unsigned int vso_end;
unsigned int vso_bline;
unsigned int vso_eline;
bool vso_eline_present;
unsigned int sy_val;
bool sy_val_present;
unsigned int sy2_val;
bool sy2_val_present;
unsigned int max_lncnt;
} encp;
};
union meson_hdmi_venc_mode meson_hdmi_enci_mode_480i = {
.enci = {
.hso_begin = 5,
.hso_end = 129,
.vso_even = 3,
.vso_odd = 260,
.macv_max_amp = 0xb,
.video_prog_mode = 0xf0,
.video_mode = 0x8,
.sch_adjust = 0x20,
.yc_delay = 0,
.pixel_start = 227,
.pixel_end = 1667,
.top_field_line_start = 18,
.top_field_line_end = 258,
.bottom_field_line_start = 19,
.bottom_field_line_end = 259,
},
};
union meson_hdmi_venc_mode meson_hdmi_enci_mode_576i = {
.enci = {
.hso_begin = 3,
.hso_end = 129,
.vso_even = 3,
.vso_odd = 260,
.macv_max_amp = 0x7,
.video_prog_mode = 0xff,
.video_mode = 0x13,
.sch_adjust = 0x28,
.yc_delay = 0x333,
.pixel_start = 251,
.pixel_end = 1691,
.top_field_line_start = 22,
.top_field_line_end = 310,
.bottom_field_line_start = 23,
.bottom_field_line_end = 311,
},
};
union meson_hdmi_venc_mode meson_hdmi_encp_mode_480p = {
.encp = {
.dvi_settings = 0x21,
.video_mode = 0x4000,
.video_mode_adv = 0x9,
.video_prog_mode = 0,
.video_prog_mode_present = true,
.video_sync_mode = 7,
.video_sync_mode_present = true,
/* video_yc_dly */
/* video_rgb_ctrl */
.video_filt_ctrl = 0x2052,
.video_filt_ctrl_present = true,
/* video_ofld_voav_ofst */
.yfp1_htime = 244,
.yfp2_htime = 1630,
.max_pxcnt = 1715,
.hspuls_begin = 0x22,
.hspuls_end = 0xa0,
.hspuls_switch = 88,
.vspuls_begin = 0,
.vspuls_end = 1589,
.vspuls_bline = 0,
.vspuls_eline = 5,
.havon_begin = 249,
.havon_end = 1689,
.vavon_bline = 42,
.vavon_eline = 521,
/* eqpuls_begin */
/* eqpuls_end */
/* eqpuls_bline */
/* eqpuls_eline */
.hso_begin = 3,
.hso_end = 5,
.vso_begin = 3,
.vso_end = 5,
.vso_bline = 0,
/* vso_eline */
.sy_val = 8,
.sy_val_present = true,
.sy2_val = 0x1d8,
.sy2_val_present = true,
.max_lncnt = 524,
},
};
union meson_hdmi_venc_mode meson_hdmi_encp_mode_576p = {
.encp = {
.dvi_settings = 0x21,
.video_mode = 0x4000,
.video_mode_adv = 0x9,
.video_prog_mode = 0,
.video_prog_mode_present = true,
.video_sync_mode = 7,
.video_sync_mode_present = true,
/* video_yc_dly */
/* video_rgb_ctrl */
.video_filt_ctrl = 0x52,
.video_filt_ctrl_present = true,
/* video_ofld_voav_ofst */
.yfp1_htime = 235,
.yfp2_htime = 1674,
.max_pxcnt = 1727,
.hspuls_begin = 0,
.hspuls_end = 0x80,
.hspuls_switch = 88,
.vspuls_begin = 0,
.vspuls_end = 1599,
.vspuls_bline = 0,
.vspuls_eline = 4,
.havon_begin = 235,
.havon_end = 1674,
.vavon_bline = 44,
.vavon_eline = 619,
/* eqpuls_begin */
/* eqpuls_end */
/* eqpuls_bline */
/* eqpuls_eline */
.hso_begin = 0x80,
.hso_end = 0,
.vso_begin = 0,
.vso_end = 5,
.vso_bline = 0,
/* vso_eline */
.sy_val = 8,
.sy_val_present = true,
.sy2_val = 0x1d8,
.sy2_val_present = true,
.max_lncnt = 624,
},
};
union meson_hdmi_venc_mode meson_hdmi_encp_mode_720p60 = {
.encp = {
.dvi_settings = 0x2029,
.video_mode = 0x4040,
.video_mode_adv = 0x19,
/* video_prog_mode */
/* video_sync_mode */
/* video_yc_dly */
/* video_rgb_ctrl */
/* video_filt_ctrl */
/* video_ofld_voav_ofst */
.yfp1_htime = 648,
.yfp2_htime = 3207,
.max_pxcnt = 3299,
.hspuls_begin = 80,
.hspuls_end = 240,
.hspuls_switch = 80,
.vspuls_begin = 688,
.vspuls_end = 3248,
.vspuls_bline = 4,
.vspuls_eline = 8,
.havon_begin = 648,
.havon_end = 3207,
.vavon_bline = 29,
.vavon_eline = 748,
/* eqpuls_begin */
/* eqpuls_end */
/* eqpuls_bline */
/* eqpuls_eline */
.hso_begin = 256,
.hso_end = 168,
.vso_begin = 168,
.vso_end = 256,
.vso_bline = 0,
.vso_eline = 5,
.vso_eline_present = true,
/* sy_val */
/* sy2_val */
.max_lncnt = 749,
},
};
union meson_hdmi_venc_mode meson_hdmi_encp_mode_720p50 = {
.encp = {
.dvi_settings = 0x202d,
.video_mode = 0x4040,
.video_mode_adv = 0x19,
.video_prog_mode = 0x100,
.video_prog_mode_present = true,
.video_sync_mode = 0x407,
.video_sync_mode_present = true,
.video_yc_dly = 0,
.video_yc_dly_present = true,
/* video_rgb_ctrl */
/* video_filt_ctrl */
/* video_ofld_voav_ofst */
.yfp1_htime = 648,
.yfp2_htime = 3207,
.max_pxcnt = 3959,
.hspuls_begin = 80,
.hspuls_end = 240,
.hspuls_switch = 80,
.vspuls_begin = 688,
.vspuls_end = 3248,
.vspuls_bline = 4,
.vspuls_eline = 8,
.havon_begin = 648,
.havon_end = 3207,
.vavon_bline = 29,
.vavon_eline = 748,
/* eqpuls_begin */
/* eqpuls_end */
/* eqpuls_bline */
/* eqpuls_eline */
.hso_begin = 128,
.hso_end = 208,
.vso_begin = 128,
.vso_end = 128,
.vso_bline = 0,
.vso_eline = 5,
.vso_eline_present = true,
/* sy_val */
/* sy2_val */
.max_lncnt = 749,
},
};
union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080i60 = {
.encp = {
.dvi_settings = 0x2029,
.video_mode = 0x5ffc,
.video_mode_adv = 0x19,
.video_prog_mode = 0x100,
.video_prog_mode_present = true,
.video_sync_mode = 0x207,
.video_sync_mode_present = true,
/* video_yc_dly */
/* video_rgb_ctrl */
/* video_filt_ctrl */
.video_ofld_voav_ofst = 0x11,
.video_ofld_voav_ofst_present = true,
.yfp1_htime = 516,
.yfp2_htime = 4355,
.max_pxcnt = 4399,
.hspuls_begin = 88,
.hspuls_end = 264,
.hspuls_switch = 88,
.vspuls_begin = 440,
.vspuls_end = 2200,
.vspuls_bline = 0,
.vspuls_eline = 4,
.havon_begin = 516,
.havon_end = 4355,
.vavon_bline = 20,
.vavon_eline = 559,
.eqpuls_begin = 2288,
.eqpuls_begin_present = true,
.eqpuls_end = 2464,
.eqpuls_end_present = true,
.eqpuls_bline = 0,
.eqpuls_bline_present = true,
.eqpuls_eline = 4,
.eqpuls_eline_present = true,
.hso_begin = 264,
.hso_end = 176,
.vso_begin = 88,
.vso_end = 88,
.vso_bline = 0,
.vso_eline = 5,
.vso_eline_present = true,
/* sy_val */
/* sy2_val */
.max_lncnt = 1124,
},
};
union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080i50 = {
.encp = {
.dvi_settings = 0x202d,
.video_mode = 0x5ffc,
.video_mode_adv = 0x19,
.video_prog_mode = 0x100,
.video_prog_mode_present = true,
.video_sync_mode = 0x7,
.video_sync_mode_present = true,
/* video_yc_dly */
/* video_rgb_ctrl */
/* video_filt_ctrl */
.video_ofld_voav_ofst = 0x11,
.video_ofld_voav_ofst_present = true,
.yfp1_htime = 526,
.yfp2_htime = 4365,
.max_pxcnt = 5279,
.hspuls_begin = 88,
.hspuls_end = 264,
.hspuls_switch = 88,
.vspuls_begin = 440,
.vspuls_end = 2200,
.vspuls_bline = 0,
.vspuls_eline = 4,
.havon_begin = 526,
.havon_end = 4365,
.vavon_bline = 20,
.vavon_eline = 559,
.eqpuls_begin = 2288,
.eqpuls_begin_present = true,
.eqpuls_end = 2464,
.eqpuls_end_present = true,
.eqpuls_bline = 0,
.eqpuls_bline_present = true,
.eqpuls_eline = 4,
.eqpuls_eline_present = true,
.hso_begin = 142,
.hso_end = 230,
.vso_begin = 142,
.vso_end = 142,
.vso_bline = 0,
.vso_eline = 5,
.vso_eline_present = true,
/* sy_val */
/* sy2_val */
.max_lncnt = 1124,
},
};
union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p24 = {
.encp = {
.dvi_settings = 0xd,
.video_mode = 0x4040,
.video_mode_adv = 0x18,
.video_prog_mode = 0x100,
.video_prog_mode_present = true,
.video_sync_mode = 0x7,
.video_sync_mode_present = true,
.video_yc_dly = 0,
.video_yc_dly_present = true,
.video_rgb_ctrl = 2,
.video_rgb_ctrl_present = true,
.video_filt_ctrl = 0x1052,
.video_filt_ctrl_present = true,
/* video_ofld_voav_ofst */
.yfp1_htime = 271,
.yfp2_htime = 2190,
.max_pxcnt = 2749,
.hspuls_begin = 44,
.hspuls_end = 132,
.hspuls_switch = 44,
.vspuls_begin = 220,
.vspuls_end = 2140,
.vspuls_bline = 0,
.vspuls_eline = 4,
.havon_begin = 271,
.havon_end = 2190,
.vavon_bline = 41,
.vavon_eline = 1120,
/* eqpuls_begin */
/* eqpuls_end */
.eqpuls_bline = 0,
.eqpuls_bline_present = true,
.eqpuls_eline = 4,
.eqpuls_eline_present = true,
.hso_begin = 79,
.hso_end = 123,
.vso_begin = 79,
.vso_end = 79,
.vso_bline = 0,
.vso_eline = 5,
.vso_eline_present = true,
/* sy_val */
/* sy2_val */
.max_lncnt = 1124,
},
};
union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p30 = {
.encp = {
.dvi_settings = 0x1,
.video_mode = 0x4040,
.video_mode_adv = 0x18,
.video_prog_mode = 0x100,
.video_prog_mode_present = true,
/* video_sync_mode */
/* video_yc_dly */
/* video_rgb_ctrl */
.video_filt_ctrl = 0x1052,
.video_filt_ctrl_present = true,
/* video_ofld_voav_ofst */
.yfp1_htime = 140,
.yfp2_htime = 2060,
.max_pxcnt = 2199,
.hspuls_begin = 2156,
.hspuls_end = 44,
.hspuls_switch = 44,
.vspuls_begin = 140,
.vspuls_end = 2059,
.vspuls_bline = 0,
.vspuls_eline = 4,
.havon_begin = 148,
.havon_end = 2067,
.vavon_bline = 41,
.vavon_eline = 1120,
/* eqpuls_begin */
/* eqpuls_end */
/* eqpuls_bline */
/* eqpuls_eline */
.hso_begin = 44,
.hso_end = 2156,
.vso_begin = 2100,
.vso_end = 2164,
.vso_bline = 0,
.vso_eline = 5,
.vso_eline_present = true,
/* sy_val */
/* sy2_val */
.max_lncnt = 1124,
},
};
union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p50 = {
.encp = {
.dvi_settings = 0xd,
.video_mode = 0x4040,
.video_mode_adv = 0x18,
.video_prog_mode = 0x100,
.video_prog_mode_present = true,
.video_sync_mode = 0x7,
.video_sync_mode_present = true,
.video_yc_dly = 0,
.video_yc_dly_present = true,
.video_rgb_ctrl = 2,
.video_rgb_ctrl_present = true,
/* video_filt_ctrl */
/* video_ofld_voav_ofst */
.yfp1_htime = 271,
.yfp2_htime = 2190,
.max_pxcnt = 2639,
.hspuls_begin = 44,
.hspuls_end = 132,
.hspuls_switch = 44,
.vspuls_begin = 220,
.vspuls_end = 2140,
.vspuls_bline = 0,
.vspuls_eline = 4,
.havon_begin = 271,
.havon_end = 2190,
.vavon_bline = 41,
.vavon_eline = 1120,
/* eqpuls_begin */
/* eqpuls_end */
.eqpuls_bline = 0,
.eqpuls_bline_present = true,
.eqpuls_eline = 4,
.eqpuls_eline_present = true,
.hso_begin = 79,
.hso_end = 123,
.vso_begin = 79,
.vso_end = 79,
.vso_bline = 0,
.vso_eline = 5,
.vso_eline_present = true,
/* sy_val */
/* sy2_val */
.max_lncnt = 1124,
},
};
union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p60 = {
.encp = {
.dvi_settings = 0x1,
.video_mode = 0x4040,
.video_mode_adv = 0x18,
.video_prog_mode = 0x100,
.video_prog_mode_present = true,
/* video_sync_mode */
/* video_yc_dly */
/* video_rgb_ctrl */
.video_filt_ctrl = 0x1052,
.video_filt_ctrl_present = true,
/* video_ofld_voav_ofst */
.yfp1_htime = 140,
.yfp2_htime = 2060,
.max_pxcnt = 2199,
.hspuls_begin = 2156,
.hspuls_end = 44,
.hspuls_switch = 44,
.vspuls_begin = 140,
.vspuls_end = 2059,
.vspuls_bline = 0,
.vspuls_eline = 4,
.havon_begin = 148,
.havon_end = 2067,
.vavon_bline = 41,
.vavon_eline = 1120,
/* eqpuls_begin */
/* eqpuls_end */
/* eqpuls_bline */
/* eqpuls_eline */
.hso_begin = 44,
.hso_end = 2156,
.vso_begin = 2100,
.vso_end = 2164,
.vso_bline = 0,
.vso_eline = 5,
.vso_eline_present = true,
/* sy_val */
/* sy2_val */
.max_lncnt = 1124,
},
};
static signed int to_signed(unsigned int a)
{
if (a <= 7)
return a;
else
return a - 16;
}
static unsigned long modulo(unsigned long a, unsigned long b)
{
if (a >= b)
return a - b;
else
return a;
}
bool meson_venc_hdmi_supported_mode(const struct display_timing *mode)
{
if (mode->flags & ~(DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_HSYNC_HIGH |
DISPLAY_FLAGS_VSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH))
return false;
if (mode->hactive.typ < 640 || mode->hactive.typ > 1920)
return false;
if (mode->vactive.typ < 480 || mode->vactive.typ > 1200)
return false;
return true;
}
static void meson_venc_hdmi_get_dmt_vmode(const struct display_timing *mode,
union meson_hdmi_venc_mode *dmt_mode)
{
memset(dmt_mode, 0, sizeof(*dmt_mode));
dmt_mode->encp.dvi_settings = 0x21;
dmt_mode->encp.video_mode = 0x4040;
dmt_mode->encp.video_mode_adv = 0x18;
dmt_mode->encp.max_pxcnt = mode->hactive.typ +
mode->hfront_porch.typ +
mode->hback_porch.typ +
mode->hsync_len.typ - 1;
dmt_mode->encp.havon_begin = mode->hback_porch.typ +
mode->hsync_len.typ;
dmt_mode->encp.havon_end = dmt_mode->encp.havon_begin +
mode->hactive.typ - 1;
dmt_mode->encp.vavon_bline = mode->vback_porch.typ +
mode->vsync_len.typ;
dmt_mode->encp.vavon_eline = dmt_mode->encp.vavon_bline +
mode->vactive.typ - 1;
/* to investigate */
dmt_mode->encp.hso_begin = 0;
dmt_mode->encp.hso_end = mode->hsync_len.typ;
dmt_mode->encp.vso_begin = 30;
dmt_mode->encp.vso_end = 50;
dmt_mode->encp.vso_bline = 0;
dmt_mode->encp.vso_eline = mode->vsync_len.typ;
dmt_mode->encp.vso_eline_present = true;
dmt_mode->encp.max_lncnt = mode->vactive.typ +
mode->vfront_porch.typ +
mode->vback_porch.typ +
mode->vsync_len.typ - 1;
}
static void meson_venc_hdmi_mode_set(struct meson_vpu_priv *priv,
const struct display_timing *mode)
{
union meson_hdmi_venc_mode *vmode = NULL;
union meson_hdmi_venc_mode vmode_dmt;
bool use_enci = false;
bool venc_repeat = false;
bool hdmi_repeat = false;
unsigned int venc_hdmi_latency = 2;
unsigned long total_pixels_venc = 0;
unsigned long active_pixels_venc = 0;
unsigned long front_porch_venc = 0;
unsigned long hsync_pixels_venc = 0;
unsigned long de_h_begin = 0;
unsigned long de_h_end = 0;
unsigned long de_v_begin_even = 0;
unsigned long de_v_end_even = 0;
unsigned long de_v_begin_odd = 0;
unsigned long de_v_end_odd = 0;
unsigned long hs_begin = 0;
unsigned long hs_end = 0;
unsigned long vs_adjust = 0;
unsigned long vs_bline_evn = 0;
unsigned long vs_eline_evn = 0;
unsigned long vs_bline_odd = 0;
unsigned long vs_eline_odd = 0;
unsigned long vso_begin_evn = 0;
unsigned long vso_begin_odd = 0;
unsigned int eof_lines;
unsigned int sof_lines;
unsigned int vsync_lines;
u32 reg;
/* Use VENCI for 480i and 576i and double HDMI pixels */
if (mode->flags & DISPLAY_FLAGS_DOUBLECLK) {
hdmi_repeat = true;
use_enci = true;
venc_hdmi_latency = 1;
}
meson_venc_hdmi_get_dmt_vmode(mode, &vmode_dmt);
vmode = &vmode_dmt;
use_enci = false;
debug(" max_pxcnt %04d, max_lncnt %04d\n"
" havon_begin %04d, havon_end %04d\n"
" vavon_bline %04d, vavon_eline %04d\n"
" hso_begin %04d, hso_end %04d\n"
" vso_begin %04d, vso_end %04d\n"
" vso_bline %04d, vso_eline %04d\n",
vmode->encp.max_pxcnt, vmode->encp.max_lncnt,
vmode->encp.havon_begin, vmode->encp.havon_end,
vmode->encp.vavon_bline, vmode->encp.vavon_eline,
vmode->encp.hso_begin, vmode->encp.hso_end,
vmode->encp.vso_begin, vmode->encp.vso_end,
vmode->encp.vso_bline, vmode->encp.vso_eline);
eof_lines = mode->vfront_porch.typ;
if (mode->flags & DISPLAY_FLAGS_INTERLACED)
eof_lines /= 2;
sof_lines = mode->vback_porch.typ;
if (mode->flags & DISPLAY_FLAGS_INTERLACED)
sof_lines /= 2;
vsync_lines = mode->vsync_len.typ;
if (mode->flags & DISPLAY_FLAGS_INTERLACED)
vsync_lines /= 2;
total_pixels_venc = mode->hback_porch.typ + mode->hactive.typ +
mode->hfront_porch.typ + mode->hsync_len.typ;
if (hdmi_repeat)
total_pixels_venc /= 2;
if (venc_repeat)
total_pixels_venc *= 2;
active_pixels_venc = mode->hactive.typ;
if (hdmi_repeat)
active_pixels_venc /= 2;
if (venc_repeat)
active_pixels_venc *= 2;
front_porch_venc = mode->hfront_porch.typ;
if (hdmi_repeat)
front_porch_venc /= 2;
if (venc_repeat)
front_porch_venc *= 2;
hsync_pixels_venc = mode->hsync_len.typ;
if (hdmi_repeat)
hsync_pixels_venc /= 2;
if (venc_repeat)
hsync_pixels_venc *= 2;
/* Disable VDACs */
writel_bits(0xff, 0xff,
priv->io_base + _REG(VENC_VDAC_SETTING));
writel(0, priv->io_base + _REG(ENCI_VIDEO_EN));
writel(0, priv->io_base + _REG(ENCP_VIDEO_EN));
debug("use_enci: %d, hdmi_repeat: %d\n", use_enci, hdmi_repeat);
if (use_enci) {
unsigned int lines_f0;
unsigned int lines_f1;
/* CVBS Filter settings */
writel(ENCI_CFILT_CMPT_SEL_HIGH | 0x10,
priv->io_base + _REG(ENCI_CFILT_CTRL));
writel(ENCI_CFILT_CMPT_CR_DLY(2) |
ENCI_CFILT_CMPT_CB_DLY(1),
priv->io_base + _REG(ENCI_CFILT_CTRL2));
/* Digital Video Select : Interlace, clk27 clk, external */
writel(0, priv->io_base + _REG(VENC_DVI_SETTING));
/* Reset Video Mode */
writel(0, priv->io_base + _REG(ENCI_VIDEO_MODE));
writel(0, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
/* Horizontal sync signal output */
writel(vmode->enci.hso_begin,
priv->io_base + _REG(ENCI_SYNC_HSO_BEGIN));
writel(vmode->enci.hso_end,
priv->io_base + _REG(ENCI_SYNC_HSO_END));
/* Vertical Sync lines */
writel(vmode->enci.vso_even,
priv->io_base + _REG(ENCI_SYNC_VSO_EVNLN));
writel(vmode->enci.vso_odd,
priv->io_base + _REG(ENCI_SYNC_VSO_ODDLN));
/* Macrovision max amplitude change */
writel(ENCI_MACV_MAX_AMP_ENABLE_CHANGE |
ENCI_MACV_MAX_AMP_VAL(vmode->enci.macv_max_amp),
priv->io_base + _REG(ENCI_MACV_MAX_AMP));
/* Video mode */
writel(vmode->enci.video_prog_mode,
priv->io_base + _REG(VENC_VIDEO_PROG_MODE));
writel(vmode->enci.video_mode,
priv->io_base + _REG(ENCI_VIDEO_MODE));
/*
* Advanced Video Mode :
* Demux shifting 0x2
* Blank line end at line17/22
* High bandwidth Luma Filter
* Low bandwidth Chroma Filter
* Bypass luma low pass filter
* No macrovision on CSYNC
*/
writel(ENCI_VIDEO_MODE_ADV_DMXMD(2) |
ENCI_VIDEO_MODE_ADV_VBICTL_LINE_17_22 |
ENCI_VIDEO_MODE_ADV_YBW_HIGH,
priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
writel(vmode->enci.sch_adjust,
priv->io_base + _REG(ENCI_VIDEO_SCH));
/* Sync mode : MASTER Master mode, free run, send HSO/VSO out */
writel(0x07, priv->io_base + _REG(ENCI_SYNC_MODE));
if (vmode->enci.yc_delay)
writel(vmode->enci.yc_delay,
priv->io_base + _REG(ENCI_YC_DELAY));
/* UNreset Interlaced TV Encoder */
writel(0, priv->io_base + _REG(ENCI_DBG_PX_RST));
/*
* Enable Vfifo2vd and set Y_Cb_Y_Cr:
* Corresponding value:
* Y => 00 or 10
* Cb => 01
* Cr => 11
* Ex: 0x4e => 01001110 would mean Cb/Y/Cr/Y
*/
writel(ENCI_VFIFO2VD_CTL_ENABLE |
ENCI_VFIFO2VD_CTL_VD_SEL(0x4e),
priv->io_base + _REG(ENCI_VFIFO2VD_CTL));
/* Timings */
writel(vmode->enci.pixel_start,
priv->io_base + _REG(ENCI_VFIFO2VD_PIXEL_START));
writel(vmode->enci.pixel_end,
priv->io_base + _REG(ENCI_VFIFO2VD_PIXEL_END));
writel(vmode->enci.top_field_line_start,
priv->io_base + _REG(ENCI_VFIFO2VD_LINE_TOP_START));
writel(vmode->enci.top_field_line_end,
priv->io_base + _REG(ENCI_VFIFO2VD_LINE_TOP_END));
writel(vmode->enci.bottom_field_line_start,
priv->io_base + _REG(ENCI_VFIFO2VD_LINE_BOT_START));
writel(vmode->enci.bottom_field_line_end,
priv->io_base + _REG(ENCI_VFIFO2VD_LINE_BOT_END));
/* Select ENCI for VIU */
meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCI);
/* Interlace video enable */
writel(ENCI_VIDEO_EN_ENABLE,
priv->io_base + _REG(ENCI_VIDEO_EN));
lines_f0 = mode->vback_porch.typ + mode->vactive.typ +
mode->vback_porch.typ + mode->vsync_len.typ;
lines_f0 = lines_f0 >> 1;
lines_f1 = lines_f0 + 1;
de_h_begin = modulo(readl(priv->io_base +
_REG(ENCI_VFIFO2VD_PIXEL_START))
+ venc_hdmi_latency,
total_pixels_venc);
de_h_end = modulo(de_h_begin + active_pixels_venc,
total_pixels_venc);
writel(de_h_begin,
priv->io_base + _REG(ENCI_DE_H_BEGIN));
writel(de_h_end,
priv->io_base + _REG(ENCI_DE_H_END));
de_v_begin_even = readl(priv->io_base +
_REG(ENCI_VFIFO2VD_LINE_TOP_START));
de_v_end_even = de_v_begin_even + mode->vactive.typ;
de_v_begin_odd = readl(priv->io_base +
_REG(ENCI_VFIFO2VD_LINE_BOT_START));
de_v_end_odd = de_v_begin_odd + mode->vactive.typ;
writel(de_v_begin_even,
priv->io_base + _REG(ENCI_DE_V_BEGIN_EVEN));
writel(de_v_end_even,
priv->io_base + _REG(ENCI_DE_V_END_EVEN));
writel(de_v_begin_odd,
priv->io_base + _REG(ENCI_DE_V_BEGIN_ODD));
writel(de_v_end_odd,
priv->io_base + _REG(ENCI_DE_V_END_ODD));
/* Program Hsync timing */
hs_begin = de_h_end + front_porch_venc;
if (de_h_end + front_porch_venc >= total_pixels_venc) {
hs_begin -= total_pixels_venc;
vs_adjust = 1;
} else {
hs_begin = de_h_end + front_porch_venc;
vs_adjust = 0;
}
hs_end = modulo(hs_begin + hsync_pixels_venc,
total_pixels_venc);
writel(hs_begin,
priv->io_base + _REG(ENCI_DVI_HSO_BEGIN));
writel(hs_end,
priv->io_base + _REG(ENCI_DVI_HSO_END));
/* Program Vsync timing for even field */
if (((de_v_end_odd - 1) + eof_lines + vs_adjust) >= lines_f1) {
vs_bline_evn = (de_v_end_odd - 1)
+ eof_lines
+ vs_adjust
- lines_f1;
vs_eline_evn = vs_bline_evn + vsync_lines;
writel(vs_bline_evn,
priv->io_base + _REG(ENCI_DVI_VSO_BLINE_EVN));
writel(vs_eline_evn,
priv->io_base + _REG(ENCI_DVI_VSO_ELINE_EVN));
writel(hs_begin,
priv->io_base + _REG(ENCI_DVI_VSO_BEGIN_EVN));
writel(hs_begin,
priv->io_base + _REG(ENCI_DVI_VSO_END_EVN));
} else {
vs_bline_odd = (de_v_end_odd - 1)
+ eof_lines
+ vs_adjust;
writel(vs_bline_odd,
priv->io_base + _REG(ENCI_DVI_VSO_BLINE_ODD));
writel(hs_begin,
priv->io_base + _REG(ENCI_DVI_VSO_BEGIN_ODD));
if ((vs_bline_odd + vsync_lines) >= lines_f1) {
vs_eline_evn = vs_bline_odd
+ vsync_lines
- lines_f1;
writel(vs_eline_evn, priv->io_base
+ _REG(ENCI_DVI_VSO_ELINE_EVN));
writel(hs_begin, priv->io_base
+ _REG(ENCI_DVI_VSO_END_EVN));
} else {
vs_eline_odd = vs_bline_odd
+ vsync_lines;
writel(vs_eline_odd, priv->io_base
+ _REG(ENCI_DVI_VSO_ELINE_ODD));
writel(hs_begin, priv->io_base
+ _REG(ENCI_DVI_VSO_END_ODD));
}
}
/* Program Vsync timing for odd field */
if (((de_v_end_even - 1) + (eof_lines + 1)) >= lines_f0) {
vs_bline_odd = (de_v_end_even - 1)
+ (eof_lines + 1)
- lines_f0;
vs_eline_odd = vs_bline_odd + vsync_lines;
writel(vs_bline_odd,
priv->io_base + _REG(ENCI_DVI_VSO_BLINE_ODD));
writel(vs_eline_odd,
priv->io_base + _REG(ENCI_DVI_VSO_ELINE_ODD));
vso_begin_odd = modulo(hs_begin
+ (total_pixels_venc >> 1),
total_pixels_venc);
writel(vso_begin_odd,
priv->io_base + _REG(ENCI_DVI_VSO_BEGIN_ODD));
writel(vso_begin_odd,
priv->io_base + _REG(ENCI_DVI_VSO_END_ODD));
} else {
vs_bline_evn = (de_v_end_even - 1)
+ (eof_lines + 1);
writel(vs_bline_evn,
priv->io_base + _REG(ENCI_DVI_VSO_BLINE_EVN));
vso_begin_evn = modulo(hs_begin
+ (total_pixels_venc >> 1),
total_pixels_venc);
writel(vso_begin_evn, priv->io_base
+ _REG(ENCI_DVI_VSO_BEGIN_EVN));
if (vs_bline_evn + vsync_lines >= lines_f0) {
vs_eline_odd = vs_bline_evn
+ vsync_lines
- lines_f0;
writel(vs_eline_odd, priv->io_base
+ _REG(ENCI_DVI_VSO_ELINE_ODD));
writel(vso_begin_evn, priv->io_base
+ _REG(ENCI_DVI_VSO_END_ODD));
} else {
vs_eline_evn = vs_bline_evn + vsync_lines;
writel(vs_eline_evn, priv->io_base
+ _REG(ENCI_DVI_VSO_ELINE_EVN));
writel(vso_begin_evn, priv->io_base
+ _REG(ENCI_DVI_VSO_END_EVN));
}
}
} else {
writel(vmode->encp.dvi_settings,
priv->io_base + _REG(VENC_DVI_SETTING));
writel(vmode->encp.video_mode,
priv->io_base + _REG(ENCP_VIDEO_MODE));
writel(vmode->encp.video_mode_adv,
priv->io_base + _REG(ENCP_VIDEO_MODE_ADV));
if (vmode->encp.video_prog_mode_present)
writel(vmode->encp.video_prog_mode,
priv->io_base + _REG(VENC_VIDEO_PROG_MODE));
if (vmode->encp.video_sync_mode_present)
writel(vmode->encp.video_sync_mode,
priv->io_base + _REG(ENCP_VIDEO_SYNC_MODE));
if (vmode->encp.video_yc_dly_present)
writel(vmode->encp.video_yc_dly,
priv->io_base + _REG(ENCP_VIDEO_YC_DLY));
if (vmode->encp.video_rgb_ctrl_present)
writel(vmode->encp.video_rgb_ctrl,
priv->io_base + _REG(ENCP_VIDEO_RGB_CTRL));
if (vmode->encp.video_filt_ctrl_present)
writel(vmode->encp.video_filt_ctrl,
priv->io_base + _REG(ENCP_VIDEO_FILT_CTRL));
if (vmode->encp.video_ofld_voav_ofst_present)
writel(vmode->encp.video_ofld_voav_ofst,
priv->io_base
+ _REG(ENCP_VIDEO_OFLD_VOAV_OFST));
writel(vmode->encp.yfp1_htime,
priv->io_base + _REG(ENCP_VIDEO_YFP1_HTIME));
writel(vmode->encp.yfp2_htime,
priv->io_base + _REG(ENCP_VIDEO_YFP2_HTIME));
writel(vmode->encp.max_pxcnt,
priv->io_base + _REG(ENCP_VIDEO_MAX_PXCNT));
writel(vmode->encp.hspuls_begin,
priv->io_base + _REG(ENCP_VIDEO_HSPULS_BEGIN));
writel(vmode->encp.hspuls_end,
priv->io_base + _REG(ENCP_VIDEO_HSPULS_END));
writel(vmode->encp.hspuls_switch,
priv->io_base + _REG(ENCP_VIDEO_HSPULS_SWITCH));
writel(vmode->encp.vspuls_begin,
priv->io_base + _REG(ENCP_VIDEO_VSPULS_BEGIN));
writel(vmode->encp.vspuls_end,
priv->io_base + _REG(ENCP_VIDEO_VSPULS_END));
writel(vmode->encp.vspuls_bline,
priv->io_base + _REG(ENCP_VIDEO_VSPULS_BLINE));
writel(vmode->encp.vspuls_eline,
priv->io_base + _REG(ENCP_VIDEO_VSPULS_ELINE));
if (vmode->encp.eqpuls_begin_present)
writel(vmode->encp.eqpuls_begin,
priv->io_base + _REG(ENCP_VIDEO_EQPULS_BEGIN));
if (vmode->encp.eqpuls_end_present)
writel(vmode->encp.eqpuls_end,
priv->io_base + _REG(ENCP_VIDEO_EQPULS_END));
if (vmode->encp.eqpuls_bline_present)
writel(vmode->encp.eqpuls_bline,
priv->io_base + _REG(ENCP_VIDEO_EQPULS_BLINE));
if (vmode->encp.eqpuls_eline_present)
writel(vmode->encp.eqpuls_eline,
priv->io_base + _REG(ENCP_VIDEO_EQPULS_ELINE));
writel(vmode->encp.havon_begin,
priv->io_base + _REG(ENCP_VIDEO_HAVON_BEGIN));
writel(vmode->encp.havon_end,
priv->io_base + _REG(ENCP_VIDEO_HAVON_END));
writel(vmode->encp.vavon_bline,
priv->io_base + _REG(ENCP_VIDEO_VAVON_BLINE));
writel(vmode->encp.vavon_eline,
priv->io_base + _REG(ENCP_VIDEO_VAVON_ELINE));
writel(vmode->encp.hso_begin,
priv->io_base + _REG(ENCP_VIDEO_HSO_BEGIN));
writel(vmode->encp.hso_end,
priv->io_base + _REG(ENCP_VIDEO_HSO_END));
writel(vmode->encp.vso_begin,
priv->io_base + _REG(ENCP_VIDEO_VSO_BEGIN));
writel(vmode->encp.vso_end,
priv->io_base + _REG(ENCP_VIDEO_VSO_END));
writel(vmode->encp.vso_bline,
priv->io_base + _REG(ENCP_VIDEO_VSO_BLINE));
if (vmode->encp.vso_eline_present)
writel(vmode->encp.vso_eline,
priv->io_base + _REG(ENCP_VIDEO_VSO_ELINE));
if (vmode->encp.sy_val_present)
writel(vmode->encp.sy_val,
priv->io_base + _REG(ENCP_VIDEO_SY_VAL));
if (vmode->encp.sy2_val_present)
writel(vmode->encp.sy2_val,
priv->io_base + _REG(ENCP_VIDEO_SY2_VAL));
writel(vmode->encp.max_lncnt,
priv->io_base + _REG(ENCP_VIDEO_MAX_LNCNT));
writel(1, priv->io_base + _REG(ENCP_VIDEO_EN));
/* Set DE signal's polarity is active high */
writel_bits(ENCP_VIDEO_MODE_DE_V_HIGH,
ENCP_VIDEO_MODE_DE_V_HIGH,
priv->io_base + _REG(ENCP_VIDEO_MODE));
/* Program DE timing */
de_h_begin = modulo(readl(priv->io_base +
_REG(ENCP_VIDEO_HAVON_BEGIN))
+ venc_hdmi_latency,
total_pixels_venc);
de_h_end = modulo(de_h_begin + active_pixels_venc,
total_pixels_venc);
writel(de_h_begin,
priv->io_base + _REG(ENCP_DE_H_BEGIN));
writel(de_h_end,
priv->io_base + _REG(ENCP_DE_H_END));
/* Program DE timing for even field */
de_v_begin_even = readl(priv->io_base
+ _REG(ENCP_VIDEO_VAVON_BLINE));
if (mode->flags & DISPLAY_FLAGS_INTERLACED)
de_v_end_even = de_v_begin_even +
(mode->vactive.typ / 2);
else
de_v_end_even = de_v_begin_even + mode->vactive.typ;
writel(de_v_begin_even,
priv->io_base + _REG(ENCP_DE_V_BEGIN_EVEN));
writel(de_v_end_even,
priv->io_base + _REG(ENCP_DE_V_END_EVEN));
/* Program DE timing for odd field if needed */
if (mode->flags & DISPLAY_FLAGS_INTERLACED) {
unsigned int ofld_voav_ofst =
readl(priv->io_base +
_REG(ENCP_VIDEO_OFLD_VOAV_OFST));
de_v_begin_odd = to_signed((ofld_voav_ofst & 0xf0) >> 4)
+ de_v_begin_even
+ ((mode->vfront_porch.typ +
mode->vactive.typ +
mode->vsync_len.typ - 1) / 2);
de_v_end_odd = de_v_begin_odd + (mode->vactive.typ / 2);
writel(de_v_begin_odd,
priv->io_base + _REG(ENCP_DE_V_BEGIN_ODD));
writel(de_v_end_odd,
priv->io_base + _REG(ENCP_DE_V_END_ODD));
}
/* Program Hsync timing */
if ((de_h_end + front_porch_venc) >= total_pixels_venc) {
hs_begin = de_h_end
+ front_porch_venc
- total_pixels_venc;
vs_adjust = 1;
} else {
hs_begin = de_h_end
+ front_porch_venc;
vs_adjust = 0;
}
hs_end = modulo(hs_begin + hsync_pixels_venc,
total_pixels_venc);
writel(hs_begin,
priv->io_base + _REG(ENCP_DVI_HSO_BEGIN));
writel(hs_end,
priv->io_base + _REG(ENCP_DVI_HSO_END));
/* Program Vsync timing for even field */
if (de_v_begin_even >=
(sof_lines + vsync_lines + (1 - vs_adjust)))
vs_bline_evn = de_v_begin_even
- sof_lines
- vsync_lines
- (1 - vs_adjust);
else
vs_bline_evn = (mode->vfront_porch.typ +
mode->vactive.typ +
mode->vsync_len.typ) +
+ de_v_begin_even
- sof_lines
- vsync_lines
- (1 - vs_adjust);
vs_eline_evn = modulo(vs_bline_evn + vsync_lines,
mode->hfront_porch.typ +
mode->hactive.typ +
mode->hsync_len.typ);
writel(vs_bline_evn,
priv->io_base + _REG(ENCP_DVI_VSO_BLINE_EVN));
writel(vs_eline_evn,
priv->io_base + _REG(ENCP_DVI_VSO_ELINE_EVN));
vso_begin_evn = hs_begin;
writel(vso_begin_evn,
priv->io_base + _REG(ENCP_DVI_VSO_BEGIN_EVN));
writel(vso_begin_evn,
priv->io_base + _REG(ENCP_DVI_VSO_END_EVN));
/* Program Vsync timing for odd field if needed */
if (mode->flags & DISPLAY_FLAGS_INTERLACED) {
vs_bline_odd = (de_v_begin_odd - 1)
- sof_lines
- vsync_lines;
vs_eline_odd = (de_v_begin_odd - 1)
- vsync_lines;
vso_begin_odd = modulo(hs_begin
+ (total_pixels_venc >> 1),
total_pixels_venc);
writel(vs_bline_odd,
priv->io_base + _REG(ENCP_DVI_VSO_BLINE_ODD));
writel(vs_eline_odd,
priv->io_base + _REG(ENCP_DVI_VSO_ELINE_ODD));
writel(vso_begin_odd,
priv->io_base + _REG(ENCP_DVI_VSO_BEGIN_ODD));
writel(vso_begin_odd,
priv->io_base + _REG(ENCP_DVI_VSO_END_ODD));
}
/* Select ENCP for VIU */
meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCP);
}
/* Set VPU HDMI setting */
/* Select ENCP or ENCI data to HDMI */
if (use_enci)
reg = VPU_HDMI_ENCI_DATA_TO_HDMI;
else
reg = VPU_HDMI_ENCP_DATA_TO_HDMI;
/* Invert polarity of HSYNC from VENC */
if (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH)
reg |= VPU_HDMI_INV_HSYNC;
/* Invert polarity of VSYNC from VENC */
if (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH)
reg |= VPU_HDMI_INV_VSYNC;
/* Output data format: CbYCr */
reg |= VPU_HDMI_OUTPUT_CBYCR;
/*
* Write rate to the async FIFO between VENC and HDMI.
* One write every 2 wr_clk.
*/
if (venc_repeat)
reg |= VPU_HDMI_WR_RATE(2);
/*
* Read rate to the async FIFO between VENC and HDMI.
* One read every 2 wr_clk.
*/
if (hdmi_repeat)
reg |= VPU_HDMI_RD_RATE(2);
writel(reg, priv->io_base + _REG(VPU_HDMI_SETTING));
}
static void meson_venci_cvbs_mode_set(struct meson_vpu_priv *priv,
struct meson_cvbs_enci_mode *mode)
{
u32 reg;
/* CVBS Filter settings */
writel(ENCI_CFILT_CMPT_SEL_HIGH | 0x10,
priv->io_base + _REG(ENCI_CFILT_CTRL));
writel(ENCI_CFILT_CMPT_CR_DLY(2) |
ENCI_CFILT_CMPT_CB_DLY(1),
priv->io_base + _REG(ENCI_CFILT_CTRL2));
/* Digital Video Select : Interlace, clk27 clk, external */
writel(0, priv->io_base + _REG(VENC_DVI_SETTING));
/* Reset Video Mode */
writel(0, priv->io_base + _REG(ENCI_VIDEO_MODE));
writel(0, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
/* Horizontal sync signal output */
writel(mode->hso_begin,
priv->io_base + _REG(ENCI_SYNC_HSO_BEGIN));
writel(mode->hso_end,
priv->io_base + _REG(ENCI_SYNC_HSO_END));
/* Vertical Sync lines */
writel(mode->vso_even,
priv->io_base + _REG(ENCI_SYNC_VSO_EVNLN));
writel(mode->vso_odd,
priv->io_base + _REG(ENCI_SYNC_VSO_ODDLN));
/* Macrovision max amplitude change */
writel(ENCI_MACV_MAX_AMP_ENABLE_CHANGE |
ENCI_MACV_MAX_AMP_VAL(mode->macv_max_amp),
priv->io_base + _REG(ENCI_MACV_MAX_AMP));
/* Video mode */
writel(mode->video_prog_mode,
priv->io_base + _REG(VENC_VIDEO_PROG_MODE));
writel(mode->video_mode,
priv->io_base + _REG(ENCI_VIDEO_MODE));
/*
* Advanced Video Mode :
* Demux shifting 0x2
* Blank line end at line17/22
* High bandwidth Luma Filter
* Low bandwidth Chroma Filter
* Bypass luma low pass filter
* No macrovision on CSYNC
*/
writel(ENCI_VIDEO_MODE_ADV_DMXMD(2) |
ENCI_VIDEO_MODE_ADV_VBICTL_LINE_17_22 |
ENCI_VIDEO_MODE_ADV_YBW_HIGH,
priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
writel(mode->sch_adjust, priv->io_base + _REG(ENCI_VIDEO_SCH));
/* Sync mode : MASTER Master mode, free run, send HSO/VSO out */
writel(0x07, priv->io_base + _REG(ENCI_SYNC_MODE));
/* 0x3 Y, C, and Component Y delay */
writel(mode->yc_delay, priv->io_base + _REG(ENCI_YC_DELAY));
/* Timings */
writel(mode->pixel_start,
priv->io_base + _REG(ENCI_VFIFO2VD_PIXEL_START));
writel(mode->pixel_end,
priv->io_base + _REG(ENCI_VFIFO2VD_PIXEL_END));
writel(mode->top_field_line_start,
priv->io_base + _REG(ENCI_VFIFO2VD_LINE_TOP_START));
writel(mode->top_field_line_end,
priv->io_base + _REG(ENCI_VFIFO2VD_LINE_TOP_END));
writel(mode->bottom_field_line_start,
priv->io_base + _REG(ENCI_VFIFO2VD_LINE_BOT_START));
writel(mode->bottom_field_line_end,
priv->io_base + _REG(ENCI_VFIFO2VD_LINE_BOT_END));
/* Internal Venc, Internal VIU Sync, Internal Vencoder */
writel(0, priv->io_base + _REG(VENC_SYNC_ROUTE));
/* UNreset Interlaced TV Encoder */
writel(0, priv->io_base + _REG(ENCI_DBG_PX_RST));
/*
* Enable Vfifo2vd and set Y_Cb_Y_Cr:
* Corresponding value:
* Y => 00 or 10
* Cb => 01
* Cr => 11
* Ex: 0x4e => 01001110 would mean Cb/Y/Cr/Y
*/
writel(ENCI_VFIFO2VD_CTL_ENABLE |
ENCI_VFIFO2VD_CTL_VD_SEL(0x4e),
priv->io_base + _REG(ENCI_VFIFO2VD_CTL));
/* Power UP Dacs */
writel(0, priv->io_base + _REG(VENC_VDAC_SETTING));
/* Video Upsampling */
/*
* CTRL0, CTRL1 and CTRL2:
* Filter0: input data sample every 2 cloks
* Filter1: filtering and upsample enable
*/
reg = VENC_UPSAMPLE_CTRL_F0_2_CLK_RATIO | VENC_UPSAMPLE_CTRL_F1_EN |
VENC_UPSAMPLE_CTRL_F1_UPSAMPLE_EN;
/*
* Upsample CTRL0:
* Interlace High Bandwidth Luma
*/
writel(VENC_UPSAMPLE_CTRL_INTERLACE_HIGH_LUMA | reg,
priv->io_base + _REG(VENC_UPSAMPLE_CTRL0));
/*
* Upsample CTRL1:
* Interlace Pb
*/
writel(VENC_UPSAMPLE_CTRL_INTERLACE_PB | reg,
priv->io_base + _REG(VENC_UPSAMPLE_CTRL1));
/*
* Upsample CTRL2:
* Interlace R
*/
writel(VENC_UPSAMPLE_CTRL_INTERLACE_PR | reg,
priv->io_base + _REG(VENC_UPSAMPLE_CTRL2));
/* Select Interlace Y DACs */
writel(0, priv->io_base + _REG(VENC_VDAC_DACSEL0));
writel(0, priv->io_base + _REG(VENC_VDAC_DACSEL1));
writel(0, priv->io_base + _REG(VENC_VDAC_DACSEL2));
writel(0, priv->io_base + _REG(VENC_VDAC_DACSEL3));
writel(0, priv->io_base + _REG(VENC_VDAC_DACSEL4));
writel(0, priv->io_base + _REG(VENC_VDAC_DACSEL5));
/* Select ENCI for VIU */
meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCI);
/* Enable ENCI FIFO */
writel(VENC_VDAC_FIFO_EN_ENCI_ENABLE,
priv->io_base + _REG(VENC_VDAC_FIFO_CTRL));
/* Select ENCI DACs 0, 1, 4, and 5 */
writel(0x11, priv->io_base + _REG(ENCI_DACSEL_0));
writel(0x11, priv->io_base + _REG(ENCI_DACSEL_1));
/* Interlace video enable */
writel(ENCI_VIDEO_EN_ENABLE,
priv->io_base + _REG(ENCI_VIDEO_EN));
/* Configure Video Saturation / Contrast / Brightness / Hue */
writel(mode->video_saturation,
priv->io_base + _REG(ENCI_VIDEO_SAT));
writel(mode->video_contrast,
priv->io_base + _REG(ENCI_VIDEO_CONT));
writel(mode->video_brightness,
priv->io_base + _REG(ENCI_VIDEO_BRIGHT));
writel(mode->video_hue,
priv->io_base + _REG(ENCI_VIDEO_HUE));
/* Enable DAC0 Filter */
writel(VENC_VDAC_DAC0_FILT_CTRL0_EN,
priv->io_base + _REG(VENC_VDAC_DAC0_FILT_CTRL0));
writel(0xfc48, priv->io_base + _REG(VENC_VDAC_DAC0_FILT_CTRL1));
/* 0 in Macrovision register 0 */
writel(0, priv->io_base + _REG(ENCI_MACV_N0));
/* Analog Synchronization and color burst value adjust */
writel(mode->analog_sync_adj,
priv->io_base + _REG(ENCI_SYNC_ADJ));
/* enable VDAC */
writel_bits(VENC_VDAC_SEL_ATV_DMD, 0,
priv->io_base + _REG(VENC_VDAC_DACSEL0));
if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
hhi_write(HHI_VDAC_CNTL0, 1);
else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL) ||
meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM))
hhi_write(HHI_VDAC_CNTL0, 0xf0001);
else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
hhi_write(HHI_VDAC_CNTL0_G12A, 0x906001);
if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
hhi_write(HHI_VDAC_CNTL1_G12A, 0);
else
hhi_write(HHI_VDAC_CNTL1, 0);
}
void meson_vpu_setup_venc(struct udevice *dev,
const struct display_timing *mode, bool is_cvbs)
{
struct meson_vpu_priv *priv = dev_get_priv(dev);
if (is_cvbs)
return meson_venci_cvbs_mode_set(priv, &meson_cvbs_enci_pal);
meson_venc_hdmi_mode_set(priv, mode);
}