1 // SPDX-License-Identifier: MIT
3 * Copyright 2021 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
5 * Author: Hans Verkuil <hverkuil-cisco@xs4all.nl>
14 #include "edid-decode.h"
16 #define MinVblankDuration 460
17 #define MinVblankLines 20
18 #define MinVsyncLeadingEdge 400
19 #define MinVsyncLELines 14
20 #define MinClockRate420 590000000
21 #define PixelFactor420 2
22 #define MinHblank444 80
23 #define MinHblank420 128
24 #define PixelClockGranularity 1000
25 #define MinHtotalGranularity 8
26 #define MaxChunkRate 650000000
27 #define AudioPacketRate 195000
28 #define AudioPacketSize 32
29 #define LineOverhead 32
31 static unsigned roundup_to_power_of_two(unsigned v
)
36 if (!v
|| v
> 0x80000000) {
37 fprintf(stderr
, "roundup_to_power_of_two: invalid input %u.\n", v
);
50 static unsigned greatest_power_of_two_divider(unsigned x
)
55 timings
edid_state::calc_ovt_mode(unsigned Hactive
, unsigned Vactive
,
56 unsigned Hratio
, unsigned Vratio
,
66 unsigned MaxVrate
= Vrate
;
67 unsigned VtotalGranularity
= 1;
71 case 24: case 25: case 30:
73 VtotalGranularity
= 20;
75 case 48: case 50: case 60:
77 VtotalGranularity
= 20;
81 VtotalGranularity
= 5;
85 VtotalGranularity
= 5;
89 VtotalGranularity
= 5;
93 VtotalGranularity
= 5;
98 double MaxActiveTime
= (1000000.0 / MaxVrate
) - MinVblankDuration
;
99 double MinLineTime
= MaxActiveTime
/ Vactive
;
100 unsigned MinVblank
= max(MinVblankLines
, ceil(MinVblankDuration
/ MinLineTime
));
101 unsigned MinVtotal
= Vactive
+ MinVblank
;
103 if (MinVtotal
% VtotalGranularity
)
104 MinVtotal
+= VtotalGranularity
- (MinVtotal
% VtotalGranularity
);
107 unsigned MinLineRate
= MaxVrate
* MinVtotal
;
108 unsigned MaxAudioPacketsPerLine
= ceil((double)AudioPacketRate
/ MinLineRate
);
111 unsigned MinHtotal
= Hactive
+
112 max(MinHblank444
, LineOverhead
+ AudioPacketSize
* MaxAudioPacketsPerLine
);
113 double MinPixelClockRate
= (double)MaxVrate
* MinHtotal
* MinVtotal
;
114 double HCalcGranularity
= roundup_to_power_of_two(ceil(MinPixelClockRate
/ MaxChunkRate
));
115 unsigned HtotalGranularity
= max(MinHtotalGranularity
, HCalcGranularity
);
117 if (MinHtotal
% HtotalGranularity
)
118 MinHtotal
+= HtotalGranularity
- (MinHtotal
% HtotalGranularity
);
120 unsigned ResolutionGranularity
= PixelClockGranularity
/
121 gcd(PixelClockGranularity
, MaxVrate
);
124 unsigned long long PixelClockRate
= 0;
128 unsigned long long RMin
= 0;
129 unsigned V
= MinVtotal
;
132 unsigned H
= MinHtotal
;
133 unsigned long long R
= H
* V
;
134 if (RMin
&& R
> RMin
)
136 while (R
% ResolutionGranularity
||
137 MaxVrate
* R
/ greatest_power_of_two_divider(H
) > MaxChunkRate
) {
138 H
+= HtotalGranularity
;
141 if (!RMin
|| R
< RMin
) {
146 V
+= VtotalGranularity
;
148 PixelClockRate
= MaxVrate
* RMin
;
151 MinHtotal
= Hactive
+ max(MinHblank420
, PixelFactor420
*
152 (LineOverhead
+ AudioPacketSize
* MaxAudioPacketsPerLine
));
153 if (PixelClockRate
>= MinClockRate420
&&
160 Vtotal
= Vtotal
* MaxVrate
/ Vrate
;
163 unsigned Vblank
= Vtotal
- Vactive
;
164 unsigned VsyncPosition
= max(MinVsyncLELines
,
165 ceil((double)MinVsyncLeadingEdge
* PixelClockRate
/ (1000000.0 * Htotal
)));
166 t
.vfp
= Vblank
- VsyncPosition
;
169 t
.vbp
= Vblank
- t
.vfp
- t
.vsync
;
170 t
.pos_pol_vsync
= true;
171 unsigned Hblank
= Htotal
- Hactive
;
174 t
.hfp
= Hblank
- t
.hsync
- t
.hbp
;
175 t
.pos_pol_hsync
= true;
176 t
.pixclk_khz
= PixelClockRate
/ 1000;
177 if (!t
.hratio
|| !t
.vratio
)