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 "osd.h"
6 #include "vpp-regs.h"
7 #include "vpu-regs.h"
8 #include "rdma-regs.h"
9 #include <ddk/debug.h>
10 #include <ddktl/device.h>
11
12 namespace astro_display {
13
14 #define READ32_VPU_REG(a) vpu_mmio_->Read32(a)
15 #define WRITE32_VPU_REG(a, v) vpu_mmio_->Write32(v, a)
16
17 namespace {
18 constexpr uint32_t VpuViuOsd1BlkCfgTblAddrShift = 16;
19 constexpr uint32_t VpuViuOsd1BlkCfgLittleEndian = (1 << 15);
20 constexpr uint32_t VpuViuOsd1BlkCfgOsdBlkMode32Bit = 5;
21 constexpr uint32_t VpuViuOsd1BlkCfgOsdBlkModeShift = 8;
22 constexpr uint32_t VpuViuOsd1BlkCfgColorMatrixArgb = 1;
23 constexpr uint32_t VpuViuOsd1BlkCfgColorMatrixShift = 2;
24 constexpr uint32_t VpuViuOsd1CtrlStat2ReplacedAlphaEn = (1 << 14);
25 constexpr uint32_t VpuViuOsd1CtrlStat2ReplacedAlphaShift = 6u;
26
27 constexpr uint32_t kOsdGlobalAlphaDef = 0xff;
28 constexpr uint32_t kHwOsdBlockEnable0 = 0x0001; // osd blk0 enable
29
30 // We use bicubic interpolation for scaling.
31 // TODO(payamm): Add support for other types of interpolation
32 unsigned int osd_filter_coefs_bicubic[] = {
33 0x00800000, 0x007f0100, 0xff7f0200, 0xfe7f0300, 0xfd7e0500, 0xfc7e0600,
34 0xfb7d0800, 0xfb7c0900, 0xfa7b0b00, 0xfa7a0dff, 0xf9790fff, 0xf97711ff,
35 0xf87613ff, 0xf87416fe, 0xf87218fe, 0xf8701afe, 0xf76f1dfd, 0xf76d1ffd,
36 0xf76b21fd, 0xf76824fd, 0xf76627fc, 0xf76429fc, 0xf7612cfc, 0xf75f2ffb,
37 0xf75d31fb, 0xf75a34fb, 0xf75837fa, 0xf7553afa, 0xf8523cfa, 0xf8503ff9,
38 0xf84d42f9, 0xf84a45f9, 0xf84848f8
39 };
40
41 } // namespace
42
RdmaThread()43 int Osd::RdmaThread() {
44 zx_status_t status;
45 while (1) {
46 status = rdma_irq_.wait(nullptr);
47 if (status != ZX_OK) {
48 DISP_ERROR("RDMA Interrupt wait failed\n");
49 break;
50 }
51 // RDMA completed. Remove source for all finished DMA channels
52 for (int i = 0; i < kMaxRdmaChannels; i++) {
53 if (vpu_mmio_->Read32(VPU_RDMA_STATUS) & RDMA_STATUS_DONE(i)) {
54 uint32_t regVal = vpu_mmio_->Read32(VPU_RDMA_ACCESS_AUTO);
55 regVal &= ~RDMA_ACCESS_AUTO_INT_EN(i); // VSYNC interrupt source
56 vpu_mmio_->Write32(regVal, VPU_RDMA_ACCESS_AUTO);
57 }
58 }
59 }
60 return status;
61 }
62
Init(zx_device_t * parent)63 zx_status_t Osd::Init(zx_device_t* parent) {
64 if (initialized_) {
65 return ZX_OK;
66 }
67
68 zx_status_t status = device_get_protocol(parent, ZX_PROTOCOL_PDEV, &pdev_);
69 if (status != ZX_OK) {
70 return status;
71 }
72
73 // Map vpu mmio used by the OSD object
74 mmio_buffer_t mmio;
75 status = pdev_map_mmio_buffer2(&pdev_, MMIO_VPU, ZX_CACHE_POLICY_UNCACHED_DEVICE,
76 &mmio);
77 if (status != ZX_OK) {
78 DISP_ERROR("osd: Could not map VPU mmio\n");
79 return status;
80 }
81
82 vpu_mmio_ = ddk::MmioBuffer(mmio);
83
84 // Get BTI from parent
85 status = pdev_get_bti(&pdev_, 0, bti_.reset_and_get_address());
86 if (status != ZX_OK) {
87 DISP_ERROR("Could not get BTI handle\n");
88 return status;
89 }
90
91 //Map RDMA Done Interrupt
92 status = pdev_map_interrupt(&pdev_, IRQ_RDMA, rdma_irq_.reset_and_get_address());
93 if (status != ZX_OK) {
94 DISP_ERROR("Could not map RDMA interrupt\n");
95 return status;
96 }
97
98 auto start_thread = [](void* arg) {return static_cast<Osd*>(arg)->RdmaThread(); };
99 status = thrd_create_with_name(&rdma_thread_, start_thread, this, "rdma_thread");
100 if (status != ZX_OK) {
101 DISP_ERROR("Could not create rdma_thread\n");
102 return status;
103 }
104
105 // Setup RDMA
106 status = SetupRdma();
107 if (status != ZX_OK) {
108 DISP_ERROR("Could not setup RDMA\n");
109 return status;
110 }
111
112 // OSD object is ready to be used.
113 initialized_ = true;
114 return ZX_OK;
115 }
116
Disable(void)117 void Osd::Disable(void) {
118 ZX_DEBUG_ASSERT(initialized_);
119 // Display RDMA
120 vpu_mmio_->ClearBits32(RDMA_ACCESS_AUTO_INT_EN_ALL, VPU_RDMA_ACCESS_AUTO);
121 vpu_mmio_->ClearBits32(1 << 0, VPU_VIU_OSD1_CTRL_STAT);
122 }
123
Enable(void)124 void Osd::Enable(void) {
125 ZX_DEBUG_ASSERT(initialized_);
126 vpu_mmio_->SetBits32(1 << 0, VPU_VIU_OSD1_CTRL_STAT);
127 }
128
Configure()129 zx_status_t Osd::Configure() {
130 // TODO(payamm): OSD for g12a is slightly different from gxl. Currently, uBoot enables
131 // scaling and 16bit mode (565) and configures various layers based on that assumption.
132 // Since we don't have a full end-to-end driver at this moment, we cannot simply turn off
133 // scaling.
134 // For now, we will only configure the OSD layer to use the new Canvas index,
135 // and use 32-bit color.
136 // Set to use BGRX instead of BGRA.
137 vpu_mmio_->SetBits32(VpuViuOsd1CtrlStat2ReplacedAlphaEn |
138 (0xff << VpuViuOsd1CtrlStat2ReplacedAlphaShift),
139 VPU_VIU_OSD1_CTRL_STAT2);
140
141 return ZX_OK;
142 }
143
FlipOnVsync(uint8_t idx)144 void Osd::FlipOnVsync(uint8_t idx) {
145
146 // Get the first available channel
147 int rdma_channel = GetNextAvailableRdmaChannel();
148 uint8_t retry_count = 0;
149 while (rdma_channel == -1 && retry_count++ < kMaxRetries) {
150 zx_nanosleep(zx_deadline_after(ZX_USEC(10)));
151 rdma_channel = GetNextAvailableRdmaChannel();
152 }
153
154 if (rdma_channel < 0) {
155 ZX_DEBUG_ASSERT(false);
156 return;
157 }
158
159 DISP_SPEW("Channel used is %d\n", rdma_channel);
160
161 // Update CFG_W0 with correct Canvas Index
162 uint32_t cfg_w0 = (idx << VpuViuOsd1BlkCfgTblAddrShift) |
163 VpuViuOsd1BlkCfgLittleEndian |
164 (VpuViuOsd1BlkCfgOsdBlkMode32Bit << VpuViuOsd1BlkCfgOsdBlkModeShift) |
165 (VpuViuOsd1BlkCfgColorMatrixArgb << VpuViuOsd1BlkCfgColorMatrixShift);
166 SetRdmaTableValue(rdma_channel, IDX_CFG_W0, cfg_w0);
167 SetRdmaTableValue(rdma_channel, IDX_CTRL_STAT,
168 vpu_mmio_->Read32(VPU_VIU_OSD1_CTRL_STAT) | (1 << 0));
169 FlushRdmaTable(rdma_channel);
170
171 // Write the start and end address of the table. End address is the last address that the
172 // RDMA engine reads from.
173 vpu_mmio_->Write32(static_cast<uint32_t> (rdma_chnl_container_[rdma_channel].phys_offset),
174 VPU_RDMA_AHB_START_ADDR(rdma_channel));
175 vpu_mmio_->Write32(static_cast<uint32_t>(rdma_chnl_container_[rdma_channel].phys_offset +
176 (sizeof(RdmaTable) * kRdmaTableMaxSize) - 4),
177 VPU_RDMA_AHB_END_ADDR(rdma_channel));
178
179 // Enable Auto mode: Non-Increment, VSync Interrupt Driven, Write
180 uint32_t regVal = vpu_mmio_->Read32(VPU_RDMA_ACCESS_AUTO);
181 regVal |= RDMA_ACCESS_AUTO_INT_EN(rdma_channel); // VSYNC interrupt source
182 regVal |= RDMA_ACCESS_AUTO_WRITE(rdma_channel); // Write
183 vpu_mmio_->Write32(regVal, VPU_RDMA_ACCESS_AUTO);
184 }
185
DefaultSetup()186 void Osd::DefaultSetup() {
187 // osd blend ctrl
188 WRITE32_REG(VPU, VIU_OSD_BLEND_CTRL,
189 4 << 29|
190 0 << 27| // blend2_premult_en
191 1 << 26| // blend_din0 input to blend0
192 0 << 25| // blend1_dout to blend2
193 0 << 24| // blend1_din3 input to blend1
194 1 << 20| // blend_din_en
195 0 << 16| // din_premult_en
196 1 << 0); // din_reoder_sel = OSD1
197
198 // vpp osd1 blend ctrl
199 WRITE32_REG(VPU, OSD1_BLEND_SRC_CTRL,
200 (0 & 0xf) << 0 |
201 (0 & 0x1) << 4 |
202 (3 & 0xf) << 8 | // postbld_src3_sel
203 (0 & 0x1) << 16| // postbld_osd1_premult
204 (1 & 0x1) << 20);
205 // vpp osd2 blend ctrl
206 WRITE32_REG(VPU, OSD2_BLEND_SRC_CTRL,
207 (0 & 0xf) << 0 |
208 (0 & 0x1) << 4 |
209 (0 & 0xf) << 8 | // postbld_src4_sel
210 (0 & 0x1) << 16 | // postbld_osd2_premult
211 (1 & 0x1) << 20);
212
213 // used default dummy data
214 WRITE32_REG(VPU, VIU_OSD_BLEND_DUMMY_DATA0,
215 0x0 << 16 |
216 0x0 << 8 |
217 0x0);
218 // used default dummy alpha data
219 WRITE32_REG(VPU, VIU_OSD_BLEND_DUMMY_ALPHA,
220 0x0 << 20 |
221 0x0 << 11 |
222 0x0);
223
224 // osdx setting
225 WRITE32_REG(VPU,
226 VPU_VIU_OSD_BLEND_DIN0_SCOPE_H,
227 (fb_width_ - 1) << 16);
228
229 WRITE32_REG(VPU,
230 VPU_VIU_OSD_BLEND_DIN0_SCOPE_V,
231 (fb_height_ - 1) << 16);
232
233 WRITE32_REG(VPU, VIU_OSD_BLEND_BLEND0_SIZE,
234 fb_height_ << 16 |
235 fb_width_);
236 WRITE32_REG(VPU, VIU_OSD_BLEND_BLEND1_SIZE,
237 fb_height_ << 16 |
238 fb_width_);
239 SET_BIT32(VPU, DOLBY_PATH_CTRL, 0x3, 2, 2);
240
241 WRITE32_REG(VPU, VPP_OSD1_IN_SIZE,
242 fb_height_ << 16 | fb_width_);
243
244 // setting blend scope
245 WRITE32_REG(VPU, VPP_OSD1_BLD_H_SCOPE,
246 0 << 16 | (fb_width_ - 1));
247 WRITE32_REG(VPU, VPP_OSD1_BLD_V_SCOPE,
248 0 << 16 | (fb_height_ - 1));
249
250 // Set geometry to normal mode
251 uint32_t data32 = ((fb_width_ - 1) & 0xfff) << 16;
252 WRITE32_REG(VPU, VPU_VIU_OSD1_BLK0_CFG_W3 , data32);
253 data32 = ((fb_height_ - 1) & 0xfff) << 16;
254 WRITE32_REG(VPU, VPU_VIU_OSD1_BLK0_CFG_W4, data32);
255
256 WRITE32_REG(VPU, VPU_VIU_OSD1_BLK0_CFG_W1, ((fb_width_ - 1) & 0x1fff) << 16);
257 WRITE32_REG(VPU, VPU_VIU_OSD1_BLK0_CFG_W2, ((fb_height_ - 1) & 0x1fff) << 16);
258
259 // enable osd blk0
260 SET_BIT32(VPU, VPU_VIU_OSD1_CTRL_STAT, kHwOsdBlockEnable0, 0, 4);
261 }
262
EnableScaling(bool enable)263 void Osd::EnableScaling(bool enable) {
264 int hf_phase_step, vf_phase_step;
265 int src_w, src_h, dst_w, dst_h;
266 int bot_ini_phase;
267 int vsc_ini_rcv_num, vsc_ini_rpt_p0_num;
268 int hsc_ini_rcv_num, hsc_ini_rpt_p0_num;
269 int hf_bank_len = 4;
270 int vf_bank_len = 0;
271 uint32_t data32 = 0x0;
272
273 vf_bank_len = 4;
274 hsc_ini_rcv_num = hf_bank_len;
275 vsc_ini_rcv_num = vf_bank_len;
276 hsc_ini_rpt_p0_num =
277 (hf_bank_len / 2 - 1) > 0 ? (hf_bank_len / 2 - 1) : 0;
278 vsc_ini_rpt_p0_num =
279 (vf_bank_len / 2 - 1) > 0 ? (vf_bank_len / 2 - 1) : 0;
280 src_w = fb_width_;
281 src_h = fb_height_;
282 dst_w = display_width_;
283 dst_h = display_height_;
284
285 data32 = 0x0;
286 if (enable) {
287 /* enable osd scaler */
288 data32 |= 1 << 2; /* enable osd scaler */
289 data32 |= 1 << 3; /* enable osd scaler path */
290 WRITE32_REG(VPU, VPU_VPP_OSD_SC_CTRL0, data32);
291 } else {
292 /* disable osd scaler path */
293 WRITE32_REG(VPU, VPU_VPP_OSD_SC_CTRL0, 0);
294 }
295 hf_phase_step = (src_w << 18) / dst_w;
296 hf_phase_step = (hf_phase_step << 6);
297 vf_phase_step = (src_h << 20) / dst_h;
298 bot_ini_phase = 0;
299 vf_phase_step = (vf_phase_step << 4);
300
301 /* config osd scaler in/out hv size */
302 data32 = 0x0;
303 if (enable) {
304 data32 = (((src_h - 1) & 0x1fff)
305 | ((src_w - 1) & 0x1fff) << 16);
306 WRITE32_REG(VPU, VPU_VPP_OSD_SCI_WH_M1, data32);
307 data32 = (((display_width_ - 1) & 0xfff));
308 WRITE32_REG(VPU, VPU_VPP_OSD_SCO_H_START_END, data32);
309 data32 = (((display_height_ - 1) & 0xfff));
310 WRITE32_REG(VPU, VPU_VPP_OSD_SCO_V_START_END, data32);
311 }
312 data32 = 0x0;
313 if (enable) {
314 data32 |= (vf_bank_len & 0x7)
315 | ((vsc_ini_rcv_num & 0xf) << 3)
316 | ((vsc_ini_rpt_p0_num & 0x3) << 8);
317 data32 |= 1 << 24;
318 }
319 WRITE32_REG(VPU, VPU_VPP_OSD_VSC_CTRL0, data32);
320 data32 = 0x0;
321 if (enable) {
322 data32 |= (hf_bank_len & 0x7)
323 | ((hsc_ini_rcv_num & 0xf) << 3)
324 | ((hsc_ini_rpt_p0_num & 0x3) << 8);
325 data32 |= 1 << 22;
326 }
327 WRITE32_REG(VPU, VPU_VPP_OSD_HSC_CTRL0, data32);
328 data32 = 0x0;
329 if (enable) {
330 data32 |= (bot_ini_phase & 0xffff) << 16;
331 SET_BIT32(VPU,VPU_VPP_OSD_HSC_PHASE_STEP,
332 hf_phase_step, 0, 28);
333 SET_BIT32(VPU,VPU_VPP_OSD_HSC_INI_PHASE, 0, 0, 16);
334 SET_BIT32(VPU,VPU_VPP_OSD_VSC_PHASE_STEP,
335 vf_phase_step, 0, 28);
336 WRITE32_REG(VPU, VPU_VPP_OSD_VSC_INI_PHASE, data32);
337 }
338 }
339
ResetRdmaTable()340 void Osd::ResetRdmaTable() {
341 // For Astro display driver, RDMA table is simple.
342 // Setup RDMA Table Register values
343 for (int i = 0; i < kMaxRdmaChannels; i++) {
344 RdmaTable* rdma_table = reinterpret_cast<RdmaTable*>(rdma_chnl_container_[i].virt_offset);
345 rdma_table[IDX_CFG_W0].reg = (VPU_VIU_OSD1_BLK0_CFG_W0 >> 2);
346 rdma_table[IDX_CTRL_STAT].reg = (VPU_VIU_OSD1_CTRL_STAT >> 2);
347 }
348
349 }
350
SetRdmaTableValue(uint32_t channel,uint32_t idx,uint32_t val)351 void Osd::SetRdmaTableValue(uint32_t channel, uint32_t idx, uint32_t val) {
352 ZX_DEBUG_ASSERT(idx < IDX_MAX);
353 ZX_DEBUG_ASSERT(channel < kMaxRdmaChannels);
354 RdmaTable* rdma_table = reinterpret_cast<RdmaTable*>(rdma_chnl_container_[channel].virt_offset);
355 rdma_table[idx].val = val;
356 }
357
FlushRdmaTable(uint32_t channel)358 void Osd::FlushRdmaTable(uint32_t channel) {
359 zx_status_t status = zx_cache_flush(rdma_chnl_container_[channel].virt_offset,
360 sizeof(RdmaTable),
361 ZX_CACHE_FLUSH_DATA | ZX_CACHE_FLUSH_INVALIDATE);
362 if (status != ZX_OK) {
363 DISP_ERROR("Could not clean cache %d\n", status);
364 return;
365 }
366 }
367
GetNextAvailableRdmaChannel()368 int Osd::GetNextAvailableRdmaChannel() {
369 // The next RDMA channel is the one that is not being used by hardware
370 // A channel is considered available if it's not busy OR the done bit is set
371 for (int i = 0; i < kMaxRdmaChannels; i++) {
372 if (!rdma_chnl_container_[i].active ||
373 vpu_mmio_->Read32(VPU_RDMA_STATUS) & RDMA_STATUS_DONE(i)) {
374 // found one
375 rdma_chnl_container_[i].active = true;
376 // clear interrupts
377 vpu_mmio_->Write32(vpu_mmio_->Read32(VPU_RDMA_CTRL) | RDMA_CTRL_INT_DONE(i),
378 VPU_RDMA_CTRL);
379 return i;
380 }
381 }
382
383 return -1;
384 }
385
SetupRdma()386 zx_status_t Osd::SetupRdma() {
387 zx_status_t status = ZX_OK;
388 DISP_INFO("Setting up RDMA\n");
389
390 // since we are flushing the caches, make sure the tables are at least cache_line apart
391 ZX_DEBUG_ASSERT(kChannelBaseOffset > zx_system_get_dcache_line_size());
392
393 // Allocate one page for RDMA Table
394 status = zx_vmo_create_contiguous(bti_.get(), ZX_PAGE_SIZE, 0,
395 rdma_vmo_.reset_and_get_address());
396 if (status != ZX_OK) {
397 DISP_ERROR("Could not create RDMA VMO (%d)\n", status);
398 return status;
399 }
400
401 status = zx_bti_pin(bti_.get(), ZX_BTI_PERM_READ | ZX_BTI_PERM_WRITE, rdma_vmo_.get(),
402 0, ZX_PAGE_SIZE, &rdma_phys_, 1, &rdma_pmt_);
403 if (status != ZX_OK) {
404 DISP_ERROR("Could not pin RDMA VMO (%d)\n", status);
405 return status;
406 }
407
408 status = zx_vmar_map(zx_vmar_root_self(), ZX_VM_PERM_READ | ZX_VM_PERM_WRITE,
409 0, rdma_vmo_.get(), 0, ZX_PAGE_SIZE,
410 reinterpret_cast<zx_vaddr_t*>(&rdma_vbuf_));
411 if (status != ZX_OK) {
412 DISP_ERROR("Could not map vmar (%d)\n", status);
413 return status;
414 }
415
416 // Initialize each rdma channel container
417 for (int i = 0; i < kMaxRdmaChannels; i++) {
418 ZX_DEBUG_ASSERT((i * kChannelBaseOffset) < ZX_PAGE_SIZE);
419 rdma_chnl_container_[i].phys_offset = rdma_phys_ + (i * kChannelBaseOffset);
420 rdma_chnl_container_[i].virt_offset = rdma_vbuf_ + (i * kChannelBaseOffset);
421 rdma_chnl_container_[i].active = false;
422 }
423
424 // Setup RDMA_CTRL:
425 // Default: no reset, no clock gating, burst size 4x16B for read and write
426 // DDR Read/Write request urgent
427 uint32_t regVal = RDMA_CTRL_READ_URGENT | RDMA_CTRL_WRITE_URGENT;
428 vpu_mmio_->Write32(regVal, VPU_RDMA_CTRL);
429
430 ResetRdmaTable();
431
432 return status;
433 }
434
HwInit()435 void Osd::HwInit() {
436 ZX_DEBUG_ASSERT(initialized_);
437 // Setup VPP horizontal width
438 WRITE32_REG(VPU, VPP_POSTBLEND_H_SIZE, display_width_);
439
440 // init vpu fifo control register
441 uint32_t regVal = READ32_REG(VPU, VPP_OFIFO_SIZE);
442 regVal = 0xfff << 20;
443 regVal |= (0xfff + 1);
444 WRITE32_REG(VPU, VPP_OFIFO_SIZE, regVal);
445
446 // init osd fifo control and set DDR request priority to be urgent
447 regVal = 1;
448 regVal |= 4 << 5; // hold_fifo_lines
449 regVal |= 1 << 10; // burst_len_sel 3 = 64. This bit is split between 10 and 31
450 regVal |= 2 << 22;
451 regVal |= 2 << 24;
452 regVal |= 1 << 31;
453 regVal |= 32 << 12; // fifo_depth_val: 32*8 = 256
454 WRITE32_REG(VPU, VPU_VIU_OSD1_FIFO_CTRL_STAT, regVal);
455 WRITE32_REG(VPU, VPU_VIU_OSD2_FIFO_CTRL_STAT, regVal);
456
457 SET_MASK32(VPU, VPP_MISC, VPP_POSTBLEND_EN);
458 CLEAR_MASK32(VPU, VPP_MISC, VPP_PREBLEND_EN);
459 // just disable osd to avoid booting hang up
460 regVal = 0x1 << 0;
461 regVal |= kOsdGlobalAlphaDef << 12;
462 regVal |= (1 << 21);
463 WRITE32_REG(VPU, VPU_VIU_OSD1_CTRL_STAT , regVal);
464 WRITE32_REG(VPU, VPU_VIU_OSD2_CTRL_STAT , regVal);
465
466 DefaultSetup();
467
468 EnableScaling(true);
469
470 // Apply scale coefficients
471 SET_BIT32(VPU, VPU_VPP_OSD_SCALE_COEF_IDX, 0x0000, 0, 9);
472 for (int i = 0; i < 33; i++) {
473 WRITE32_REG(VPU, VPU_VPP_OSD_SCALE_COEF, osd_filter_coefs_bicubic[i]);
474 }
475
476 SET_BIT32(VPU, VPU_VPP_OSD_SCALE_COEF_IDX, 0x0100, 0, 9);
477 for (int i = 0; i < 33; i++) {
478 WRITE32_REG(VPU, VPU_VPP_OSD_SCALE_COEF, osd_filter_coefs_bicubic[i]);
479 }
480
481 // update blending
482 WRITE32_REG(VPU, VPU_VPP_OSD1_BLD_H_SCOPE, display_width_ - 1);
483 WRITE32_REG(VPU, VPU_VPP_OSD1_BLD_V_SCOPE, display_height_ - 1);
484 WRITE32_REG(VPU, VPU_VPP_OUT_H_V_SIZE, display_width_ << 16 | display_height_);
485 }
486
487 #define REG_OFFSET (0x20 << 2)
Dump()488 void Osd::Dump() {
489 ZX_DEBUG_ASSERT(initialized_);
490 uint32_t reg = 0;
491 uint32_t offset = 0;
492 uint32_t index = 0;
493
494 reg = VPU_VIU_VENC_MUX_CTRL;
495 DISP_INFO("reg[0x%x]: 0x%08x\n", reg, READ32_REG(VPU, reg));
496 reg = VPU_VPP_MISC;
497 DISP_INFO("reg[0x%x]: 0x%08x\n", reg, READ32_REG(VPU, reg));
498 reg = VPU_VPP_OFIFO_SIZE;
499 DISP_INFO("reg[0x%x]: 0x%08x\n", reg, READ32_REG(VPU, reg));
500 reg = VPU_VPP_HOLD_LINES;
501 DISP_INFO("reg[0x%x]: 0x%08x\n", reg, READ32_REG(VPU, reg));
502
503 reg = VPU_OSD_PATH_MISC_CTRL;
504 DISP_INFO("reg[0x%x]: 0x%08x\n", reg, READ32_REG(VPU, reg));
505 reg = VPU_VIU_OSD_BLEND_CTRL;
506 DISP_INFO("reg[0x%x]: 0x%08x\n", reg, READ32_REG(VPU, reg));
507 reg = VPU_VIU_OSD_BLEND_DIN0_SCOPE_H;
508 DISP_INFO("reg[0x%x]: 0x%08x\n", reg, READ32_REG(VPU, reg));
509 reg = VPU_VIU_OSD_BLEND_DIN0_SCOPE_V;
510 DISP_INFO("reg[0x%x]: 0x%08x\n", reg, READ32_REG(VPU, reg));
511 reg = VPU_VIU_OSD_BLEND_DIN1_SCOPE_H;
512 DISP_INFO("reg[0x%x]: 0x%08x\n", reg, READ32_REG(VPU, reg));
513 reg = VPU_VIU_OSD_BLEND_DIN1_SCOPE_V;
514 DISP_INFO("reg[0x%x]: 0x%08x\n", reg, READ32_REG(VPU, reg));
515 reg = VPU_VIU_OSD_BLEND_DIN2_SCOPE_H;
516 DISP_INFO("reg[0x%x]: 0x%08x\n", reg, READ32_REG(VPU, reg));
517 reg = VPU_VIU_OSD_BLEND_DIN2_SCOPE_V;
518 DISP_INFO("reg[0x%x]: 0x%08x\n", reg, READ32_REG(VPU, reg));
519 reg = VPU_VIU_OSD_BLEND_DIN3_SCOPE_H;
520 DISP_INFO("reg[0x%x]: 0x%08x\n", reg, READ32_REG(VPU, reg));
521 reg = VPU_VIU_OSD_BLEND_DIN3_SCOPE_V;
522 DISP_INFO("reg[0x%x]: 0x%08x\n", reg, READ32_REG(VPU, reg));
523 reg = VPU_VIU_OSD_BLEND_DUMMY_DATA0;
524 DISP_INFO("reg[0x%x]: 0x%08x\n", reg, READ32_REG(VPU, reg));
525 reg = VPU_VIU_OSD_BLEND_DUMMY_ALPHA;
526 DISP_INFO("reg[0x%x]: 0x%08x\n", reg, READ32_REG(VPU, reg));
527 reg = VPU_VIU_OSD_BLEND_BLEND0_SIZE;
528 DISP_INFO("reg[0x%x]: 0x%08x\n", reg, READ32_REG(VPU, reg));
529 reg = VPU_VIU_OSD_BLEND_BLEND1_SIZE;
530 DISP_INFO("reg[0x%x]: 0x%08x\n", reg, READ32_REG(VPU, reg));
531
532 reg = VPU_VPP_OSD1_IN_SIZE;
533 DISP_INFO("reg[0x%x]: 0x%08x\n", reg, READ32_REG(VPU, reg));
534 reg = VPU_VPP_OSD1_BLD_H_SCOPE;
535 DISP_INFO("reg[0x%x]: 0x%08x\n", reg, READ32_REG(VPU, reg));
536 reg = VPU_VPP_OSD1_BLD_V_SCOPE;
537 DISP_INFO("reg[0x%x]: 0x%08x\n", reg, READ32_REG(VPU, reg));
538 reg = VPU_VPP_OSD2_BLD_H_SCOPE;
539 DISP_INFO("reg[0x%x]: 0x%08x\n", reg, READ32_REG(VPU, reg));
540 reg = VPU_VPP_OSD2_BLD_V_SCOPE;
541 DISP_INFO("reg[0x%x]: 0x%08x\n", reg, READ32_REG(VPU, reg));
542 reg = OSD1_BLEND_SRC_CTRL;
543 DISP_INFO("reg[0x%x]: 0x%08x\n", reg, READ32_REG(VPU, reg));
544 reg = OSD2_BLEND_SRC_CTRL;
545 DISP_INFO("reg[0x%x]: 0x%08x\n", reg, READ32_REG(VPU, reg));
546 reg = VPU_VPP_POSTBLEND_H_SIZE;
547 DISP_INFO("reg[0x%x]: 0x%08x\n", reg, READ32_REG(VPU, reg));
548 reg = VPU_VPP_OUT_H_V_SIZE;
549 DISP_INFO("reg[0x%x]: 0x%08x\n", reg, READ32_REG(VPU, reg));
550
551 reg = VPU_VPP_OSD_SC_CTRL0;
552 DISP_INFO("reg[0x%x]: 0x%08x\n", reg, READ32_REG(VPU, reg));
553 reg = VPU_VPP_OSD_SCI_WH_M1;
554 DISP_INFO("reg[0x%x]: 0x%08x\n", reg, READ32_REG(VPU, reg));
555 reg = VPU_VPP_OSD_SCO_H_START_END;
556 DISP_INFO("reg[0x%x]: 0x%08x\n", reg, READ32_REG(VPU, reg));
557 reg = VPU_VPP_OSD_SCO_V_START_END;
558 DISP_INFO("reg[0x%x]: 0x%08x\n\n", reg, READ32_REG(VPU, reg));
559 reg = VPU_VPP_POSTBLEND_H_SIZE;
560 DISP_INFO("reg[0x%x]: 0x%08x\n\n", reg, READ32_REG(VPU, reg));
561 for (index = 0; index < 2; index++) {
562 if (index == 1)
563 offset = REG_OFFSET;
564 reg = offset + VPU_VIU_OSD1_FIFO_CTRL_STAT;
565 DISP_INFO("reg[0x%x]: 0x%08x\n", reg, READ32_REG(VPU, reg));
566 reg = offset + VPU_VIU_OSD1_CTRL_STAT;
567 DISP_INFO("reg[0x%x]: 0x%08x\n", reg, READ32_REG(VPU, reg));
568 reg = offset + VPU_VIU_OSD1_BLK0_CFG_W0;
569 DISP_INFO("reg[0x%x]: 0x%08x\n", reg, READ32_REG(VPU, reg));
570 reg = offset + VPU_VIU_OSD1_BLK0_CFG_W1;
571 DISP_INFO("reg[0x%x]: 0x%08x\n", reg, READ32_REG(VPU, reg));
572 reg = offset + VPU_VIU_OSD1_BLK0_CFG_W2;
573 DISP_INFO("reg[0x%x]: 0x%08x\n", reg, READ32_REG(VPU, reg));
574 reg = offset + VPU_VIU_OSD1_BLK0_CFG_W3;
575 DISP_INFO("reg[0x%x]: 0x%08x\n", reg, READ32_REG(VPU, reg));
576 reg = VPU_VIU_OSD1_BLK0_CFG_W4;
577 if (index == 1)
578 reg = VPU_VIU_OSD2_BLK0_CFG_W4;
579 DISP_INFO("reg[0x%x]: 0x%08x\n\n", reg, READ32_REG(VPU, reg));
580 }
581 }
582
Release()583 void Osd::Release() {
584 Disable();
585 rdma_irq_.destroy();
586 thrd_join(rdma_thread_, NULL);
587 zx_pmt_unpin(rdma_pmt_);
588 }
589
590 } // namespace astro_display
591