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 "vpu.h"
6 #include "vpu-regs.h"
7 #include "hhi-regs.h"
8 #include "vpp-regs.h"
9 #include <ddk/debug.h>
10 #include <ddktl/device.h>
11 
12 namespace astro_display {
13 
14 namespace {
15 constexpr uint32_t kVpuMux = 0;
16 constexpr uint32_t kVpuDiv = 3;
17 
18 constexpr int16_t RGB709_to_YUV709l_coeff[24] = {
19     0x0000, 0x0000, 0x0000,
20     0x00bb, 0x0275, 0x003f,
21     0x1f99, 0x1ea6, 0x01c2,
22     0x01c2, 0x1e67, 0x1fd7,
23     0x0000, 0x0000, 0x0000,
24     0x0000, 0x0000, 0x0000,
25     0x0040, 0x0200, 0x0200,
26     0x0000, 0x0000, 0x0000,
27 };
28 
29 constexpr int16_t YUV709l_to_RGB709_coeff12[24] = {
30     -256, -2048, -2048,
31     4788, 0, 7372,
32     4788, -876, -2190,
33     4788, 8686, 0,
34     0, 0, 0,
35     0, 0, 0,
36     0, 0, 0,
37     0, 0, 0,
38 };
39 } // namespace
40 
41 // AOBUS Register
42 #define AOBUS_GEN_PWR_SLEEP0            (0x03a << 2)
43 
44 // CBUS Reset Register
45 #define RESET0_LEVEL                    (0x0420 << 2)
46 #define RESET1_LEVEL                    (0x0421 << 2)
47 #define RESET2_LEVEL                    (0x0422 << 2)
48 #define RESET4_LEVEL                    (0x0424 << 2)
49 #define RESET7_LEVEL                    (0x0427 << 2)
50 
51 #define READ32_VPU_REG(a)               vpu_mmio_->Read32(a)
52 #define WRITE32_VPU_REG(a, v)           vpu_mmio_->Write32(v, a)
53 
54 #define READ32_HHI_REG(a)               hhi_mmio_->Read32(a)
55 #define WRITE32_HHI_REG(a, v)           hhi_mmio_->Write32(v, a)
56 
57 #define READ32_AOBUS_REG(a)             aobus_mmio_->Read32(a)
58 #define WRITE32_AOBUS_REG(a, v)         aobus_mmio_->Write32(v, a)
59 
60 #define READ32_CBUS_REG(a)              cbus_mmio_->Read32(a)
61 #define WRITE32_CBUS_REG(a, v)          cbus_mmio_->Write32(v, a)
62 
Init(zx_device_t * parent)63 zx_status_t Vpu::Init(zx_device_t* parent) {
64     if (initialized_) {
65         return ZX_OK;
66     }
67     zx_status_t status = device_get_protocol(parent, ZX_PROTOCOL_PDEV, &pdev_);
68     if (status != ZX_OK) {
69         return status;
70     }
71 
72     // Map VPU registers
73     mmio_buffer_t mmio;
74     status = pdev_map_mmio_buffer2(&pdev_, MMIO_VPU, ZX_CACHE_POLICY_UNCACHED_DEVICE,
75                                   &mmio);
76     if (status != ZX_OK) {
77         DISP_ERROR("vpu: Could not map VPU mmio\n");
78         return status;
79     }
80     vpu_mmio_ = ddk::MmioBuffer(mmio);
81 
82     // Map HHI registers
83     status = pdev_map_mmio_buffer2(&pdev_, MMIO_HHI, ZX_CACHE_POLICY_UNCACHED_DEVICE,
84                                   &mmio);
85     if (status != ZX_OK) {
86         DISP_ERROR("vpu: Could not map HHI mmio\n");
87         return status;
88     }
89     hhi_mmio_ = ddk::MmioBuffer(mmio);
90 
91     // Map AOBUS registers
92     status = pdev_map_mmio_buffer2(&pdev_, MMIO_AOBUS, ZX_CACHE_POLICY_UNCACHED_DEVICE,
93                                   &mmio);
94     if (status != ZX_OK) {
95         DISP_ERROR("vpu: Could not map AOBUS mmio\n");
96         return status;
97     }
98     aobus_mmio_ = ddk::MmioBuffer(mmio);
99 
100     // Map CBUS registers
101     status = pdev_map_mmio_buffer2(&pdev_, MMIO_CBUS, ZX_CACHE_POLICY_UNCACHED_DEVICE,
102                                   &mmio);
103     if (status != ZX_OK) {
104         DISP_ERROR("vpu: Could not map CBUS mmio\n");
105         return status;
106     }
107     cbus_mmio_ = ddk::MmioBuffer(mmio);
108 
109     // VPU object is ready to be used
110     initialized_ = true;
111     return ZX_OK;
112 }
113 
VppInit()114 void Vpu::VppInit() {
115     ZX_DEBUG_ASSERT(initialized_);
116 
117     // init vpu fifo control register
118     SET_BIT32(VPU, VPP_OFIFO_SIZE, 0xFFF, 0, 12);
119     WRITE32_REG(VPU, VPP_HOLD_LINES, 0x08080808);
120     // default probe_sel, for highlight en
121     SET_BIT32(VPU, VPP_MATRIX_CTRL, 0x7, 12, 3);
122 
123     // setting up os1 for rgb -> yuv limit
124     const int16_t* m = RGB709_to_YUV709l_coeff;
125 
126     // VPP WRAP OSD1 matrix
127     WRITE32_REG(VPU, VPP_WRAP_OSD1_MATRIX_PRE_OFFSET0_1,
128         ((m[0] & 0xfff) << 16) | (m[1] & 0xfff));
129     WRITE32_REG(VPU, VPP_WRAP_OSD1_MATRIX_PRE_OFFSET2,
130         m[2] & 0xfff);
131     WRITE32_REG(VPU, VPP_WRAP_OSD1_MATRIX_COEF00_01,
132         ((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff));
133     WRITE32_REG(VPU, VPP_WRAP_OSD1_MATRIX_COEF02_10,
134         ((m[5]  & 0x1fff) << 16) | (m[6] & 0x1fff));
135     WRITE32_REG(VPU, VPP_WRAP_OSD1_MATRIX_COEF11_12,
136         ((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff));
137     WRITE32_REG(VPU, VPP_WRAP_OSD1_MATRIX_COEF20_21,
138         ((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff));
139     WRITE32_REG(VPU, VPP_WRAP_OSD1_MATRIX_COEF22,
140         m[11] & 0x1fff);
141     WRITE32_REG(VPU, VPP_WRAP_OSD1_MATRIX_OFFSET0_1,
142         ((m[18] & 0xfff) << 16) | (m[19] & 0xfff));
143     WRITE32_REG(VPU, VPP_WRAP_OSD1_MATRIX_OFFSET2,
144         m[20] & 0xfff);
145     SET_BIT32(VPU, VPP_WRAP_OSD1_MATRIX_EN_CTRL, 1, 0, 1);
146 
147     // VPP WRAP OSD2 matrix
148     WRITE32_REG(VPU, VPP_WRAP_OSD2_MATRIX_PRE_OFFSET0_1,
149         ((m[0] & 0xfff) << 16) | (m[1] & 0xfff));
150     WRITE32_REG(VPU, VPP_WRAP_OSD2_MATRIX_PRE_OFFSET2,
151         m[2] & 0xfff);
152     WRITE32_REG(VPU, VPP_WRAP_OSD2_MATRIX_COEF00_01,
153         ((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff));
154     WRITE32_REG(VPU, VPP_WRAP_OSD2_MATRIX_COEF02_10,
155         ((m[5]  & 0x1fff) << 16) | (m[6] & 0x1fff));
156     WRITE32_REG(VPU, VPP_WRAP_OSD2_MATRIX_COEF11_12,
157         ((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff));
158     WRITE32_REG(VPU, VPP_WRAP_OSD2_MATRIX_COEF20_21,
159         ((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff));
160     WRITE32_REG(VPU, VPP_WRAP_OSD2_MATRIX_COEF22,
161         m[11] & 0x1fff);
162     WRITE32_REG(VPU, VPP_WRAP_OSD2_MATRIX_OFFSET0_1,
163         ((m[18] & 0xfff) << 16) | (m[19] & 0xfff));
164     WRITE32_REG(VPU, VPP_WRAP_OSD2_MATRIX_OFFSET2,
165         m[20] & 0xfff);
166     SET_BIT32(VPU, VPP_WRAP_OSD2_MATRIX_EN_CTRL, 1, 0, 1);
167 
168     // VPP WRAP OSD3 matrix
169     WRITE32_REG(VPU, VPP_WRAP_OSD3_MATRIX_PRE_OFFSET0_1,
170         ((m[0] & 0xfff) << 16) | (m[1] & 0xfff));
171     WRITE32_REG(VPU, VPP_WRAP_OSD3_MATRIX_PRE_OFFSET2,
172         m[2] & 0xfff);
173     WRITE32_REG(VPU, VPP_WRAP_OSD3_MATRIX_COEF00_01,
174         ((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff));
175     WRITE32_REG(VPU, VPP_WRAP_OSD3_MATRIX_COEF02_10,
176         ((m[5]  & 0x1fff) << 16) | (m[6] & 0x1fff));
177     WRITE32_REG(VPU, VPP_WRAP_OSD3_MATRIX_COEF11_12,
178         ((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff));
179     WRITE32_REG(VPU, VPP_WRAP_OSD3_MATRIX_COEF20_21,
180         ((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff));
181     WRITE32_REG(VPU, VPP_WRAP_OSD3_MATRIX_COEF22,
182         m[11] & 0x1fff);
183     WRITE32_REG(VPU, VPP_WRAP_OSD3_MATRIX_OFFSET0_1,
184         ((m[18] & 0xfff) << 16) | (m[19] & 0xfff));
185     WRITE32_REG(VPU, VPP_WRAP_OSD3_MATRIX_OFFSET2,
186         m[20] & 0xfff);
187     SET_BIT32(VPU, VPP_WRAP_OSD3_MATRIX_EN_CTRL, 1, 0, 1);
188 
189     WRITE32_REG(VPU, DOLBY_PATH_CTRL, 0xf);
190 
191     // POST2 matrix: YUV limit -> RGB  default is 12bit
192     m = YUV709l_to_RGB709_coeff12;
193 
194     // VPP WRAP POST2 matrix
195     WRITE32_REG(VPU, VPP_POST2_MATRIX_PRE_OFFSET0_1,
196         (((m[0] >> 2) & 0xfff) << 16) | ((m[1] >> 2) & 0xfff));
197     WRITE32_REG(VPU, VPP_POST2_MATRIX_PRE_OFFSET2,
198         (m[2] >> 2) & 0xfff);
199     WRITE32_REG(VPU, VPP_POST2_MATRIX_COEF00_01,
200         (((m[3] >> 2) & 0x1fff) << 16) | ((m[4] >> 2) & 0x1fff));
201     WRITE32_REG(VPU, VPP_POST2_MATRIX_COEF02_10,
202         (((m[5] >> 2) & 0x1fff) << 16) | ((m[6] >> 2) & 0x1fff));
203     WRITE32_REG(VPU, VPP_POST2_MATRIX_COEF11_12,
204         (((m[7] >> 2) & 0x1fff) << 16) | ((m[8] >> 2) & 0x1fff));
205     WRITE32_REG(VPU, VPP_POST2_MATRIX_COEF20_21,
206         (((m[9] >> 2) & 0x1fff) << 16) | ((m[10] >> 2) & 0x1fff));
207     WRITE32_REG(VPU, VPP_POST2_MATRIX_COEF22,
208         (m[11] >> 2) & 0x1fff);
209     WRITE32_REG(VPU, VPP_POST2_MATRIX_OFFSET0_1,
210         (((m[18] >> 2) & 0xfff) << 16) | ((m[19] >> 2) & 0xfff));
211     WRITE32_REG(VPU, VPP_POST2_MATRIX_OFFSET2,
212         (m[20] >> 2) & 0xfff);
213     SET_BIT32(VPU, VPP_POST2_MATRIX_EN_CTRL, 1, 0, 1);
214 
215 
216     SET_BIT32(VPU, VPP_MATRIX_CTRL, 1, 0, 1);
217     SET_BIT32(VPU, VPP_MATRIX_CTRL, 0, 8, 3);
218 
219     // 709L to RGB
220     WRITE32_REG(VPU, VPP_MATRIX_PRE_OFFSET0_1, 0x0FC00E00);
221     WRITE32_REG(VPU, VPP_MATRIX_PRE_OFFSET2, 0x00000E00);
222     // ycbcr limit range, 709 to RGB
223     // -16      1.164  0      1.793  0
224     // -128     1.164 -0.213 -0.534  0
225     // -128     1.164  2.115  0      0
226     WRITE32_REG(VPU, VPP_MATRIX_COEF00_01, 0x04A80000);
227     WRITE32_REG(VPU, VPP_MATRIX_COEF02_10, 0x072C04A8);
228     WRITE32_REG(VPU, VPP_MATRIX_COEF11_12, 0x1F261DDD);
229     WRITE32_REG(VPU, VPP_MATRIX_COEF20_21, 0x04A80876);
230     WRITE32_REG(VPU, VPP_MATRIX_COEF22, 0x0);
231     WRITE32_REG(VPU, VPP_MATRIX_OFFSET0_1, 0x0);
232     WRITE32_REG(VPU, VPP_MATRIX_OFFSET2, 0x0);
233 
234     SET_BIT32(VPU, VPP_MATRIX_CLIP, 0, 5, 3);
235 }
236 
ConfigureClock()237 void Vpu::ConfigureClock() {
238     ZX_DEBUG_ASSERT(initialized_);
239     // vpu clock
240     WRITE32_REG(HHI, HHI_VPU_CLK_CNTL, ((kVpuMux << 9) | (kVpuDiv << 0)));
241     SET_BIT32(HHI, HHI_VPU_CLK_CNTL, 1, 8, 1);
242 
243     // vpu clkb
244     // bit 0 is set since kVpuClkFrequency > clkB max frequency (350MHz)
245     WRITE32_REG(HHI, HHI_VPU_CLKB_CNTL, ((1 << 8) | (1 << 0)));
246 
247     // vapb clk
248     // turn on ge2d clock since kVpuClkFrequency > 250MHz
249     WRITE32_REG(HHI, HHI_VAPBCLK_CNTL, (1 << 30) | (0 << 9) | (1 << 0));
250 
251     SET_BIT32(HHI, HHI_VAPBCLK_CNTL, 1, 8, 1);
252 
253     SET_BIT32(HHI, HHI_VID_CLK_CNTL2, 0, 0, 8);
254 
255     // dmc_arb_config
256     WRITE32_REG(VPU, VPU_RDARB_MODE_L1C1, 0x0);
257     WRITE32_REG(VPU, VPU_RDARB_MODE_L1C2, 0x10000);
258     WRITE32_REG(VPU, VPU_RDARB_MODE_L2C1, 0x900000);
259     WRITE32_REG(VPU, VPU_WRARB_MODE_L2C1, 0x20000);
260 }
261 
PowerOn()262 void Vpu::PowerOn() {
263     ZX_DEBUG_ASSERT(initialized_);
264     SET_BIT32(AOBUS, AOBUS_GEN_PWR_SLEEP0, 0, 8, 1); // [8] power on
265 
266     // power up memories
267     for (int i = 0; i < 32; i+=2) {
268         SET_BIT32(HHI, HHI_VPU_MEM_PD_REG0, 0, i, 2);
269         zx_nanosleep(zx_deadline_after(ZX_USEC(5)));
270     }
271     for (int i = 0; i < 32; i+=2) {
272         SET_BIT32(HHI, HHI_VPU_MEM_PD_REG1, 0, i, 2);
273         zx_nanosleep(zx_deadline_after(ZX_USEC(5)));
274     }
275     SET_BIT32(HHI, HHI_VPU_MEM_PD_REG2, 0, 0, 2);
276     zx_nanosleep(zx_deadline_after(ZX_USEC(5)));
277     for (int i = 4; i < 18; i+=2) {
278         SET_BIT32(HHI, HHI_VPU_MEM_PD_REG2, 0, i, 2);
279         zx_nanosleep(zx_deadline_after(ZX_USEC(5)));
280     }
281     SET_BIT32(HHI, HHI_VPU_MEM_PD_REG2, 0, 30, 2);
282     zx_nanosleep(zx_deadline_after(ZX_USEC(5)));
283 
284     for (int i = 8; i < 16; i++) {
285         SET_BIT32(HHI, HHI_MEM_PD_REG0, 0, i, 1);
286         zx_nanosleep(zx_deadline_after(ZX_USEC(5)));
287     }
288     zx_nanosleep(zx_deadline_after(ZX_USEC(20)));
289 
290     // Reset VIU + VENC
291     // Reset VENCI + VENCP + VADC + VENCL
292     // Reset HDMI-APB + HDMI-SYS + HDMI-TX + HDMI-CEC
293     CLEAR_MASK32(CBUS, RESET0_LEVEL, ((1<<5) | (1<<10) | (1<<19) | (1<<13)));
294     CLEAR_MASK32(CBUS, RESET1_LEVEL, (1<<5));
295     CLEAR_MASK32(CBUS, RESET2_LEVEL, (1<<15));
296     CLEAR_MASK32(CBUS, RESET4_LEVEL,
297                  ((1<<6) | (1<<7) | (1<<13) | (1<<5) | (1<<9) | (1<<4) | (1<<12)));
298     CLEAR_MASK32(CBUS, RESET7_LEVEL, (1<<7));
299 
300     // Remove VPU_HDMI ISO
301     SET_BIT32(AOBUS, AOBUS_GEN_PWR_SLEEP0, 0, 9, 1); // [9] VPU_HDMI
302 
303     // release Reset
304     SET_MASK32(CBUS, RESET0_LEVEL, ((1 << 5) | (1<<10) | (1<<19) | (1<<13)));
305     SET_MASK32(CBUS, RESET1_LEVEL, (1<<5));
306     SET_MASK32(CBUS, RESET2_LEVEL, (1<<15));
307     SET_MASK32(CBUS, RESET4_LEVEL,
308                ((1<<6) | (1<<7) | (1<<13) | (1<<5) | (1<<9) | (1<<4) | (1<<12)));
309     SET_MASK32(CBUS, RESET7_LEVEL, (1<<7));
310 
311     ConfigureClock();
312 }
313 
PowerOff()314 void Vpu::PowerOff() {
315     ZX_DEBUG_ASSERT(initialized_);
316     // Power down VPU_HDMI
317     // Enable Isolation
318     SET_BIT32(AOBUS, AOBUS_GEN_PWR_SLEEP0, 1, 9, 1); // ISO
319     zx_nanosleep(zx_deadline_after(ZX_USEC(20)));
320 
321     // power down memories
322     for (int i = 0; i < 32; i+=2) {
323         SET_BIT32(HHI, HHI_VPU_MEM_PD_REG0, 0x3, i, 2);
324         zx_nanosleep(zx_deadline_after(ZX_USEC(5)));
325     }
326     for (int i = 0; i < 32; i+=2) {
327         SET_BIT32(HHI, HHI_VPU_MEM_PD_REG1, 0x3, i, 2);
328         zx_nanosleep(zx_deadline_after(ZX_USEC(5)));
329     }
330     SET_BIT32(HHI, HHI_VPU_MEM_PD_REG2, 0x3, 0, 2);
331     zx_nanosleep(zx_deadline_after(ZX_USEC(5)));
332     for (int i = 4; i < 18; i+=2) {
333         SET_BIT32(HHI, HHI_VPU_MEM_PD_REG2, 0x3, i, 2);
334         zx_nanosleep(zx_deadline_after(ZX_USEC(5)));
335     }
336     SET_BIT32(HHI, HHI_VPU_MEM_PD_REG2, 0x3, 30, 2);
337     zx_nanosleep(zx_deadline_after(ZX_USEC(5)));
338 
339     for (int i = 8; i < 16; i++) {
340         SET_BIT32(HHI, HHI_MEM_PD_REG0, 0x1, i, 1);
341         zx_nanosleep(zx_deadline_after(ZX_USEC(5)));
342     }
343     zx_nanosleep(zx_deadline_after(ZX_USEC(20)));
344 
345     // Power down VPU domain
346     SET_BIT32(AOBUS, AOBUS_GEN_PWR_SLEEP0, 1, 8, 1); // PDN
347 
348     SET_BIT32(HHI, HHI_VAPBCLK_CNTL, 0, 8, 1);
349     SET_BIT32(HHI, HHI_VPU_CLK_CNTL, 0, 8, 1);
350 }
351 } // namespace astro_display
352