1use display_types::cea861::hdmi_forum::HdmiForumFrl;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub struct LtpPattern(u8);
12
13impl LtpPattern {
14 pub fn new(raw: u8) -> Self {
20 Self(raw)
21 }
22
23 pub fn value(self) -> u8 {
25 self.0
26 }
27}
28
29#[non_exhaustive]
34#[derive(Debug, Clone, Copy, Default)]
35pub struct LaneEqParams {}
36
37#[non_exhaustive]
44#[derive(Debug, Clone, Copy, Default)]
45pub struct EqParams {
46 pub lane0: LaneEqParams,
48 pub lane1: LaneEqParams,
50 pub lane2: LaneEqParams,
52 pub lane3: Option<LaneEqParams>,
54}
55
56impl EqParams {
57 pub fn new() -> Self {
59 Self::default()
60 }
61}
62
63pub trait HdmiPhy {
69 type Error;
71
72 fn set_frl_rate(&mut self, rate: HdmiForumFrl) -> Result<(), Self::Error>;
74
75 fn send_ltp(&mut self, pattern: LtpPattern) -> Result<(), Self::Error>;
77
78 fn adjust_equalization(&mut self, params: EqParams) -> Result<(), Self::Error>;
80
81 fn set_scrambling(&mut self, enabled: bool) -> Result<(), Self::Error>;
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88 use display_types::cea861::hdmi_forum::HdmiForumFrl;
89
90 struct MockPhy {
91 frl_rate: Option<HdmiForumFrl>,
92 scrambling: Option<bool>,
93 eq_calls: u32,
94 last_ltp: Option<LtpPattern>,
95 }
96
97 impl MockPhy {
98 fn new() -> Self {
99 Self {
100 frl_rate: None,
101 scrambling: None,
102 eq_calls: 0,
103 last_ltp: None,
104 }
105 }
106 }
107
108 impl HdmiPhy for MockPhy {
109 type Error = core::convert::Infallible;
110
111 fn send_ltp(&mut self, pattern: LtpPattern) -> Result<(), Self::Error> {
112 self.last_ltp = Some(pattern);
113 Ok(())
114 }
115
116 fn set_frl_rate(&mut self, rate: HdmiForumFrl) -> Result<(), Self::Error> {
117 self.frl_rate = Some(rate);
118 Ok(())
119 }
120
121 fn adjust_equalization(&mut self, _params: EqParams) -> Result<(), Self::Error> {
122 self.eq_calls += 1;
123 Ok(())
124 }
125
126 fn set_scrambling(&mut self, enabled: bool) -> Result<(), Self::Error> {
127 self.scrambling = Some(enabled);
128 Ok(())
129 }
130 }
131
132 #[test]
133 fn ltp_pattern_value() {
134 assert_eq!(LtpPattern::new(1).value(), 1);
135 assert_eq!(LtpPattern::new(4).value(), 4);
136 }
137
138 #[test]
139 fn ltp_pattern_clone_eq() {
140 let a = LtpPattern::new(2);
141 assert_eq!(a, a);
142 assert_ne!(LtpPattern::new(1), LtpPattern::new(2));
143 }
144
145 #[test]
146 fn send_ltp_records_pattern() {
147 let mut phy = MockPhy::new();
148 phy.send_ltp(LtpPattern::new(1)).unwrap();
149 assert_eq!(phy.last_ltp, Some(LtpPattern::new(1)));
150 }
151
152 #[test]
153 fn send_ltp_updates_on_each_call() {
154 let mut phy = MockPhy::new();
155 phy.send_ltp(LtpPattern::new(1)).unwrap();
156 phy.send_ltp(LtpPattern::new(3)).unwrap();
157 assert_eq!(phy.last_ltp, Some(LtpPattern::new(3)));
158 }
159
160 #[test]
161 fn eq_params_constructors_are_equivalent() {
162 let _a = EqParams::new();
163 let _b = EqParams::default();
164 }
165
166 #[test]
167 fn set_frl_rate_records_rate() {
168 let mut phy = MockPhy::new();
169 phy.set_frl_rate(HdmiForumFrl::Rate6Gbps4Lanes).unwrap();
170 assert_eq!(phy.frl_rate, Some(HdmiForumFrl::Rate6Gbps4Lanes));
171 }
172
173 #[test]
174 fn set_frl_rate_not_supported_is_valid() {
175 let mut phy = MockPhy::new();
176 phy.set_frl_rate(HdmiForumFrl::NotSupported).unwrap();
177 assert_eq!(phy.frl_rate, Some(HdmiForumFrl::NotSupported));
178 }
179
180 #[test]
181 fn set_frl_rate_can_be_updated() {
182 let mut phy = MockPhy::new();
183 phy.set_frl_rate(HdmiForumFrl::Rate3Gbps3Lanes).unwrap();
184 phy.set_frl_rate(HdmiForumFrl::Rate12Gbps4Lanes).unwrap();
185 assert_eq!(phy.frl_rate, Some(HdmiForumFrl::Rate12Gbps4Lanes));
186 }
187
188 #[test]
189 fn set_scrambling_enable() {
190 let mut phy = MockPhy::new();
191 phy.set_scrambling(true).unwrap();
192 assert_eq!(phy.scrambling, Some(true));
193 }
194
195 #[test]
196 fn set_scrambling_disable() {
197 let mut phy = MockPhy::new();
198 phy.set_scrambling(false).unwrap();
199 assert_eq!(phy.scrambling, Some(false));
200 }
201
202 #[test]
203 fn set_scrambling_can_be_toggled() {
204 let mut phy = MockPhy::new();
205 phy.set_scrambling(true).unwrap();
206 phy.set_scrambling(false).unwrap();
207 assert_eq!(phy.scrambling, Some(false));
208 }
209
210 #[test]
211 fn adjust_equalization_tracks_call_count() {
212 let mut phy = MockPhy::new();
213 phy.adjust_equalization(EqParams::new()).unwrap();
214 phy.adjust_equalization(EqParams::new()).unwrap();
215 assert_eq!(phy.eq_calls, 2);
216 }
217}