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 <assert.h> 6#include <ddk/binding.h> 7#include <ddk/debug.h> 8#include <ddk/device.h> 9#include <ddk/driver.h> 10#include <ddk/io-buffer.h> 11#include <ddk/protocol/platform-defs.h> 12#include <ddk/protocol/platform-device.h> 13#include <stdint.h> 14#include <stdio.h> 15#include <stdlib.h> 16#include <string.h> 17#include <unistd.h> 18 19#include "hdmitx.h" 20#include "registers.h" 21#include "vim-display.h" 22#include <hw/reg.h> 23#include <zircon/assert.h> 24#include <zircon/syscalls.h> 25 26void osd_debug_dump_register_all(vim2_display_t* display) { 27 uint32_t reg = 0; 28 uint32_t offset = 0; 29 uint32_t index = 0; 30 31 reg = VPU_VPU_VIU_VENC_MUX_CTRL; 32 DISP_INFO("reg[0x%x]: 0x%08x\n", (reg >> 2), READ32_VPU_REG(reg)); 33 reg = VPU_VPP_MISC; 34 DISP_INFO("reg[0x%x]: 0x%08x\n", (reg >> 2), READ32_VPU_REG(reg)); 35 reg = VPU_VPP_OFIFO_SIZE; 36 DISP_INFO("reg[0x%x]: 0x%08x\n", (reg >> 2), READ32_VPU_REG(reg)); 37 reg = VPU_VPP_HOLD_LINES; 38 DISP_INFO("reg[0x%x]: 0x%08x\n", (reg >> 2), READ32_VPU_REG(reg)); 39 reg = VPU_VPP_OSD_SC_CTRL0; 40 DISP_INFO("reg[0x%x]: 0x%08x\n", (reg >> 2), READ32_VPU_REG(reg)); 41 reg = VPU_VPP_OSD_SCI_WH_M1; 42 DISP_INFO("reg[0x%x]: 0x%08x\n", (reg >> 2), READ32_VPU_REG(reg)); 43 reg = VPU_VPP_OSD_SCO_H_START_END; 44 DISP_INFO("reg[0x%x]: 0x%08x\n", (reg >> 2), READ32_VPU_REG(reg)); 45 reg = VPU_VPP_OSD_SCO_V_START_END; 46 DISP_INFO("reg[0x%x]: 0x%08x\n\n", (reg >> 2), READ32_VPU_REG(reg)); 47 reg = VPU_VPP_POSTBLEND_H_SIZE; 48 DISP_INFO("reg[0x%x]: 0x%08x\n\n", (reg >> 2), READ32_VPU_REG(reg)); 49 50 for (index = 0; index < 2; index++) { 51 if (index == 1) 52 offset = (0x20 << 2); 53 reg = offset + VPU_VIU_OSD1_FIFO_CTRL_STAT; 54 DISP_INFO("reg[0x%x]: 0x%08x\n", (reg >> 2), READ32_VPU_REG(reg)); 55 reg = offset + VPU_VIU_OSD1_CTRL_STAT; 56 DISP_INFO("reg[0x%x]: 0x%08x\n", (reg >> 2), READ32_VPU_REG(reg)); 57 reg = offset + VPU_VIU_OSD1_BLK0_CFG_W0; 58 DISP_INFO("reg[0x%x]: 0x%08x\n", (reg >> 2), READ32_VPU_REG(reg)); 59 reg = offset + VPU_VIU_OSD1_BLK0_CFG_W1; 60 DISP_INFO("reg[0x%x]: 0x%08x\n", (reg >> 2), READ32_VPU_REG(reg)); 61 reg = offset + VPU_VIU_OSD1_BLK0_CFG_W2; 62 DISP_INFO("reg[0x%x]: 0x%08x\n", (reg >> 2), READ32_VPU_REG(reg)); 63 reg = offset + VPU_VIU_OSD1_BLK0_CFG_W3; 64 DISP_INFO("reg[0x%x]: 0x%08x\n", (reg >> 2), READ32_VPU_REG(reg)); 65 reg = VPU_VIU_OSD1_BLK0_CFG_W4; 66 if (index == 1) 67 reg = VPU_VIU_OSD2_BLK0_CFG_W4; 68 DISP_INFO("reg[0x%x]: 0x%08x\n\n", (reg >> 2), READ32_VPU_REG(reg)); 69 } 70} 71 72void disable_vd(vim2_display* display, uint32_t vd_index) { 73 display->vd1_image_valid = false; 74 hwreg::RegisterIo vpu(io_buffer_virt(&display->mmio_vpu)); 75 registers::Vd(vd_index).IfGenReg().ReadFrom(&vpu).set_enable(false).WriteTo(&vpu); 76 registers::VpuVppMisc::Get() 77 .ReadFrom(&vpu) 78 .set_vd1_enable_postblend(false) 79 .WriteTo(&vpu); 80} 81 82void configure_vd(vim2_display* display, uint32_t vd_index) { 83 disable_vd(display, vd_index); 84 hwreg::RegisterIo vpu(io_buffer_virt(&display->mmio_vpu)); 85 uint32_t x_start, x_end, y_start, y_end; 86 x_start = y_start = 0; 87 x_end = display->cur_display_mode.h_addressable - 1; 88 y_end = display->cur_display_mode.v_addressable - 1; 89 90 auto vd = registers::Vd(vd_index); 91 vd.IfLumaX0().FromValue(0).set_end(x_end).set_start(x_start).WriteTo(&vpu); 92 vd.IfLumaY0().FromValue(0).set_end(y_end).set_start(y_start).WriteTo(&vpu); 93 vd.IfChromaX0().FromValue(0).set_end(x_end / 2).set_start(x_start / 2).WriteTo(&vpu); 94 vd.IfChromaY0().FromValue(0).set_end(y_end / 2).set_start(y_start / 2).WriteTo(&vpu); 95 vd.IfGenReg2().FromValue(0).set_color_map(1).WriteTo(&vpu); 96 vd.FmtCtrl() 97 .FromValue(0) 98 .set_vertical_enable(true) 99 .set_vertical_phase_step(8) 100 .set_vertical_initial_phase(0xc) 101 .set_vertical_repeat_line0(true) 102 .set_horizontal_enable(true) 103 .set_horizontal_yc_ratio(1) 104 .WriteTo(&vpu); 105 vd.FmtW() 106 .FromValue(0) 107 .set_horizontal_width(display->cur_display_mode.h_addressable) 108 .set_vertical_width(display->cur_display_mode.h_addressable / 2) 109 .WriteTo(&vpu); 110 111 vd.IfRptLoop().FromValue(0).WriteTo(&vpu); 112 vd.IfLuma0RptPat().FromValue(0).WriteTo(&vpu); 113 vd.IfChroma0RptPat().FromValue(0).WriteTo(&vpu); 114 vd.IfLumaPsel().FromValue(0).WriteTo(&vpu); 115 vd.IfChromaPsel().FromValue(0).WriteTo(&vpu); 116} 117 118void flip_vd(vim2_display* display, uint32_t vd_index, uint32_t index) { 119 display->vd1_image_valid = true; 120 display->vd1_image = index; 121 hwreg::RegisterIo vpu(io_buffer_virt(&display->mmio_vpu)); 122 auto vd = registers::Vd(vd_index); 123 vd.IfGenReg() 124 .FromValue(0) 125 .set_enable(true) 126 .set_separate_en(true) 127 .set_chro_rpt_lastl_ctrl(true) 128 .set_hold_lines(3) 129 .set_urgent_luma(true) 130 .set_urgent_chroma(true) 131 .WriteTo(&vpu); 132 vd.IfCanvas0().FromValue(index).WriteTo(&vpu); 133 registers::VpuVppMisc::Get() 134 .ReadFrom(&vpu) 135 .set_vd1_enable_postblend(true) 136 .WriteTo(&vpu); 137} 138 139void disable_osd(vim2_display_t* display, uint32_t osd_index) { 140 display->current_image_valid = false; 141 hwreg::RegisterIo vpu(io_buffer_virt(&display->mmio_vpu)); 142 auto osd = registers::Osd(osd_index); 143 osd 144 .CtrlStat() 145 .ReadFrom(&vpu) 146 .set_osd_blk_enable(false) 147 .WriteTo(&vpu); 148 if (osd_index == 0) { 149 registers::VpuVppMisc::Get() 150 .ReadFrom(&vpu) 151 .set_osd2_enable_postblend(false) 152 .WriteTo(&vpu); 153 } else { 154 registers::VpuVppMisc::Get() 155 .ReadFrom(&vpu) 156 .set_osd1_enable_postblend(false) 157 .WriteTo(&vpu); 158 } 159} 160 161// Disables the OSD until a flip happens 162zx_status_t configure_osd(vim2_display_t* display, uint32_t osd_index) { 163 uint32_t x_start, x_end, y_start, y_end; 164 x_start = y_start = 0; 165 x_end = display->cur_display_mode.h_addressable - 1; 166 y_end = display->cur_display_mode.v_addressable - 1; 167 168 disable_osd(display, osd_index); 169 hwreg::RegisterIo vpu(io_buffer_virt(&display->mmio_vpu)); 170 auto osd = registers::Osd(osd_index); 171 registers::VpuVppOsdScCtrl0::Get().FromValue(0).WriteTo(&vpu); 172 173 osd.CtrlStat2() 174 .ReadFrom(&vpu) 175 .set_replaced_alpha_en(true) 176 .set_replaced_alpha(0xff) 177 .WriteTo(&vpu); 178 179 osd.Blk0CfgW1() 180 .FromValue(0) 181 .set_virtual_canvas_x_end(x_end) 182 .set_virtual_canvas_x_start(x_start) 183 .WriteTo(&vpu); 184 osd.Blk0CfgW2() 185 .FromValue(0) 186 .set_virtual_canvas_y_end(y_end) 187 .set_virtual_canvas_y_start(y_start) 188 .WriteTo(&vpu); 189 osd.Blk0CfgW3().FromValue(0).set_display_h_end(x_end).set_display_h_start(x_start).WriteTo( 190 &vpu); 191 osd.Blk0CfgW4().FromValue(0).set_display_v_end(y_end).set_display_v_start(y_start).WriteTo( 192 &vpu); 193 194 registers::VpuVppOsdScoHStartEnd::Get().FromValue(0).WriteTo(&vpu); 195 registers::VpuVppOsdScoVStartEnd::Get().FromValue(0).WriteTo(&vpu); 196 197 registers::VpuVppPostblendHSize::Get() 198 .FromValue(display->cur_display_mode.h_addressable) 199 .WriteTo(&vpu); 200 registers::VpuVppOsdSciWhM1::Get().FromValue(0).WriteTo(&vpu); 201 202 return ZX_OK; 203} 204 205void flip_osd(vim2_display_t* display, uint32_t osd_index, uint8_t idx) { 206 display->current_image = idx; 207 display->current_image_valid = true; 208 hwreg::RegisterIo vpu(io_buffer_virt(&display->mmio_vpu)); 209 auto osd = registers::Osd(osd_index); 210 osd.Blk0CfgW0() 211 .FromValue(0) 212 .set_tbl_addr(idx) 213 .set_little_endian(true) 214 .set_block_mode(registers::VpuViuOsdBlk0CfgW0::kBlockMode32Bit) 215 .set_rgb_en(true) 216 .set_color_matrix(registers::VpuViuOsdBlk0CfgW0::kColorMatrixARGB8888) 217 .WriteTo(&vpu); 218 osd.CtrlStat() 219 .ReadFrom(&vpu) 220 .set_osd_blk_enable(true) 221 .WriteTo(&vpu); 222 if (osd_index == 0) { 223 registers::VpuVppMisc::Get() 224 .ReadFrom(&vpu) 225 .set_osd1_enable_postblend(true) 226 .WriteTo(&vpu); 227 } else { 228 registers::VpuVppMisc::Get() 229 .ReadFrom(&vpu) 230 .set_osd2_enable_postblend(true) 231 .WriteTo(&vpu); 232 } 233} 234