Skip to content

Commit 0cee6c4

Browse files
xdarklightsuperna9999
authored andcommitted
drm/meson: fix more rounding issues with 59.94Hz modes
Commit 1017560 ("drm/meson: use unsigned long long / Hz for frequency types") attempts to resolve video playback using 59.94Hz. using YUV420 by changing the clock calculation to use Hz instead of kHz (thus yielding more precision). The basic calculation itself is correct, however the comparisions in meson_vclk_vic_supported_freq() and meson_vclk_setup() don't work anymore for 59.94Hz modes (using the freq * 1000 / 1001 logic). For example, drm/edid specifies a 593407kHz clock for [email protected]. With the mentioend commit we convert this to Hz. Then meson_vclk tries to find a matchig "params" entry (as the clock setup code currently only supports specific frequencies) by taking the venc_freq from the params and calculating the "alt frequency" (used for the 59.94Hz modes) from it, which is: (594000000Hz * 1000) / 1001 = 593406593Hz Similar calculation is applied to the phy_freq (TMDS clock), which is 10 times the pixel clock. Implement a new meson_vclk_freqs_are_matching_param() function whose purpose is to compare if the requested and calculated frequencies. They may not match exactly (for the reasons mentioned above). Allow the clocks to deviate slightly to make the 59.94Hz modes again. Fixes: 1017560 ("drm/meson: use unsigned long long / Hz for frequency types") Reported-by: Christian Hewitt <[email protected]> Signed-off-by: Martin Blumenstingl <[email protected]> Reviewed-by: Neil Armstrong <[email protected]> Signed-off-by: Neil Armstrong <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent faf2f83 commit 0cee6c4

File tree

1 file changed

+34
-21
lines changed

1 file changed

+34
-21
lines changed

drivers/gpu/drm/meson/meson_vclk.c

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,7 @@
110110
#define HDMI_PLL_LOCK BIT(31)
111111
#define HDMI_PLL_LOCK_G12A (3 << 30)
112112

113-
#define PIXEL_FREQ_1000_1001(_freq) \
114-
DIV_ROUND_CLOSEST_ULL((_freq) * 1000ULL, 1001ULL)
115-
#define PHY_FREQ_1000_1001(_freq) \
116-
(PIXEL_FREQ_1000_1001(DIV_ROUND_DOWN_ULL(_freq, 10ULL)) * 10)
113+
#define FREQ_1000_1001(_freq) DIV_ROUND_CLOSEST_ULL((_freq) * 1000ULL, 1001ULL)
117114

118115
/* VID PLL Dividers */
119116
enum {
@@ -772,6 +769,36 @@ static void meson_hdmi_pll_generic_set(struct meson_drm *priv,
772769
pll_freq);
773770
}
774771

772+
static bool meson_vclk_freqs_are_matching_param(unsigned int idx,
773+
unsigned long long phy_freq,
774+
unsigned long long vclk_freq)
775+
{
776+
DRM_DEBUG_DRIVER("i = %d vclk_freq = %lluHz alt = %lluHz\n",
777+
idx, params[idx].vclk_freq,
778+
FREQ_1000_1001(params[idx].vclk_freq));
779+
DRM_DEBUG_DRIVER("i = %d phy_freq = %lluHz alt = %lluHz\n",
780+
idx, params[idx].phy_freq,
781+
FREQ_1000_1001(params[idx].phy_freq));
782+
783+
/* Match strict frequency */
784+
if (phy_freq == params[idx].phy_freq &&
785+
vclk_freq == params[idx].vclk_freq)
786+
return true;
787+
788+
/* Match 1000/1001 variant: vclk deviation has to be less than 1kHz
789+
* (drm EDID is defined in 1kHz steps, so everything smaller must be
790+
* rounding error) and the PHY freq deviation has to be less than
791+
* 10kHz (as the TMDS clock is 10 times the pixel clock, so anything
792+
* smaller must be rounding error as well).
793+
*/
794+
if (abs(vclk_freq - FREQ_1000_1001(params[idx].vclk_freq)) < 1000 &&
795+
abs(phy_freq - FREQ_1000_1001(params[idx].phy_freq)) < 10000)
796+
return true;
797+
798+
/* no match */
799+
return false;
800+
}
801+
775802
enum drm_mode_status
776803
meson_vclk_vic_supported_freq(struct meson_drm *priv,
777804
unsigned long long phy_freq,
@@ -790,19 +817,7 @@ meson_vclk_vic_supported_freq(struct meson_drm *priv,
790817
}
791818

792819
for (i = 0 ; params[i].pixel_freq ; ++i) {
793-
DRM_DEBUG_DRIVER("i = %d vclk_freq = %lluHz alt = %lluHz\n",
794-
i, params[i].vclk_freq,
795-
PIXEL_FREQ_1000_1001(params[i].vclk_freq));
796-
DRM_DEBUG_DRIVER("i = %d phy_freq = %lluHz alt = %lluHz\n",
797-
i, params[i].phy_freq,
798-
PHY_FREQ_1000_1001(params[i].phy_freq));
799-
/* Match strict frequency */
800-
if (phy_freq == params[i].phy_freq &&
801-
vclk_freq == params[i].vclk_freq)
802-
return MODE_OK;
803-
/* Match 1000/1001 variant */
804-
if (phy_freq == PHY_FREQ_1000_1001(params[i].phy_freq) &&
805-
vclk_freq == PIXEL_FREQ_1000_1001(params[i].vclk_freq))
820+
if (meson_vclk_freqs_are_matching_param(i, phy_freq, vclk_freq))
806821
return MODE_OK;
807822
}
808823

@@ -1075,10 +1090,8 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
10751090
}
10761091

10771092
for (freq = 0 ; params[freq].pixel_freq ; ++freq) {
1078-
if ((phy_freq == params[freq].phy_freq ||
1079-
phy_freq == PHY_FREQ_1000_1001(params[freq].phy_freq)) &&
1080-
(vclk_freq == params[freq].vclk_freq ||
1081-
vclk_freq == PIXEL_FREQ_1000_1001(params[freq].vclk_freq))) {
1093+
if (meson_vclk_freqs_are_matching_param(freq, phy_freq,
1094+
vclk_freq)) {
10821095
if (vclk_freq != params[freq].vclk_freq)
10831096
vic_alternate_clock = true;
10841097
else

0 commit comments

Comments
 (0)