Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
certo
linux
Commits
b2eab3b8
Commit
b2eab3b8
authored
Jun 22, 2025
by
Vladimir Bashkirtsev
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fixed VC4 driver in Raspberry Pi patch
parent
d9237d13
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
260 additions
and
90 deletions
+260
-90
linux-5.12.10-rpi.patch
linux-5.12.10-rpi.patch
+260
-90
No files found.
linux-5.12.10-rpi.patch
View file @
b2eab3b8
...
...
@@ -74298,7 +74298,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/Makefile linux-5.12.10-rpi/drivers/g
vc4_hdmi.o \
diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_crtc.c linux-5.12.10-rpi/drivers/gpu/drm/vc4/vc4_crtc.c
--- linux-5.12.10/drivers/gpu/drm/vc4/vc4_crtc.c 2021-06-10 11:41:49.000000000 +0000
+++ linux-5.12.10-rpi/drivers/gpu/drm/vc4/vc4_crtc.c 2025-06-
20 00:09:07.027997723
+0000
+++ linux-5.12.10-rpi/drivers/gpu/drm/vc4/vc4_crtc.c 2025-06-
19 12:13:33.443261180
+0000
@@ -279,19 +279,15 @@
* allows drivers to push pixels to more than one encoder from the
* same CRTC.
...
...
@@ -74326,7 +74326,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_crtc.c linux-5.12.10-rpi/drivers
return NULL;
}
@@ -305,
11 +301,11
@@
@@ -305,
22 +301,29
@@
CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_FIFO_CLR);
}
...
...
@@ -74340,7 +74340,11 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_crtc.c linux-5.12.10-rpi/drivers
struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
const struct vc4_pv_data *pv_data = vc4_crtc_to_vc4_pv_data(vc4_crtc);
@@ -319,8 +315,15 @@
- struct drm_crtc_state *state = crtc->state;
- struct drm_display_mode *mode = &state->adjusted_mode;
+ struct drm_crtc_state *crtc_state = crtc->state;
+ struct drm_display_mode *mode = &crtc_state->adjusted_mode;
bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1;
bool is_dsi = (vc4_encoder->type == VC4_ENCODER_TYPE_DSI0 ||
vc4_encoder->type == VC4_ENCODER_TYPE_DSI1);
...
...
@@ -74443,7 +74447,68 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_crtc.c linux-5.12.10-rpi/drivers
if (is_dsi)
CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep);
@@ -496,8 +510,12 @@
@@ -421,10 +435,10 @@
}
static int vc4_crtc_disable(struct drm_crtc *crtc,
+ struct drm_encoder *encoder,
struct drm_atomic_state *state,
unsigned int channel)
{
- struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc);
struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
struct drm_device *dev = crtc->dev;
@@ -465,10 +479,29 @@
return 0;
}
+static struct drm_encoder *vc4_crtc_get_encoder_by_type(struct drm_crtc *crtc,
+ enum vc4_encoder_type type)
+{
+ struct drm_encoder *encoder;
+
+ drm_for_each_encoder(encoder, crtc->dev) {
+ struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
+
+ if (vc4_encoder->type == type)
+ return encoder;
+ }
+
+ return NULL;
+}
+
int vc4_crtc_disable_at_boot(struct drm_crtc *crtc)
{
struct drm_device *drm = crtc->dev;
struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+ enum vc4_encoder_type encoder_type;
+ const struct vc4_pv_data *pv_data;
+ struct drm_encoder *encoder;
+ unsigned encoder_sel;
int channel;
if (!(of_device_is_compatible(vc4_crtc->pdev->dev.of_node,
@@ -487,7 +520,17 @@
if (channel < 0)
return 0;
- return vc4_crtc_disable(crtc, NULL, channel);
+ encoder_sel = VC4_GET_FIELD(CRTC_READ(PV_CONTROL), PV_CONTROL_CLK_SELECT);
+ if (WARN_ON(encoder_sel != 0))
+ return 0;
+
+ pv_data = vc4_crtc_to_vc4_pv_data(vc4_crtc);
+ encoder_type = pv_data->encoder_types[encoder_sel];
+ encoder = vc4_crtc_get_encoder_by_type(crtc, encoder_type);
+ if (WARN_ON(!encoder))
+ return 0;
+
+ return vc4_crtc_disable(crtc, encoder, NULL, channel);
}
static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
@@ -496,14 +539,18 @@
struct drm_crtc_state *old_state = drm_atomic_get_old_crtc_state(state,
crtc);
struct vc4_crtc_state *old_vc4_state = to_vc4_crtc_state(old_state);
...
...
@@ -74456,7 +74521,14 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_crtc.c linux-5.12.10-rpi/drivers
require_hvs_enabled(dev);
/* Disable vblank irq handling before crtc is disabled. */
@@ -522,11 +540,16 @@
drm_crtc_vblank_off(crtc);
- vc4_crtc_disable(crtc, state, old_vc4_state->assigned_channel);
+ vc4_crtc_disable(crtc, encoder, state, old_vc4_state->assigned_channel);
/*
* Make sure we issue a vblank event after disabling the CRTC if
@@ -522,11 +569,16 @@
static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
struct drm_atomic_state *state)
{
...
...
@@ -74474,7 +74546,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_crtc.c linux-5.12.10-rpi/drivers
require_hvs_enabled(dev);
/* Enable vblank irq handling before crtc is started otherwise
@@ -539,7 +5
62
,7 @@
@@ -539,7 +5
91
,7 @@
if (vc4_encoder->pre_crtc_configure)
vc4_encoder->pre_crtc_configure(encoder, state);
...
...
@@ -74483,7 +74555,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_crtc.c linux-5.12.10-rpi/drivers
CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
@@ -608,12 +6
31
,27 @@
@@ -608,12 +6
60
,27 @@
struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state);
struct drm_connector *conn;
struct drm_connector_state *conn_state;
...
...
@@ -74511,6 +74583,25 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_crtc.c linux-5.12.10-rpi/drivers
for_each_new_connector_in_state(state, conn, conn_state,
i) {
if (conn_state->crtc != crtc)
@@ -994,7 +1061,7 @@
.fifo_depth = 64,
.pixels_per_clock = 1,
.encoder_types = {
- [0] = VC4_ENCODER_TYPE_VEC,
+ [PV_CONTROL_CLK_SELECT_VEC] = VC4_ENCODER_TYPE_VEC,
},
};
@@ -1035,6 +1102,9 @@
struct vc4_encoder *vc4_encoder;
int i;
+ if (encoder->encoder_type == DRM_MODE_ENCODER_VIRTUAL)
+ continue;
+
vc4_encoder = to_vc4_encoder(encoder);
for (i = 0; i < ARRAY_SIZE(pv_data->encoder_types); i++) {
if (vc4_encoder->type == encoder_types[i]) {
diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_debugfs.c linux-5.12.10-rpi/drivers/gpu/drm/vc4/vc4_debugfs.c
--- linux-5.12.10/drivers/gpu/drm/vc4/vc4_debugfs.c 2021-06-10 11:41:49.000000000 +0000
+++ linux-5.12.10-rpi/drivers/gpu/drm/vc4/vc4_debugfs.c 2025-06-19 19:37:20.021894985 +0000
...
...
@@ -77103,7 +77194,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_firmware_kms.c linux-5.12.10-rpi
+};
diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers/gpu/drm/vc4/vc4_hdmi.c
--- linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c 2021-06-10 11:41:49.000000000 +0000
+++ linux-5.12.10-rpi/drivers/gpu/drm/vc4/vc4_hdmi.c 2025-06-
20 00:26:58.693402678
+0000
+++ linux-5.12.10-rpi/drivers/gpu/drm/vc4/vc4_hdmi.c 2025-06-
19 12:13:33.455261053
+0000
@@ -35,6 +35,7 @@
#include <drm/drm_edid.h>
#include <drm/drm_probe_helper.h>
...
...
@@ -77169,7 +77260,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
return 0;
}
@@ -153,
6 +172,8
@@
@@ -153,
18 +172,20
@@
static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi) {}
#endif
...
...
@@ -77178,7 +77269,12 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
static enum drm_connector_status
vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
{
@@ -163,8 +184,6 @@
struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector);
bool connected = false;
+ WARN_ON(pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev));
+
if (vc4_hdmi->hpd_gpio) {
if (gpio_get_value_cansleep(vc4_hdmi->hpd_gpio) ^
vc4_hdmi->hpd_active_low)
connected = true;
...
...
@@ -77187,16 +77283,22 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
} else if (HDMI_READ(HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED) {
connected = true;
}
@@ -180,
6 +199,8
@@
@@ -180,
10 +201,14
@@
}
}
+ vc4_hdmi_enable_scrambling(&vc4_hdmi->encoder.base.base);
+
+ pm_runtime_put(&vc4_hdmi->pdev->dev);
return connector_status_connected;
}
@@ -211,9 +232,47 @@
cec_phys_addr_invalidate(vc4_hdmi->cec_adap);
+ pm_runtime_put(&vc4_hdmi->pdev->dev);
return connector_status_disconnected;
}
@@ -211,9 +236,47 @@
ret = drm_add_edid_modes(connector, edid);
kfree(edid);
...
...
@@ -77244,7 +77346,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
static void vc4_hdmi_connector_reset(struct drm_connector *connector)
{
struct vc4_hdmi_connector_state *old_state =
@@ -263,6 +32
2
,7 @@
@@ -263,6 +32
6
,7 @@
static const struct drm_connector_helper_funcs vc4_hdmi_connector_helper_funcs = {
.get_modes = vc4_hdmi_connector_get_modes,
...
...
@@ -77252,7 +77354,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
};
static int vc4_hdmi_connector_init(struct drm_device *dev,
@@ -290,6 +35
0
,11 @@
@@ -290,6 +35
4
,11 @@
if (ret)
return ret;
...
...
@@ -77264,7 +77366,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
drm_connector_attach_tv_margin_properties(connector);
drm_connector_attach_max_bpc_property(connector, 8, 12);
@@ -298,6 +36
3
,10 @@
@@ -298,6 +36
7
,10 @@
connector->interlace_allowed = 1;
connector->doublescan_allowed = 0;
...
...
@@ -77275,7 +77377,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
drm_connector_attach_encoder(connector, encoder);
@@ -329,9 +
398
,11 @@
@@ -329,9 +
402
,11 @@
const struct vc4_hdmi_register *ram_packet_start =
&vc4_hdmi->variant->registers[HDMI_RAM_PACKET_START];
u32 packet_reg = ram_packet_start->offset + VC4_HDMI_PACKET_STRIDE * packet_id;
...
...
@@ -77288,7 +77390,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
ssize_t len, i;
int ret;
@@ -364,6 +43
5
,13 @@
@@ -364,6 +43
9
,13 @@
packet_reg += 4;
}
...
...
@@ -77302,7 +77404,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
HDMI_READ(HDMI_RAM_PACKET_CONFIG) | BIT(packet_id));
ret = wait_for((HDMI_READ(HDMI_RAM_PACKET_STATUS) &
@@ -395,7 +47
3
,7 @@
@@ -395,7 +47
7
,7 @@
vc4_encoder->limited_rgb_range ?
HDMI_QUANTIZATION_RANGE_LIMITED :
HDMI_QUANTIZATION_RANGE_FULL);
...
...
@@ -77311,32 +77413,32 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
drm_hdmi_avi_infoframe_bars(&frame.avi, cstate);
vc4_hdmi_write_infoframe(encoder, &frame);
@@ -420,14 +
498
,28 @@
@@ -420,14 +
502
,28 @@
static void vc4_hdmi_set_audio_infoframe(struct drm_encoder *encoder)
{
struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
+ struct hdmi_audio_infoframe *audio = &vc4_hdmi->audio.infoframe;
union hdmi_infoframe frame;
- hdmi_audio_infoframe_init(&frame.audio);
+ union hdmi_infoframe frame;
+
+ memcpy(&frame.audio, audio, sizeof(*audio));
+ vc4_hdmi_write_infoframe(encoder, &frame);
+}
- frame.audio.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM;
- frame.audio.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM;
- frame.audio.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM;
- frame.audio.channels = vc4_hdmi->audio.channels;
+
+static void vc4_hdmi_set_hdr_infoframe(struct drm_encoder *encoder)
+{
+ struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
+ struct drm_connector *connector = &vc4_hdmi->connector;
+ struct drm_connector_state *conn_state = connector->state;
+ union hdmi_infoframe frame;
+
union hdmi_infoframe frame;
- hdmi_audio_infoframe_init(&frame.audio);
+ if (!vc4_hdmi->variant->supports_hdr)
+ return;
+
- frame.audio.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM;
- frame.audio.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM;
- frame.audio.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM;
- frame.audio.channels = vc4_hdmi->audio.channels;
+ if (!conn_state->hdr_output_metadata)
+ return;
+
...
...
@@ -77345,7 +77447,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
vc4_hdmi_write_infoframe(encoder, &frame);
}
@@ -444,6 +5
36
,94 @@
@@ -444,6 +5
40
,94 @@
*/
if (vc4_hdmi->audio.streaming)
vc4_hdmi_set_audio_infoframe(encoder);
...
...
@@ -77440,7 +77542,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
}
static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder,
@@ -453,11 +63
3
,13 @@
@@ -453,11 +63
7
,13 @@
HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0);
...
...
@@ -77457,7 +77559,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
}
static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder,
@@ -466,1
3 +648
,16 @@
@@ -466,1
4 +652
,16 @@
struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
int ret;
...
...
@@ -77471,13 +77573,14 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
- HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
-
clk_disable_unprepare(vc4_hdmi->pixel_bvb_clock);
- clk_disable_unprepare(vc4_hdmi->hsm_clock);
+ if (vc4_hdmi->bvb_req)
+ clk_request_done(vc4_hdmi->bvb_req);
+ clk_request_done(vc4_hdmi->hsm_req);
clk_disable_unprepare(vc4_hdmi->hsm_clock);
clk_disable_unprepare(vc4_hdmi->pixel_clock);
@@ -573,12 +758,12 @@
ret = pm_runtime_put(&vc4_hdmi->pdev->dev);
@@ -573,12 +761,12 @@
VC4_HDMI_VERTA_VFP) |
VC4_SET_FIELD(mode->crtc_vdisplay, VC4_HDMI_VERTA_VAL));
u32 vertb = (VC4_SET_FIELD(0, VC4_HDMI_VERTB_VSPO) |
...
...
@@ -77493,7 +77596,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
VC4_HDMI_VERTB_VBP));
HDMI_WRITE(HDMI_HORZA,
@@ -619,12 +80
4
,12 @@
@@ -619,12 +80
7
,12 @@
VC5_HDMI_VERTA_VFP) |
VC4_SET_FIELD(mode->crtc_vdisplay, VC5_HDMI_VERTA_VAL));
u32 vertb = (VC4_SET_FIELD(0, VC5_HDMI_VERTB_VSPO) |
...
...
@@ -77509,7 +77612,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
VC4_HDMI_VERTB_VBP));
unsigned char gcp;
bool gcp_en;
@@ -687,6 +87
2
,11 @@
@@ -687,6 +87
5
,11 @@
reg |= gcp_en ? VC5_HDMI_GCP_CONFIG_GCP_ENABLE : 0;
HDMI_WRITE(HDMI_GCP_CONFIG, reg);
...
...
@@ -77521,7 +77624,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
HDMI_WRITE(HDMI_CLOCK_STOP, 0);
}
@@ -714,32 +90
4
,17 @@
@@ -714,32 +90
7
,17 @@
"VC4_HDMI_FIFO_CTL_RECENTER_DONE");
}
...
...
@@ -77558,7 +77661,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
int ret;
ret = pm_runtime_get_sync(&vc4_hdmi->pdev->dev);
@@ -752,
36 +927,20
@@
@@ -752,
66 +930,42
@@
ret = clk_set_rate(vc4_hdmi->pixel_clock, pixel_rate);
if (ret) {
DRM_ERROR("Failed to set pixel clock rate: %d\n", ret);
...
...
@@ -77594,6 +77697,13 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
- if (ret) {
- DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
- return;
- }
-
- ret = clk_prepare_enable(vc4_hdmi->hsm_clock);
- if (ret) {
- DRM_ERROR("Failed to turn on HSM clock: %d\n", ret);
- clk_disable_unprepare(vc4_hdmi->pixel_clock);
- return;
+ hsm_rate = vc4_hdmi->variant->calc_hsm_clock(vc4_hdmi, pixel_rate);
+ vc4_hdmi->hsm_req = clk_request_start(vc4_hdmi->hsm_clock, hsm_rate);
+ if (IS_ERR(vc4_hdmi->hsm_req)) {
...
...
@@ -77601,9 +77711,6 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
+ goto err_disable_pixel_clk;
}
ret = clk_prepare_enable(vc4_hdmi->hsm_clock);
@@ -793,25 +952,24 @@
vc4_hdmi_cec_update_clk_div(vc4_hdmi);
- /*
...
...
@@ -77641,7 +77748,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
}
if (vc4_hdmi->variant->phy_init)
@@ -824,6 +9
82
,19 @@
@@ -824,6 +9
78
,19 @@
if (vc4_hdmi->variant->set_timings)
vc4_hdmi->variant->set_timings(vc4_hdmi, conn_state, mode);
...
...
@@ -77661,7 +77768,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
}
static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder,
@@ -861,6 +10
32
,7 @@
@@ -861,6 +10
28
,7 @@
HDMI_WRITE(HDMI_VID_CTL,
VC4_HD_VID_CTL_ENABLE |
...
...
@@ -77669,7 +77776,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
VC4_HD_VID_CTL_UNDERFLOW_ENABLE |
VC4_HD_VID_CTL_FRAME_COUNTER_RESET |
(vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
@@ -906,6 +107
8
,7 @@
@@ -906,6 +107
4
,7 @@
}
vc4_hdmi_recenter_fifo(vc4_hdmi);
...
...
@@ -77677,7 +77784,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
}
static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
@@ -926,6 +109
9
,7 @@
@@ -926,6 +109
5
,7 @@
unsigned long long tmds_rate;
if (vc4_hdmi->variant->unsupported_odd_h_timings &&
...
...
@@ -77685,7 +77792,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
((mode->hdisplay % 2) || (mode->hsync_start % 2) ||
(mode->hsync_end % 2) || (mode->htotal % 2)))
return -EINVAL;
@@ -958,6 +11
32
,9 @@
@@ -958,6 +11
28
,9 @@
if (pixel_rate > vc4_hdmi->variant->max_pixel_clock)
return -EINVAL;
...
...
@@ -77695,7 +77802,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
vc4_state->pixel_rate = pixel_rate;
return 0;
@@ -970,6 +114
7
,7 @@
@@ -970,6 +114
3
,7 @@
struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
if (vc4_hdmi->variant->unsupported_odd_h_timings &&
...
...
@@ -77703,7 +77810,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
((mode->hdisplay % 2) || (mode->hsync_start % 2) ||
(mode->hsync_end % 2) || (mode->htotal % 2)))
return MODE_H_ILLEGAL;
@@ -977,6 +115
5
,9 @@
@@ -977,6 +115
1
,9 @@
if ((mode->clock * 1000) > vc4_hdmi->variant->max_pixel_clock)
return MODE_CLOCK_HIGH;
...
...
@@ -77713,7 +77820,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
return MODE_OK;
}
@@ -987,6 +116
8
,39 @@
@@ -987,6 +116
4
,39 @@
.enable = vc4_hdmi_encoder_enable,
};
...
...
@@ -77753,7 +77860,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
static u32 vc4_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask)
{
int i;
@@ -1012,12 +122
6
,13 @@
@@ -1012,12 +122
2
,13 @@
}
/* HDMI audio codec callbacks */
...
...
@@ -77769,7 +77876,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
VC4_HD_MAI_SMP_N_MASK >>
VC4_HD_MAI_SMP_N_SHIFT,
(VC4_HD_MAI_SMP_M_MASK >>
@@ -1029,12 +124
4
,11 @@
@@ -1029,12 +124
0
,11 @@
VC4_SET_FIELD(m - 1, VC4_HD_MAI_SMP_M));
}
...
...
@@ -77783,7 +77890,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
u32 n, cts;
u64 tmp;
@@ -1063,18 +127
7
,10 @@
@@ -1063,18 +127
3
,10 @@
return snd_soc_card_get_drvdata(card);
}
...
...
@@ -77804,7 +77911,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
/*
* If the HDMI encoder hasn't probed, or the encoder is
@@ -1084,15 +12
90
,18 @@
@@ -1084,15 +12
86
,18 @@
VC4_HDMI_RAM_PACKET_ENABLE))
return -ENODEV;
...
...
@@ -77830,7 +77937,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
return 0;
}
@@ -1112,48 +13
21
,96 @@
@@ -1112,48 +13
17
,96 @@
HDMI_WRITE(HDMI_MAI_CTL, VC4_HD_MAI_CTL_FLUSH);
}
...
...
@@ -77847,10 +77954,10 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
+ VC4_HD_MAI_CTL_DLATE |
+ VC4_HD_MAI_CTL_ERRORE |
+ VC4_HD_MAI_CTL_ERRORF);
+
+ if (vc4_hdmi->variant->phy_rng_disable)
+ vc4_hdmi->variant->phy_rng_disable(vc4_hdmi);
+
+ vc4_hdmi->audio.streaming = false;
vc4_hdmi_audio_reset(vc4_hdmi);
+}
...
...
@@ -77953,7 +78060,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
/* The B frame identifier should match the value used by alsa-lib (8) */
audio_packet_config =
@@ -1161,122 +141
8
,33 @@
@@ -1161,122 +141
4
,33 @@
VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_INACTIVE_CHANNELS |
VC4_SET_FIELD(0x8, VC4_HDMI_AUDIO_PACKET_B_FRAME_IDENTIFIER);
...
...
@@ -78086,7 +78193,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
static const struct snd_soc_dapm_widget vc4_hdmi_audio_widgets[] = {
SND_SOC_DAPM_OUTPUT("TX"),
};
@@ -1287,8 +145
5
,6 @@
@@ -1287,8 +145
1
,6 @@
static const struct snd_soc_component_driver vc4_hdmi_audio_component_drv = {
.name = "vc4-hdmi-codec-dai-component",
...
...
@@ -78095,7 +78202,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
.dapm_widgets = vc4_hdmi_audio_widgets,
.num_dapm_widgets = ARRAY_SIZE(vc4_hdmi_audio_widgets),
.dapm_routes = vc4_hdmi_audio_routes,
@@ -1299,28 +146
5
,6 @@
@@ -1299,28 +146
1
,6 @@
.non_legacy_dai_naming = 1,
};
...
...
@@ -78124,7 +78231,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
static const struct snd_soc_component_driver vc4_hdmi_audio_cpu_dai_comp = {
.name = "vc4-hdmi-cpu-dai-component",
};
@@ -1347,7 +14
91
,6 @@
@@ -1347,7 +14
87
,6 @@
SNDRV_PCM_RATE_192000,
.formats = SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE,
},
...
...
@@ -78132,7 +78239,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
};
static const struct snd_dmaengine_pcm_config pcm_conf = {
@@ -1355,6 +149
8
,31 @@
@@ -1355,6 +149
4
,31 @@
.prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
};
...
...
@@ -78164,7 +78271,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
{
const struct vc4_hdmi_register *mai_data =
@@ -1362,13 +15
30
,16 @@
@@ -1362,13 +15
26
,16 @@
struct snd_soc_dai_link *dai_link = &vc4_hdmi->audio.link;
struct snd_soc_card *card = &vc4_hdmi->audio.card;
struct device *dev = &vc4_hdmi->pdev->dev;
...
...
@@ -78183,7 +78290,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
return 0;
}
@@ -1408,12 +157
9
,13 @@
@@ -1408,12 +157
5
,13 @@
return ret;
}
...
...
@@ -78203,7 +78310,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
}
dai_link->cpus = &vc4_hdmi->audio.cpu;
@@ -1426,9 +159
8
,9 @@
@@ -1426,9 +159
4
,9 @@
dai_link->name = "MAI";
dai_link->stream_name = "MAI PCM";
...
...
@@ -78215,7 +78322,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
dai_link->platforms->name = dev_name(dev);
card->dai_link = dai_link;
@@ -1454,6 +162
6
,60 @@
@@ -1454,6 +162
2
,60 @@
}
...
...
@@ -78276,7 +78383,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
#ifdef CONFIG_DRM_VC4_HDMI_CEC
static irqreturn_t vc4_cec_irq_handler_rx_thread(int irq, void *priv)
{
@@ -1572,51 +179
8
,74 @@
@@ -1572,51 +179
4
,74 @@
return ret;
}
...
...
@@ -78289,11 +78396,11 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
- u32 val = HDMI_READ(HDMI_CEC_CNTRL_5);
+ u32 val;
+ int ret;
+
+ ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev);
+ if (ret)
+ return ret;
+
+ val = HDMI_READ(HDMI_CEC_CNTRL_5);
val &= ~(VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET |
VC4_HDMI_CEC_CNT_TO_4700_US_MASK |
...
...
@@ -78381,7 +78488,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
static int vc4_hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
{
struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap);
@@ -1696,38 +194
5
,46 @@
@@ -1696,38 +194
1
,46 @@
vc4_hdmi_cec_update_clk_div(vc4_hdmi);
if (vc4_hdmi->variant->external_irq_controller) {
...
...
@@ -78444,7 +78551,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
err_delete_cec_adap:
cec_delete_adapter(vc4_hdmi->cec_adap);
@@ -1736,6 +19
93
,15 @@
@@ -1736,6 +19
89
,15 @@
static void vc4_hdmi_cec_exit(struct vc4_hdmi *vc4_hdmi)
{
...
...
@@ -78460,7 +78567,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
cec_unregister_adapter(vc4_hdmi->cec_adap);
}
#else
@@ -1830,6 +209
6
,7 @@
@@ -1830,6 +209
2
,7 @@
struct platform_device *pdev = vc4_hdmi->pdev;
struct device *dev = &pdev->dev;
struct resource *res;
...
...
@@ -78468,7 +78575,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi");
if (!res)
@@ -1926,
6 +2193,38
@@
@@ -1926,
9 +2189,64
@@
return PTR_ERR(vc4_hdmi->reset);
}
...
...
@@ -78503,11 +78610,37 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
+ ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->rm_regset, VC5_RM);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int vc4_hdmi_runtime_suspend(struct device *dev)
+{
+ struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev);
+
+ clk_disable_unprepare(vc4_hdmi->hsm_clock);
+
return 0;
}
@@ -1943,6 +2242,7 @@
+static int vc4_hdmi_runtime_resume(struct device *dev)
+{
+ struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev);
+ int ret;
+
+ ret = clk_prepare_enable(vc4_hdmi->hsm_clock);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+#endif
+
static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
{
const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev);
@@ -1943,6 +2261,7 @@
vc4_hdmi = devm_kzalloc(dev, sizeof(*vc4_hdmi), GFP_KERNEL);
if (!vc4_hdmi)
return -ENOMEM;
...
...
@@ -78515,12 +78648,19 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
dev_set_drvdata(dev, vc4_hdmi);
encoder = &vc4_hdmi->encoder.base.base;
@@ -1992,11 +2292,55 @@
@@ -1983,7 +2302,7 @@
&hpd_gpio_flags);
if (vc4_hdmi->hpd_gpio < 0) {
ret = vc4_hdmi->hpd_gpio;
- goto err_unprepare_hsm;
+ goto err_put_ddc;
}
vc4_hdmi->hpd_active_low = hpd_gpio_flags & OF_GPIO_ACTIVE_LOW;
@@ -1992,10 +2311,62 @@
vc4_hdmi->disable_wifi_frequencies =
of_property_read_bool(dev->of_node, "wifi-2.4ghz-coexistence");
- if (vc4_hdmi->variant->reset)
- vc4_hdmi->variant->reset(vc4_hdmi);
+ if (variant->max_pixel_clock == 600000000) {
+ struct vc4_dev *vc4 = to_vc4_dev(drm);
+ long max_rate = clk_round_rate(vc4->hvs->core_clk, 550000000);
...
...
@@ -78562,18 +78702,26 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
+ ret = vc4_hdmi_runtime_resume(dev);
+ if (ret)
+ goto err_put_ddc;
+
+ pm_runtime_get_noresume(dev);
+ pm_runtime_set_active(dev);
pm_runtime_enable(dev);
+ if (vc4_hdmi->variant->reset)
+ vc4_hdmi->variant->reset(vc4_hdmi);
+ pm_runtime_enable(dev);
+
if (vc4_hdmi->variant->reset)
vc4_hdmi->variant->reset(vc4_hdmi);
- pm_runtime_enable(dev);
+ if ((of_device_is_compatible(dev->of_node, "brcm,bcm2711-hdmi0") ||
+ of_device_is_compatible(dev->of_node, "brcm,bcm2711-hdmi1")) &&
+ HDMI_READ(HDMI_VID_CTL) & VC4_HD_VID_CTL_ENABLE) {
+ clk_prepare_enable(vc4_hdmi->pixel_clock);
+ clk_prepare_enable(vc4_hdmi->hsm_clock);
+ clk_prepare_enable(vc4_hdmi->pixel_bvb_clock);
+ }
drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
drm_encoder_helper_add(encoder, &vc4_hdmi_encoder_helper_funcs);
@@ -2004,10 +2348,14 @@
@@ -2004,10 +2375,14 @@
if (ret)
goto err_destroy_encoder;
...
...
@@ -78589,7 +78737,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
ret = vc4_hdmi_audio_init(vc4_hdmi);
if (ret)
goto err_free_cec;
@@ -2016,1
4 +2364,19
@@
@@ -2016,1
6 +2391,21
@@
vc4_hdmi_debugfs_regs,
vc4_hdmi);
...
...
@@ -78605,11 +78753,14 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
err_destroy_encoder:
drm_encoder_cleanup(encoder);
-err_unprepare_hsm:
+ pm_runtime_put_sync(dev);
err_unprepare_hsm:
pm_runtime_disable(dev);
+err_put_ddc:
put_device(&vc4_hdmi->ddc->dev);
@@ -2061,6 +2414,7 @@
return ret;
@@ -2061,6 +2441,7 @@
kfree(vc4_hdmi->hd_regset.regs);
vc4_hdmi_cec_exit(vc4_hdmi);
...
...
@@ -78617,7 +78768,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
drm_encoder_cleanup(&vc4_hdmi->encoder.base.base);
@@ -2101,14 +24
55
,16 @@
@@ -2101,14 +24
82
,16 @@
.phy_disable = vc4_hdmi_phy_disable,
.phy_rng_enable = vc4_hdmi_phy_rng_enable,
.phy_rng_disable = vc4_hdmi_phy_rng_disable,
...
...
@@ -78635,7 +78786,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
.registers = vc5_hdmi_hdmi0_fields,
.num_registers = ARRAY_SIZE(vc5_hdmi_hdmi0_fields),
.phy_lane_mapping = {
@@ -2128,7 +2
484
,9 @@
@@ -2128,7 +2
511
,9 @@
.phy_disable = vc5_hdmi_phy_disable,
.phy_rng_enable = vc5_hdmi_phy_rng_enable,
.phy_rng_disable = vc5_hdmi_phy_rng_disable,
...
...
@@ -78645,7 +78796,7 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
};
static const struct vc4_hdmi_variant bcm2711_hdmi1_variant = {
@@ -2155,7 +25
13
,9 @@
@@ -2155,7 +25
40
,9 @@
.phy_disable = vc5_hdmi_phy_disable,
.phy_rng_enable = vc5_hdmi_phy_rng_enable,
.phy_rng_disable = vc5_hdmi_phy_rng_disable,
...
...
@@ -78655,6 +78806,25 @@ diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.c linux-5.12.10-rpi/drivers
};
static const struct of_device_id vc4_hdmi_dt_match[] = {
@@ -2165,11 +2552,18 @@
{}
};
+static const struct dev_pm_ops vc4_hdmi_pm_ops = {
+ SET_RUNTIME_PM_OPS(vc4_hdmi_runtime_suspend,
+ vc4_hdmi_runtime_resume,
+ NULL)
+};
+
struct platform_driver vc4_hdmi_driver = {
.probe = vc4_hdmi_dev_probe,
.remove = vc4_hdmi_dev_remove,
.driver = {
.name = "vc4_hdmi",
.of_match_table = vc4_hdmi_dt_match,
+ .pm = &vc4_hdmi_pm_ops,
},
};
diff -uNr linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.h linux-5.12.10-rpi/drivers/gpu/drm/vc4/vc4_hdmi.h
--- linux-5.12.10/drivers/gpu/drm/vc4/vc4_hdmi.h 2021-06-10 11:41:49.000000000 +0000
+++ linux-5.12.10-rpi/drivers/gpu/drm/vc4/vc4_hdmi.h 2025-06-19 19:37:20.049894724 +0000
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment