1// Copyright 2018 The Fuchsia Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "vpu.h" 6#include "vpu-regs.h" 7#include "hhi-regs.h" 8#include "vpp-regs.h" 9#include <ddk/debug.h> 10#include <ddktl/device.h> 11 12namespace astro_display { 13 14namespace { 15constexpr uint32_t kVpuMux = 0; 16constexpr uint32_t kVpuDiv = 3; 17 18constexpr int16_t RGB709_to_YUV709l_coeff[24] = { 19 0x0000, 0x0000, 0x0000, 20 0x00bb, 0x0275, 0x003f, 21 0x1f99, 0x1ea6, 0x01c2, 22 0x01c2, 0x1e67, 0x1fd7, 23 0x0000, 0x0000, 0x0000, 24 0x0000, 0x0000, 0x0000, 25 0x0040, 0x0200, 0x0200, 26 0x0000, 0x0000, 0x0000, 27}; 28 29constexpr int16_t YUV709l_to_RGB709_coeff12[24] = { 30 -256, -2048, -2048, 31 4788, 0, 7372, 32 4788, -876, -2190, 33 4788, 8686, 0, 34 0, 0, 0, 35 0, 0, 0, 36 0, 0, 0, 37 0, 0, 0, 38}; 39} // namespace 40 41// AOBUS Register 42#define AOBUS_GEN_PWR_SLEEP0 (0x03a << 2) 43 44// CBUS Reset Register 45#define RESET0_LEVEL (0x0420 << 2) 46#define RESET1_LEVEL (0x0421 << 2) 47#define RESET2_LEVEL (0x0422 << 2) 48#define RESET4_LEVEL (0x0424 << 2) 49#define RESET7_LEVEL (0x0427 << 2) 50 51#define READ32_VPU_REG(a) vpu_regs_->Read<uint32_t>(a) 52#define WRITE32_VPU_REG(a, v) vpu_regs_->Write<uint32_t>(a, v) 53 54#define READ32_HHI_REG(a) hhi_regs_->Read<uint32_t>(a) 55#define WRITE32_HHI_REG(a, v) hhi_regs_->Write<uint32_t>(a, v) 56 57#define READ32_AOBUS_REG(a) aobus_regs_->Read<uint32_t>(a) 58#define WRITE32_AOBUS_REG(a, v) aobus_regs_->Write<uint32_t>(a, v) 59 60#define READ32_CBUS_REG(a) cbus_regs_->Read<uint32_t>(a) 61#define WRITE32_CBUS_REG(a, v) cbus_regs_->Write<uint32_t>(a, v) 62 63zx_status_t Vpu::Init(zx_device_t* parent) { 64 if (initialized_) { 65 return ZX_OK; 66 } 67 zx_status_t status = device_get_protocol(parent, ZX_PROTOCOL_PLATFORM_DEV, &pdev_); 68 if (status != ZX_OK) { 69 return status; 70 } 71 72 // Map VPU registers 73 status = pdev_map_mmio_buffer(&pdev_, MMIO_VPU, ZX_CACHE_POLICY_UNCACHED_DEVICE, 74 &mmio_vpu_); 75 if (status != ZX_OK) { 76 DISP_ERROR("vpu: Could not map VPU mmio\n"); 77 return status; 78 } 79 vpu_regs_ = fbl::make_unique<hwreg::RegisterIo>(io_buffer_virt(&mmio_vpu_)); 80 81 // Map HHI registers 82 status = pdev_map_mmio_buffer(&pdev_, MMIO_HHI, ZX_CACHE_POLICY_UNCACHED_DEVICE, 83 &mmio_hhi_); 84 if (status != ZX_OK) { 85 DISP_ERROR("vpu: Could not map HHI mmio\n"); 86 return status; 87 } 88 hhi_regs_ = fbl::make_unique<hwreg::RegisterIo>(io_buffer_virt(&mmio_hhi_)); 89 90 // Map AOBUS registers 91 status = pdev_map_mmio_buffer(&pdev_, MMIO_AOBUS, ZX_CACHE_POLICY_UNCACHED_DEVICE, 92 &mmio_aobus_); 93 if (status != ZX_OK) { 94 DISP_ERROR("vpu: Could not map AOBUS mmio\n"); 95 return status; 96 } 97 aobus_regs_ = fbl::make_unique<hwreg::RegisterIo>(io_buffer_virt(&mmio_aobus_)); 98 99 // Map CBUS registers 100 status = pdev_map_mmio_buffer(&pdev_, MMIO_CBUS, ZX_CACHE_POLICY_UNCACHED_DEVICE, 101 &mmio_cbus_); 102 if (status != ZX_OK) { 103 DISP_ERROR("vpu: Could not map CBUS mmio\n"); 104 return status; 105 } 106 cbus_regs_ = fbl::make_unique<hwreg::RegisterIo>(io_buffer_virt(&mmio_cbus_)); 107 108 // VPU object is ready to be used 109 initialized_ = true; 110 return ZX_OK; 111} 112 113void Vpu::VppInit() { 114 ZX_DEBUG_ASSERT(initialized_); 115 116 // init vpu fifo control register 117 SET_BIT32(VPU, VPP_OFIFO_SIZE, 0xFFF, 0, 12); 118 WRITE32_REG(VPU, VPP_HOLD_LINES, 0x08080808); 119 // default probe_sel, for highlight en 120 SET_BIT32(VPU, VPP_MATRIX_CTRL, 0x7, 12, 3); 121 122 // setting up os1 for rgb -> yuv limit 123 const int16_t* m = RGB709_to_YUV709l_coeff; 124 125 // VPP WRAP OSD1 matrix 126 WRITE32_REG(VPU, VPP_WRAP_OSD1_MATRIX_PRE_OFFSET0_1, 127 ((m[0] & 0xfff) << 16) | (m[1] & 0xfff)); 128 WRITE32_REG(VPU, VPP_WRAP_OSD1_MATRIX_PRE_OFFSET2, 129 m[2] & 0xfff); 130 WRITE32_REG(VPU, VPP_WRAP_OSD1_MATRIX_COEF00_01, 131 ((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff)); 132 WRITE32_REG(VPU, VPP_WRAP_OSD1_MATRIX_COEF02_10, 133 ((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff)); 134 WRITE32_REG(VPU, VPP_WRAP_OSD1_MATRIX_COEF11_12, 135 ((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff)); 136 WRITE32_REG(VPU, VPP_WRAP_OSD1_MATRIX_COEF20_21, 137 ((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff)); 138 WRITE32_REG(VPU, VPP_WRAP_OSD1_MATRIX_COEF22, 139 m[11] & 0x1fff); 140 WRITE32_REG(VPU, VPP_WRAP_OSD1_MATRIX_OFFSET0_1, 141 ((m[18] & 0xfff) << 16) | (m[19] & 0xfff)); 142 WRITE32_REG(VPU, VPP_WRAP_OSD1_MATRIX_OFFSET2, 143 m[20] & 0xfff); 144 SET_BIT32(VPU, VPP_WRAP_OSD1_MATRIX_EN_CTRL, 1, 0, 1); 145 146 // VPP WRAP OSD2 matrix 147 WRITE32_REG(VPU, VPP_WRAP_OSD2_MATRIX_PRE_OFFSET0_1, 148 ((m[0] & 0xfff) << 16) | (m[1] & 0xfff)); 149 WRITE32_REG(VPU, VPP_WRAP_OSD2_MATRIX_PRE_OFFSET2, 150 m[2] & 0xfff); 151 WRITE32_REG(VPU, VPP_WRAP_OSD2_MATRIX_COEF00_01, 152 ((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff)); 153 WRITE32_REG(VPU, VPP_WRAP_OSD2_MATRIX_COEF02_10, 154 ((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff)); 155 WRITE32_REG(VPU, VPP_WRAP_OSD2_MATRIX_COEF11_12, 156 ((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff)); 157 WRITE32_REG(VPU, VPP_WRAP_OSD2_MATRIX_COEF20_21, 158 ((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff)); 159 WRITE32_REG(VPU, VPP_WRAP_OSD2_MATRIX_COEF22, 160 m[11] & 0x1fff); 161 WRITE32_REG(VPU, VPP_WRAP_OSD2_MATRIX_OFFSET0_1, 162 ((m[18] & 0xfff) << 16) | (m[19] & 0xfff)); 163 WRITE32_REG(VPU, VPP_WRAP_OSD2_MATRIX_OFFSET2, 164 m[20] & 0xfff); 165 SET_BIT32(VPU, VPP_WRAP_OSD2_MATRIX_EN_CTRL, 1, 0, 1); 166 167 // VPP WRAP OSD3 matrix 168 WRITE32_REG(VPU, VPP_WRAP_OSD3_MATRIX_PRE_OFFSET0_1, 169 ((m[0] & 0xfff) << 16) | (m[1] & 0xfff)); 170 WRITE32_REG(VPU, VPP_WRAP_OSD3_MATRIX_PRE_OFFSET2, 171 m[2] & 0xfff); 172 WRITE32_REG(VPU, VPP_WRAP_OSD3_MATRIX_COEF00_01, 173 ((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff)); 174 WRITE32_REG(VPU, VPP_WRAP_OSD3_MATRIX_COEF02_10, 175 ((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff)); 176 WRITE32_REG(VPU, VPP_WRAP_OSD3_MATRIX_COEF11_12, 177 ((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff)); 178 WRITE32_REG(VPU, VPP_WRAP_OSD3_MATRIX_COEF20_21, 179 ((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff)); 180 WRITE32_REG(VPU, VPP_WRAP_OSD3_MATRIX_COEF22, 181 m[11] & 0x1fff); 182 WRITE32_REG(VPU, VPP_WRAP_OSD3_MATRIX_OFFSET0_1, 183 ((m[18] & 0xfff) << 16) | (m[19] & 0xfff)); 184 WRITE32_REG(VPU, VPP_WRAP_OSD3_MATRIX_OFFSET2, 185 m[20] & 0xfff); 186 SET_BIT32(VPU, VPP_WRAP_OSD3_MATRIX_EN_CTRL, 1, 0, 1); 187 188 WRITE32_REG(VPU, DOLBY_PATH_CTRL, 0xf); 189 190 // POST2 matrix: YUV limit -> RGB default is 12bit 191 m = YUV709l_to_RGB709_coeff12; 192 193 // VPP WRAP POST2 matrix 194 WRITE32_REG(VPU, VPP_POST2_MATRIX_PRE_OFFSET0_1, 195 (((m[0] >> 2) & 0xfff) << 16) | ((m[1] >> 2) & 0xfff)); 196 WRITE32_REG(VPU, VPP_POST2_MATRIX_PRE_OFFSET2, 197 (m[2] >> 2) & 0xfff); 198 WRITE32_REG(VPU, VPP_POST2_MATRIX_COEF00_01, 199 (((m[3] >> 2) & 0x1fff) << 16) | ((m[4] >> 2) & 0x1fff)); 200 WRITE32_REG(VPU, VPP_POST2_MATRIX_COEF02_10, 201 (((m[5] >> 2) & 0x1fff) << 16) | ((m[6] >> 2) & 0x1fff)); 202 WRITE32_REG(VPU, VPP_POST2_MATRIX_COEF11_12, 203 (((m[7] >> 2) & 0x1fff) << 16) | ((m[8] >> 2) & 0x1fff)); 204 WRITE32_REG(VPU, VPP_POST2_MATRIX_COEF20_21, 205 (((m[9] >> 2) & 0x1fff) << 16) | ((m[10] >> 2) & 0x1fff)); 206 WRITE32_REG(VPU, VPP_POST2_MATRIX_COEF22, 207 (m[11] >> 2) & 0x1fff); 208 WRITE32_REG(VPU, VPP_POST2_MATRIX_OFFSET0_1, 209 (((m[18] >> 2) & 0xfff) << 16) | ((m[19] >> 2) & 0xfff)); 210 WRITE32_REG(VPU, VPP_POST2_MATRIX_OFFSET2, 211 (m[20] >> 2) & 0xfff); 212 SET_BIT32(VPU, VPP_POST2_MATRIX_EN_CTRL, 1, 0, 1); 213 214 215 SET_BIT32(VPU, VPP_MATRIX_CTRL, 1, 0, 1); 216 SET_BIT32(VPU, VPP_MATRIX_CTRL, 0, 8, 3); 217 218 // 709L to RGB 219 WRITE32_REG(VPU, VPP_MATRIX_PRE_OFFSET0_1, 0x0FC00E00); 220 WRITE32_REG(VPU, VPP_MATRIX_PRE_OFFSET2, 0x00000E00); 221 // ycbcr limit range, 709 to RGB 222 // -16 1.164 0 1.793 0 223 // -128 1.164 -0.213 -0.534 0 224 // -128 1.164 2.115 0 0 225 WRITE32_REG(VPU, VPP_MATRIX_COEF00_01, 0x04A80000); 226 WRITE32_REG(VPU, VPP_MATRIX_COEF02_10, 0x072C04A8); 227 WRITE32_REG(VPU, VPP_MATRIX_COEF11_12, 0x1F261DDD); 228 WRITE32_REG(VPU, VPP_MATRIX_COEF20_21, 0x04A80876); 229 WRITE32_REG(VPU, VPP_MATRIX_COEF22, 0x0); 230 WRITE32_REG(VPU, VPP_MATRIX_OFFSET0_1, 0x0); 231 WRITE32_REG(VPU, VPP_MATRIX_OFFSET2, 0x0); 232 233 SET_BIT32(VPU, VPP_MATRIX_CLIP, 0, 5, 3); 234} 235 236void Vpu::ConfigureClock() { 237 ZX_DEBUG_ASSERT(initialized_); 238 // vpu clock 239 WRITE32_REG(HHI, HHI_VPU_CLK_CNTL, ((kVpuMux << 9) | (kVpuDiv << 0))); 240 SET_BIT32(HHI, HHI_VPU_CLK_CNTL, 1, 8, 1); 241 242 // vpu clkb 243 // bit 0 is set since kVpuClkFrequency > clkB max frequency (350MHz) 244 WRITE32_REG(HHI, HHI_VPU_CLKB_CNTL, ((1 << 8) | (1 << 0))); 245 246 // vapb clk 247 // turn on ge2d clock since kVpuClkFrequency > 250MHz 248 WRITE32_REG(HHI, HHI_VAPBCLK_CNTL, (1 << 30) | (0 << 9) | (1 << 0)); 249 250 SET_BIT32(HHI, HHI_VAPBCLK_CNTL, 1, 8, 1); 251 252 SET_BIT32(HHI, HHI_VID_CLK_CNTL2, 0, 0, 8); 253 254 // dmc_arb_config 255 WRITE32_REG(VPU, VPU_RDARB_MODE_L1C1, 0x0); 256 WRITE32_REG(VPU, VPU_RDARB_MODE_L1C2, 0x10000); 257 WRITE32_REG(VPU, VPU_RDARB_MODE_L2C1, 0x900000); 258 WRITE32_REG(VPU, VPU_WRARB_MODE_L2C1, 0x20000); 259} 260 261void Vpu::PowerOn() { 262 ZX_DEBUG_ASSERT(initialized_); 263 SET_BIT32(AOBUS, AOBUS_GEN_PWR_SLEEP0, 0, 8, 1); // [8] power on 264 265 // power up memories 266 for (int i = 0; i < 32; i+=2) { 267 SET_BIT32(HHI, HHI_VPU_MEM_PD_REG0, 0, i, 2); 268 zx_nanosleep(zx_deadline_after(ZX_USEC(5))); 269 } 270 for (int i = 0; i < 32; i+=2) { 271 SET_BIT32(HHI, HHI_VPU_MEM_PD_REG1, 0, i, 2); 272 zx_nanosleep(zx_deadline_after(ZX_USEC(5))); 273 } 274 SET_BIT32(HHI, HHI_VPU_MEM_PD_REG2, 0, 0, 2); 275 zx_nanosleep(zx_deadline_after(ZX_USEC(5))); 276 for (int i = 4; i < 18; i+=2) { 277 SET_BIT32(HHI, HHI_VPU_MEM_PD_REG2, 0, i, 2); 278 zx_nanosleep(zx_deadline_after(ZX_USEC(5))); 279 } 280 SET_BIT32(HHI, HHI_VPU_MEM_PD_REG2, 0, 30, 2); 281 zx_nanosleep(zx_deadline_after(ZX_USEC(5))); 282 283 for (int i = 8; i < 16; i++) { 284 SET_BIT32(HHI, HHI_MEM_PD_REG0, 0, i, 1); 285 zx_nanosleep(zx_deadline_after(ZX_USEC(5))); 286 } 287 zx_nanosleep(zx_deadline_after(ZX_USEC(20))); 288 289 // Reset VIU + VENC 290 // Reset VENCI + VENCP + VADC + VENCL 291 // Reset HDMI-APB + HDMI-SYS + HDMI-TX + HDMI-CEC 292 CLEAR_MASK32(CBUS, RESET0_LEVEL, ((1<<5) | (1<<10) | (1<<19) | (1<<13))); 293 CLEAR_MASK32(CBUS, RESET1_LEVEL, (1<<5)); 294 CLEAR_MASK32(CBUS, RESET2_LEVEL, (1<<15)); 295 CLEAR_MASK32(CBUS, RESET4_LEVEL, 296 ((1<<6) | (1<<7) | (1<<13) | (1<<5) | (1<<9) | (1<<4) | (1<<12))); 297 CLEAR_MASK32(CBUS, RESET7_LEVEL, (1<<7)); 298 299 // Remove VPU_HDMI ISO 300 SET_BIT32(AOBUS, AOBUS_GEN_PWR_SLEEP0, 0, 9, 1); // [9] VPU_HDMI 301 302 // release Reset 303 SET_MASK32(CBUS, RESET0_LEVEL, ((1 << 5) | (1<<10) | (1<<19) | (1<<13))); 304 SET_MASK32(CBUS, RESET1_LEVEL, (1<<5)); 305 SET_MASK32(CBUS, RESET2_LEVEL, (1<<15)); 306 SET_MASK32(CBUS, RESET4_LEVEL, 307 ((1<<6) | (1<<7) | (1<<13) | (1<<5) | (1<<9) | (1<<4) | (1<<12))); 308 SET_MASK32(CBUS, RESET7_LEVEL, (1<<7)); 309 310 ConfigureClock(); 311} 312 313void Vpu::PowerOff() { 314 ZX_DEBUG_ASSERT(initialized_); 315 // Power down VPU_HDMI 316 // Enable Isolation 317 SET_BIT32(AOBUS, AOBUS_GEN_PWR_SLEEP0, 1, 9, 1); // ISO 318 zx_nanosleep(zx_deadline_after(ZX_USEC(20))); 319 320 // power down memories 321 for (int i = 0; i < 32; i+=2) { 322 SET_BIT32(HHI, HHI_VPU_MEM_PD_REG0, 0x3, i, 2); 323 zx_nanosleep(zx_deadline_after(ZX_USEC(5))); 324 } 325 for (int i = 0; i < 32; i+=2) { 326 SET_BIT32(HHI, HHI_VPU_MEM_PD_REG1, 0x3, i, 2); 327 zx_nanosleep(zx_deadline_after(ZX_USEC(5))); 328 } 329 SET_BIT32(HHI, HHI_VPU_MEM_PD_REG2, 0x3, 0, 2); 330 zx_nanosleep(zx_deadline_after(ZX_USEC(5))); 331 for (int i = 4; i < 18; i+=2) { 332 SET_BIT32(HHI, HHI_VPU_MEM_PD_REG2, 0x3, i, 2); 333 zx_nanosleep(zx_deadline_after(ZX_USEC(5))); 334 } 335 SET_BIT32(HHI, HHI_VPU_MEM_PD_REG2, 0x3, 30, 2); 336 zx_nanosleep(zx_deadline_after(ZX_USEC(5))); 337 338 for (int i = 8; i < 16; i++) { 339 SET_BIT32(HHI, HHI_MEM_PD_REG0, 0x1, i, 1); 340 zx_nanosleep(zx_deadline_after(ZX_USEC(5))); 341 } 342 zx_nanosleep(zx_deadline_after(ZX_USEC(20))); 343 344 // Power down VPU domain 345 SET_BIT32(AOBUS, AOBUS_GEN_PWR_SLEEP0, 1, 8, 1); // PDN 346 347 SET_BIT32(HHI, HHI_VAPBCLK_CNTL, 0, 8, 1); 348 SET_BIT32(HHI, HHI_VPU_CLK_CNTL, 0, 8, 1); 349} 350} // namespace astro_display 351