1
0
Fork 0
mirror of https://github.com/Ysurac/openmptcprouter.git synced 2025-02-15 04:42:02 +00:00
openmptcprouter/6.1/target/linux/bcm27xx/patches-6.1/950-0790-drm-edid-Add-option-to-report-basic-audio-support-wi.patch
Ycarus (Yannick Chabanois) 3743692973 Fix RPI5 support
2023-11-17 17:31:36 +01:00

128 lines
4.2 KiB
Diff

From 460d0537c4061a636e5f66a6db3d97ab4504cd83 Mon Sep 17 00:00:00 2001
From: Dom Cobley <popcornmix@gmail.com>
Date: Fri, 15 Sep 2023 17:25:17 +0100
Subject: [PATCH] drm/edid: Add option to report basic audio support with a
generic edid
Hardware that fails to read the edid is quite common.
The kernel provides a mechanism to use one a of a few
pre-built generic edid files for getting a basic video mode.
However there is no easy was to add basic audio support,
which requires a CTA extension block to report capabilities.
Add an module option to request this.
Signed-off-by: Dom Cobley <popcornmix@gmail.com>
---
drivers/gpu/drm/drm_edid.c | 16 +++++++++++++++
drivers/gpu/drm/drm_edid_load.c | 36 +++++++++++++++++++++++++++++++++
include/drm/drm_edid.h | 2 ++
3 files changed, 54 insertions(+)
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -2091,6 +2091,22 @@ static struct edid *edid_filter_invalid_
return new;
}
+/*
+ * add a CTA extension (block) comtaining audio support
+ * fix up the base extension to include the extra
+ * extension and report as digital (required for audio)
+ * and fix up checksums.
+ */
+void drm_edid_add_audio_extension(void *block)
+{
+ struct edid *edid = block;
+ edid->input = DRM_EDID_INPUT_DIGITAL;
+ edid->extensions++;
+ edid->checksum = edid_block_compute_checksum(edid);
+ edid = block + EDID_LENGTH;
+ edid->checksum = edid_block_compute_checksum(edid);
+}
+
#define DDC_SEGMENT_ADDR 0x30
/**
* drm_do_probe_ddc_edid() - get EDID information via I2C
--- a/drivers/gpu/drm/drm_edid_load.c
+++ b/drivers/gpu/drm/drm_edid_load.c
@@ -22,6 +22,9 @@ module_param_string(edid_firmware, edid_
MODULE_PARM_DESC(edid_firmware, "Do not probe monitor, use specified EDID blob "
"from built-in data or /lib/firmware instead. ");
+static bool support_audio;
+module_param(support_audio, bool, 0400);
+
/* Use only for backward compatibility with drm_kms_helper.edid_firmware */
int __drm_set_edid_firmware_path(const char *path)
{
@@ -167,12 +170,29 @@ static int edid_size(const u8 *edid, int
return (edid[0x7e] + 1) * EDID_LENGTH;
}
+/* Minimal edid extension block that reports basic audio support */
+static const u8 generic_edid_audio[] = {
+ 0x02, /* CTA extension block */
+ 0x03, /* version */
+ 0x12, /* 18 bytes are valid */
+ 0xc0, /* underscan | basic audio */
+ 0x23, /* Audio Data Block, length 3 */
+ 0x09, /* Linear PCM, 2 channel */
+ 0x07, /* Supported sample rates (kHz): 48 44.1 32 */
+ 0x07, /* Supported sample sizes (bits): 24 20 16 */
+ 0x83, /* Speaker Allocation Data Block, length 3 */
+ 0x01, 0x00, 0x00, /* FL/FR */
+ 0x65, /* Vendor-Specific Data Block, length 3 */
+ 0x03, 0x0c, 0x00, 0x00, 0x00, /* HDMI PA:0.0.0.0 */
+};
+
static void *edid_load(struct drm_connector *connector, const char *name,
const char *connector_name)
{
const struct firmware *fw = NULL;
const u8 *fwdata;
u8 *edid;
+ u8 *fwdata2 = NULL;
int fwsize, builtin;
int i, valid_extensions = 0;
bool print_bad_edid = !connector->bad_edid_counter || drm_debug_enabled(DRM_UT_KMS);
@@ -181,6 +201,20 @@ static void *edid_load(struct drm_connec
if (builtin >= 0) {
fwdata = generic_edid[builtin];
fwsize = sizeof(generic_edid[builtin]);
+ if (support_audio) {
+ fwdata2 = kzalloc(fwsize + EDID_LENGTH, GFP_KERNEL);
+ if (!fwdata2) {
+ drm_err(connector->dev,
+ "[CONNECTOR:%d:%s] Failed to allocate combined EDID firmware \"%s\"\n",
+ connector->base.id, connector->name, name);
+ return ERR_PTR(-ENOMEM);
+ }
+ memcpy(fwdata2, fwdata, fwsize);
+ memcpy(fwdata2 + fwsize, generic_edid_audio, sizeof generic_edid_audio);
+ drm_edid_add_audio_extension(fwdata2);
+ fwsize += EDID_LENGTH;
+ fwdata = fwdata2;
+ }
} else {
struct platform_device *pdev;
int err;
@@ -260,6 +294,8 @@ static void *edid_load(struct drm_connec
out:
release_firmware(fw);
+ if (fwdata2)
+ kfree(fwdata2);
return edid;
}
--- a/include/drm/drm_edid.h
+++ b/include/drm/drm_edid.h
@@ -614,4 +614,6 @@ int drm_edid_connector_update(struct drm
const u8 *drm_find_edid_extension(const struct drm_edid *drm_edid,
int ext_id, int *ext_index);
+void drm_edid_add_audio_extension(void *block);
+
#endif /* __DRM_EDID_H__ */