11ccea77eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2bbbe775eSNeil Armstrong /* 3bbbe775eSNeil Armstrong * Copyright (C) 2016 BayLibre, SAS 4bbbe775eSNeil Armstrong * Author: Neil Armstrong <narmstrong@baylibre.com> 5bbbe775eSNeil Armstrong * Copyright (C) 2015 Amlogic, Inc. All rights reserved. 6bbbe775eSNeil Armstrong * Copyright (C) 2014 Endless Mobile 7bbbe775eSNeil Armstrong */ 8bbbe775eSNeil Armstrong 966620f48SSam Ravnborg #include <linux/export.h> 1066620f48SSam Ravnborg 11bbbe775eSNeil Armstrong #include "meson_drv.h" 12bbbe775eSNeil Armstrong #include "meson_viu.h" 13bbbe775eSNeil Armstrong #include "meson_registers.h" 14bbbe775eSNeil Armstrong 152021d5b7SNeil Armstrong /** 162021d5b7SNeil Armstrong * DOC: Video Input Unit 172021d5b7SNeil Armstrong * 18bbbe775eSNeil Armstrong * VIU Handles the Pixel scanout and the basic Colorspace conversions 19bbbe775eSNeil Armstrong * We handle the following features : 202021d5b7SNeil Armstrong * 21bbbe775eSNeil Armstrong * - OSD1 RGB565/RGB888/xRGB8888 scanout 22bbbe775eSNeil Armstrong * - RGB conversion to x/cb/cr 23bbbe775eSNeil Armstrong * - Progressive or Interlace buffer scanout 24bbbe775eSNeil Armstrong * - OSD1 Commit on Vsync 25bbbe775eSNeil Armstrong * - HDR OSD matrix for GXL/GXM 26bbbe775eSNeil Armstrong * 27bbbe775eSNeil Armstrong * What is missing : 282021d5b7SNeil Armstrong * 29bbbe775eSNeil Armstrong * - BGR888/xBGR8888/BGRx8888/BGRx8888 modes 30bbbe775eSNeil Armstrong * - YUV4:2:2 Y0CbY1Cr scanout 31bbbe775eSNeil Armstrong * - Conversion to YUV 4:4:4 from 4:2:2 input 32bbbe775eSNeil Armstrong * - Colorkey Alpha matching 33bbbe775eSNeil Armstrong * - Big endian scanout 34bbbe775eSNeil Armstrong * - X/Y reverse scanout 35bbbe775eSNeil Armstrong * - Global alpha setup 36bbbe775eSNeil Armstrong * - OSD2 support, would need interlace switching on vsync 37bbbe775eSNeil Armstrong * - OSD1 full scaling to support TV overscan 38bbbe775eSNeil Armstrong */ 39bbbe775eSNeil Armstrong 40bbbe775eSNeil Armstrong /* OSD csc defines */ 41bbbe775eSNeil Armstrong 42bbbe775eSNeil Armstrong enum viu_matrix_sel_e { 43bbbe775eSNeil Armstrong VIU_MATRIX_OSD_EOTF = 0, 44bbbe775eSNeil Armstrong VIU_MATRIX_OSD, 45bbbe775eSNeil Armstrong }; 46bbbe775eSNeil Armstrong 47bbbe775eSNeil Armstrong enum viu_lut_sel_e { 48bbbe775eSNeil Armstrong VIU_LUT_OSD_EOTF = 0, 49bbbe775eSNeil Armstrong VIU_LUT_OSD_OETF, 50bbbe775eSNeil Armstrong }; 51bbbe775eSNeil Armstrong 52bbbe775eSNeil Armstrong #define COEFF_NORM(a) ((int)((((a) * 2048.0) + 1) / 2)) 53bbbe775eSNeil Armstrong #define MATRIX_5X3_COEF_SIZE 24 54bbbe775eSNeil Armstrong 55bbbe775eSNeil Armstrong #define EOTF_COEFF_NORM(a) ((int)((((a) * 4096.0) + 1) / 2)) 56bbbe775eSNeil Armstrong #define EOTF_COEFF_SIZE 10 57bbbe775eSNeil Armstrong #define EOTF_COEFF_RIGHTSHIFT 1 58bbbe775eSNeil Armstrong 59bbbe775eSNeil Armstrong static int RGB709_to_YUV709l_coeff[MATRIX_5X3_COEF_SIZE] = { 60bbbe775eSNeil Armstrong 0, 0, 0, /* pre offset */ 61bbbe775eSNeil Armstrong COEFF_NORM(0.181873), COEFF_NORM(0.611831), COEFF_NORM(0.061765), 62bbbe775eSNeil Armstrong COEFF_NORM(-0.100251), COEFF_NORM(-0.337249), COEFF_NORM(0.437500), 63bbbe775eSNeil Armstrong COEFF_NORM(0.437500), COEFF_NORM(-0.397384), COEFF_NORM(-0.040116), 64bbbe775eSNeil Armstrong 0, 0, 0, /* 10'/11'/12' */ 65bbbe775eSNeil Armstrong 0, 0, 0, /* 20'/21'/22' */ 66bbbe775eSNeil Armstrong 64, 512, 512, /* offset */ 67bbbe775eSNeil Armstrong 0, 0, 0 /* mode, right_shift, clip_en */ 68bbbe775eSNeil Armstrong }; 69bbbe775eSNeil Armstrong 70bbbe775eSNeil Armstrong /* eotf matrix: bypass */ 71bbbe775eSNeil Armstrong static int eotf_bypass_coeff[EOTF_COEFF_SIZE] = { 72bbbe775eSNeil Armstrong EOTF_COEFF_NORM(1.0), EOTF_COEFF_NORM(0.0), EOTF_COEFF_NORM(0.0), 73bbbe775eSNeil Armstrong EOTF_COEFF_NORM(0.0), EOTF_COEFF_NORM(1.0), EOTF_COEFF_NORM(0.0), 74bbbe775eSNeil Armstrong EOTF_COEFF_NORM(0.0), EOTF_COEFF_NORM(0.0), EOTF_COEFF_NORM(1.0), 75bbbe775eSNeil Armstrong EOTF_COEFF_RIGHTSHIFT /* right shift */ 76bbbe775eSNeil Armstrong }; 77bbbe775eSNeil Armstrong 782ccb8433SYueHaibing static void meson_viu_set_g12a_osd1_matrix(struct meson_drm *priv, 792ccb8433SYueHaibing int *m, bool csc_on) 8072888394SNeil Armstrong { 8172888394SNeil Armstrong /* VPP WRAP OSD1 matrix */ 8272888394SNeil Armstrong writel(((m[0] & 0xfff) << 16) | (m[1] & 0xfff), 8372888394SNeil Armstrong priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET0_1)); 8472888394SNeil Armstrong writel(m[2] & 0xfff, 8572888394SNeil Armstrong priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET2)); 8672888394SNeil Armstrong writel(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff), 8772888394SNeil Armstrong priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF00_01)); 8872888394SNeil Armstrong writel(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff), 8972888394SNeil Armstrong priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF02_10)); 9072888394SNeil Armstrong writel(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff), 9172888394SNeil Armstrong priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF11_12)); 9272888394SNeil Armstrong writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff), 9372888394SNeil Armstrong priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF20_21)); 9472888394SNeil Armstrong writel((m[11] & 0x1fff) << 16, 9572888394SNeil Armstrong priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF22)); 9672888394SNeil Armstrong 9772888394SNeil Armstrong writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff), 9872888394SNeil Armstrong priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET0_1)); 9972888394SNeil Armstrong writel(m[20] & 0xfff, 10072888394SNeil Armstrong priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET2)); 10172888394SNeil Armstrong 10272888394SNeil Armstrong writel_bits_relaxed(BIT(0), csc_on ? BIT(0) : 0, 10372888394SNeil Armstrong priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL)); 10472888394SNeil Armstrong } 10572888394SNeil Armstrong 1062ccb8433SYueHaibing static void meson_viu_set_osd_matrix(struct meson_drm *priv, 107bbbe775eSNeil Armstrong enum viu_matrix_sel_e m_select, 108bbbe775eSNeil Armstrong int *m, bool csc_on) 109bbbe775eSNeil Armstrong { 110bbbe775eSNeil Armstrong if (m_select == VIU_MATRIX_OSD) { 111bbbe775eSNeil Armstrong /* osd matrix, VIU_MATRIX_0 */ 112bbbe775eSNeil Armstrong writel(((m[0] & 0xfff) << 16) | (m[1] & 0xfff), 113bbbe775eSNeil Armstrong priv->io_base + _REG(VIU_OSD1_MATRIX_PRE_OFFSET0_1)); 114bbbe775eSNeil Armstrong writel(m[2] & 0xfff, 115bbbe775eSNeil Armstrong priv->io_base + _REG(VIU_OSD1_MATRIX_PRE_OFFSET2)); 116bbbe775eSNeil Armstrong writel(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff), 117bbbe775eSNeil Armstrong priv->io_base + _REG(VIU_OSD1_MATRIX_COEF00_01)); 118bbbe775eSNeil Armstrong writel(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff), 119bbbe775eSNeil Armstrong priv->io_base + _REG(VIU_OSD1_MATRIX_COEF02_10)); 120bbbe775eSNeil Armstrong writel(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff), 121bbbe775eSNeil Armstrong priv->io_base + _REG(VIU_OSD1_MATRIX_COEF11_12)); 122bbbe775eSNeil Armstrong writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff), 123bbbe775eSNeil Armstrong priv->io_base + _REG(VIU_OSD1_MATRIX_COEF20_21)); 124bbbe775eSNeil Armstrong 125bbbe775eSNeil Armstrong if (m[21]) { 126bbbe775eSNeil Armstrong writel(((m[11] & 0x1fff) << 16) | (m[12] & 0x1fff), 127bbbe775eSNeil Armstrong priv->io_base + 128bbbe775eSNeil Armstrong _REG(VIU_OSD1_MATRIX_COEF22_30)); 129bbbe775eSNeil Armstrong writel(((m[13] & 0x1fff) << 16) | (m[14] & 0x1fff), 130bbbe775eSNeil Armstrong priv->io_base + 131bbbe775eSNeil Armstrong _REG(VIU_OSD1_MATRIX_COEF31_32)); 132bbbe775eSNeil Armstrong writel(((m[15] & 0x1fff) << 16) | (m[16] & 0x1fff), 133bbbe775eSNeil Armstrong priv->io_base + 134bbbe775eSNeil Armstrong _REG(VIU_OSD1_MATRIX_COEF40_41)); 135bbbe775eSNeil Armstrong writel(m[17] & 0x1fff, priv->io_base + 136bbbe775eSNeil Armstrong _REG(VIU_OSD1_MATRIX_COLMOD_COEF42)); 137bbbe775eSNeil Armstrong } else 138bbbe775eSNeil Armstrong writel((m[11] & 0x1fff) << 16, priv->io_base + 139bbbe775eSNeil Armstrong _REG(VIU_OSD1_MATRIX_COEF22_30)); 140bbbe775eSNeil Armstrong 141bbbe775eSNeil Armstrong writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff), 142bbbe775eSNeil Armstrong priv->io_base + _REG(VIU_OSD1_MATRIX_OFFSET0_1)); 143bbbe775eSNeil Armstrong writel(m[20] & 0xfff, 144bbbe775eSNeil Armstrong priv->io_base + _REG(VIU_OSD1_MATRIX_OFFSET2)); 145bbbe775eSNeil Armstrong 146bbbe775eSNeil Armstrong writel_bits_relaxed(3 << 30, m[21] << 30, 147bbbe775eSNeil Armstrong priv->io_base + _REG(VIU_OSD1_MATRIX_COLMOD_COEF42)); 148bbbe775eSNeil Armstrong writel_bits_relaxed(7 << 16, m[22] << 16, 149bbbe775eSNeil Armstrong priv->io_base + _REG(VIU_OSD1_MATRIX_COLMOD_COEF42)); 150bbbe775eSNeil Armstrong 151bbbe775eSNeil Armstrong /* 23 reserved for clipping control */ 152bbbe775eSNeil Armstrong writel_bits_relaxed(BIT(0), csc_on ? BIT(0) : 0, 153bbbe775eSNeil Armstrong priv->io_base + _REG(VIU_OSD1_MATRIX_CTRL)); 154bbbe775eSNeil Armstrong writel_bits_relaxed(BIT(1), 0, 155bbbe775eSNeil Armstrong priv->io_base + _REG(VIU_OSD1_MATRIX_CTRL)); 156bbbe775eSNeil Armstrong } else if (m_select == VIU_MATRIX_OSD_EOTF) { 157bbbe775eSNeil Armstrong int i; 158bbbe775eSNeil Armstrong 159bbbe775eSNeil Armstrong /* osd eotf matrix, VIU_MATRIX_OSD_EOTF */ 160bbbe775eSNeil Armstrong for (i = 0; i < 5; i++) 161bbbe775eSNeil Armstrong writel(((m[i * 2] & 0x1fff) << 16) | 162bbbe775eSNeil Armstrong (m[i * 2 + 1] & 0x1fff), priv->io_base + 163bbbe775eSNeil Armstrong _REG(VIU_OSD1_EOTF_CTL + i + 1)); 164bbbe775eSNeil Armstrong 165bbbe775eSNeil Armstrong writel_bits_relaxed(BIT(30), csc_on ? BIT(30) : 0, 166bbbe775eSNeil Armstrong priv->io_base + _REG(VIU_OSD1_EOTF_CTL)); 167bbbe775eSNeil Armstrong writel_bits_relaxed(BIT(31), csc_on ? BIT(31) : 0, 168bbbe775eSNeil Armstrong priv->io_base + _REG(VIU_OSD1_EOTF_CTL)); 169bbbe775eSNeil Armstrong } 170bbbe775eSNeil Armstrong } 171bbbe775eSNeil Armstrong 172bbbe775eSNeil Armstrong #define OSD_EOTF_LUT_SIZE 33 173bbbe775eSNeil Armstrong #define OSD_OETF_LUT_SIZE 41 174bbbe775eSNeil Armstrong 1752ccb8433SYueHaibing static void 1762ccb8433SYueHaibing meson_viu_set_osd_lut(struct meson_drm *priv, enum viu_lut_sel_e lut_sel, 177bbbe775eSNeil Armstrong unsigned int *r_map, unsigned int *g_map, 1782ccb8433SYueHaibing unsigned int *b_map, bool csc_on) 179bbbe775eSNeil Armstrong { 180bbbe775eSNeil Armstrong unsigned int addr_port; 181bbbe775eSNeil Armstrong unsigned int data_port; 182bbbe775eSNeil Armstrong unsigned int ctrl_port; 183bbbe775eSNeil Armstrong int i; 184bbbe775eSNeil Armstrong 185bbbe775eSNeil Armstrong if (lut_sel == VIU_LUT_OSD_EOTF) { 186bbbe775eSNeil Armstrong addr_port = VIU_OSD1_EOTF_LUT_ADDR_PORT; 187bbbe775eSNeil Armstrong data_port = VIU_OSD1_EOTF_LUT_DATA_PORT; 188bbbe775eSNeil Armstrong ctrl_port = VIU_OSD1_EOTF_CTL; 189bbbe775eSNeil Armstrong } else if (lut_sel == VIU_LUT_OSD_OETF) { 190bbbe775eSNeil Armstrong addr_port = VIU_OSD1_OETF_LUT_ADDR_PORT; 191bbbe775eSNeil Armstrong data_port = VIU_OSD1_OETF_LUT_DATA_PORT; 192bbbe775eSNeil Armstrong ctrl_port = VIU_OSD1_OETF_CTL; 193bbbe775eSNeil Armstrong } else 194bbbe775eSNeil Armstrong return; 195bbbe775eSNeil Armstrong 196bbbe775eSNeil Armstrong if (lut_sel == VIU_LUT_OSD_OETF) { 197bbbe775eSNeil Armstrong writel(0, priv->io_base + _REG(addr_port)); 198bbbe775eSNeil Armstrong 19997b2a318SLyude Paul for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++) 200bbbe775eSNeil Armstrong writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16), 201bbbe775eSNeil Armstrong priv->io_base + _REG(data_port)); 202bbbe775eSNeil Armstrong 203bbbe775eSNeil Armstrong writel(r_map[OSD_OETF_LUT_SIZE - 1] | (g_map[0] << 16), 204bbbe775eSNeil Armstrong priv->io_base + _REG(data_port)); 205bbbe775eSNeil Armstrong 20697b2a318SLyude Paul for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++) 207bbbe775eSNeil Armstrong writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16), 208bbbe775eSNeil Armstrong priv->io_base + _REG(data_port)); 209bbbe775eSNeil Armstrong 21097b2a318SLyude Paul for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++) 211bbbe775eSNeil Armstrong writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16), 212bbbe775eSNeil Armstrong priv->io_base + _REG(data_port)); 213bbbe775eSNeil Armstrong 214bbbe775eSNeil Armstrong writel(b_map[OSD_OETF_LUT_SIZE - 1], 215bbbe775eSNeil Armstrong priv->io_base + _REG(data_port)); 216bbbe775eSNeil Armstrong 217bbbe775eSNeil Armstrong if (csc_on) 218bbbe775eSNeil Armstrong writel_bits_relaxed(0x7 << 29, 7 << 29, 219bbbe775eSNeil Armstrong priv->io_base + _REG(ctrl_port)); 220bbbe775eSNeil Armstrong else 221bbbe775eSNeil Armstrong writel_bits_relaxed(0x7 << 29, 0, 222bbbe775eSNeil Armstrong priv->io_base + _REG(ctrl_port)); 223bbbe775eSNeil Armstrong } else if (lut_sel == VIU_LUT_OSD_EOTF) { 224bbbe775eSNeil Armstrong writel(0, priv->io_base + _REG(addr_port)); 225bbbe775eSNeil Armstrong 22697b2a318SLyude Paul for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++) 227bbbe775eSNeil Armstrong writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16), 228bbbe775eSNeil Armstrong priv->io_base + _REG(data_port)); 229bbbe775eSNeil Armstrong 230bbbe775eSNeil Armstrong writel(r_map[OSD_EOTF_LUT_SIZE - 1] | (g_map[0] << 16), 231bbbe775eSNeil Armstrong priv->io_base + _REG(data_port)); 232bbbe775eSNeil Armstrong 23397b2a318SLyude Paul for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++) 234bbbe775eSNeil Armstrong writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16), 235bbbe775eSNeil Armstrong priv->io_base + _REG(data_port)); 236bbbe775eSNeil Armstrong 23797b2a318SLyude Paul for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++) 238bbbe775eSNeil Armstrong writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16), 239bbbe775eSNeil Armstrong priv->io_base + _REG(data_port)); 240bbbe775eSNeil Armstrong 241bbbe775eSNeil Armstrong writel(b_map[OSD_EOTF_LUT_SIZE - 1], 242bbbe775eSNeil Armstrong priv->io_base + _REG(data_port)); 243bbbe775eSNeil Armstrong 244bbbe775eSNeil Armstrong if (csc_on) 245bbbe775eSNeil Armstrong writel_bits_relaxed(7 << 27, 7 << 27, 246bbbe775eSNeil Armstrong priv->io_base + _REG(ctrl_port)); 247bbbe775eSNeil Armstrong else 248bbbe775eSNeil Armstrong writel_bits_relaxed(7 << 27, 0, 249bbbe775eSNeil Armstrong priv->io_base + _REG(ctrl_port)); 250bbbe775eSNeil Armstrong 251bbbe775eSNeil Armstrong writel_bits_relaxed(BIT(31), BIT(31), 252bbbe775eSNeil Armstrong priv->io_base + _REG(ctrl_port)); 253bbbe775eSNeil Armstrong } 254bbbe775eSNeil Armstrong } 255bbbe775eSNeil Armstrong 256bbbe775eSNeil Armstrong /* eotf lut: linear */ 257bbbe775eSNeil Armstrong static unsigned int eotf_33_linear_mapping[OSD_EOTF_LUT_SIZE] = { 258bbbe775eSNeil Armstrong 0x0000, 0x0200, 0x0400, 0x0600, 259bbbe775eSNeil Armstrong 0x0800, 0x0a00, 0x0c00, 0x0e00, 260bbbe775eSNeil Armstrong 0x1000, 0x1200, 0x1400, 0x1600, 261bbbe775eSNeil Armstrong 0x1800, 0x1a00, 0x1c00, 0x1e00, 262bbbe775eSNeil Armstrong 0x2000, 0x2200, 0x2400, 0x2600, 263bbbe775eSNeil Armstrong 0x2800, 0x2a00, 0x2c00, 0x2e00, 264bbbe775eSNeil Armstrong 0x3000, 0x3200, 0x3400, 0x3600, 265bbbe775eSNeil Armstrong 0x3800, 0x3a00, 0x3c00, 0x3e00, 266bbbe775eSNeil Armstrong 0x4000 267bbbe775eSNeil Armstrong }; 268bbbe775eSNeil Armstrong 269bbbe775eSNeil Armstrong /* osd oetf lut: linear */ 270bbbe775eSNeil Armstrong static unsigned int oetf_41_linear_mapping[OSD_OETF_LUT_SIZE] = { 271bbbe775eSNeil Armstrong 0, 0, 0, 0, 272bbbe775eSNeil Armstrong 0, 32, 64, 96, 273bbbe775eSNeil Armstrong 128, 160, 196, 224, 274bbbe775eSNeil Armstrong 256, 288, 320, 352, 275bbbe775eSNeil Armstrong 384, 416, 448, 480, 276bbbe775eSNeil Armstrong 512, 544, 576, 608, 277bbbe775eSNeil Armstrong 640, 672, 704, 736, 278bbbe775eSNeil Armstrong 768, 800, 832, 864, 279bbbe775eSNeil Armstrong 896, 928, 960, 992, 280bbbe775eSNeil Armstrong 1023, 1023, 1023, 1023, 281bbbe775eSNeil Armstrong 1023 282bbbe775eSNeil Armstrong }; 283bbbe775eSNeil Armstrong 284bbbe775eSNeil Armstrong static void meson_viu_load_matrix(struct meson_drm *priv) 285bbbe775eSNeil Armstrong { 286bbbe775eSNeil Armstrong /* eotf lut bypass */ 287bbbe775eSNeil Armstrong meson_viu_set_osd_lut(priv, VIU_LUT_OSD_EOTF, 288bbbe775eSNeil Armstrong eotf_33_linear_mapping, /* R */ 289bbbe775eSNeil Armstrong eotf_33_linear_mapping, /* G */ 290bbbe775eSNeil Armstrong eotf_33_linear_mapping, /* B */ 291bbbe775eSNeil Armstrong false); 292bbbe775eSNeil Armstrong 293bbbe775eSNeil Armstrong /* eotf matrix bypass */ 294bbbe775eSNeil Armstrong meson_viu_set_osd_matrix(priv, VIU_MATRIX_OSD_EOTF, 295bbbe775eSNeil Armstrong eotf_bypass_coeff, 296bbbe775eSNeil Armstrong false); 297bbbe775eSNeil Armstrong 298bbbe775eSNeil Armstrong /* oetf lut bypass */ 299bbbe775eSNeil Armstrong meson_viu_set_osd_lut(priv, VIU_LUT_OSD_OETF, 300bbbe775eSNeil Armstrong oetf_41_linear_mapping, /* R */ 301bbbe775eSNeil Armstrong oetf_41_linear_mapping, /* G */ 302bbbe775eSNeil Armstrong oetf_41_linear_mapping, /* B */ 303bbbe775eSNeil Armstrong false); 304bbbe775eSNeil Armstrong 305bbbe775eSNeil Armstrong /* osd matrix RGB709 to YUV709 limit */ 306bbbe775eSNeil Armstrong meson_viu_set_osd_matrix(priv, VIU_MATRIX_OSD, 307bbbe775eSNeil Armstrong RGB709_to_YUV709l_coeff, 308bbbe775eSNeil Armstrong true); 309bbbe775eSNeil Armstrong } 310bbbe775eSNeil Armstrong 3113a936bc2SNeil Armstrong /* VIU OSD1 Reset as workaround for GXL+ Alpha OSD Bug */ 3123a936bc2SNeil Armstrong void meson_viu_osd1_reset(struct meson_drm *priv) 3133a936bc2SNeil Armstrong { 3143a936bc2SNeil Armstrong uint32_t osd1_fifo_ctrl_stat, osd1_ctrl_stat2; 3153a936bc2SNeil Armstrong 3163a936bc2SNeil Armstrong /* Save these 2 registers state */ 3173a936bc2SNeil Armstrong osd1_fifo_ctrl_stat = readl_relaxed( 3183a936bc2SNeil Armstrong priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT)); 3193a936bc2SNeil Armstrong osd1_ctrl_stat2 = readl_relaxed( 3203a936bc2SNeil Armstrong priv->io_base + _REG(VIU_OSD1_CTRL_STAT2)); 3213a936bc2SNeil Armstrong 3223a936bc2SNeil Armstrong /* Reset OSD1 */ 323147ae1cbSJulien Masson writel_bits_relaxed(VIU_SW_RESET_OSD1, VIU_SW_RESET_OSD1, 3243a936bc2SNeil Armstrong priv->io_base + _REG(VIU_SW_RESET)); 325147ae1cbSJulien Masson writel_bits_relaxed(VIU_SW_RESET_OSD1, 0, 3263a936bc2SNeil Armstrong priv->io_base + _REG(VIU_SW_RESET)); 3273a936bc2SNeil Armstrong 3283a936bc2SNeil Armstrong /* Rewrite these registers state lost in the reset */ 3293a936bc2SNeil Armstrong writel_relaxed(osd1_fifo_ctrl_stat, 3303a936bc2SNeil Armstrong priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT)); 3313a936bc2SNeil Armstrong writel_relaxed(osd1_ctrl_stat2, 3323a936bc2SNeil Armstrong priv->io_base + _REG(VIU_OSD1_CTRL_STAT2)); 3333a936bc2SNeil Armstrong 3343a936bc2SNeil Armstrong /* Reload the conversion matrix */ 3353a936bc2SNeil Armstrong meson_viu_load_matrix(priv); 3363a936bc2SNeil Armstrong } 3373a936bc2SNeil Armstrong 338147ae1cbSJulien Masson static inline uint32_t meson_viu_osd_burst_length_reg(uint32_t length) 339147ae1cbSJulien Masson { 340147ae1cbSJulien Masson uint32_t val = (((length & 0x80) % 24) / 12); 341147ae1cbSJulien Masson 342147ae1cbSJulien Masson return (((val & 0x3) << 10) | (((val & 0x4) >> 2) << 31)); 343147ae1cbSJulien Masson } 344147ae1cbSJulien Masson 345bbbe775eSNeil Armstrong void meson_viu_init(struct meson_drm *priv) 346bbbe775eSNeil Armstrong { 347bbbe775eSNeil Armstrong uint32_t reg; 348bbbe775eSNeil Armstrong 349bbbe775eSNeil Armstrong /* Disable OSDs */ 350147ae1cbSJulien Masson writel_bits_relaxed(VIU_OSD1_OSD_BLK_ENABLE | VIU_OSD1_OSD_ENABLE, 0, 351bbbe775eSNeil Armstrong priv->io_base + _REG(VIU_OSD1_CTRL_STAT)); 352147ae1cbSJulien Masson writel_bits_relaxed(VIU_OSD1_OSD_BLK_ENABLE | VIU_OSD1_OSD_ENABLE, 0, 353bbbe775eSNeil Armstrong priv->io_base + _REG(VIU_OSD2_CTRL_STAT)); 354bbbe775eSNeil Armstrong 355bbbe775eSNeil Armstrong /* On GXL/GXM, Use the 10bit HDR conversion matrix */ 356528a25d0SJulien Masson if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) || 357528a25d0SJulien Masson meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL)) 358bbbe775eSNeil Armstrong meson_viu_load_matrix(priv); 359528a25d0SJulien Masson else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) 36072888394SNeil Armstrong meson_viu_set_g12a_osd1_matrix(priv, RGB709_to_YUV709l_coeff, 36172888394SNeil Armstrong true); 362bbbe775eSNeil Armstrong 363bbbe775eSNeil Armstrong /* Initialize OSD1 fifo control register */ 364147ae1cbSJulien Masson reg = VIU_OSD_DDR_PRIORITY_URGENT | 365147ae1cbSJulien Masson VIU_OSD_HOLD_FIFO_LINES(4) | 366147ae1cbSJulien Masson VIU_OSD_FIFO_DEPTH_VAL(32) | /* fifo_depth_val: 32*8=256 */ 367147ae1cbSJulien Masson VIU_OSD_WORDS_PER_BURST(4) | /* 4 words in 1 burst */ 368147ae1cbSJulien Masson VIU_OSD_FIFO_LIMITS(2); /* fifo_lim: 2*16=32 */ 369147ae1cbSJulien Masson 370528a25d0SJulien Masson if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) 371147ae1cbSJulien Masson reg |= meson_viu_osd_burst_length_reg(32); 37272888394SNeil Armstrong else 373147ae1cbSJulien Masson reg |= meson_viu_osd_burst_length_reg(64); 374147ae1cbSJulien Masson 375bbbe775eSNeil Armstrong writel_relaxed(reg, priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT)); 376bbbe775eSNeil Armstrong writel_relaxed(reg, priv->io_base + _REG(VIU_OSD2_FIFO_CTRL_STAT)); 377bbbe775eSNeil Armstrong 378bbbe775eSNeil Armstrong /* Set OSD alpha replace value */ 379bbbe775eSNeil Armstrong writel_bits_relaxed(0xff << OSD_REPLACE_SHIFT, 380bbbe775eSNeil Armstrong 0xff << OSD_REPLACE_SHIFT, 381bbbe775eSNeil Armstrong priv->io_base + _REG(VIU_OSD1_CTRL_STAT2)); 382bbbe775eSNeil Armstrong writel_bits_relaxed(0xff << OSD_REPLACE_SHIFT, 383bbbe775eSNeil Armstrong 0xff << OSD_REPLACE_SHIFT, 384bbbe775eSNeil Armstrong priv->io_base + _REG(VIU_OSD2_CTRL_STAT2)); 385bbbe775eSNeil Armstrong 386f9a23481SNeil Armstrong /* Disable VD1 AFBC */ 387147ae1cbSJulien Masson /* di_mif0_en=0 mif0_to_vpp_en=0 di_mad_en=0 and afbc vd1 set=0*/ 388147ae1cbSJulien Masson writel_bits_relaxed(VIU_CTRL0_VD1_AFBC_MASK, 0, 389f9a23481SNeil Armstrong priv->io_base + _REG(VIU_MISC_CTRL0)); 390f9a23481SNeil Armstrong writel_relaxed(0, priv->io_base + _REG(AFBC_ENABLE)); 391f9a23481SNeil Armstrong 392f9a23481SNeil Armstrong writel_relaxed(0x00FF00C0, 393f9a23481SNeil Armstrong priv->io_base + _REG(VD1_IF0_LUMA_FIFO_SIZE)); 394f9a23481SNeil Armstrong writel_relaxed(0x00FF00C0, 395f9a23481SNeil Armstrong priv->io_base + _REG(VD2_IF0_LUMA_FIFO_SIZE)); 396f9a23481SNeil Armstrong 397528a25d0SJulien Masson if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) { 398147ae1cbSJulien Masson writel_relaxed(VIU_OSD_BLEND_REORDER(0, 1) | 399147ae1cbSJulien Masson VIU_OSD_BLEND_REORDER(1, 0) | 400147ae1cbSJulien Masson VIU_OSD_BLEND_REORDER(2, 0) | 401147ae1cbSJulien Masson VIU_OSD_BLEND_REORDER(3, 0) | 402147ae1cbSJulien Masson VIU_OSD_BLEND_DIN_EN(1) | 403147ae1cbSJulien Masson VIU_OSD_BLEND1_DIN3_BYPASS_TO_DOUT1 | 404147ae1cbSJulien Masson VIU_OSD_BLEND1_DOUT_BYPASS_TO_BLEND2 | 405147ae1cbSJulien Masson VIU_OSD_BLEND_DIN0_BYPASS_TO_DOUT0 | 406147ae1cbSJulien Masson VIU_OSD_BLEND_BLEN2_PREMULT_EN(1) | 407147ae1cbSJulien Masson VIU_OSD_BLEND_HOLD_LINES(4), 40872888394SNeil Armstrong priv->io_base + _REG(VIU_OSD_BLEND_CTRL)); 409147ae1cbSJulien Masson 410147ae1cbSJulien Masson writel_relaxed(OSD_BLEND_PATH_SEL_ENABLE, 41172888394SNeil Armstrong priv->io_base + _REG(OSD1_BLEND_SRC_CTRL)); 412147ae1cbSJulien Masson writel_relaxed(OSD_BLEND_PATH_SEL_ENABLE, 41372888394SNeil Armstrong priv->io_base + _REG(OSD2_BLEND_SRC_CTRL)); 41472888394SNeil Armstrong writel_relaxed(0, priv->io_base + _REG(VD1_BLEND_SRC_CTRL)); 41572888394SNeil Armstrong writel_relaxed(0, priv->io_base + _REG(VD2_BLEND_SRC_CTRL)); 41672888394SNeil Armstrong writel_relaxed(0, 41772888394SNeil Armstrong priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_DATA0)); 41872888394SNeil Armstrong writel_relaxed(0, 41972888394SNeil Armstrong priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_ALPHA)); 420147ae1cbSJulien Masson 421147ae1cbSJulien Masson writel_bits_relaxed(DOLBY_BYPASS_EN(0xc), DOLBY_BYPASS_EN(0xc), 42272888394SNeil Armstrong priv->io_base + _REG(DOLBY_PATH_CTRL)); 42372888394SNeil Armstrong } 424f9a23481SNeil Armstrong 425bbbe775eSNeil Armstrong priv->viu.osd1_enabled = false; 426bbbe775eSNeil Armstrong priv->viu.osd1_commit = false; 427bbbe775eSNeil Armstrong priv->viu.osd1_interlace = false; 428bbbe775eSNeil Armstrong } 429