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> 101b85270fSNeil Armstrong #include <linux/bitfield.h> 111b85270fSNeil Armstrong 121b85270fSNeil Armstrong #include <drm/drm_fourcc.h> 1366620f48SSam Ravnborg 14bbbe775eSNeil Armstrong #include "meson_drv.h" 15bbbe775eSNeil Armstrong #include "meson_viu.h" 16bbbe775eSNeil Armstrong #include "meson_registers.h" 17bbbe775eSNeil Armstrong 182021d5b7SNeil Armstrong /** 192021d5b7SNeil Armstrong * DOC: Video Input Unit 202021d5b7SNeil Armstrong * 21bbbe775eSNeil Armstrong * VIU Handles the Pixel scanout and the basic Colorspace conversions 22bbbe775eSNeil Armstrong * We handle the following features : 232021d5b7SNeil Armstrong * 24bbbe775eSNeil Armstrong * - OSD1 RGB565/RGB888/xRGB8888 scanout 25bbbe775eSNeil Armstrong * - RGB conversion to x/cb/cr 26bbbe775eSNeil Armstrong * - Progressive or Interlace buffer scanout 27bbbe775eSNeil Armstrong * - OSD1 Commit on Vsync 28bbbe775eSNeil Armstrong * - HDR OSD matrix for GXL/GXM 29bbbe775eSNeil Armstrong * 30bbbe775eSNeil Armstrong * What is missing : 312021d5b7SNeil Armstrong * 32bbbe775eSNeil Armstrong * - BGR888/xBGR8888/BGRx8888/BGRx8888 modes 33bbbe775eSNeil Armstrong * - YUV4:2:2 Y0CbY1Cr scanout 34bbbe775eSNeil Armstrong * - Conversion to YUV 4:4:4 from 4:2:2 input 35bbbe775eSNeil Armstrong * - Colorkey Alpha matching 36bbbe775eSNeil Armstrong * - Big endian scanout 37bbbe775eSNeil Armstrong * - X/Y reverse scanout 38bbbe775eSNeil Armstrong * - Global alpha setup 39bbbe775eSNeil Armstrong * - OSD2 support, would need interlace switching on vsync 40bbbe775eSNeil Armstrong * - OSD1 full scaling to support TV overscan 41bbbe775eSNeil Armstrong */ 42bbbe775eSNeil Armstrong 43bbbe775eSNeil Armstrong /* OSD csc defines */ 44bbbe775eSNeil Armstrong 45bbbe775eSNeil Armstrong enum viu_matrix_sel_e { 46bbbe775eSNeil Armstrong VIU_MATRIX_OSD_EOTF = 0, 47bbbe775eSNeil Armstrong VIU_MATRIX_OSD, 48bbbe775eSNeil Armstrong }; 49bbbe775eSNeil Armstrong 50bbbe775eSNeil Armstrong enum viu_lut_sel_e { 51bbbe775eSNeil Armstrong VIU_LUT_OSD_EOTF = 0, 52bbbe775eSNeil Armstrong VIU_LUT_OSD_OETF, 53bbbe775eSNeil Armstrong }; 54bbbe775eSNeil Armstrong 55bbbe775eSNeil Armstrong #define COEFF_NORM(a) ((int)((((a) * 2048.0) + 1) / 2)) 56bbbe775eSNeil Armstrong #define MATRIX_5X3_COEF_SIZE 24 57bbbe775eSNeil Armstrong 58bbbe775eSNeil Armstrong #define EOTF_COEFF_NORM(a) ((int)((((a) * 4096.0) + 1) / 2)) 59bbbe775eSNeil Armstrong #define EOTF_COEFF_SIZE 10 60bbbe775eSNeil Armstrong #define EOTF_COEFF_RIGHTSHIFT 1 61bbbe775eSNeil Armstrong 62bbbe775eSNeil Armstrong static int RGB709_to_YUV709l_coeff[MATRIX_5X3_COEF_SIZE] = { 63bbbe775eSNeil Armstrong 0, 0, 0, /* pre offset */ 64bbbe775eSNeil Armstrong COEFF_NORM(0.181873), COEFF_NORM(0.611831), COEFF_NORM(0.061765), 65bbbe775eSNeil Armstrong COEFF_NORM(-0.100251), COEFF_NORM(-0.337249), COEFF_NORM(0.437500), 66bbbe775eSNeil Armstrong COEFF_NORM(0.437500), COEFF_NORM(-0.397384), COEFF_NORM(-0.040116), 67bbbe775eSNeil Armstrong 0, 0, 0, /* 10'/11'/12' */ 68bbbe775eSNeil Armstrong 0, 0, 0, /* 20'/21'/22' */ 69bbbe775eSNeil Armstrong 64, 512, 512, /* offset */ 70bbbe775eSNeil Armstrong 0, 0, 0 /* mode, right_shift, clip_en */ 71bbbe775eSNeil Armstrong }; 72bbbe775eSNeil Armstrong 73bbbe775eSNeil Armstrong /* eotf matrix: bypass */ 74bbbe775eSNeil Armstrong static int eotf_bypass_coeff[EOTF_COEFF_SIZE] = { 75bbbe775eSNeil Armstrong EOTF_COEFF_NORM(1.0), EOTF_COEFF_NORM(0.0), EOTF_COEFF_NORM(0.0), 76bbbe775eSNeil Armstrong EOTF_COEFF_NORM(0.0), EOTF_COEFF_NORM(1.0), EOTF_COEFF_NORM(0.0), 77bbbe775eSNeil Armstrong EOTF_COEFF_NORM(0.0), EOTF_COEFF_NORM(0.0), EOTF_COEFF_NORM(1.0), 78bbbe775eSNeil Armstrong EOTF_COEFF_RIGHTSHIFT /* right shift */ 79bbbe775eSNeil Armstrong }; 80bbbe775eSNeil Armstrong 812ccb8433SYueHaibing static void meson_viu_set_g12a_osd1_matrix(struct meson_drm *priv, 822ccb8433SYueHaibing int *m, bool csc_on) 8372888394SNeil Armstrong { 8472888394SNeil Armstrong /* VPP WRAP OSD1 matrix */ 8572888394SNeil Armstrong writel(((m[0] & 0xfff) << 16) | (m[1] & 0xfff), 8672888394SNeil Armstrong priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET0_1)); 8772888394SNeil Armstrong writel(m[2] & 0xfff, 8872888394SNeil Armstrong priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET2)); 8972888394SNeil Armstrong writel(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff), 9072888394SNeil Armstrong priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF00_01)); 9172888394SNeil Armstrong writel(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff), 9272888394SNeil Armstrong priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF02_10)); 9372888394SNeil Armstrong writel(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff), 9472888394SNeil Armstrong priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF11_12)); 9572888394SNeil Armstrong writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff), 9672888394SNeil Armstrong priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF20_21)); 9772888394SNeil Armstrong writel((m[11] & 0x1fff) << 16, 9872888394SNeil Armstrong priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF22)); 9972888394SNeil Armstrong 10072888394SNeil Armstrong writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff), 10172888394SNeil Armstrong priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET0_1)); 10272888394SNeil Armstrong writel(m[20] & 0xfff, 10372888394SNeil Armstrong priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET2)); 10472888394SNeil Armstrong 10572888394SNeil Armstrong writel_bits_relaxed(BIT(0), csc_on ? BIT(0) : 0, 10672888394SNeil Armstrong priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL)); 10772888394SNeil Armstrong } 10872888394SNeil Armstrong 1092ccb8433SYueHaibing static void meson_viu_set_osd_matrix(struct meson_drm *priv, 110bbbe775eSNeil Armstrong enum viu_matrix_sel_e m_select, 111bbbe775eSNeil Armstrong int *m, bool csc_on) 112bbbe775eSNeil Armstrong { 113bbbe775eSNeil Armstrong if (m_select == VIU_MATRIX_OSD) { 114bbbe775eSNeil Armstrong /* osd matrix, VIU_MATRIX_0 */ 115bbbe775eSNeil Armstrong writel(((m[0] & 0xfff) << 16) | (m[1] & 0xfff), 116bbbe775eSNeil Armstrong priv->io_base + _REG(VIU_OSD1_MATRIX_PRE_OFFSET0_1)); 117bbbe775eSNeil Armstrong writel(m[2] & 0xfff, 118bbbe775eSNeil Armstrong priv->io_base + _REG(VIU_OSD1_MATRIX_PRE_OFFSET2)); 119bbbe775eSNeil Armstrong writel(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff), 120bbbe775eSNeil Armstrong priv->io_base + _REG(VIU_OSD1_MATRIX_COEF00_01)); 121bbbe775eSNeil Armstrong writel(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff), 122bbbe775eSNeil Armstrong priv->io_base + _REG(VIU_OSD1_MATRIX_COEF02_10)); 123bbbe775eSNeil Armstrong writel(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff), 124bbbe775eSNeil Armstrong priv->io_base + _REG(VIU_OSD1_MATRIX_COEF11_12)); 125bbbe775eSNeil Armstrong writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff), 126bbbe775eSNeil Armstrong priv->io_base + _REG(VIU_OSD1_MATRIX_COEF20_21)); 127bbbe775eSNeil Armstrong 128bbbe775eSNeil Armstrong if (m[21]) { 129bbbe775eSNeil Armstrong writel(((m[11] & 0x1fff) << 16) | (m[12] & 0x1fff), 130bbbe775eSNeil Armstrong priv->io_base + 131bbbe775eSNeil Armstrong _REG(VIU_OSD1_MATRIX_COEF22_30)); 132bbbe775eSNeil Armstrong writel(((m[13] & 0x1fff) << 16) | (m[14] & 0x1fff), 133bbbe775eSNeil Armstrong priv->io_base + 134bbbe775eSNeil Armstrong _REG(VIU_OSD1_MATRIX_COEF31_32)); 135bbbe775eSNeil Armstrong writel(((m[15] & 0x1fff) << 16) | (m[16] & 0x1fff), 136bbbe775eSNeil Armstrong priv->io_base + 137bbbe775eSNeil Armstrong _REG(VIU_OSD1_MATRIX_COEF40_41)); 138bbbe775eSNeil Armstrong writel(m[17] & 0x1fff, priv->io_base + 139bbbe775eSNeil Armstrong _REG(VIU_OSD1_MATRIX_COLMOD_COEF42)); 140bbbe775eSNeil Armstrong } else 141bbbe775eSNeil Armstrong writel((m[11] & 0x1fff) << 16, priv->io_base + 142bbbe775eSNeil Armstrong _REG(VIU_OSD1_MATRIX_COEF22_30)); 143bbbe775eSNeil Armstrong 144bbbe775eSNeil Armstrong writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff), 145bbbe775eSNeil Armstrong priv->io_base + _REG(VIU_OSD1_MATRIX_OFFSET0_1)); 146bbbe775eSNeil Armstrong writel(m[20] & 0xfff, 147bbbe775eSNeil Armstrong priv->io_base + _REG(VIU_OSD1_MATRIX_OFFSET2)); 148bbbe775eSNeil Armstrong 149bbbe775eSNeil Armstrong writel_bits_relaxed(3 << 30, m[21] << 30, 150bbbe775eSNeil Armstrong priv->io_base + _REG(VIU_OSD1_MATRIX_COLMOD_COEF42)); 151bbbe775eSNeil Armstrong writel_bits_relaxed(7 << 16, m[22] << 16, 152bbbe775eSNeil Armstrong priv->io_base + _REG(VIU_OSD1_MATRIX_COLMOD_COEF42)); 153bbbe775eSNeil Armstrong 154bbbe775eSNeil Armstrong /* 23 reserved for clipping control */ 155bbbe775eSNeil Armstrong writel_bits_relaxed(BIT(0), csc_on ? BIT(0) : 0, 156bbbe775eSNeil Armstrong priv->io_base + _REG(VIU_OSD1_MATRIX_CTRL)); 157bbbe775eSNeil Armstrong writel_bits_relaxed(BIT(1), 0, 158bbbe775eSNeil Armstrong priv->io_base + _REG(VIU_OSD1_MATRIX_CTRL)); 159bbbe775eSNeil Armstrong } else if (m_select == VIU_MATRIX_OSD_EOTF) { 160bbbe775eSNeil Armstrong int i; 161bbbe775eSNeil Armstrong 162bbbe775eSNeil Armstrong /* osd eotf matrix, VIU_MATRIX_OSD_EOTF */ 163bbbe775eSNeil Armstrong for (i = 0; i < 5; i++) 164bbbe775eSNeil Armstrong writel(((m[i * 2] & 0x1fff) << 16) | 165bbbe775eSNeil Armstrong (m[i * 2 + 1] & 0x1fff), priv->io_base + 166bbbe775eSNeil Armstrong _REG(VIU_OSD1_EOTF_CTL + i + 1)); 167bbbe775eSNeil Armstrong 168bbbe775eSNeil Armstrong writel_bits_relaxed(BIT(30), csc_on ? BIT(30) : 0, 169bbbe775eSNeil Armstrong priv->io_base + _REG(VIU_OSD1_EOTF_CTL)); 170bbbe775eSNeil Armstrong writel_bits_relaxed(BIT(31), csc_on ? BIT(31) : 0, 171bbbe775eSNeil Armstrong priv->io_base + _REG(VIU_OSD1_EOTF_CTL)); 172bbbe775eSNeil Armstrong } 173bbbe775eSNeil Armstrong } 174bbbe775eSNeil Armstrong 175bbbe775eSNeil Armstrong #define OSD_EOTF_LUT_SIZE 33 176bbbe775eSNeil Armstrong #define OSD_OETF_LUT_SIZE 41 177bbbe775eSNeil Armstrong 1782ccb8433SYueHaibing static void 1792ccb8433SYueHaibing meson_viu_set_osd_lut(struct meson_drm *priv, enum viu_lut_sel_e lut_sel, 180bbbe775eSNeil Armstrong unsigned int *r_map, unsigned int *g_map, 1812ccb8433SYueHaibing unsigned int *b_map, bool csc_on) 182bbbe775eSNeil Armstrong { 183bbbe775eSNeil Armstrong unsigned int addr_port; 184bbbe775eSNeil Armstrong unsigned int data_port; 185bbbe775eSNeil Armstrong unsigned int ctrl_port; 186bbbe775eSNeil Armstrong int i; 187bbbe775eSNeil Armstrong 188bbbe775eSNeil Armstrong if (lut_sel == VIU_LUT_OSD_EOTF) { 189bbbe775eSNeil Armstrong addr_port = VIU_OSD1_EOTF_LUT_ADDR_PORT; 190bbbe775eSNeil Armstrong data_port = VIU_OSD1_EOTF_LUT_DATA_PORT; 191bbbe775eSNeil Armstrong ctrl_port = VIU_OSD1_EOTF_CTL; 192bbbe775eSNeil Armstrong } else if (lut_sel == VIU_LUT_OSD_OETF) { 193bbbe775eSNeil Armstrong addr_port = VIU_OSD1_OETF_LUT_ADDR_PORT; 194bbbe775eSNeil Armstrong data_port = VIU_OSD1_OETF_LUT_DATA_PORT; 195bbbe775eSNeil Armstrong ctrl_port = VIU_OSD1_OETF_CTL; 196bbbe775eSNeil Armstrong } else 197bbbe775eSNeil Armstrong return; 198bbbe775eSNeil Armstrong 199bbbe775eSNeil Armstrong if (lut_sel == VIU_LUT_OSD_OETF) { 200bbbe775eSNeil Armstrong writel(0, priv->io_base + _REG(addr_port)); 201bbbe775eSNeil Armstrong 20297b2a318SLyude Paul for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++) 203bbbe775eSNeil Armstrong writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16), 204bbbe775eSNeil Armstrong priv->io_base + _REG(data_port)); 205bbbe775eSNeil Armstrong 206bbbe775eSNeil Armstrong writel(r_map[OSD_OETF_LUT_SIZE - 1] | (g_map[0] << 16), 207bbbe775eSNeil Armstrong priv->io_base + _REG(data_port)); 208bbbe775eSNeil Armstrong 20997b2a318SLyude Paul for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++) 210bbbe775eSNeil Armstrong writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16), 211bbbe775eSNeil Armstrong priv->io_base + _REG(data_port)); 212bbbe775eSNeil Armstrong 21397b2a318SLyude Paul for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++) 214bbbe775eSNeil Armstrong writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16), 215bbbe775eSNeil Armstrong priv->io_base + _REG(data_port)); 216bbbe775eSNeil Armstrong 217bbbe775eSNeil Armstrong writel(b_map[OSD_OETF_LUT_SIZE - 1], 218bbbe775eSNeil Armstrong priv->io_base + _REG(data_port)); 219bbbe775eSNeil Armstrong 220bbbe775eSNeil Armstrong if (csc_on) 221bbbe775eSNeil Armstrong writel_bits_relaxed(0x7 << 29, 7 << 29, 222bbbe775eSNeil Armstrong priv->io_base + _REG(ctrl_port)); 223bbbe775eSNeil Armstrong else 224bbbe775eSNeil Armstrong writel_bits_relaxed(0x7 << 29, 0, 225bbbe775eSNeil Armstrong priv->io_base + _REG(ctrl_port)); 226bbbe775eSNeil Armstrong } else if (lut_sel == VIU_LUT_OSD_EOTF) { 227bbbe775eSNeil Armstrong writel(0, priv->io_base + _REG(addr_port)); 228bbbe775eSNeil Armstrong 22997b2a318SLyude Paul for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++) 230bbbe775eSNeil Armstrong writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16), 231bbbe775eSNeil Armstrong priv->io_base + _REG(data_port)); 232bbbe775eSNeil Armstrong 233bbbe775eSNeil Armstrong writel(r_map[OSD_EOTF_LUT_SIZE - 1] | (g_map[0] << 16), 234bbbe775eSNeil Armstrong priv->io_base + _REG(data_port)); 235bbbe775eSNeil Armstrong 23697b2a318SLyude Paul for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++) 237bbbe775eSNeil Armstrong writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16), 238bbbe775eSNeil Armstrong priv->io_base + _REG(data_port)); 239bbbe775eSNeil Armstrong 24097b2a318SLyude Paul for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++) 241bbbe775eSNeil Armstrong writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16), 242bbbe775eSNeil Armstrong priv->io_base + _REG(data_port)); 243bbbe775eSNeil Armstrong 244bbbe775eSNeil Armstrong writel(b_map[OSD_EOTF_LUT_SIZE - 1], 245bbbe775eSNeil Armstrong priv->io_base + _REG(data_port)); 246bbbe775eSNeil Armstrong 247bbbe775eSNeil Armstrong if (csc_on) 248bbbe775eSNeil Armstrong writel_bits_relaxed(7 << 27, 7 << 27, 249bbbe775eSNeil Armstrong priv->io_base + _REG(ctrl_port)); 250bbbe775eSNeil Armstrong else 251bbbe775eSNeil Armstrong writel_bits_relaxed(7 << 27, 0, 252bbbe775eSNeil Armstrong priv->io_base + _REG(ctrl_port)); 253bbbe775eSNeil Armstrong 254bbbe775eSNeil Armstrong writel_bits_relaxed(BIT(31), BIT(31), 255bbbe775eSNeil Armstrong priv->io_base + _REG(ctrl_port)); 256bbbe775eSNeil Armstrong } 257bbbe775eSNeil Armstrong } 258bbbe775eSNeil Armstrong 259bbbe775eSNeil Armstrong /* eotf lut: linear */ 260bbbe775eSNeil Armstrong static unsigned int eotf_33_linear_mapping[OSD_EOTF_LUT_SIZE] = { 261bbbe775eSNeil Armstrong 0x0000, 0x0200, 0x0400, 0x0600, 262bbbe775eSNeil Armstrong 0x0800, 0x0a00, 0x0c00, 0x0e00, 263bbbe775eSNeil Armstrong 0x1000, 0x1200, 0x1400, 0x1600, 264bbbe775eSNeil Armstrong 0x1800, 0x1a00, 0x1c00, 0x1e00, 265bbbe775eSNeil Armstrong 0x2000, 0x2200, 0x2400, 0x2600, 266bbbe775eSNeil Armstrong 0x2800, 0x2a00, 0x2c00, 0x2e00, 267bbbe775eSNeil Armstrong 0x3000, 0x3200, 0x3400, 0x3600, 268bbbe775eSNeil Armstrong 0x3800, 0x3a00, 0x3c00, 0x3e00, 269bbbe775eSNeil Armstrong 0x4000 270bbbe775eSNeil Armstrong }; 271bbbe775eSNeil Armstrong 272bbbe775eSNeil Armstrong /* osd oetf lut: linear */ 273bbbe775eSNeil Armstrong static unsigned int oetf_41_linear_mapping[OSD_OETF_LUT_SIZE] = { 274bbbe775eSNeil Armstrong 0, 0, 0, 0, 275bbbe775eSNeil Armstrong 0, 32, 64, 96, 276bbbe775eSNeil Armstrong 128, 160, 196, 224, 277bbbe775eSNeil Armstrong 256, 288, 320, 352, 278bbbe775eSNeil Armstrong 384, 416, 448, 480, 279bbbe775eSNeil Armstrong 512, 544, 576, 608, 280bbbe775eSNeil Armstrong 640, 672, 704, 736, 281bbbe775eSNeil Armstrong 768, 800, 832, 864, 282bbbe775eSNeil Armstrong 896, 928, 960, 992, 283bbbe775eSNeil Armstrong 1023, 1023, 1023, 1023, 284bbbe775eSNeil Armstrong 1023 285bbbe775eSNeil Armstrong }; 286bbbe775eSNeil Armstrong 287bbbe775eSNeil Armstrong static void meson_viu_load_matrix(struct meson_drm *priv) 288bbbe775eSNeil Armstrong { 289bbbe775eSNeil Armstrong /* eotf lut bypass */ 290bbbe775eSNeil Armstrong meson_viu_set_osd_lut(priv, VIU_LUT_OSD_EOTF, 291bbbe775eSNeil Armstrong eotf_33_linear_mapping, /* R */ 292bbbe775eSNeil Armstrong eotf_33_linear_mapping, /* G */ 293bbbe775eSNeil Armstrong eotf_33_linear_mapping, /* B */ 294bbbe775eSNeil Armstrong false); 295bbbe775eSNeil Armstrong 296bbbe775eSNeil Armstrong /* eotf matrix bypass */ 297bbbe775eSNeil Armstrong meson_viu_set_osd_matrix(priv, VIU_MATRIX_OSD_EOTF, 298bbbe775eSNeil Armstrong eotf_bypass_coeff, 299bbbe775eSNeil Armstrong false); 300bbbe775eSNeil Armstrong 301bbbe775eSNeil Armstrong /* oetf lut bypass */ 302bbbe775eSNeil Armstrong meson_viu_set_osd_lut(priv, VIU_LUT_OSD_OETF, 303bbbe775eSNeil Armstrong oetf_41_linear_mapping, /* R */ 304bbbe775eSNeil Armstrong oetf_41_linear_mapping, /* G */ 305bbbe775eSNeil Armstrong oetf_41_linear_mapping, /* B */ 306bbbe775eSNeil Armstrong false); 307bbbe775eSNeil Armstrong 308bbbe775eSNeil Armstrong /* osd matrix RGB709 to YUV709 limit */ 309bbbe775eSNeil Armstrong meson_viu_set_osd_matrix(priv, VIU_MATRIX_OSD, 310bbbe775eSNeil Armstrong RGB709_to_YUV709l_coeff, 311bbbe775eSNeil Armstrong true); 312bbbe775eSNeil Armstrong } 313bbbe775eSNeil Armstrong 3143a936bc2SNeil Armstrong /* VIU OSD1 Reset as workaround for GXL+ Alpha OSD Bug */ 3153a936bc2SNeil Armstrong void meson_viu_osd1_reset(struct meson_drm *priv) 3163a936bc2SNeil Armstrong { 3173a936bc2SNeil Armstrong uint32_t osd1_fifo_ctrl_stat, osd1_ctrl_stat2; 3183a936bc2SNeil Armstrong 3193a936bc2SNeil Armstrong /* Save these 2 registers state */ 3203a936bc2SNeil Armstrong osd1_fifo_ctrl_stat = readl_relaxed( 3213a936bc2SNeil Armstrong priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT)); 3223a936bc2SNeil Armstrong osd1_ctrl_stat2 = readl_relaxed( 3233a936bc2SNeil Armstrong priv->io_base + _REG(VIU_OSD1_CTRL_STAT2)); 3243a936bc2SNeil Armstrong 3253a936bc2SNeil Armstrong /* Reset OSD1 */ 326147ae1cbSJulien Masson writel_bits_relaxed(VIU_SW_RESET_OSD1, VIU_SW_RESET_OSD1, 3273a936bc2SNeil Armstrong priv->io_base + _REG(VIU_SW_RESET)); 328147ae1cbSJulien Masson writel_bits_relaxed(VIU_SW_RESET_OSD1, 0, 3293a936bc2SNeil Armstrong priv->io_base + _REG(VIU_SW_RESET)); 3303a936bc2SNeil Armstrong 3313a936bc2SNeil Armstrong /* Rewrite these registers state lost in the reset */ 3323a936bc2SNeil Armstrong writel_relaxed(osd1_fifo_ctrl_stat, 3333a936bc2SNeil Armstrong priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT)); 3343a936bc2SNeil Armstrong writel_relaxed(osd1_ctrl_stat2, 3353a936bc2SNeil Armstrong priv->io_base + _REG(VIU_OSD1_CTRL_STAT2)); 3363a936bc2SNeil Armstrong 3373a936bc2SNeil Armstrong /* Reload the conversion matrix */ 3383a936bc2SNeil Armstrong meson_viu_load_matrix(priv); 3393a936bc2SNeil Armstrong } 3403a936bc2SNeil Armstrong 3411b85270fSNeil Armstrong #define OSD1_MALI_ORDER_ABGR \ 3421b85270fSNeil Armstrong (FIELD_PREP(VIU_OSD1_MALI_AFBCD_A_REORDER, \ 3431b85270fSNeil Armstrong VIU_OSD1_MALI_REORDER_A) | \ 3441b85270fSNeil Armstrong FIELD_PREP(VIU_OSD1_MALI_AFBCD_B_REORDER, \ 3451b85270fSNeil Armstrong VIU_OSD1_MALI_REORDER_B) | \ 3461b85270fSNeil Armstrong FIELD_PREP(VIU_OSD1_MALI_AFBCD_G_REORDER, \ 3471b85270fSNeil Armstrong VIU_OSD1_MALI_REORDER_G) | \ 3481b85270fSNeil Armstrong FIELD_PREP(VIU_OSD1_MALI_AFBCD_R_REORDER, \ 3491b85270fSNeil Armstrong VIU_OSD1_MALI_REORDER_R)) 3501b85270fSNeil Armstrong 3511b85270fSNeil Armstrong #define OSD1_MALI_ORDER_ARGB \ 3521b85270fSNeil Armstrong (FIELD_PREP(VIU_OSD1_MALI_AFBCD_A_REORDER, \ 3531b85270fSNeil Armstrong VIU_OSD1_MALI_REORDER_A) | \ 3541b85270fSNeil Armstrong FIELD_PREP(VIU_OSD1_MALI_AFBCD_B_REORDER, \ 3551b85270fSNeil Armstrong VIU_OSD1_MALI_REORDER_R) | \ 3561b85270fSNeil Armstrong FIELD_PREP(VIU_OSD1_MALI_AFBCD_G_REORDER, \ 3571b85270fSNeil Armstrong VIU_OSD1_MALI_REORDER_G) | \ 3581b85270fSNeil Armstrong FIELD_PREP(VIU_OSD1_MALI_AFBCD_R_REORDER, \ 3591b85270fSNeil Armstrong VIU_OSD1_MALI_REORDER_B)) 3601b85270fSNeil Armstrong 3611b85270fSNeil Armstrong void meson_viu_g12a_enable_osd1_afbc(struct meson_drm *priv) 3621b85270fSNeil Armstrong { 3631b85270fSNeil Armstrong u32 afbc_order = OSD1_MALI_ORDER_ARGB; 3641b85270fSNeil Armstrong 3651b85270fSNeil Armstrong /* Enable Mali AFBC Unpack */ 3661b85270fSNeil Armstrong writel_bits_relaxed(VIU_OSD1_MALI_UNPACK_EN, 3671b85270fSNeil Armstrong VIU_OSD1_MALI_UNPACK_EN, 3681b85270fSNeil Armstrong priv->io_base + _REG(VIU_OSD1_MALI_UNPACK_CTRL)); 3691b85270fSNeil Armstrong 3701b85270fSNeil Armstrong switch (priv->afbcd.format) { 3711b85270fSNeil Armstrong case DRM_FORMAT_XBGR8888: 3721b85270fSNeil Armstrong case DRM_FORMAT_ABGR8888: 3731b85270fSNeil Armstrong afbc_order = OSD1_MALI_ORDER_ABGR; 3741b85270fSNeil Armstrong break; 3751b85270fSNeil Armstrong } 3761b85270fSNeil Armstrong 3771b85270fSNeil Armstrong /* Setup RGBA Reordering */ 3781b85270fSNeil Armstrong writel_bits_relaxed(VIU_OSD1_MALI_AFBCD_A_REORDER | 3791b85270fSNeil Armstrong VIU_OSD1_MALI_AFBCD_B_REORDER | 3801b85270fSNeil Armstrong VIU_OSD1_MALI_AFBCD_G_REORDER | 3811b85270fSNeil Armstrong VIU_OSD1_MALI_AFBCD_R_REORDER, 3821b85270fSNeil Armstrong afbc_order, 3831b85270fSNeil Armstrong priv->io_base + _REG(VIU_OSD1_MALI_UNPACK_CTRL)); 3841b85270fSNeil Armstrong 3851b85270fSNeil Armstrong /* Select AFBCD path for OSD1 */ 3861b85270fSNeil Armstrong writel_bits_relaxed(OSD_PATH_OSD_AXI_SEL_OSD1_AFBCD, 3871b85270fSNeil Armstrong OSD_PATH_OSD_AXI_SEL_OSD1_AFBCD, 3881b85270fSNeil Armstrong priv->io_base + _REG(OSD_PATH_MISC_CTRL)); 3891b85270fSNeil Armstrong } 3901b85270fSNeil Armstrong 3911b85270fSNeil Armstrong void meson_viu_g12a_disable_osd1_afbc(struct meson_drm *priv) 3921b85270fSNeil Armstrong { 3931b85270fSNeil Armstrong /* Disable AFBCD path for OSD1 */ 3941b85270fSNeil Armstrong writel_bits_relaxed(OSD_PATH_OSD_AXI_SEL_OSD1_AFBCD, 0, 3951b85270fSNeil Armstrong priv->io_base + _REG(OSD_PATH_MISC_CTRL)); 3961b85270fSNeil Armstrong 3971b85270fSNeil Armstrong /* Disable AFBCD unpack */ 3981b85270fSNeil Armstrong writel_bits_relaxed(VIU_OSD1_MALI_UNPACK_EN, 0, 3991b85270fSNeil Armstrong priv->io_base + _REG(VIU_OSD1_MALI_UNPACK_CTRL)); 4001b85270fSNeil Armstrong } 4011b85270fSNeil Armstrong 4021b85270fSNeil Armstrong void meson_viu_gxm_enable_osd1_afbc(struct meson_drm *priv) 4031b85270fSNeil Armstrong { 4041b85270fSNeil Armstrong writel_bits_relaxed(MALI_AFBC_MISC, FIELD_PREP(MALI_AFBC_MISC, 0x90), 4051b85270fSNeil Armstrong priv->io_base + _REG(VIU_MISC_CTRL1)); 4061b85270fSNeil Armstrong } 4071b85270fSNeil Armstrong 4081b85270fSNeil Armstrong void meson_viu_gxm_disable_osd1_afbc(struct meson_drm *priv) 4091b85270fSNeil Armstrong { 4101b85270fSNeil Armstrong writel_bits_relaxed(MALI_AFBC_MISC, FIELD_PREP(MALI_AFBC_MISC, 0x00), 4111b85270fSNeil Armstrong priv->io_base + _REG(VIU_MISC_CTRL1)); 4121b85270fSNeil Armstrong } 4131b85270fSNeil Armstrong 414bbbe775eSNeil Armstrong void meson_viu_init(struct meson_drm *priv) 415bbbe775eSNeil Armstrong { 416bbbe775eSNeil Armstrong uint32_t reg; 417bbbe775eSNeil Armstrong 418bbbe775eSNeil Armstrong /* Disable OSDs */ 419147ae1cbSJulien Masson writel_bits_relaxed(VIU_OSD1_OSD_BLK_ENABLE | VIU_OSD1_OSD_ENABLE, 0, 420bbbe775eSNeil Armstrong priv->io_base + _REG(VIU_OSD1_CTRL_STAT)); 421147ae1cbSJulien Masson writel_bits_relaxed(VIU_OSD1_OSD_BLK_ENABLE | VIU_OSD1_OSD_ENABLE, 0, 422bbbe775eSNeil Armstrong priv->io_base + _REG(VIU_OSD2_CTRL_STAT)); 423bbbe775eSNeil Armstrong 424bbbe775eSNeil Armstrong /* On GXL/GXM, Use the 10bit HDR conversion matrix */ 425528a25d0SJulien Masson if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) || 426528a25d0SJulien Masson meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL)) 427bbbe775eSNeil Armstrong meson_viu_load_matrix(priv); 428bf33677aSChristian Hewitt else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) { 42972888394SNeil Armstrong meson_viu_set_g12a_osd1_matrix(priv, RGB709_to_YUV709l_coeff, 43072888394SNeil Armstrong true); 431bf33677aSChristian Hewitt /* fix green/pink color distortion from vendor u-boot */ 432bf33677aSChristian Hewitt writel_bits_relaxed(OSD1_HDR2_CTRL_REG_ONLY_MAT | 433bf33677aSChristian Hewitt OSD1_HDR2_CTRL_VDIN0_HDR2_TOP_EN, 0, 434bf33677aSChristian Hewitt priv->io_base + _REG(OSD1_HDR2_CTRL)); 435bf33677aSChristian Hewitt } 436bbbe775eSNeil Armstrong 437bbbe775eSNeil Armstrong /* Initialize OSD1 fifo control register */ 438147ae1cbSJulien Masson reg = VIU_OSD_DDR_PRIORITY_URGENT | 43924e0d405SNeil Armstrong VIU_OSD_HOLD_FIFO_LINES(31) | 440147ae1cbSJulien Masson VIU_OSD_FIFO_DEPTH_VAL(32) | /* fifo_depth_val: 32*8=256 */ 441147ae1cbSJulien Masson VIU_OSD_WORDS_PER_BURST(4) | /* 4 words in 1 burst */ 442147ae1cbSJulien Masson VIU_OSD_FIFO_LIMITS(2); /* fifo_lim: 2*16=32 */ 443147ae1cbSJulien Masson 444528a25d0SJulien Masson if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) 44517f64701SMartin Blumenstingl reg |= VIU_OSD_BURST_LENGTH_32; 44672888394SNeil Armstrong else 44717f64701SMartin Blumenstingl reg |= VIU_OSD_BURST_LENGTH_64; 448147ae1cbSJulien Masson 449bbbe775eSNeil Armstrong writel_relaxed(reg, priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT)); 450bbbe775eSNeil Armstrong writel_relaxed(reg, priv->io_base + _REG(VIU_OSD2_FIFO_CTRL_STAT)); 451bbbe775eSNeil Armstrong 452bbbe775eSNeil Armstrong /* Set OSD alpha replace value */ 453bbbe775eSNeil Armstrong writel_bits_relaxed(0xff << OSD_REPLACE_SHIFT, 454bbbe775eSNeil Armstrong 0xff << OSD_REPLACE_SHIFT, 455bbbe775eSNeil Armstrong priv->io_base + _REG(VIU_OSD1_CTRL_STAT2)); 456bbbe775eSNeil Armstrong writel_bits_relaxed(0xff << OSD_REPLACE_SHIFT, 457bbbe775eSNeil Armstrong 0xff << OSD_REPLACE_SHIFT, 458bbbe775eSNeil Armstrong priv->io_base + _REG(VIU_OSD2_CTRL_STAT2)); 459bbbe775eSNeil Armstrong 460f9a23481SNeil Armstrong /* Disable VD1 AFBC */ 461147ae1cbSJulien Masson /* di_mif0_en=0 mif0_to_vpp_en=0 di_mad_en=0 and afbc vd1 set=0*/ 462147ae1cbSJulien Masson writel_bits_relaxed(VIU_CTRL0_VD1_AFBC_MASK, 0, 463f9a23481SNeil Armstrong priv->io_base + _REG(VIU_MISC_CTRL0)); 464f9a23481SNeil Armstrong writel_relaxed(0, priv->io_base + _REG(AFBC_ENABLE)); 465f9a23481SNeil Armstrong 466f9a23481SNeil Armstrong writel_relaxed(0x00FF00C0, 467f9a23481SNeil Armstrong priv->io_base + _REG(VD1_IF0_LUMA_FIFO_SIZE)); 468f9a23481SNeil Armstrong writel_relaxed(0x00FF00C0, 469f9a23481SNeil Armstrong priv->io_base + _REG(VD2_IF0_LUMA_FIFO_SIZE)); 470f9a23481SNeil Armstrong 471528a25d0SJulien Masson if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) { 472*98692f52SSai Prakash Ranjan u32 val = (u32)VIU_OSD_BLEND_REORDER(0, 1) | 473*98692f52SSai Prakash Ranjan (u32)VIU_OSD_BLEND_REORDER(1, 0) | 474*98692f52SSai Prakash Ranjan (u32)VIU_OSD_BLEND_REORDER(2, 0) | 475*98692f52SSai Prakash Ranjan (u32)VIU_OSD_BLEND_REORDER(3, 0) | 476*98692f52SSai Prakash Ranjan (u32)VIU_OSD_BLEND_DIN_EN(1) | 477*98692f52SSai Prakash Ranjan (u32)VIU_OSD_BLEND1_DIN3_BYPASS_TO_DOUT1 | 478*98692f52SSai Prakash Ranjan (u32)VIU_OSD_BLEND1_DOUT_BYPASS_TO_BLEND2 | 479*98692f52SSai Prakash Ranjan (u32)VIU_OSD_BLEND_DIN0_BYPASS_TO_DOUT0 | 480*98692f52SSai Prakash Ranjan (u32)VIU_OSD_BLEND_BLEN2_PREMULT_EN(1) | 481*98692f52SSai Prakash Ranjan (u32)VIU_OSD_BLEND_HOLD_LINES(4); 482*98692f52SSai Prakash Ranjan writel_relaxed(val, priv->io_base + _REG(VIU_OSD_BLEND_CTRL)); 483147ae1cbSJulien Masson 484147ae1cbSJulien Masson writel_relaxed(OSD_BLEND_PATH_SEL_ENABLE, 48572888394SNeil Armstrong priv->io_base + _REG(OSD1_BLEND_SRC_CTRL)); 486147ae1cbSJulien Masson writel_relaxed(OSD_BLEND_PATH_SEL_ENABLE, 48772888394SNeil Armstrong priv->io_base + _REG(OSD2_BLEND_SRC_CTRL)); 48872888394SNeil Armstrong writel_relaxed(0, priv->io_base + _REG(VD1_BLEND_SRC_CTRL)); 48972888394SNeil Armstrong writel_relaxed(0, priv->io_base + _REG(VD2_BLEND_SRC_CTRL)); 49072888394SNeil Armstrong writel_relaxed(0, 49172888394SNeil Armstrong priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_DATA0)); 49272888394SNeil Armstrong writel_relaxed(0, 49372888394SNeil Armstrong priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_ALPHA)); 494147ae1cbSJulien Masson 495147ae1cbSJulien Masson writel_bits_relaxed(DOLBY_BYPASS_EN(0xc), DOLBY_BYPASS_EN(0xc), 49672888394SNeil Armstrong priv->io_base + _REG(DOLBY_PATH_CTRL)); 4971b85270fSNeil Armstrong 4981b85270fSNeil Armstrong meson_viu_g12a_disable_osd1_afbc(priv); 49972888394SNeil Armstrong } 500f9a23481SNeil Armstrong 5011b85270fSNeil Armstrong if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM)) 5021b85270fSNeil Armstrong meson_viu_gxm_disable_osd1_afbc(priv); 5031b85270fSNeil Armstrong 504bbbe775eSNeil Armstrong priv->viu.osd1_enabled = false; 505bbbe775eSNeil Armstrong priv->viu.osd1_commit = false; 506bbbe775eSNeil Armstrong priv->viu.osd1_interlace = false; 507bbbe775eSNeil Armstrong } 508