Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright (C) 2016 BayLibre, SAS
0004  * Author: Neil Armstrong <narmstrong@baylibre.com>
0005  * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
0006  * Copyright (C) 2014 Endless Mobile
0007  */
0008 
0009 #include <linux/export.h>
0010 #include <linux/bitfield.h>
0011 
0012 #include <drm/drm_fourcc.h>
0013 
0014 #include "meson_drv.h"
0015 #include "meson_viu.h"
0016 #include "meson_registers.h"
0017 
0018 /**
0019  * DOC: Video Input Unit
0020  *
0021  * VIU Handles the Pixel scanout and the basic Colorspace conversions
0022  * We handle the following features :
0023  *
0024  * - OSD1 RGB565/RGB888/xRGB8888 scanout
0025  * - RGB conversion to x/cb/cr
0026  * - Progressive or Interlace buffer scanout
0027  * - OSD1 Commit on Vsync
0028  * - HDR OSD matrix for GXL/GXM
0029  *
0030  * What is missing :
0031  *
0032  * - BGR888/xBGR8888/BGRx8888/BGRx8888 modes
0033  * - YUV4:2:2 Y0CbY1Cr scanout
0034  * - Conversion to YUV 4:4:4 from 4:2:2 input
0035  * - Colorkey Alpha matching
0036  * - Big endian scanout
0037  * - X/Y reverse scanout
0038  * - Global alpha setup
0039  * - OSD2 support, would need interlace switching on vsync
0040  * - OSD1 full scaling to support TV overscan
0041  */
0042 
0043 /* OSD csc defines */
0044 
0045 enum viu_matrix_sel_e {
0046     VIU_MATRIX_OSD_EOTF = 0,
0047     VIU_MATRIX_OSD,
0048 };
0049 
0050 enum viu_lut_sel_e {
0051     VIU_LUT_OSD_EOTF = 0,
0052     VIU_LUT_OSD_OETF,
0053 };
0054 
0055 #define COEFF_NORM(a) ((int)((((a) * 2048.0) + 1) / 2))
0056 #define MATRIX_5X3_COEF_SIZE 24
0057 
0058 #define EOTF_COEFF_NORM(a) ((int)((((a) * 4096.0) + 1) / 2))
0059 #define EOTF_COEFF_SIZE 10
0060 #define EOTF_COEFF_RIGHTSHIFT 1
0061 
0062 static int RGB709_to_YUV709l_coeff[MATRIX_5X3_COEF_SIZE] = {
0063     0, 0, 0, /* pre offset */
0064     COEFF_NORM(0.181873),   COEFF_NORM(0.611831),   COEFF_NORM(0.061765),
0065     COEFF_NORM(-0.100251),  COEFF_NORM(-0.337249),  COEFF_NORM(0.437500),
0066     COEFF_NORM(0.437500),   COEFF_NORM(-0.397384),  COEFF_NORM(-0.040116),
0067     0, 0, 0, /* 10'/11'/12' */
0068     0, 0, 0, /* 20'/21'/22' */
0069     64, 512, 512, /* offset */
0070     0, 0, 0 /* mode, right_shift, clip_en */
0071 };
0072 
0073 /*  eotf matrix: bypass */
0074 static int eotf_bypass_coeff[EOTF_COEFF_SIZE] = {
0075     EOTF_COEFF_NORM(1.0),   EOTF_COEFF_NORM(0.0),   EOTF_COEFF_NORM(0.0),
0076     EOTF_COEFF_NORM(0.0),   EOTF_COEFF_NORM(1.0),   EOTF_COEFF_NORM(0.0),
0077     EOTF_COEFF_NORM(0.0),   EOTF_COEFF_NORM(0.0),   EOTF_COEFF_NORM(1.0),
0078     EOTF_COEFF_RIGHTSHIFT /* right shift */
0079 };
0080 
0081 static void meson_viu_set_g12a_osd1_matrix(struct meson_drm *priv,
0082                        int *m, bool csc_on)
0083 {
0084     /* VPP WRAP OSD1 matrix */
0085     writel(((m[0] & 0xfff) << 16) | (m[1] & 0xfff),
0086         priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET0_1));
0087     writel(m[2] & 0xfff,
0088         priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET2));
0089     writel(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff),
0090         priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF00_01));
0091     writel(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff),
0092         priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF02_10));
0093     writel(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff),
0094         priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF11_12));
0095     writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff),
0096         priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF20_21));
0097     writel((m[11] & 0x1fff),
0098         priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF22));
0099 
0100     writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff),
0101         priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET0_1));
0102     writel(m[20] & 0xfff,
0103         priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET2));
0104 
0105     writel_bits_relaxed(BIT(0), csc_on ? BIT(0) : 0,
0106         priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL));
0107 }
0108 
0109 static void meson_viu_set_osd_matrix(struct meson_drm *priv,
0110                      enum viu_matrix_sel_e m_select,
0111                   int *m, bool csc_on)
0112 {
0113     if (m_select == VIU_MATRIX_OSD) {
0114         /* osd matrix, VIU_MATRIX_0 */
0115         writel(((m[0] & 0xfff) << 16) | (m[1] & 0xfff),
0116             priv->io_base + _REG(VIU_OSD1_MATRIX_PRE_OFFSET0_1));
0117         writel(m[2] & 0xfff,
0118             priv->io_base + _REG(VIU_OSD1_MATRIX_PRE_OFFSET2));
0119         writel(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff),
0120             priv->io_base + _REG(VIU_OSD1_MATRIX_COEF00_01));
0121         writel(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff),
0122             priv->io_base + _REG(VIU_OSD1_MATRIX_COEF02_10));
0123         writel(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff),
0124             priv->io_base + _REG(VIU_OSD1_MATRIX_COEF11_12));
0125         writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff),
0126             priv->io_base + _REG(VIU_OSD1_MATRIX_COEF20_21));
0127 
0128         if (m[21]) {
0129             writel(((m[11] & 0x1fff) << 16) | (m[12] & 0x1fff),
0130                 priv->io_base +
0131                     _REG(VIU_OSD1_MATRIX_COEF22_30));
0132             writel(((m[13] & 0x1fff) << 16) | (m[14] & 0x1fff),
0133                 priv->io_base +
0134                     _REG(VIU_OSD1_MATRIX_COEF31_32));
0135             writel(((m[15] & 0x1fff) << 16) | (m[16] & 0x1fff),
0136                 priv->io_base +
0137                     _REG(VIU_OSD1_MATRIX_COEF40_41));
0138             writel(m[17] & 0x1fff, priv->io_base +
0139                 _REG(VIU_OSD1_MATRIX_COLMOD_COEF42));
0140         } else
0141             writel((m[11] & 0x1fff) << 16, priv->io_base +
0142                 _REG(VIU_OSD1_MATRIX_COEF22_30));
0143 
0144         writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff),
0145             priv->io_base + _REG(VIU_OSD1_MATRIX_OFFSET0_1));
0146         writel(m[20] & 0xfff,
0147             priv->io_base + _REG(VIU_OSD1_MATRIX_OFFSET2));
0148 
0149         writel_bits_relaxed(3 << 30, m[21] << 30,
0150             priv->io_base + _REG(VIU_OSD1_MATRIX_COLMOD_COEF42));
0151         writel_bits_relaxed(7 << 16, m[22] << 16,
0152             priv->io_base + _REG(VIU_OSD1_MATRIX_COLMOD_COEF42));
0153 
0154         /* 23 reserved for clipping control */
0155         writel_bits_relaxed(BIT(0), csc_on ? BIT(0) : 0,
0156             priv->io_base + _REG(VIU_OSD1_MATRIX_CTRL));
0157         writel_bits_relaxed(BIT(1), 0,
0158             priv->io_base + _REG(VIU_OSD1_MATRIX_CTRL));
0159     } else if (m_select == VIU_MATRIX_OSD_EOTF) {
0160         int i;
0161 
0162         /* osd eotf matrix, VIU_MATRIX_OSD_EOTF */
0163         for (i = 0; i < 5; i++)
0164             writel(((m[i * 2] & 0x1fff) << 16) |
0165                 (m[i * 2 + 1] & 0x1fff), priv->io_base +
0166                 _REG(VIU_OSD1_EOTF_CTL + i + 1));
0167 
0168         writel_bits_relaxed(BIT(30), csc_on ? BIT(30) : 0,
0169             priv->io_base + _REG(VIU_OSD1_EOTF_CTL));
0170         writel_bits_relaxed(BIT(31), csc_on ? BIT(31) : 0,
0171             priv->io_base + _REG(VIU_OSD1_EOTF_CTL));
0172     }
0173 }
0174 
0175 #define OSD_EOTF_LUT_SIZE 33
0176 #define OSD_OETF_LUT_SIZE 41
0177 
0178 static void
0179 meson_viu_set_osd_lut(struct meson_drm *priv, enum viu_lut_sel_e lut_sel,
0180               unsigned int *r_map, unsigned int *g_map,
0181               unsigned int *b_map, bool csc_on)
0182 {
0183     unsigned int addr_port;
0184     unsigned int data_port;
0185     unsigned int ctrl_port;
0186     int i;
0187 
0188     if (lut_sel == VIU_LUT_OSD_EOTF) {
0189         addr_port = VIU_OSD1_EOTF_LUT_ADDR_PORT;
0190         data_port = VIU_OSD1_EOTF_LUT_DATA_PORT;
0191         ctrl_port = VIU_OSD1_EOTF_CTL;
0192     } else if (lut_sel == VIU_LUT_OSD_OETF) {
0193         addr_port = VIU_OSD1_OETF_LUT_ADDR_PORT;
0194         data_port = VIU_OSD1_OETF_LUT_DATA_PORT;
0195         ctrl_port = VIU_OSD1_OETF_CTL;
0196     } else
0197         return;
0198 
0199     if (lut_sel == VIU_LUT_OSD_OETF) {
0200         writel(0, priv->io_base + _REG(addr_port));
0201 
0202         for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++)
0203             writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16),
0204                 priv->io_base + _REG(data_port));
0205 
0206         writel(r_map[OSD_OETF_LUT_SIZE - 1] | (g_map[0] << 16),
0207             priv->io_base + _REG(data_port));
0208 
0209         for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++)
0210             writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16),
0211                 priv->io_base + _REG(data_port));
0212 
0213         for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++)
0214             writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16),
0215                 priv->io_base + _REG(data_port));
0216 
0217         writel(b_map[OSD_OETF_LUT_SIZE - 1],
0218             priv->io_base + _REG(data_port));
0219 
0220         if (csc_on)
0221             writel_bits_relaxed(0x7 << 29, 7 << 29,
0222                         priv->io_base + _REG(ctrl_port));
0223         else
0224             writel_bits_relaxed(0x7 << 29, 0,
0225                         priv->io_base + _REG(ctrl_port));
0226     } else if (lut_sel == VIU_LUT_OSD_EOTF) {
0227         writel(0, priv->io_base + _REG(addr_port));
0228 
0229         for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++)
0230             writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16),
0231                 priv->io_base + _REG(data_port));
0232 
0233         writel(r_map[OSD_EOTF_LUT_SIZE - 1] | (g_map[0] << 16),
0234             priv->io_base + _REG(data_port));
0235 
0236         for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++)
0237             writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16),
0238                 priv->io_base + _REG(data_port));
0239 
0240         for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++)
0241             writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16),
0242                 priv->io_base + _REG(data_port));
0243 
0244         writel(b_map[OSD_EOTF_LUT_SIZE - 1],
0245             priv->io_base + _REG(data_port));
0246 
0247         if (csc_on)
0248             writel_bits_relaxed(7 << 27, 7 << 27,
0249                         priv->io_base + _REG(ctrl_port));
0250         else
0251             writel_bits_relaxed(7 << 27, 0,
0252                         priv->io_base + _REG(ctrl_port));
0253 
0254         writel_bits_relaxed(BIT(31), BIT(31),
0255                     priv->io_base + _REG(ctrl_port));
0256     }
0257 }
0258 
0259 /* eotf lut: linear */
0260 static unsigned int eotf_33_linear_mapping[OSD_EOTF_LUT_SIZE] = {
0261     0x0000, 0x0200, 0x0400, 0x0600,
0262     0x0800, 0x0a00, 0x0c00, 0x0e00,
0263     0x1000, 0x1200, 0x1400, 0x1600,
0264     0x1800, 0x1a00, 0x1c00, 0x1e00,
0265     0x2000, 0x2200, 0x2400, 0x2600,
0266     0x2800, 0x2a00, 0x2c00, 0x2e00,
0267     0x3000, 0x3200, 0x3400, 0x3600,
0268     0x3800, 0x3a00, 0x3c00, 0x3e00,
0269     0x4000
0270 };
0271 
0272 /* osd oetf lut: linear */
0273 static unsigned int oetf_41_linear_mapping[OSD_OETF_LUT_SIZE] = {
0274     0, 0, 0, 0,
0275     0, 32, 64, 96,
0276     128, 160, 196, 224,
0277     256, 288, 320, 352,
0278     384, 416, 448, 480,
0279     512, 544, 576, 608,
0280     640, 672, 704, 736,
0281     768, 800, 832, 864,
0282     896, 928, 960, 992,
0283     1023, 1023, 1023, 1023,
0284     1023
0285 };
0286 
0287 static void meson_viu_load_matrix(struct meson_drm *priv)
0288 {
0289     /* eotf lut bypass */
0290     meson_viu_set_osd_lut(priv, VIU_LUT_OSD_EOTF,
0291                   eotf_33_linear_mapping, /* R */
0292                   eotf_33_linear_mapping, /* G */
0293                   eotf_33_linear_mapping, /* B */
0294                   false);
0295 
0296     /* eotf matrix bypass */
0297     meson_viu_set_osd_matrix(priv, VIU_MATRIX_OSD_EOTF,
0298                  eotf_bypass_coeff,
0299                  false);
0300 
0301     /* oetf lut bypass */
0302     meson_viu_set_osd_lut(priv, VIU_LUT_OSD_OETF,
0303                   oetf_41_linear_mapping, /* R */
0304                   oetf_41_linear_mapping, /* G */
0305                   oetf_41_linear_mapping, /* B */
0306                   false);
0307 
0308     /* osd matrix RGB709 to YUV709 limit */
0309     meson_viu_set_osd_matrix(priv, VIU_MATRIX_OSD,
0310                  RGB709_to_YUV709l_coeff,
0311                  true);
0312 }
0313 
0314 /* VIU OSD1 Reset as workaround for GXL+ Alpha OSD Bug */
0315 void meson_viu_osd1_reset(struct meson_drm *priv)
0316 {
0317     uint32_t osd1_fifo_ctrl_stat, osd1_ctrl_stat2;
0318 
0319     /* Save these 2 registers state */
0320     osd1_fifo_ctrl_stat = readl_relaxed(
0321                 priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT));
0322     osd1_ctrl_stat2 = readl_relaxed(
0323                 priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
0324 
0325     /* Reset OSD1 */
0326     writel_bits_relaxed(VIU_SW_RESET_OSD1, VIU_SW_RESET_OSD1,
0327                 priv->io_base + _REG(VIU_SW_RESET));
0328     writel_bits_relaxed(VIU_SW_RESET_OSD1, 0,
0329                 priv->io_base + _REG(VIU_SW_RESET));
0330 
0331     /* Rewrite these registers state lost in the reset */
0332     writel_relaxed(osd1_fifo_ctrl_stat,
0333                priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT));
0334     writel_relaxed(osd1_ctrl_stat2,
0335                priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
0336 
0337     /* Reload the conversion matrix */
0338     meson_viu_load_matrix(priv);
0339 }
0340 
0341 #define OSD1_MALI_ORDER_ABGR                \
0342     (FIELD_PREP(VIU_OSD1_MALI_AFBCD_A_REORDER,  \
0343             VIU_OSD1_MALI_REORDER_A) |      \
0344      FIELD_PREP(VIU_OSD1_MALI_AFBCD_B_REORDER,  \
0345             VIU_OSD1_MALI_REORDER_B) |      \
0346      FIELD_PREP(VIU_OSD1_MALI_AFBCD_G_REORDER,  \
0347             VIU_OSD1_MALI_REORDER_G) |      \
0348      FIELD_PREP(VIU_OSD1_MALI_AFBCD_R_REORDER,  \
0349             VIU_OSD1_MALI_REORDER_R))
0350 
0351 #define OSD1_MALI_ORDER_ARGB                \
0352     (FIELD_PREP(VIU_OSD1_MALI_AFBCD_A_REORDER,  \
0353             VIU_OSD1_MALI_REORDER_A) |      \
0354      FIELD_PREP(VIU_OSD1_MALI_AFBCD_B_REORDER,  \
0355             VIU_OSD1_MALI_REORDER_R) |      \
0356      FIELD_PREP(VIU_OSD1_MALI_AFBCD_G_REORDER,  \
0357             VIU_OSD1_MALI_REORDER_G) |      \
0358      FIELD_PREP(VIU_OSD1_MALI_AFBCD_R_REORDER,  \
0359             VIU_OSD1_MALI_REORDER_B))
0360 
0361 void meson_viu_g12a_enable_osd1_afbc(struct meson_drm *priv)
0362 {
0363     u32 afbc_order = OSD1_MALI_ORDER_ARGB;
0364 
0365     /* Enable Mali AFBC Unpack */
0366     writel_bits_relaxed(VIU_OSD1_MALI_UNPACK_EN,
0367                 VIU_OSD1_MALI_UNPACK_EN,
0368                 priv->io_base + _REG(VIU_OSD1_MALI_UNPACK_CTRL));
0369 
0370     switch (priv->afbcd.format) {
0371     case DRM_FORMAT_XBGR8888:
0372     case DRM_FORMAT_ABGR8888:
0373         afbc_order = OSD1_MALI_ORDER_ABGR;
0374         break;
0375     }
0376 
0377     /* Setup RGBA Reordering */
0378     writel_bits_relaxed(VIU_OSD1_MALI_AFBCD_A_REORDER |
0379                 VIU_OSD1_MALI_AFBCD_B_REORDER |
0380                 VIU_OSD1_MALI_AFBCD_G_REORDER |
0381                 VIU_OSD1_MALI_AFBCD_R_REORDER,
0382                 afbc_order,
0383                 priv->io_base + _REG(VIU_OSD1_MALI_UNPACK_CTRL));
0384 
0385     /* Select AFBCD path for OSD1 */
0386     writel_bits_relaxed(OSD_PATH_OSD_AXI_SEL_OSD1_AFBCD,
0387                 OSD_PATH_OSD_AXI_SEL_OSD1_AFBCD,
0388                 priv->io_base + _REG(OSD_PATH_MISC_CTRL));
0389 }
0390 
0391 void meson_viu_g12a_disable_osd1_afbc(struct meson_drm *priv)
0392 {
0393     /* Disable AFBCD path for OSD1 */
0394     writel_bits_relaxed(OSD_PATH_OSD_AXI_SEL_OSD1_AFBCD, 0,
0395                 priv->io_base + _REG(OSD_PATH_MISC_CTRL));
0396 
0397     /* Disable AFBCD unpack */
0398     writel_bits_relaxed(VIU_OSD1_MALI_UNPACK_EN, 0,
0399                 priv->io_base + _REG(VIU_OSD1_MALI_UNPACK_CTRL));
0400 }
0401 
0402 void meson_viu_gxm_enable_osd1_afbc(struct meson_drm *priv)
0403 {
0404     writel_bits_relaxed(MALI_AFBC_MISC, FIELD_PREP(MALI_AFBC_MISC, 0x90),
0405                 priv->io_base + _REG(VIU_MISC_CTRL1));
0406 }
0407 
0408 void meson_viu_gxm_disable_osd1_afbc(struct meson_drm *priv)
0409 {
0410     writel_bits_relaxed(MALI_AFBC_MISC, FIELD_PREP(MALI_AFBC_MISC, 0x00),
0411                 priv->io_base + _REG(VIU_MISC_CTRL1));
0412 }
0413 
0414 void meson_viu_init(struct meson_drm *priv)
0415 {
0416     uint32_t reg;
0417 
0418     /* Disable OSDs */
0419     writel_bits_relaxed(VIU_OSD1_OSD_BLK_ENABLE | VIU_OSD1_OSD_ENABLE, 0,
0420                 priv->io_base + _REG(VIU_OSD1_CTRL_STAT));
0421     writel_bits_relaxed(VIU_OSD1_OSD_BLK_ENABLE | VIU_OSD1_OSD_ENABLE, 0,
0422                 priv->io_base + _REG(VIU_OSD2_CTRL_STAT));
0423 
0424     /* On GXL/GXM, Use the 10bit HDR conversion matrix */
0425     if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
0426         meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
0427         meson_viu_load_matrix(priv);
0428     else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
0429         meson_viu_set_g12a_osd1_matrix(priv, RGB709_to_YUV709l_coeff,
0430                            true);
0431         /* fix green/pink color distortion from vendor u-boot */
0432         writel_bits_relaxed(OSD1_HDR2_CTRL_REG_ONLY_MAT |
0433                 OSD1_HDR2_CTRL_VDIN0_HDR2_TOP_EN, 0,
0434                 priv->io_base + _REG(OSD1_HDR2_CTRL));
0435     }
0436 
0437     /* Initialize OSD1 fifo control register */
0438     reg = VIU_OSD_DDR_PRIORITY_URGENT |
0439         VIU_OSD_HOLD_FIFO_LINES(31) |
0440         VIU_OSD_FIFO_DEPTH_VAL(32) | /* fifo_depth_val: 32*8=256 */
0441         VIU_OSD_WORDS_PER_BURST(4) | /* 4 words in 1 burst */
0442         VIU_OSD_FIFO_LIMITS(2);      /* fifo_lim: 2*16=32 */
0443 
0444     if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
0445         reg |= VIU_OSD_BURST_LENGTH_32;
0446     else
0447         reg |= VIU_OSD_BURST_LENGTH_64;
0448 
0449     writel_relaxed(reg, priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT));
0450     writel_relaxed(reg, priv->io_base + _REG(VIU_OSD2_FIFO_CTRL_STAT));
0451 
0452     /* Set OSD alpha replace value */
0453     writel_bits_relaxed(0xff << OSD_REPLACE_SHIFT,
0454                 0xff << OSD_REPLACE_SHIFT,
0455                 priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
0456     writel_bits_relaxed(0xff << OSD_REPLACE_SHIFT,
0457                 0xff << OSD_REPLACE_SHIFT,
0458                 priv->io_base + _REG(VIU_OSD2_CTRL_STAT2));
0459 
0460     /* Disable VD1 AFBC */
0461     /* di_mif0_en=0 mif0_to_vpp_en=0 di_mad_en=0 and afbc vd1 set=0*/
0462     writel_bits_relaxed(VIU_CTRL0_VD1_AFBC_MASK, 0,
0463                 priv->io_base + _REG(VIU_MISC_CTRL0));
0464     writel_relaxed(0, priv->io_base + _REG(AFBC_ENABLE));
0465 
0466     writel_relaxed(0x00FF00C0,
0467             priv->io_base + _REG(VD1_IF0_LUMA_FIFO_SIZE));
0468     writel_relaxed(0x00FF00C0,
0469             priv->io_base + _REG(VD2_IF0_LUMA_FIFO_SIZE));
0470 
0471     if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
0472         u32 val = (u32)VIU_OSD_BLEND_REORDER(0, 1) |
0473               (u32)VIU_OSD_BLEND_REORDER(1, 0) |
0474               (u32)VIU_OSD_BLEND_REORDER(2, 0) |
0475               (u32)VIU_OSD_BLEND_REORDER(3, 0) |
0476               (u32)VIU_OSD_BLEND_DIN_EN(1) |
0477               (u32)VIU_OSD_BLEND1_DIN3_BYPASS_TO_DOUT1 |
0478               (u32)VIU_OSD_BLEND1_DOUT_BYPASS_TO_BLEND2 |
0479               (u32)VIU_OSD_BLEND_DIN0_BYPASS_TO_DOUT0 |
0480               (u32)VIU_OSD_BLEND_BLEN2_PREMULT_EN(1) |
0481               (u32)VIU_OSD_BLEND_HOLD_LINES(4);
0482         writel_relaxed(val, priv->io_base + _REG(VIU_OSD_BLEND_CTRL));
0483 
0484         writel_relaxed(OSD_BLEND_PATH_SEL_ENABLE,
0485                    priv->io_base + _REG(OSD1_BLEND_SRC_CTRL));
0486         writel_relaxed(OSD_BLEND_PATH_SEL_ENABLE,
0487                    priv->io_base + _REG(OSD2_BLEND_SRC_CTRL));
0488         writel_relaxed(0, priv->io_base + _REG(VD1_BLEND_SRC_CTRL));
0489         writel_relaxed(0, priv->io_base + _REG(VD2_BLEND_SRC_CTRL));
0490         writel_relaxed(0,
0491                 priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_DATA0));
0492         writel_relaxed(0,
0493                 priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_ALPHA));
0494 
0495         writel_bits_relaxed(DOLBY_BYPASS_EN(0xc), DOLBY_BYPASS_EN(0xc),
0496                     priv->io_base + _REG(DOLBY_PATH_CTRL));
0497 
0498         meson_viu_g12a_disable_osd1_afbc(priv);
0499     }
0500 
0501     if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM))
0502         meson_viu_gxm_disable_osd1_afbc(priv);
0503 
0504     priv->viu.osd1_enabled = false;
0505     priv->viu.osd1_commit = false;
0506     priv->viu.osd1_interlace = false;
0507 }