linux/drivers/gpu/drm/meson/meson_viu.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 * Copyright (C) 2014 Endless Mobile
   7 */
   8
   9#include <linux/export.h>
  10#include <linux/bitfield.h>
  11
  12#include <drm/drm_fourcc.h>
  13
  14#include "meson_drv.h"
  15#include "meson_viu.h"
  16#include "meson_registers.h"
  17
  18/**
  19 * DOC: Video Input Unit
  20 *
  21 * VIU Handles the Pixel scanout and the basic Colorspace conversions
  22 * We handle the following features :
  23 *
  24 * - OSD1 RGB565/RGB888/xRGB8888 scanout
  25 * - RGB conversion to x/cb/cr
  26 * - Progressive or Interlace buffer scanout
  27 * - OSD1 Commit on Vsync
  28 * - HDR OSD matrix for GXL/GXM
  29 *
  30 * What is missing :
  31 *
  32 * - BGR888/xBGR8888/BGRx8888/BGRx8888 modes
  33 * - YUV4:2:2 Y0CbY1Cr scanout
  34 * - Conversion to YUV 4:4:4 from 4:2:2 input
  35 * - Colorkey Alpha matching
  36 * - Big endian scanout
  37 * - X/Y reverse scanout
  38 * - Global alpha setup
  39 * - OSD2 support, would need interlace switching on vsync
  40 * - OSD1 full scaling to support TV overscan
  41 */
  42
  43/* OSD csc defines */
  44
  45enum viu_matrix_sel_e {
  46        VIU_MATRIX_OSD_EOTF = 0,
  47        VIU_MATRIX_OSD,
  48};
  49
  50enum viu_lut_sel_e {
  51        VIU_LUT_OSD_EOTF = 0,
  52        VIU_LUT_OSD_OETF,
  53};
  54
  55#define COEFF_NORM(a) ((int)((((a) * 2048.0) + 1) / 2))
  56#define MATRIX_5X3_COEF_SIZE 24
  57
  58#define EOTF_COEFF_NORM(a) ((int)((((a) * 4096.0) + 1) / 2))
  59#define EOTF_COEFF_SIZE 10
  60#define EOTF_COEFF_RIGHTSHIFT 1
  61
  62static int RGB709_to_YUV709l_coeff[MATRIX_5X3_COEF_SIZE] = {
  63        0, 0, 0, /* pre offset */
  64        COEFF_NORM(0.181873),   COEFF_NORM(0.611831),   COEFF_NORM(0.061765),
  65        COEFF_NORM(-0.100251),  COEFF_NORM(-0.337249),  COEFF_NORM(0.437500),
  66        COEFF_NORM(0.437500),   COEFF_NORM(-0.397384),  COEFF_NORM(-0.040116),
  67        0, 0, 0, /* 10'/11'/12' */
  68        0, 0, 0, /* 20'/21'/22' */
  69        64, 512, 512, /* offset */
  70        0, 0, 0 /* mode, right_shift, clip_en */
  71};
  72
  73/*  eotf matrix: bypass */
  74static int eotf_bypass_coeff[EOTF_COEFF_SIZE] = {
  75        EOTF_COEFF_NORM(1.0),   EOTF_COEFF_NORM(0.0),   EOTF_COEFF_NORM(0.0),
  76        EOTF_COEFF_NORM(0.0),   EOTF_COEFF_NORM(1.0),   EOTF_COEFF_NORM(0.0),
  77        EOTF_COEFF_NORM(0.0),   EOTF_COEFF_NORM(0.0),   EOTF_COEFF_NORM(1.0),
  78        EOTF_COEFF_RIGHTSHIFT /* right shift */
  79};
  80
  81static void meson_viu_set_g12a_osd1_matrix(struct meson_drm *priv,
  82                                           int *m, bool csc_on)
  83{
  84        /* VPP WRAP OSD1 matrix */
  85        writel(((m[0] & 0xfff) << 16) | (m[1] & 0xfff),
  86                priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET0_1));
  87        writel(m[2] & 0xfff,
  88                priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET2));
  89        writel(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff),
  90                priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF00_01));
  91        writel(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff),
  92                priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF02_10));
  93        writel(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff),
  94                priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF11_12));
  95        writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff),
  96                priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF20_21));
  97        writel((m[11] & 0x1fff) << 16,
  98                priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF22));
  99
 100        writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff),
 101                priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET0_1));
 102        writel(m[20] & 0xfff,
 103                priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET2));
 104
 105        writel_bits_relaxed(BIT(0), csc_on ? BIT(0) : 0,
 106                priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL));
 107}
 108
 109static void meson_viu_set_osd_matrix(struct meson_drm *priv,
 110                                     enum viu_matrix_sel_e m_select,
 111                              int *m, bool csc_on)
 112{
 113        if (m_select == VIU_MATRIX_OSD) {
 114                /* osd matrix, VIU_MATRIX_0 */
 115                writel(((m[0] & 0xfff) << 16) | (m[1] & 0xfff),
 116                        priv->io_base + _REG(VIU_OSD1_MATRIX_PRE_OFFSET0_1));
 117                writel(m[2] & 0xfff,
 118                        priv->io_base + _REG(VIU_OSD1_MATRIX_PRE_OFFSET2));
 119                writel(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff),
 120                        priv->io_base + _REG(VIU_OSD1_MATRIX_COEF00_01));
 121                writel(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff),
 122                        priv->io_base + _REG(VIU_OSD1_MATRIX_COEF02_10));
 123                writel(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff),
 124                        priv->io_base + _REG(VIU_OSD1_MATRIX_COEF11_12));
 125                writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff),
 126                        priv->io_base + _REG(VIU_OSD1_MATRIX_COEF20_21));
 127
 128                if (m[21]) {
 129                        writel(((m[11] & 0x1fff) << 16) | (m[12] & 0x1fff),
 130                                priv->io_base +
 131                                        _REG(VIU_OSD1_MATRIX_COEF22_30));
 132                        writel(((m[13] & 0x1fff) << 16) | (m[14] & 0x1fff),
 133                                priv->io_base +
 134                                        _REG(VIU_OSD1_MATRIX_COEF31_32));
 135                        writel(((m[15] & 0x1fff) << 16) | (m[16] & 0x1fff),
 136                                priv->io_base +
 137                                        _REG(VIU_OSD1_MATRIX_COEF40_41));
 138                        writel(m[17] & 0x1fff, priv->io_base +
 139                                _REG(VIU_OSD1_MATRIX_COLMOD_COEF42));
 140                } else
 141                        writel((m[11] & 0x1fff) << 16, priv->io_base +
 142                                _REG(VIU_OSD1_MATRIX_COEF22_30));
 143
 144                writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff),
 145                        priv->io_base + _REG(VIU_OSD1_MATRIX_OFFSET0_1));
 146                writel(m[20] & 0xfff,
 147                        priv->io_base + _REG(VIU_OSD1_MATRIX_OFFSET2));
 148
 149                writel_bits_relaxed(3 << 30, m[21] << 30,
 150                        priv->io_base + _REG(VIU_OSD1_MATRIX_COLMOD_COEF42));
 151                writel_bits_relaxed(7 << 16, m[22] << 16,
 152                        priv->io_base + _REG(VIU_OSD1_MATRIX_COLMOD_COEF42));
 153
 154                /* 23 reserved for clipping control */
 155                writel_bits_relaxed(BIT(0), csc_on ? BIT(0) : 0,
 156                        priv->io_base + _REG(VIU_OSD1_MATRIX_CTRL));
 157                writel_bits_relaxed(BIT(1), 0,
 158                        priv->io_base + _REG(VIU_OSD1_MATRIX_CTRL));
 159        } else if (m_select == VIU_MATRIX_OSD_EOTF) {
 160                int i;
 161
 162                /* osd eotf matrix, VIU_MATRIX_OSD_EOTF */
 163                for (i = 0; i < 5; i++)
 164                        writel(((m[i * 2] & 0x1fff) << 16) |
 165                                (m[i * 2 + 1] & 0x1fff), priv->io_base +
 166                                _REG(VIU_OSD1_EOTF_CTL + i + 1));
 167
 168                writel_bits_relaxed(BIT(30), csc_on ? BIT(30) : 0,
 169                        priv->io_base + _REG(VIU_OSD1_EOTF_CTL));
 170                writel_bits_relaxed(BIT(31), csc_on ? BIT(31) : 0,
 171                        priv->io_base + _REG(VIU_OSD1_EOTF_CTL));
 172        }
 173}
 174
 175#define OSD_EOTF_LUT_SIZE 33
 176#define OSD_OETF_LUT_SIZE 41
 177
 178static void
 179meson_viu_set_osd_lut(struct meson_drm *priv, enum viu_lut_sel_e lut_sel,
 180                      unsigned int *r_map, unsigned int *g_map,
 181                      unsigned int *b_map, bool csc_on)
 182{
 183        unsigned int addr_port;
 184        unsigned int data_port;
 185        unsigned int ctrl_port;
 186        int i;
 187
 188        if (lut_sel == VIU_LUT_OSD_EOTF) {
 189                addr_port = VIU_OSD1_EOTF_LUT_ADDR_PORT;
 190                data_port = VIU_OSD1_EOTF_LUT_DATA_PORT;
 191                ctrl_port = VIU_OSD1_EOTF_CTL;
 192        } else if (lut_sel == VIU_LUT_OSD_OETF) {
 193                addr_port = VIU_OSD1_OETF_LUT_ADDR_PORT;
 194                data_port = VIU_OSD1_OETF_LUT_DATA_PORT;
 195                ctrl_port = VIU_OSD1_OETF_CTL;
 196        } else
 197                return;
 198
 199        if (lut_sel == VIU_LUT_OSD_OETF) {
 200                writel(0, priv->io_base + _REG(addr_port));
 201
 202                for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++)
 203                        writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16),
 204                                priv->io_base + _REG(data_port));
 205
 206                writel(r_map[OSD_OETF_LUT_SIZE - 1] | (g_map[0] << 16),
 207                        priv->io_base + _REG(data_port));
 208
 209                for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++)
 210                        writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16),
 211                                priv->io_base + _REG(data_port));
 212
 213                for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++)
 214                        writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16),
 215                                priv->io_base + _REG(data_port));
 216
 217                writel(b_map[OSD_OETF_LUT_SIZE - 1],
 218                        priv->io_base + _REG(data_port));
 219
 220                if (csc_on)
 221                        writel_bits_relaxed(0x7 << 29, 7 << 29,
 222                                            priv->io_base + _REG(ctrl_port));
 223                else
 224                        writel_bits_relaxed(0x7 << 29, 0,
 225                                            priv->io_base + _REG(ctrl_port));
 226        } else if (lut_sel == VIU_LUT_OSD_EOTF) {
 227                writel(0, priv->io_base + _REG(addr_port));
 228
 229                for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++)
 230                        writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16),
 231                                priv->io_base + _REG(data_port));
 232
 233                writel(r_map[OSD_EOTF_LUT_SIZE - 1] | (g_map[0] << 16),
 234                        priv->io_base + _REG(data_port));
 235
 236                for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++)
 237                        writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16),
 238                                priv->io_base + _REG(data_port));
 239
 240                for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++)
 241                        writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16),
 242                                priv->io_base + _REG(data_port));
 243
 244                writel(b_map[OSD_EOTF_LUT_SIZE - 1],
 245                        priv->io_base + _REG(data_port));
 246
 247                if (csc_on)
 248                        writel_bits_relaxed(7 << 27, 7 << 27,
 249                                            priv->io_base + _REG(ctrl_port));
 250                else
 251                        writel_bits_relaxed(7 << 27, 0,
 252                                            priv->io_base + _REG(ctrl_port));
 253
 254                writel_bits_relaxed(BIT(31), BIT(31),
 255                                    priv->io_base + _REG(ctrl_port));
 256        }
 257}
 258
 259/* eotf lut: linear */
 260static unsigned int eotf_33_linear_mapping[OSD_EOTF_LUT_SIZE] = {
 261        0x0000, 0x0200, 0x0400, 0x0600,
 262        0x0800, 0x0a00, 0x0c00, 0x0e00,
 263        0x1000, 0x1200, 0x1400, 0x1600,
 264        0x1800, 0x1a00, 0x1c00, 0x1e00,
 265        0x2000, 0x2200, 0x2400, 0x2600,
 266        0x2800, 0x2a00, 0x2c00, 0x2e00,
 267        0x3000, 0x3200, 0x3400, 0x3600,
 268        0x3800, 0x3a00, 0x3c00, 0x3e00,
 269        0x4000
 270};
 271
 272/* osd oetf lut: linear */
 273static unsigned int oetf_41_linear_mapping[OSD_OETF_LUT_SIZE] = {
 274        0, 0, 0, 0,
 275        0, 32, 64, 96,
 276        128, 160, 196, 224,
 277        256, 288, 320, 352,
 278        384, 416, 448, 480,
 279        512, 544, 576, 608,
 280        640, 672, 704, 736,
 281        768, 800, 832, 864,
 282        896, 928, 960, 992,
 283        1023, 1023, 1023, 1023,
 284        1023
 285};
 286
 287static void meson_viu_load_matrix(struct meson_drm *priv)
 288{
 289        /* eotf lut bypass */
 290        meson_viu_set_osd_lut(priv, VIU_LUT_OSD_EOTF,
 291                              eotf_33_linear_mapping, /* R */
 292                              eotf_33_linear_mapping, /* G */
 293                              eotf_33_linear_mapping, /* B */
 294                              false);
 295
 296        /* eotf matrix bypass */
 297        meson_viu_set_osd_matrix(priv, VIU_MATRIX_OSD_EOTF,
 298                                 eotf_bypass_coeff,
 299                                 false);
 300
 301        /* oetf lut bypass */
 302        meson_viu_set_osd_lut(priv, VIU_LUT_OSD_OETF,
 303                              oetf_41_linear_mapping, /* R */
 304                              oetf_41_linear_mapping, /* G */
 305                              oetf_41_linear_mapping, /* B */
 306                              false);
 307
 308        /* osd matrix RGB709 to YUV709 limit */
 309        meson_viu_set_osd_matrix(priv, VIU_MATRIX_OSD,
 310                                 RGB709_to_YUV709l_coeff,
 311                                 true);
 312}
 313
 314/* VIU OSD1 Reset as workaround for GXL+ Alpha OSD Bug */
 315void meson_viu_osd1_reset(struct meson_drm *priv)
 316{
 317        uint32_t osd1_fifo_ctrl_stat, osd1_ctrl_stat2;
 318
 319        /* Save these 2 registers state */
 320        osd1_fifo_ctrl_stat = readl_relaxed(
 321                                priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT));
 322        osd1_ctrl_stat2 = readl_relaxed(
 323                                priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
 324
 325        /* Reset OSD1 */
 326        writel_bits_relaxed(VIU_SW_RESET_OSD1, VIU_SW_RESET_OSD1,
 327                            priv->io_base + _REG(VIU_SW_RESET));
 328        writel_bits_relaxed(VIU_SW_RESET_OSD1, 0,
 329                            priv->io_base + _REG(VIU_SW_RESET));
 330
 331        /* Rewrite these registers state lost in the reset */
 332        writel_relaxed(osd1_fifo_ctrl_stat,
 333                       priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT));
 334        writel_relaxed(osd1_ctrl_stat2,
 335                       priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
 336
 337        /* Reload the conversion matrix */
 338        meson_viu_load_matrix(priv);
 339}
 340
 341#define OSD1_MALI_ORDER_ABGR                            \
 342        (FIELD_PREP(VIU_OSD1_MALI_AFBCD_A_REORDER,      \
 343                    VIU_OSD1_MALI_REORDER_A) |          \
 344         FIELD_PREP(VIU_OSD1_MALI_AFBCD_B_REORDER,      \
 345                    VIU_OSD1_MALI_REORDER_B) |          \
 346         FIELD_PREP(VIU_OSD1_MALI_AFBCD_G_REORDER,      \
 347                    VIU_OSD1_MALI_REORDER_G) |          \
 348         FIELD_PREP(VIU_OSD1_MALI_AFBCD_R_REORDER,      \
 349                    VIU_OSD1_MALI_REORDER_R))
 350
 351#define OSD1_MALI_ORDER_ARGB                            \
 352        (FIELD_PREP(VIU_OSD1_MALI_AFBCD_A_REORDER,      \
 353                    VIU_OSD1_MALI_REORDER_A) |          \
 354         FIELD_PREP(VIU_OSD1_MALI_AFBCD_B_REORDER,      \
 355                    VIU_OSD1_MALI_REORDER_R) |          \
 356         FIELD_PREP(VIU_OSD1_MALI_AFBCD_G_REORDER,      \
 357                    VIU_OSD1_MALI_REORDER_G) |          \
 358         FIELD_PREP(VIU_OSD1_MALI_AFBCD_R_REORDER,      \
 359                    VIU_OSD1_MALI_REORDER_B))
 360
 361void meson_viu_g12a_enable_osd1_afbc(struct meson_drm *priv)
 362{
 363        u32 afbc_order = OSD1_MALI_ORDER_ARGB;
 364
 365        /* Enable Mali AFBC Unpack */
 366        writel_bits_relaxed(VIU_OSD1_MALI_UNPACK_EN,
 367                            VIU_OSD1_MALI_UNPACK_EN,
 368                            priv->io_base + _REG(VIU_OSD1_MALI_UNPACK_CTRL));
 369
 370        switch (priv->afbcd.format) {
 371        case DRM_FORMAT_XBGR8888:
 372        case DRM_FORMAT_ABGR8888:
 373                afbc_order = OSD1_MALI_ORDER_ABGR;
 374                break;
 375        }
 376
 377        /* Setup RGBA Reordering */
 378        writel_bits_relaxed(VIU_OSD1_MALI_AFBCD_A_REORDER |
 379                            VIU_OSD1_MALI_AFBCD_B_REORDER |
 380                            VIU_OSD1_MALI_AFBCD_G_REORDER |
 381                            VIU_OSD1_MALI_AFBCD_R_REORDER,
 382                            afbc_order,
 383                            priv->io_base + _REG(VIU_OSD1_MALI_UNPACK_CTRL));
 384
 385        /* Select AFBCD path for OSD1 */
 386        writel_bits_relaxed(OSD_PATH_OSD_AXI_SEL_OSD1_AFBCD,
 387                            OSD_PATH_OSD_AXI_SEL_OSD1_AFBCD,
 388                            priv->io_base + _REG(OSD_PATH_MISC_CTRL));
 389}
 390
 391void meson_viu_g12a_disable_osd1_afbc(struct meson_drm *priv)
 392{
 393        /* Disable AFBCD path for OSD1 */
 394        writel_bits_relaxed(OSD_PATH_OSD_AXI_SEL_OSD1_AFBCD, 0,
 395                            priv->io_base + _REG(OSD_PATH_MISC_CTRL));
 396
 397        /* Disable AFBCD unpack */
 398        writel_bits_relaxed(VIU_OSD1_MALI_UNPACK_EN, 0,
 399                            priv->io_base + _REG(VIU_OSD1_MALI_UNPACK_CTRL));
 400}
 401
 402void meson_viu_gxm_enable_osd1_afbc(struct meson_drm *priv)
 403{
 404        writel_bits_relaxed(MALI_AFBC_MISC, FIELD_PREP(MALI_AFBC_MISC, 0x90),
 405                            priv->io_base + _REG(VIU_MISC_CTRL1));
 406}
 407
 408void meson_viu_gxm_disable_osd1_afbc(struct meson_drm *priv)
 409{
 410        writel_bits_relaxed(MALI_AFBC_MISC, FIELD_PREP(MALI_AFBC_MISC, 0x00),
 411                            priv->io_base + _REG(VIU_MISC_CTRL1));
 412}
 413
 414void meson_viu_init(struct meson_drm *priv)
 415{
 416        uint32_t reg;
 417
 418        /* Disable OSDs */
 419        writel_bits_relaxed(VIU_OSD1_OSD_BLK_ENABLE | VIU_OSD1_OSD_ENABLE, 0,
 420                            priv->io_base + _REG(VIU_OSD1_CTRL_STAT));
 421        writel_bits_relaxed(VIU_OSD1_OSD_BLK_ENABLE | VIU_OSD1_OSD_ENABLE, 0,
 422                            priv->io_base + _REG(VIU_OSD2_CTRL_STAT));
 423
 424        /* On GXL/GXM, Use the 10bit HDR conversion matrix */
 425        if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
 426            meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
 427                meson_viu_load_matrix(priv);
 428        else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
 429                meson_viu_set_g12a_osd1_matrix(priv, RGB709_to_YUV709l_coeff,
 430                                               true);
 431                /* fix green/pink color distortion from vendor u-boot */
 432                writel_bits_relaxed(OSD1_HDR2_CTRL_REG_ONLY_MAT |
 433                                OSD1_HDR2_CTRL_VDIN0_HDR2_TOP_EN, 0,
 434                                priv->io_base + _REG(OSD1_HDR2_CTRL));
 435        }
 436
 437        /* Initialize OSD1 fifo control register */
 438        reg = VIU_OSD_DDR_PRIORITY_URGENT |
 439                VIU_OSD_HOLD_FIFO_LINES(31) |
 440                VIU_OSD_FIFO_DEPTH_VAL(32) | /* fifo_depth_val: 32*8=256 */
 441                VIU_OSD_WORDS_PER_BURST(4) | /* 4 words in 1 burst */
 442                VIU_OSD_FIFO_LIMITS(2);      /* fifo_lim: 2*16=32 */
 443
 444        if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
 445                reg |= VIU_OSD_BURST_LENGTH_32;
 446        else
 447                reg |= VIU_OSD_BURST_LENGTH_64;
 448
 449        writel_relaxed(reg, priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT));
 450        writel_relaxed(reg, priv->io_base + _REG(VIU_OSD2_FIFO_CTRL_STAT));
 451
 452        /* Set OSD alpha replace value */
 453        writel_bits_relaxed(0xff << OSD_REPLACE_SHIFT,
 454                            0xff << OSD_REPLACE_SHIFT,
 455                            priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
 456        writel_bits_relaxed(0xff << OSD_REPLACE_SHIFT,
 457                            0xff << OSD_REPLACE_SHIFT,
 458                            priv->io_base + _REG(VIU_OSD2_CTRL_STAT2));
 459
 460        /* Disable VD1 AFBC */
 461        /* di_mif0_en=0 mif0_to_vpp_en=0 di_mad_en=0 and afbc vd1 set=0*/
 462        writel_bits_relaxed(VIU_CTRL0_VD1_AFBC_MASK, 0,
 463                            priv->io_base + _REG(VIU_MISC_CTRL0));
 464        writel_relaxed(0, priv->io_base + _REG(AFBC_ENABLE));
 465
 466        writel_relaxed(0x00FF00C0,
 467                        priv->io_base + _REG(VD1_IF0_LUMA_FIFO_SIZE));
 468        writel_relaxed(0x00FF00C0,
 469                        priv->io_base + _REG(VD2_IF0_LUMA_FIFO_SIZE));
 470
 471        if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
 472                writel_relaxed(VIU_OSD_BLEND_REORDER(0, 1) |
 473                               VIU_OSD_BLEND_REORDER(1, 0) |
 474                               VIU_OSD_BLEND_REORDER(2, 0) |
 475                               VIU_OSD_BLEND_REORDER(3, 0) |
 476                               VIU_OSD_BLEND_DIN_EN(1) |
 477                               VIU_OSD_BLEND1_DIN3_BYPASS_TO_DOUT1 |
 478                               VIU_OSD_BLEND1_DOUT_BYPASS_TO_BLEND2 |
 479                               VIU_OSD_BLEND_DIN0_BYPASS_TO_DOUT0 |
 480                               VIU_OSD_BLEND_BLEN2_PREMULT_EN(1) |
 481                               VIU_OSD_BLEND_HOLD_LINES(4),
 482                               priv->io_base + _REG(VIU_OSD_BLEND_CTRL));
 483
 484                writel_relaxed(OSD_BLEND_PATH_SEL_ENABLE,
 485                               priv->io_base + _REG(OSD1_BLEND_SRC_CTRL));
 486                writel_relaxed(OSD_BLEND_PATH_SEL_ENABLE,
 487                               priv->io_base + _REG(OSD2_BLEND_SRC_CTRL));
 488                writel_relaxed(0, priv->io_base + _REG(VD1_BLEND_SRC_CTRL));
 489                writel_relaxed(0, priv->io_base + _REG(VD2_BLEND_SRC_CTRL));
 490                writel_relaxed(0,
 491                                priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_DATA0));
 492                writel_relaxed(0,
 493                                priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_ALPHA));
 494
 495                writel_bits_relaxed(DOLBY_BYPASS_EN(0xc), DOLBY_BYPASS_EN(0xc),
 496                                    priv->io_base + _REG(DOLBY_PATH_CTRL));
 497
 498                meson_viu_g12a_disable_osd1_afbc(priv);
 499        }
 500
 501        if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM))
 502                meson_viu_gxm_disable_osd1_afbc(priv);
 503
 504        priv->viu.osd1_enabled = false;
 505        priv->viu.osd1_commit = false;
 506        priv->viu.osd1_interlace = false;
 507}
 508