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 "ovl.h"
6 #include "registers-ovl.h"
7 #include <fbl/alloc_checker.h>
8 #include <math.h>
9
10 namespace mt8167s_display {
11
12 namespace {
13 constexpr uint32_t kDefaultBackgroundColor = 0xFF000000; // alpha/red/green/blue
14 constexpr int kIdleTimeout = 20000;
15 } // namespace
16
Init(zx_device_t * parent)17 zx_status_t Ovl::Init(zx_device_t* parent) {
18 if (initialized_) {
19 return ZX_OK;
20 }
21
22 zx_status_t status = device_get_protocol(parent, ZX_PROTOCOL_PDEV, &pdev_);
23 if (status != ZX_OK) {
24 return status;
25 }
26
27 // Map Ovl mmio
28 mmio_buffer_t mmio;
29 status = pdev_map_mmio_buffer2(&pdev_, MMIO_DISP_OVL, ZX_CACHE_POLICY_UNCACHED_DEVICE,
30 &mmio);
31 if (status != ZX_OK) {
32 DISP_ERROR("Could not map OVL mmio\n");
33 return status;
34 }
35 fbl::AllocChecker ac;
36 ovl_mmio_ = fbl::make_unique_checked<ddk::MmioBuffer>(&ac, mmio);
37 if (!ac.check()) {
38 DISP_ERROR("Could not mapp Overlay MMIO\n");
39 return ZX_ERR_NO_MEMORY;
40 }
41
42 // Get BTI from parent
43 status = pdev_get_bti(&pdev_, 0, bti_.reset_and_get_address());
44 if (status != ZX_OK) {
45 DISP_ERROR("Could not get BTI handle\n");
46 return status;
47 }
48
49 // Ovl is ready to be used
50 initialized_ = true;
51 return ZX_OK;
52 }
53
Reset()54 void Ovl::Reset() {
55 ZX_DEBUG_ASSERT(initialized_);
56 Stop();
57 active_layers_ = 0;
58 layer_handle_[0] = 0;
59 layer_handle_[1] = 0;
60 layer_handle_[2] = 0;
61 layer_handle_[3] = 0;
62 }
63
IsSupportedFormat(zx_pixel_format_t format)64 bool Ovl::IsSupportedFormat(zx_pixel_format_t format) {
65 if ((format == ZX_PIXEL_FORMAT_RGB_565) ||
66 (format == ZX_PIXEL_FORMAT_ARGB_8888) ||
67 (format == ZX_PIXEL_FORMAT_RGB_x888)) {
68 return true;
69 } else {
70 return false;
71 }
72 }
73
GetFormat(zx_pixel_format_t format)74 uint32_t Ovl::GetFormat(zx_pixel_format_t format) {
75 switch (format) {
76 case ZX_PIXEL_FORMAT_RGB_565:
77 return RGB565;
78 case ZX_PIXEL_FORMAT_ARGB_8888:
79 return BGRA8888;
80 case ZX_PIXEL_FORMAT_RGB_x888:
81 return RGB888;
82 }
83
84 return 0;
85 }
86
ByteSwapNeeded(zx_pixel_format_t format)87 bool Ovl::ByteSwapNeeded(zx_pixel_format_t format) {
88 switch (format) {
89 case ZX_PIXEL_FORMAT_ARGB_8888:
90 case ZX_PIXEL_FORMAT_RGB_x888:
91 return false;
92 case ZX_PIXEL_FORMAT_RGB_565:
93 return true;
94 default:
95 ZX_DEBUG_ASSERT(false);
96 }
97
98 return false;
99 }
100
GetBytesPerPixel(zx_pixel_format_t format)101 uint32_t Ovl::GetBytesPerPixel(zx_pixel_format_t format) {
102 switch (format) {
103 case ZX_PIXEL_FORMAT_RGB_565:
104 return 2;
105 case ZX_PIXEL_FORMAT_ARGB_8888:
106 case ZX_PIXEL_FORMAT_RGB_x888:
107 return 4;
108 default:
109 ZX_DEBUG_ASSERT(false);
110 }
111
112 return 0;
113 }
114
Start()115 void Ovl::Start() {
116 ZX_DEBUG_ASSERT(initialized_);
117 // Enable the overlay engine and interrupts
118 ovl_mmio_->Write32(INT_FRAME_COMPLETE, OVL_INTEN);
119 ovl_mmio_->Write32(0x1, OVL_EN);
120 ovl_mmio_->ModifyBits32(0x1, 0, 1, OVL_DATAPATH_CON);
121 }
122
Stop()123 void Ovl::Stop() {
124 ZX_DEBUG_ASSERT(initialized_);
125 int timeout = kIdleTimeout;
126
127 // Disable sources of interrupt and display the overlay engine first
128 ovl_mmio_->Write32(0x0, OVL_INTEN);
129 ovl_mmio_->Write32(0x0, OVL_EN);
130 ovl_mmio_->Write32(0x0, OVL_INTSTA);
131
132 // Wait for all operations to finish and the state machine is idle
133 while (!IsIdle() && timeout--) {
134 zx_nanosleep(zx_deadline_after(ZX_USEC(1)));
135 }
136 ZX_ASSERT(timeout > 0);
137
138 // Now that we are idle, we can disable other parts of the engine
139 ovl_mmio_->Write32(0, OVL_DATAPATH_CON);
140 ovl_mmio_->Write32(0, OVL_RDMAx_CTRL(0));
141 ovl_mmio_->Write32(0, OVL_RDMAx_CTRL(1));
142 ovl_mmio_->Write32(0, OVL_RDMAx_CTRL(2));
143 ovl_mmio_->Write32(0, OVL_RDMAx_CTRL(3));
144 ovl_mmio_->Write32(0, OVL_SRC_CON);
145 }
146
Config(uint8_t layer,OvlConfig & cfg)147 zx_status_t Ovl::Config(uint8_t layer, OvlConfig &cfg) {
148 ZX_DEBUG_ASSERT(initialized_);
149 ZX_DEBUG_ASSERT(layer < kMaxLayer);
150
151 // Configure ROI first. ROI abbreviation is not clarified in docs. Assuming it means
152 // Region Of Interest. Also, ROI does not seem to be "layer" related. So it might mean the
153 // final screen after all the layers have been mixed.
154 ovl_mmio_->Write32(height_ << 16 | width_, OVL_ROI_SIZE);
155 ovl_mmio_->Write32(kDefaultBackgroundColor,OVL_ROI_BGCLR);
156
157 // Enable Layer
158 // We cannot simply enable a layer and/or its RDMA channel source. This could
159 // only be done at IDLE time. Config should only be called after calling the stop function
160 // which places the engine in Idle.
161 if (IsIdle()) {
162 ovl_mmio_->Write32(ovl_mmio_->Read32(OVL_SRC_CON) |
163 SRC_CON_ENABLE_LAYER(layer), OVL_SRC_CON);
164 ovl_mmio_->ModifyBits32(1, 0, 1, OVL_RDMAx_CTRL(layer));
165 } else {
166 // We are not Idle! Let's dump all registers and crash
167 Dump();
168 ZX_ASSERT(false);
169 }
170
171 // Make sure we support the input format
172 if (!IsSupportedFormat(cfg.format)) {
173 DISP_ERROR("Unsupported format: 0x%x\n", cfg.format);
174 ZX_ASSERT(false);
175 }
176
177 // Setup various OVL CON register <layer specific>
178 uint32_t regVal = 0;
179 if (cfg.alpha_mode != ALPHA_DISABLE) {
180 regVal = Lx_CON_AEN; // enable alpha blending
181 if (!isnan(cfg.alpha_val)) {
182 // Apply alpha value
183 regVal |= Lx_CON_ALPHA(static_cast<uint8_t>(round(cfg.alpha_val * 255)));
184 } else {
185 // Enable per-pixel only, therefore set multiplier to 1
186 regVal |= Lx_CON_ALPHA(0xFF);
187 }
188 }
189
190 if (ByteSwapNeeded(cfg.format)) {
191 regVal |= Lx_CON_BYTE_SWAP;
192 }
193 regVal |= Lx_CON_CLRFMT(GetFormat(cfg.format));
194 ovl_mmio_->Write32(regVal, OVL_Lx_CON(layer));
195
196 // write the height and width of source buffer for this layer
197 ovl_mmio_->Write32(height_ << 16 | width_, OVL_Lx_SRC_SIZE(layer));
198
199 // set the offset of actual image within the buffer
200 ovl_mmio_->Write32(y_ << 16 | x_, OVL_Lx_OFFSET(layer));
201
202 // set the physical address of the buffer for this layer
203 uint32_t finaladdr = static_cast<uint32_t>(cfg.paddr) +
204 x_ * GetBytesPerPixel(cfg.format) + y_ * pitch_;
205 ovl_mmio_->Write32(finaladdr, OVL_Lx_ADDR(layer));
206
207 // setup Lx_PITCH_PITCH register
208 regVal = 0;
209 regVal |= Lx_PITCH_PITCH(pitch_);
210 ovl_mmio_->Write32(regVal, OVL_Lx_PITCH(layer));
211
212 // Setup magical register with undocumented magic value
213 ovl_mmio_->Write32(0x6070, OVL_RDMAx_MEM_GMC_SETTING(layer));
214 active_layers_ |= static_cast<uint8_t>((1 << layer));
215 layer_handle_[layer] = cfg.paddr;
216 return ZX_OK;
217 }
218
Dump()219 void Ovl::Dump() {
220 zxlogf(INFO, "Dumping OVL Registers:\n");
221 zxlogf(INFO, "######################\n\n");
222 zxlogf(INFO, "OVL_STA = 0x%x\n", ovl_mmio_->Read32(OVL_STA));
223 zxlogf(INFO, "OVL_INTEN = 0x%x\n", ovl_mmio_->Read32(OVL_INTEN));
224 zxlogf(INFO, "OVL_INTSTA = 0x%x\n", ovl_mmio_->Read32(OVL_INTSTA));
225 zxlogf(INFO, "OVL_EN = 0x%x\n", ovl_mmio_->Read32(OVL_EN));
226 zxlogf(INFO, "OVL_TRIG = 0x%x\n", ovl_mmio_->Read32(OVL_TRIG));
227 zxlogf(INFO, "OVL_RST = 0x%x\n", ovl_mmio_->Read32(OVL_RST));
228 zxlogf(INFO, "OVL_ROI_SIZE = 0x%x\n", ovl_mmio_->Read32(OVL_ROI_SIZE));
229 zxlogf(INFO, "OVL_DATAPATH_CON = 0x%x\n", ovl_mmio_->Read32(OVL_DATAPATH_CON));
230 zxlogf(INFO, "OVL_ROI_BGCLR = 0x%x\n", ovl_mmio_->Read32(OVL_ROI_BGCLR));
231 zxlogf(INFO, "OVL_SRC_CON = 0x%x\n", ovl_mmio_->Read32(OVL_SRC_CON));
232 zxlogf(INFO, "OVL_Lx_CON0123 = 0x%x, 0x%x, 0x%x, 0x%x\n",
233 ovl_mmio_->Read32(OVL_Lx_CON(0)),
234 ovl_mmio_->Read32(OVL_Lx_CON(1)),
235 ovl_mmio_->Read32(OVL_Lx_CON(2)),
236 ovl_mmio_->Read32(OVL_Lx_CON(3)));
237 zxlogf(INFO, "OVL_Lx_SRCKEY0123 = 0x%x, 0x%x, 0x%x, 0x%x\n",
238 ovl_mmio_->Read32(OVL_Lx_SRCKEY(0)),
239 ovl_mmio_->Read32(OVL_Lx_SRCKEY(1)),
240 ovl_mmio_->Read32(OVL_Lx_SRCKEY(2)),
241 ovl_mmio_->Read32(OVL_Lx_SRCKEY(3)));
242 zxlogf(INFO, "OVL_Lx_SRC_SIZE0123 = 0x%x, 0x%x, 0x%x, 0x%x\n",
243 ovl_mmio_->Read32(OVL_Lx_SRC_SIZE(0)),
244 ovl_mmio_->Read32(OVL_Lx_SRC_SIZE(1)),
245 ovl_mmio_->Read32(OVL_Lx_SRC_SIZE(2)),
246 ovl_mmio_->Read32(OVL_Lx_SRC_SIZE(3)));
247 zxlogf(INFO, "OVL_Lx_OFFSET0123 = 0x%x, 0x%x, 0x%x, 0x%x\n",
248 ovl_mmio_->Read32(OVL_Lx_OFFSET(0)),
249 ovl_mmio_->Read32(OVL_Lx_OFFSET(1)),
250 ovl_mmio_->Read32(OVL_Lx_OFFSET(2)),
251 ovl_mmio_->Read32(OVL_Lx_OFFSET(3)));
252 zxlogf(INFO, "OVL_Lx_ADDR0123 = 0x%x, 0x%x, 0x%x, 0x%x\n",
253 ovl_mmio_->Read32(OVL_Lx_ADDR(0)),
254 ovl_mmio_->Read32(OVL_Lx_ADDR(1)),
255 ovl_mmio_->Read32(OVL_Lx_ADDR(2)),
256 ovl_mmio_->Read32(OVL_Lx_ADDR(3)));
257 zxlogf(INFO, "OVL_Lx_PITCH0123 = 0x%x, 0x%x, 0x%x, 0x%x\n",
258 ovl_mmio_->Read32(OVL_Lx_PITCH(0)),
259 ovl_mmio_->Read32(OVL_Lx_PITCH(1)),
260 ovl_mmio_->Read32(OVL_Lx_PITCH(2)),
261 ovl_mmio_->Read32(OVL_Lx_PITCH(3)));
262 zxlogf(INFO, "OVL_Lx_TILE0123 = 0x%x, 0x%x, 0x%x, 0x%x\n",
263 ovl_mmio_->Read32(OVL_Lx_TILE(0)),
264 ovl_mmio_->Read32(OVL_Lx_TILE(1)),
265 ovl_mmio_->Read32(OVL_Lx_TILE(2)),
266 ovl_mmio_->Read32(OVL_Lx_TILE(3)));
267 zxlogf(INFO, "OVL_RDMAx_CTRL0123 = 0x%x, 0x%x, 0x%x, 0x%x\n",
268 ovl_mmio_->Read32(OVL_RDMAx_CTRL(0)),
269 ovl_mmio_->Read32(OVL_RDMAx_CTRL(1)),
270 ovl_mmio_->Read32(OVL_RDMAx_CTRL(2)),
271 ovl_mmio_->Read32(OVL_RDMAx_CTRL(3)));
272 zxlogf(INFO, "OVL_RDMAx_MEM_GMC_SETTING0123 = 0x%x, 0x%x, 0x%x, 0x%x\n",
273 ovl_mmio_->Read32(OVL_RDMAx_MEM_GMC_SETTING(0)),
274 ovl_mmio_->Read32(OVL_RDMAx_MEM_GMC_SETTING(1)),
275 ovl_mmio_->Read32(OVL_RDMAx_MEM_GMC_SETTING(2)),
276 ovl_mmio_->Read32(OVL_RDMAx_MEM_GMC_SETTING(3)));
277 zxlogf(INFO, "OVL_RDMAx_MEM_SLOW_CON0123 = 0x%x, 0x%x, 0x%x, 0x%x\n",
278 ovl_mmio_->Read32(OVL_RDMAx_MEM_SLOW_CON(0)),
279 ovl_mmio_->Read32(OVL_RDMAx_MEM_SLOW_CON(1)),
280 ovl_mmio_->Read32(OVL_RDMAx_MEM_SLOW_CON(2)),
281 ovl_mmio_->Read32(OVL_RDMAx_MEM_SLOW_CON(3)));
282 zxlogf(INFO, "OVL_RDMAx_FIFO_CTRL0123 = 0x%x, 0x%x, 0x%x, 0x%x\n",
283 ovl_mmio_->Read32(OVL_RDMAx_FIFO_CTRL(0)),
284 ovl_mmio_->Read32(OVL_RDMAx_FIFO_CTRL(1)),
285 ovl_mmio_->Read32(OVL_RDMAx_FIFO_CTRL(2)),
286 ovl_mmio_->Read32(OVL_RDMAx_FIFO_CTRL(3)));
287 zxlogf(INFO, "OVL_Lx_Y2R_PARA_R00123 = 0x%x, 0x%x, 0x%x, 0x%x\n",
288 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_R0(0)),
289 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_R0(1)),
290 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_R0(2)),
291 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_R0(3)));
292 zxlogf(INFO, "OVL_Lx_Y2R_PARA_R10123 = 0x%x, 0x%x, 0x%x, 0x%x\n",
293 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_R1(0)),
294 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_R1(1)),
295 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_R1(2)),
296 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_R1(3)));
297 zxlogf(INFO, "OVL_Lx_Y2R_PARA_G00123 = 0x%x, 0x%x, 0x%x, 0x%x\n",
298 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_G0(0)),
299 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_G0(1)),
300 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_G0(2)),
301 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_G0(3)));
302 zxlogf(INFO, "OVL_Lx_Y2R_PARA_G10123 = 0x%x, 0x%x, 0x%x, 0x%x\n",
303 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_G1(0)),
304 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_G1(1)),
305 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_G1(2)),
306 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_G1(3)));
307 zxlogf(INFO, "OVL_Lx_Y2R_PARA_B00123 = 0x%x, 0x%x, 0x%x, 0x%x\n",
308 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_B0(0)),
309 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_B0(1)),
310 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_B0(2)),
311 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_B0(3)));
312 zxlogf(INFO, "OVL_Lx_Y2R_PARA_B10123 = 0x%x, 0x%x, 0x%x, 0x%x\n",
313 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_B1(0)),
314 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_B1(1)),
315 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_B1(2)),
316 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_B1(3)));
317 zxlogf(INFO, "OVL_Lx_Y2R_PARA_YUV_A_00123 = 0x%x, 0x%x, 0x%x, 0x%x\n",
318 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_YUV_A_0(0)),
319 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_YUV_A_0(1)),
320 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_YUV_A_0(2)),
321 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_YUV_A_0(3)));
322 zxlogf(INFO, "OVL_Lx_Y2R_PARA_YUV_A_10123 = 0x%x, 0x%x, 0x%x, 0x%x\n",
323 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_YUV_A_1(0)),
324 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_YUV_A_1(1)),
325 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_YUV_A_1(2)),
326 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_YUV_A_1(3)));
327 zxlogf(INFO, "OVL_Lx_Y2R_PARA_RGB_A_00123 = 0x%x, 0x%x, 0x%x, 0x%x\n",
328 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_RGB_A_0(0)),
329 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_RGB_A_0(1)),
330 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_RGB_A_0(2)),
331 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_RGB_A_0(3)));
332 zxlogf(INFO, "OVL_Lx_Y2R_PARA_RGB_A_10123 = 0x%x, 0x%x, 0x%x, 0x%x\n",
333 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_RGB_A_1(0)),
334 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_RGB_A_1(1)),
335 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_RGB_A_1(2)),
336 ovl_mmio_->Read32(OVL_Lx_Y2R_PARA_RGB_A_1(3)));
337 zxlogf(INFO, "OVL_DEBUG_MON_SEL = 0x%x\n", ovl_mmio_->Read32(OVL_DEBUG_MON_SEL));
338 zxlogf(INFO, "OVL_RDMAx_MEM_GMC_S20123 = 0x%x, 0x%x, 0x%x, 0x%x\n",
339 ovl_mmio_->Read32(OVL_RDMAx_MEM_GMC_S2(0)),
340 ovl_mmio_->Read32(OVL_RDMAx_MEM_GMC_S2(1)),
341 ovl_mmio_->Read32(OVL_RDMAx_MEM_GMC_S2(2)),
342 ovl_mmio_->Read32(OVL_RDMAx_MEM_GMC_S2(3)));
343 zxlogf(INFO, "OVL_DUMMY_REG = 0x%x\n", ovl_mmio_->Read32(OVL_DUMMY_REG));
344 zxlogf(INFO, "OVL_SMI_DBG = 0x%x\n", ovl_mmio_->Read32(OVL_SMI_DBG));
345 zxlogf(INFO, "OVL_GREQ_LAYER_CNT = 0x%x\n", ovl_mmio_->Read32(OVL_GREQ_LAYER_CNT));
346 zxlogf(INFO, "OVL_FLOW_CTRL_DBG = 0x%x\n", ovl_mmio_->Read32(OVL_FLOW_CTRL_DBG));
347 zxlogf(INFO, "OVL_ADDCON_DBG = 0x%x\n", ovl_mmio_->Read32(OVL_ADDCON_DBG));
348 zxlogf(INFO, "OVL_RDMAx_DBG0123 = 0x%x, 0x%x, 0x%x, 0x%x\n",
349 ovl_mmio_->Read32(OVL_RDMAx_DBG(0)),
350 ovl_mmio_->Read32(OVL_RDMAx_DBG(1)),
351 ovl_mmio_->Read32(OVL_RDMAx_DBG(2)),
352 ovl_mmio_->Read32(OVL_RDMAx_DBG(3)));
353 zxlogf(INFO, "OVL_Lx_CLR0123 = 0x%x, 0x%x, 0x%x, 0x%x\n",
354 ovl_mmio_->Read32(OVL_Lx_CLR(0)),
355 ovl_mmio_->Read32(OVL_Lx_CLR(1)),
356 ovl_mmio_->Read32(OVL_Lx_CLR(2)),
357 ovl_mmio_->Read32(OVL_Lx_CLR(3)));
358 zxlogf(INFO, "######################\n\n");
359 }
360
361 } //namespace mt8167s_display