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