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 #pragma once
6 
7 #include <lib/zx/bti.h>
8 #include <zircon/compiler.h>
9 #include <ddk/protocol/platform/device.h>
10 #include <ddk/protocol/platform-device-lib.h>
11 #include <zircon/assert.h>
12 #include <ddktl/device.h>
13 #include <ddktl/mmio.h>
14 #include <fbl/unique_ptr.h>
15 #include <optional>
16 #include "common.h"
17 #include "registers-ovl.h"
18 
19 namespace mt8167s_display {
20 
21 // [Ovl] --> [Clr] --> [Clr Correction] --> [AAL] --> [Gamma] --> [Dither] --> [RDMA] --> [DSI]
22 
23 //
24 // Overlay class is the first element in the display subsystem. It is responsible
25 // for fetching pixels from memory, perform blending (up to 4 layers), support RGB and UYVY
26 // swapping, fixed color conversion coefficient (T601, T709, JPEG), alpha blending and flipping
27 // (veritical, horizontal, 180-degree flip). The supported memory source formats are as follows:
28 // RGB565, RGB888, ARGB8888, PARGB8888, XRGB, YUV422
29 // Single Ovl object will manage all four layers
30 //
31 
32 constexpr uint16_t kMaxWidth = 4095;
33 constexpr uint16_t kMaxHeight = 4095;
34 constexpr uint32_t kMaxLayer = 4;
35 
36 class Ovl {
37 public:
38     // Contructor
Ovl(uint32_t height,uint32_t width,uint32_t pitch,uint32_t x,uint32_t y)39     Ovl(uint32_t height, uint32_t width, uint32_t pitch, uint32_t x, uint32_t y)
40         : height_(height), width_(width), pitch_(pitch), x_(x), y_(y) {
41         ZX_DEBUG_ASSERT(height_ < kMaxHeight);
42         ZX_DEBUG_ASSERT(width_ < kMaxWidth);
43     }
44 
45     // Init
46     zx_status_t Init(zx_device_t* parent);
47 
48     // Stops the overlay engine and resets the active layers
49     void Reset();
50 
51     // Configure the corresponding layer. Should only be called after Stop has been called
52     zx_status_t Config(uint8_t layer, OvlConfig &cfg);
53 
54     // Start OVL engine. This will enable interrupts (VSync) and the Overalay engine itself
55     void Start();
56 
57     // Stop OVL engine. This will place the Overlay engine in Idle mode and safely stop all
58     // transactions that may be happening. This function should be called before configuring
59     // the Overlay engine with new parameters
60     void Stop();
61 
Restart()62     void Restart() {
63         Stop();
64         Start();
65     }
66 
67     // Clears all IRQ sources
ClearIrq()68     void ClearIrq() {
69         ovl_mmio_->Write32(0x0, OVL_INTSTA);
70     }
71 
72     // Returns true if interrupt was not spurious
IsValidIrq()73     bool IsValidIrq() {
74         return ovl_mmio_->Read32(OVL_INTSTA) != 0;
75     }
76 
77     // Return true if the input layer is active
IsLayerActive(uint8_t layer)78     bool IsLayerActive(uint8_t layer) {
79         return ((active_layers_ & (1 << layer)) != 0);
80     }
81 
82     // Clears the active layer
ClearLayer(uint8_t layer)83     void ClearLayer(uint8_t layer) {
84         active_layers_ &= static_cast<uint8_t>(~(1 << layer));
85     }
86 
87     // Returns the layer handle which is the physical address of the VMO backed image
GetLayerHandle(uint8_t layer)88     zx_paddr_t GetLayerHandle(uint8_t layer) {
89         return layer_handle_[layer];
90     }
91 
92     // Prints the relevant status registers in the Overlay Engine
PrintStatusRegisters()93     void PrintStatusRegisters() {
94         DISP_INFO("STA = 0x%x, INTSTA = 0x%x, FLOW_CTRL_DBG = 0x%x\n",
95                    ovl_mmio_->Read32(OVL_STA),
96                    ovl_mmio_->Read32(OVL_INTSTA),
97                    ovl_mmio_->Read32(OVL_FLOW_CTRL_DBG));
98     }
99 
100     // Return true is Overlay Engine is Idle
IsIdle()101     bool IsIdle() {
102         return (ovl_mmio_->Read32(OVL_FLOW_CTRL_DBG) & (OVL_IDLE)) == (OVL_IDLE);
103     }
104 
105     // Dumps all relevant Overlay Registers
106     void Dump();
107 
108 private:
109 
110     // Overlay support ARGB, RGB and YUV formats only
111     bool IsSupportedFormat(zx_pixel_format_t format);
112 
113     // Return format as expected by OVL register
114     uint32_t GetFormat(zx_pixel_format_t format);
115 
116     // BYTE_SWAP: Determines the need for swapping bytes based on format
117     bool ByteSwapNeeded(zx_pixel_format_t format);
118 
119     // get Bytes per Pixel.
120     // TODO(payam): ZX_PIXEL_FORMAT_BYTES returns 4 for x888. We need three
121     uint32_t GetBytesPerPixel(zx_pixel_format_t format);
122 
123     fbl::unique_ptr<ddk::MmioBuffer>    ovl_mmio_;
124     pdev_protocol_t                     pdev_ = {nullptr, nullptr};
125     zx::bti                             bti_;
126 
127     const uint32_t                      height_; // height of buffer
128     const uint32_t                      width_; // width of buffer
129     const uint32_t                      pitch_; // i.e. stride
130     const uint32_t                      x_; // x-offset for the actual start of image in buffer
131     const uint32_t                      y_; // y-offset for the actual start of image in buffer
132 
133     bool                                initialized_ = false;
134 
135     uint8_t                             active_layers_ = 0;
136     zx_paddr_t                          layer_handle_[kMaxLayer] = {};
137 };
138 
139 } // namespace mt8167s_display