kernel: bump 5.15 to 5.15.100
[openwrt/openwrt.git] / target / linux / bcm27xx / patches-5.15 / 950-0634-drm-vc4-hdmi-Always-try-to-have-the-highest-bpc.patch
1 From 5194c69ca3e4af8c3a6ffc77e5eb1ee0a62a6bbe Mon Sep 17 00:00:00 2001
2 From: Maxime Ripard <maxime@cerno.tech>
3 Date: Fri, 10 Dec 2021 15:29:56 +0100
4 Subject: [PATCH] drm/vc4: hdmi: Always try to have the highest bpc
5
6 Currently we take the max_bpc property as the bpc value and do not try
7 anything else.
8
9 However, what the other drivers seem to be doing is that they would try
10 with the highest bpc allowed by the max_bpc property and the hardware
11 capabilities, test if it results in an acceptable configuration, and if
12 not decrease the bpc and try again.
13
14 Let's use the same logic.
15
16 Signed-off-by: Maxime Ripard <maxime@cerno.tech>
17 ---
18 drivers/gpu/drm/vc4/vc4_hdmi.c | 44 ++++++++++++++++++++++++++++++----
19 drivers/gpu/drm/vc4/vc4_hdmi.h | 4 +++-
20 2 files changed, 43 insertions(+), 5 deletions(-)
21
22 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
23 +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
24 @@ -357,6 +357,7 @@ vc4_hdmi_connector_duplicate_state(struc
25 return NULL;
26
27 new_state->pixel_rate = vc4_state->pixel_rate;
28 + new_state->output_bpc = vc4_state->output_bpc;
29 __drm_atomic_helper_connector_duplicate_state(connector, &new_state->base);
30
31 return &new_state->base;
32 @@ -914,6 +915,8 @@ static void vc5_hdmi_set_timings(struct
33 struct drm_connector_state *state,
34 struct drm_display_mode *mode)
35 {
36 + const struct vc4_hdmi_connector_state *vc4_state =
37 + conn_state_to_vc4_hdmi_conn_state(state);
38 bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
39 bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
40 bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
41 @@ -962,7 +965,7 @@ static void vc5_hdmi_set_timings(struct
42 HDMI_WRITE(HDMI_VERTB0, vertb_even);
43 HDMI_WRITE(HDMI_VERTB1, vertb);
44
45 - switch (state->max_bpc) {
46 + switch (vc4_state->output_bpc) {
47 case 12:
48 gcp = 6;
49 gcp_en = true;
50 @@ -1252,9 +1255,11 @@ static void vc4_hdmi_encoder_atomic_mode
51 struct drm_connector_state *conn_state)
52 {
53 struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
54 + struct vc4_hdmi_connector_state *vc4_state =
55 + conn_state_to_vc4_hdmi_conn_state(conn_state);
56
57 mutex_lock(&vc4_hdmi->mutex);
58 - vc4_hdmi->output_bpc = conn_state->max_bpc;
59 + vc4_hdmi->output_bpc = vc4_state->output_bpc;
60 memcpy(&vc4_hdmi->saved_adjusted_mode,
61 &crtc_state->adjusted_mode,
62 sizeof(vc4_hdmi->saved_adjusted_mode));
63 @@ -1309,6 +1314,38 @@ vc4_hdmi_encoder_compute_clock(const str
64 return 0;
65 }
66
67 +static int
68 +vc4_hdmi_encoder_compute_config(const struct vc4_hdmi *vc4_hdmi,
69 + struct vc4_hdmi_connector_state *vc4_state,
70 + const struct drm_display_mode *mode)
71 +{
72 + struct drm_connector_state *conn_state = &vc4_state->base;
73 + unsigned int max_bpc = clamp_t(unsigned int, conn_state->max_bpc, 8, 12);
74 + unsigned int bpc;
75 + int ret;
76 +
77 + for (bpc = max_bpc; bpc >= 8; bpc -= 2) {
78 + drm_dbg(dev, "Trying with a %d bpc output\n", bpc);
79 +
80 + ret = vc4_hdmi_encoder_compute_clock(vc4_hdmi, vc4_state,
81 + mode, bpc);
82 + if (ret)
83 + continue;
84 +
85 + vc4_state->output_bpc = bpc;
86 +
87 + drm_dbg(dev,
88 + "Mode %ux%u @ %uHz: Found configuration: bpc: %u, clock: %llu\n",
89 + mode->hdisplay, mode->vdisplay, drm_mode_vrefresh(mode),
90 + vc4_state->output_bpc,
91 + vc4_state->pixel_rate);
92 +
93 + break;
94 + }
95 +
96 + return ret;
97 +}
98 +
99 #define WIFI_2_4GHz_CH1_MIN_FREQ 2400000000ULL
100 #define WIFI_2_4GHz_CH1_MAX_FREQ 2422000000ULL
101
102 @@ -1343,8 +1380,7 @@ static int vc4_hdmi_encoder_atomic_check
103 pixel_rate = mode->clock * 1000;
104 }
105
106 - ret = vc4_hdmi_encoder_compute_clock(vc4_hdmi, vc4_state, mode,
107 - conn_state->max_bpc);
108 + ret = vc4_hdmi_encoder_compute_config(vc4_hdmi, vc4_state, mode);
109 if (ret)
110 return ret;
111
112 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
113 +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
114 @@ -222,7 +222,8 @@ struct vc4_hdmi {
115 bool scdc_enabled;
116
117 /**
118 - * @output_bpc: BPC currently being used. Protected by @mutex.
119 + * @output_bpc: Copy of @vc4_connector_state.output_bpc for use
120 + * outside of KMS hooks. Protected by @mutex.
121 */
122 unsigned int output_bpc;
123
124 @@ -252,6 +253,7 @@ encoder_to_vc4_hdmi(struct drm_encoder *
125 struct vc4_hdmi_connector_state {
126 struct drm_connector_state base;
127 unsigned long long pixel_rate;
128 + unsigned int output_bpc;
129 };
130
131 static inline struct vc4_hdmi_connector_state *