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 MinVsyncLeadingEdge 400
18 #define MinClockRate420 590000000
19 #define PixelFactor420 2
20 #define MinHblank444 80
21 #define MinHblank420 128
22 #define PixelClockGranularity 1000
23 #define MinHtotalGranularity 8
24 #define MaxChunkRate 650000000
25 #define AudioPacketRate 195000
26 #define AudioPacketSize 32
27 #define LineOverhead 32
29 static unsigned roundup_to_power_of_two(unsigned v
)
34 if (!v
|| v
> 0x80000000) {
35 fprintf(stderr
, "roundup_to_power_of_two: invalid input %u.\n", v
);
48 static unsigned greatest_power_of_two_divider(unsigned x
)
53 timings
edid_state::calc_ovt_mode(unsigned Hactive
, unsigned Vactive
,
54 unsigned Hratio
, unsigned Vratio
,
64 unsigned MaxVrate
= Vrate
;
65 unsigned VtotalGranularity
= 1;
69 case 24: case 25: case 30:
71 VtotalGranularity
= 20;
73 case 48: case 50: case 60:
75 VtotalGranularity
= 20;
79 VtotalGranularity
= 5;
83 VtotalGranularity
= 5;
87 VtotalGranularity
= 5;
91 VtotalGranularity
= 5;
96 double MaxActiveTime
= (1000000.0 / MaxVrate
) - MinVblankDuration
;
97 double MinLineTime
= MaxActiveTime
/ Vactive
;
98 unsigned MinVblank
= ceil(MinVblankDuration
/ MinLineTime
);
99 unsigned MinVtotal
= Vactive
+ MinVblank
;
101 if (MinVtotal
% VtotalGranularity
)
102 MinVtotal
+= VtotalGranularity
- (MinVtotal
% VtotalGranularity
);
105 unsigned MinLineRate
= MaxVrate
* MinVtotal
;
106 unsigned MaxAudioPacketsPerLine
= ceil((double)AudioPacketRate
/ MinLineRate
);
109 unsigned MinHtotal
= Hactive
+
110 max(MinHblank444
, LineOverhead
+ AudioPacketSize
* MaxAudioPacketsPerLine
);
111 double MinPixelClockRate
= (double)MaxVrate
* MinHtotal
* MinVtotal
;
112 double HCalcGranularity
= roundup_to_power_of_two(ceil(MinPixelClockRate
/ MaxChunkRate
));
113 unsigned HtotalGranularity
= max(MinHtotalGranularity
, HCalcGranularity
);
115 if (MinHtotal
% HtotalGranularity
)
116 MinHtotal
+= HtotalGranularity
- (MinHtotal
% HtotalGranularity
);
118 unsigned ResolutionGranularity
= PixelClockGranularity
/
119 gcd(PixelClockGranularity
, MaxVrate
);
122 unsigned long long PixelClockRate
= 0;
126 unsigned long long RMin
= 0;
127 unsigned V
= MinVtotal
;
130 unsigned H
= MinHtotal
;
131 unsigned long long R
= H
* V
;
132 if (RMin
&& R
> RMin
)
134 while (R
% ResolutionGranularity
||
135 MaxVrate
* R
/ greatest_power_of_two_divider(H
) > MaxChunkRate
) {
136 H
+= HtotalGranularity
;
139 if (!RMin
|| R
< RMin
) {
144 V
+= VtotalGranularity
;
146 PixelClockRate
= MaxVrate
* RMin
;
149 MinHtotal
= Hactive
+ max(MinHblank420
, PixelFactor420
*
150 (LineOverhead
+ AudioPacketSize
* MaxAudioPacketsPerLine
));
151 if (PixelClockRate
>= MinClockRate420
&&
158 Vtotal
= Vtotal
* MaxVrate
/ Vrate
;
161 unsigned Vblank
= Vtotal
- Vactive
;
162 unsigned VsyncPosition
= ceil((double)MinVsyncLeadingEdge
* PixelClockRate
/ (1000000.0 * Htotal
));
163 t
.vfp
= Vblank
- VsyncPosition
;
166 t
.vbp
= Vblank
- t
.vfp
- t
.vsync
;
167 t
.pos_pol_vsync
= true;
168 unsigned Hblank
= Htotal
- Hactive
;
171 t
.hfp
= Hblank
- t
.hsync
- t
.hbp
;
172 t
.pos_pol_hsync
= true;
173 t
.pixclk_khz
= PixelClockRate
/ 1000;
174 if (!t
.hratio
|| !t
.vratio
)