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 <zircon/compiler.h>
8 #include <ddk/protocol/platform/device.h>
9 #include <ddk/protocol/platform-device-lib.h>
10 #include <ddktl/mmio.h>
11 #include <lib/zx/interrupt.h>
12 #include <lib/zx/bti.h>
13 #include <threads.h>
14 #include "common.h"
15 #include <optional>
16 
17 namespace astro_display {
18 
19 struct RdmaTable {
20     uint32_t reg;
21     uint32_t val;
22 };
23 
24 enum {
25     IDX_CFG_W0,
26     IDX_CTRL_STAT,
27     IDX_MAX,
28 };
29 
30 struct RdmaChannelContainer {
31     zx_paddr_t      phys_offset;    // offset into physical address
32     uint8_t*        virt_offset;    // offset into virtual address (vmar buf)
33     bool            active;         // indicated whether channel is being used or not
34 };
35 
36 constexpr uint32_t kRdmaTableMaxSize = IDX_MAX;
37 
38 // RDMA Channels used by OSD. Three channels should be more than enough
39 constexpr uint8_t kMaxRdmaChannels = 3;
40 constexpr uint8_t kMaxRetries = 100;
41 // spread channels 512B apart (make sure it's greater than a cache line size)
42 constexpr size_t  kChannelBaseOffset = 512;
43 
44 class Osd {
45 public:
Osd(uint32_t fb_width,uint32_t fb_height,uint32_t display_width,uint32_t display_height)46     Osd(uint32_t fb_width, uint32_t fb_height, uint32_t display_width, uint32_t display_height)
47         : fb_width_(fb_width), fb_height_(fb_height),
48           display_width_(display_width), display_height_(display_height) {}
49 
50     zx_status_t Init(zx_device_t* parent);
51     void HwInit();
52     zx_status_t Configure();
53     void Disable();
54     // This function will apply configuration when VSYNC interrupt occurs using RDMA
55     void FlipOnVsync(uint8_t idx);
56     void Dump();
57     void Release();
58 
59 private:
60     void DefaultSetup();
61     // this function sets up scaling based on framebuffer and actual display
62     // dimensions. The scaling IP and registers and undocumented.
63     void EnableScaling(bool enable);
64     void Enable();
65     zx_status_t SetupRdma();
66     void ResetRdmaTable();
67     void SetRdmaTableValue(uint32_t channel, uint32_t idx, uint32_t val);
68     void FlushRdmaTable(uint32_t channel);
69     int GetNextAvailableRdmaChannel();
70     int RdmaThread();
71 
72     std::optional<ddk::MmioBuffer>      vpu_mmio_;
73     pdev_protocol_t                     pdev_ = {nullptr, nullptr};
74     zx::bti                             bti_;
75 
76     // RDMA IRQ handle and thread
77     zx::interrupt                       rdma_irq_;
78     thrd_t                              rdma_thread_;
79 
80     // use a single vmo for all channels
81     zx::vmo                             rdma_vmo_;
82     zx_handle_t                         rdma_pmt_;
83     zx_paddr_t                          rdma_phys_;
84     uint8_t*                            rdma_vbuf_;
85 
86     // container that holds channel specific properties
87     RdmaChannelContainer               rdma_chnl_container_[kMaxRdmaChannels];
88 
89     // Framebuffer dimension
90     uint32_t                            fb_width_;
91     uint32_t                            fb_height_;
92     // Actual display dimension
93     uint32_t                            display_width_;
94     uint32_t                            display_height_;
95 
96     bool                                initialized_ = false;
97 };
98 
99 } // namespace astro_display
100