drm: meson: venc: use proper macros instead of magic constants

This patch add new macros which are used to set the following
registers:
- ENCI_CFILT_CTRL
- ENCI_CFILT_CTRL2
- ENCI_MACV_MAX_AMP
- ENCI_VIDEO_MODE_ADV
- ENCI_VFIFO2VD_CTL
- ENCI_VIDEO_EN
- ENCP_VIDEO_MODE
- VPU_HDMI_SETTING
- VENC_UPSAMPLE_CTRL0
- VENC_UPSAMPLE_CTRL1
- VENC_UPSAMPLE_CTRL2
- VENC_VDAC_FIFO_CTRL
- VENC_VDAC_DAC0_FILT_CTRL0
- VENC_INTCTRL

Signed-off-by: Julien Masson <jmasson@baylibre.com>
Reviewed-by: Neil Armstrong <narmstrong@baylibre.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Link: https://patchwork.freedesktop.org/patch/msgid/86r27j82ef.fsf@baylibre.com
This commit is contained in:
Julien Masson
2019-06-24 16:48:50 +02:00
committed by Neil Armstrong
parent 147ae1cbaa
commit 7eef9e6104
3 changed files with 177 additions and 32 deletions

View File

@@ -976,6 +976,7 @@ void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic,
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 & DRM_MODE_FLAG_DBLCLK) {
@@ -1048,8 +1049,11 @@ void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic,
unsigned int lines_f1;
/* CVBS Filter settings */
writel_relaxed(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL));
writel_relaxed(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL2));
writel_relaxed(ENCI_CFILT_CMPT_SEL_HIGH | 0x10,
priv->io_base + _REG(ENCI_CFILT_CTRL));
writel_relaxed(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_relaxed(0, priv->io_base + _REG(VENC_DVI_SETTING));
@@ -1071,8 +1075,9 @@ void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic,
priv->io_base + _REG(ENCI_SYNC_VSO_ODDLN));
/* Macrovision max amplitude change */
writel_relaxed(vmode->enci.macv_max_amp,
priv->io_base + _REG(ENCI_MACV_MAX_AMP));
writel_relaxed(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_relaxed(vmode->enci.video_prog_mode,
@@ -1088,7 +1093,10 @@ void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic,
* Bypass luma low pass filter
* No macrovision on CSYNC
*/
writel_relaxed(0x26, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
writel_relaxed(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));
@@ -1104,8 +1112,17 @@ void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic,
/* UNreset Interlaced TV Encoder */
writel_relaxed(0, priv->io_base + _REG(ENCI_DBG_PX_RST));
/* Enable Vfifo2vd, Y_Cb_Y_Cr select */
writel_relaxed(0x4e01, priv->io_base + _REG(ENCI_VFIFO2VD_CTL));
/*
* 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_relaxed(ENCI_VFIFO2VD_CTL_ENABLE |
ENCI_VFIFO2VD_CTL_VD_SEL(0x4e),
priv->io_base + _REG(ENCI_VFIFO2VD_CTL));
/* Timings */
writel_relaxed(vmode->enci.pixel_start,
@@ -1127,7 +1144,8 @@ void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic,
meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCI);
/* Interlace video enable */
writel_relaxed(1, priv->io_base + _REG(ENCI_VIDEO_EN));
writel_relaxed(ENCI_VIDEO_EN_ENABLE,
priv->io_base + _REG(ENCI_VIDEO_EN));
lines_f0 = mode->vtotal >> 1;
lines_f1 = lines_f0 + 1;
@@ -1374,7 +1392,8 @@ void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic,
writel_relaxed(1, priv->io_base + _REG(ENCP_VIDEO_EN));
/* Set DE signals polarity is active high */
writel_bits_relaxed(BIT(14), BIT(14),
writel_bits_relaxed(ENCP_VIDEO_MODE_DE_V_HIGH,
ENCP_VIDEO_MODE_DE_V_HIGH,
priv->io_base + _REG(ENCP_VIDEO_MODE));
/* Program DE timing */
@@ -1493,13 +1512,39 @@ void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic,
meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCP);
}
writel_relaxed((use_enci ? 1 : 2) |
(mode->flags & DRM_MODE_FLAG_PHSYNC ? 1 << 2 : 0) |
(mode->flags & DRM_MODE_FLAG_PVSYNC ? 1 << 3 : 0) |
4 << 5 |
(venc_repeat ? 1 << 8 : 0) |
(hdmi_repeat ? 1 << 12 : 0),
priv->io_base + _REG(VPU_HDMI_SETTING));
/* 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 & DRM_MODE_FLAG_PHSYNC)
reg |= VPU_HDMI_INV_HSYNC;
/* Invert polarity of VSYNC from VENC */
if (mode->flags & DRM_MODE_FLAG_PVSYNC)
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_relaxed(reg, priv->io_base + _REG(VPU_HDMI_SETTING));
priv->venc.hdmi_repeat = hdmi_repeat;
priv->venc.venc_repeat = venc_repeat;
@@ -1512,12 +1557,17 @@ EXPORT_SYMBOL_GPL(meson_venc_hdmi_mode_set);
void meson_venci_cvbs_mode_set(struct meson_drm *priv,
struct meson_cvbs_enci_mode *mode)
{
u32 reg;
if (mode->mode_tag == priv->venc.current_mode)
return;
/* CVBS Filter settings */
writel_relaxed(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL));
writel_relaxed(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL2));
writel_relaxed(ENCI_CFILT_CMPT_SEL_HIGH | 0x10,
priv->io_base + _REG(ENCI_CFILT_CTRL));
writel_relaxed(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_relaxed(0, priv->io_base + _REG(VENC_DVI_SETTING));
@@ -1539,8 +1589,9 @@ void meson_venci_cvbs_mode_set(struct meson_drm *priv,
priv->io_base + _REG(ENCI_SYNC_VSO_ODDLN));
/* Macrovision max amplitude change */
writel_relaxed(0x8100 + mode->macv_max_amp,
priv->io_base + _REG(ENCI_MACV_MAX_AMP));
writel_relaxed(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_relaxed(mode->video_prog_mode,
@@ -1556,7 +1607,10 @@ void meson_venci_cvbs_mode_set(struct meson_drm *priv,
* Bypass luma low pass filter
* No macrovision on CSYNC
*/
writel_relaxed(0x26, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
writel_relaxed(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));
@@ -1588,16 +1642,50 @@ void meson_venci_cvbs_mode_set(struct meson_drm *priv,
/* UNreset Interlaced TV Encoder */
writel_relaxed(0, priv->io_base + _REG(ENCI_DBG_PX_RST));
/* Enable Vfifo2vd, Y_Cb_Y_Cr select */
writel_relaxed(0x4e01, priv->io_base + _REG(ENCI_VFIFO2VD_CTL));
/*
* 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_relaxed(ENCI_VFIFO2VD_CTL_ENABLE |
ENCI_VFIFO2VD_CTL_VD_SEL(0x4e),
priv->io_base + _REG(ENCI_VFIFO2VD_CTL));
/* Power UP Dacs */
writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_SETTING));
/* Video Upsampling */
writel_relaxed(0x0061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL0));
writel_relaxed(0x4061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL1));
writel_relaxed(0x5061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL2));
/*
* 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_relaxed(VENC_UPSAMPLE_CTRL_INTERLACE_HIGH_LUMA | reg,
priv->io_base + _REG(VENC_UPSAMPLE_CTRL0));
/*
* Upsample CTRL1:
* Interlace Pb
*/
writel_relaxed(VENC_UPSAMPLE_CTRL_INTERLACE_PB | reg,
priv->io_base + _REG(VENC_UPSAMPLE_CTRL1));
/*
* Upsample CTRL2:
* Interlace R
*/
writel_relaxed(VENC_UPSAMPLE_CTRL_INTERLACE_PR | reg,
priv->io_base + _REG(VENC_UPSAMPLE_CTRL2));
/* Select Interlace Y DACs */
writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL0));
@@ -1611,14 +1699,16 @@ void meson_venci_cvbs_mode_set(struct meson_drm *priv,
meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCI);
/* Enable ENCI FIFO */
writel_relaxed(0x2000, priv->io_base + _REG(VENC_VDAC_FIFO_CTRL));
writel_relaxed(VENC_VDAC_FIFO_EN_ENCI_ENABLE,
priv->io_base + _REG(VENC_VDAC_FIFO_CTRL));
/* Select ENCI DACs 0, 1, 4, and 5 */
writel_relaxed(0x11, priv->io_base + _REG(ENCI_DACSEL_0));
writel_relaxed(0x11, priv->io_base + _REG(ENCI_DACSEL_1));
/* Interlace video enable */
writel_relaxed(1, priv->io_base + _REG(ENCI_VIDEO_EN));
writel_relaxed(ENCI_VIDEO_EN_ENABLE,
priv->io_base + _REG(ENCI_VIDEO_EN));
/* Configure Video Saturation / Contrast / Brightness / Hue */
writel_relaxed(mode->video_saturation,
@@ -1631,7 +1721,8 @@ void meson_venci_cvbs_mode_set(struct meson_drm *priv,
priv->io_base + _REG(ENCI_VIDEO_HUE));
/* Enable DAC0 Filter */
writel_relaxed(0x1, priv->io_base + _REG(VENC_VDAC_DAC0_FILT_CTRL0));
writel_relaxed(VENC_VDAC_DAC0_FILT_CTRL0_EN,
priv->io_base + _REG(VENC_VDAC_DAC0_FILT_CTRL0));
writel_relaxed(0xfc48, priv->io_base + _REG(VENC_VDAC_DAC0_FILT_CTRL1));
/* 0 in Macrovision register 0 */
@@ -1652,7 +1743,8 @@ unsigned int meson_venci_get_field(struct meson_drm *priv)
void meson_venc_enable_vsync(struct meson_drm *priv)
{
writel_relaxed(2, priv->io_base + _REG(VENC_INTCTRL));
writel_relaxed(VENC_INTCTRL_ENCI_LNRST_INT_EN,
priv->io_base + _REG(VENC_INTCTRL));
regmap_update_bits(priv->hhi, HHI_GCLK_MPEG2, BIT(25), BIT(25));
}
@@ -1680,7 +1772,8 @@ void meson_venc_init(struct meson_drm *priv)
regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0);
/* Disable HDMI */
writel_bits_relaxed(0x3, 0,
writel_bits_relaxed(VPU_HDMI_ENCI_DATA_TO_HDMI |
VPU_HDMI_ENCP_DATA_TO_HDMI, 0,
priv->io_base + _REG(VPU_HDMI_SETTING));
/* Disable all encoders */