1 // Copyright 2017 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 <hwreg/bitfields.h>
8 #include "registers-pipe.h"
9 
10 namespace registers {
11 
12 static constexpr uint32_t kTransCount = 4;
13 
14 enum Trans { TRANS_A, TRANS_B, TRANS_C, TRANS_EDP };
15 
16 static const Trans kTrans[kTransCount] = {
17     TRANS_A, TRANS_B, TRANS_C, TRANS_EDP,
18 };
19 
20 // TRANS_HTOTAL, TRANS_HBLANK,
21 // TRANS_VTOTAL, TRANS_VBLANK
22 class TransHVTotal : public hwreg::RegisterBase<TransHVTotal, uint32_t> {
23 public:
24     DEF_FIELD(28, 16, count_total); // same as blank_start
25     DEF_FIELD(12, 0, count_active); // same as blank_end
26 };
27 
28 // TRANS_HSYNC, TRANS_VSYNC
29 class TransHVSync : public hwreg::RegisterBase<TransHVSync, uint32_t> {
30 public:
31     DEF_FIELD(28, 16, sync_end);
32     DEF_FIELD(12, 0, sync_start);
33 };
34 
35 // TRANS_DDI_FUNC_CTL
36 class TransDdiFuncControl : public hwreg::RegisterBase<TransDdiFuncControl, uint32_t> {
37 public:
38     DEF_BIT(31, trans_ddi_function_enable);
39     DEF_FIELD(30, 28, ddi_select);
40 
41     DEF_FIELD(26, 24, trans_ddi_mode_select);
42     static constexpr uint32_t kModeHdmi = 0;
43     static constexpr uint32_t kModeDvi = 1;
44     static constexpr uint32_t kModeDisplayPortSst = 2;
45     static constexpr uint32_t kModeDisplayPortMst = 3;
46 
47     DEF_FIELD(22, 20, bits_per_color);
48     static constexpr uint32_t k8bbc = 0;
49     static constexpr uint32_t k10bbc = 1;
50     static constexpr uint32_t k6bbc = 2;
51     static constexpr uint32_t k12bbc = 3;
52     DEF_FIELD(19, 18, port_sync_mode_master_select);
53     DEF_FIELD(17, 16, sync_polarity);
54     DEF_BIT(15, port_sync_mode_enable);
55     DEF_FIELD(14, 12, edp_input_select);
56     static constexpr uint32_t kPipeA = 0;
57     static constexpr uint32_t kPipeB = 5;
58     static constexpr uint32_t kPipeC = 6;
59     DEF_BIT(8, dp_vc_payload_allocate);
60     DEF_FIELD(3, 1, dp_port_width_selection);
61 };
62 
63 // TRANS_CONF
64 class TransConf : public hwreg::RegisterBase<TransConf, uint32_t> {
65 public:
66     DEF_BIT(31, transcoder_enable);
67     DEF_BIT(30, transcoder_state);
68     DEF_FIELD(22, 21, interlaced_mode);
69 };
70 
71 // TRANS_CLK_SEL
72 class TransClockSelect : public hwreg::RegisterBase<TransClockSelect, uint32_t> {
73 public:
74     DEF_FIELD(31, 29, trans_clock_select);
75 };
76 
77 
78 // DATAM
79 class TransDataM : public hwreg::RegisterBase<TransDataM, uint32_t> {
80 public:
81     DEF_FIELD(30, 25, tu_or_vcpayload_size);
82     DEF_FIELD(23, 0, data_m_value);
83 };
84 
85 // DATAN
86 class TransDataN : public hwreg::RegisterBase<TransDataN, uint32_t> {
87 public:
88     DEF_FIELD(23, 0, data_n_value);
89 };
90 
91 // LINKM1
92 class TransLinkM : public hwreg::RegisterBase<TransLinkM, uint32_t> {
93 public:
94     DEF_FIELD(23, 0, link_m_value);
95 };
96 
97 // LINKN1
98 class TransLinkN : public hwreg::RegisterBase<TransLinkN, uint32_t> {
99 public:
100     DEF_FIELD(23, 0, link_n_value);
101 };
102 
103 // TRANS_MSA_MISC
104 class TransMsaMisc : public hwreg::RegisterBase<TransMsaMisc, uint32_t> {
105 public:
106     // Byte 1 is MISC1 from DP spec
107     DEF_FIELD(10, 9, stereo_video);
108     DEF_BIT(8, interlaced_vertical_total_even);
109     // Byte 0 is MISC0 from DP spec
110     DEF_FIELD(7, 5, bits_per_color);
111     static constexpr uint32_t k6Bbc = 0;
112     static constexpr uint32_t k8Bbc = 1;
113     static constexpr uint32_t k10Bbc = 2;
114     static constexpr uint32_t k12Bbc = 3;
115     static constexpr uint32_t k16Bbc = 4;
116     DEF_BIT(4, colorimetry);
117     DEF_BIT(3, dynamic_range);
118     DEF_FIELD(2, 1, color_format);
119     static constexpr uint32_t kRgb = 0;
120     static constexpr uint32_t kYcbCr422 = 1;
121     static constexpr uint32_t kYcbCr444 = 2;
122     DEF_BIT(0, sync_clock);
123 };
124 
125 class TranscoderRegs {
126 public:
TranscoderRegs(Trans trans)127     TranscoderRegs(Trans trans) : trans_(trans) {
128         offset_ = trans == TRANS_EDP ? 0xf000 : (trans * 0x1000);
129     }
130 
HTotal()131     hwreg::RegisterAddr<TransHVTotal> HTotal() { return GetReg<TransHVTotal>(0x60000); }
HBlank()132     hwreg::RegisterAddr<TransHVTotal> HBlank() { return GetReg<TransHVTotal>(0x60004); }
HSync()133     hwreg::RegisterAddr<TransHVSync> HSync() { return GetReg<TransHVSync>(0x60008); }
VTotal()134     hwreg::RegisterAddr<TransHVTotal> VTotal() { return GetReg<TransHVTotal>(0x6000c); }
VBlank()135     hwreg::RegisterAddr<TransHVTotal> VBlank() { return GetReg<TransHVTotal>(0x60010); }
VSync()136     hwreg::RegisterAddr<TransHVSync> VSync() { return GetReg<TransHVSync>(0x60014); }
DdiFuncControl()137     hwreg::RegisterAddr<TransDdiFuncControl> DdiFuncControl() {
138         return GetReg<TransDdiFuncControl>(0x60400);
139     }
Conf()140     hwreg::RegisterAddr<TransConf> Conf() { return GetReg<TransConf>(0x70008); }
141 
ClockSelect()142     hwreg::RegisterAddr<TransClockSelect> ClockSelect() {
143         ZX_ASSERT(trans_ != TRANS_EDP);
144         // This uses a different offset from the other transcoder registers.
145         return hwreg::RegisterAddr<TransClockSelect>(0x46140 + trans_ * 4);
146     }
DataM()147     hwreg::RegisterAddr<TransDataM> DataM() { return GetReg<TransDataM>(0x60030); }
DataN()148     hwreg::RegisterAddr<TransDataN> DataN() { return GetReg<TransDataN>(0x60034); }
LinkM()149     hwreg::RegisterAddr<TransLinkM> LinkM() { return GetReg<TransLinkM>(0x60040); }
LinkN()150     hwreg::RegisterAddr<TransLinkN> LinkN() { return GetReg<TransLinkN>(0x60044); }
MsaMisc()151     hwreg::RegisterAddr<TransMsaMisc> MsaMisc() { return GetReg<TransMsaMisc>(0x60410); }
152 
153 private:
GetReg(uint32_t base_addr)154     template <class RegType> hwreg::RegisterAddr<RegType> GetReg(uint32_t base_addr) {
155         return hwreg::RegisterAddr<RegType>(base_addr + offset_);
156     }
157 
158     Trans trans_;
159     uint32_t offset_;
160 
161 };
162 } // namespace registers
163