Skip to content

Commit

Permalink
drm/connector: hdmi: Fix writing Dynamic Range Mastering infoframes
Browse files Browse the repository at this point in the history
The largest infoframe we create is the DRM (Dynamic Range Mastering)
infoframe which is 26 bytes + a 4 byte header, for a total of 30
bytes.

With HDMI_MAX_INFOFRAME_SIZE set to 29 bytes, as it is now, we
allocate too little space to pack a DRM infoframe in
write_device_infoframe(), leading to an ENOSPC return from
hdmi_infoframe_pack(), and never calling the connector's
write_infoframe() vfunc.

Instead of having HDMI_MAX_INFOFRAME_SIZE defined in two places,
replace HDMI_MAX_INFOFRAME_SIZE with HDMI_INFOFRAME_SIZE(MAX) and make
MAX 27 bytes - which is defined by the HDMI specification to be the
largest infoframe payload.

Fixes: f378b77 ("drm/connector: hdmi: Add Infoframes generation")
Fixes: c602e49 ("drm/connector: hdmi: Create Infoframe DebugFS entries")

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
Acked-by: Maxime Ripard <mripard@kernel.org>
Reviewed-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240827163918.48160-1-derek.foreman@collabora.com
Signed-off-by: Maxime Ripard <mripard@kernel.org>
  • Loading branch information
Derek Foreman authored and Maxime Ripard committed Sep 24, 2024
1 parent 440d52b commit f0fa69b
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 6 deletions.
4 changes: 1 addition & 3 deletions drivers/gpu/drm/display/drm_hdmi_state_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -521,8 +521,6 @@ int drm_atomic_helper_connector_hdmi_check(struct drm_connector *connector,
}
EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_check);

#define HDMI_MAX_INFOFRAME_SIZE 29

static int clear_device_infoframe(struct drm_connector *connector,
enum hdmi_infoframe_type type)
{
Expand Down Expand Up @@ -563,7 +561,7 @@ static int write_device_infoframe(struct drm_connector *connector,
{
const struct drm_connector_hdmi_funcs *funcs = connector->hdmi.funcs;
struct drm_device *dev = connector->dev;
u8 buffer[HDMI_MAX_INFOFRAME_SIZE];
u8 buffer[HDMI_INFOFRAME_SIZE(MAX)];
int ret;
int len;

Expand Down
4 changes: 1 addition & 3 deletions drivers/gpu/drm/drm_debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -520,8 +520,6 @@ static const struct file_operations drm_connector_fops = {
.write = connector_write
};

#define HDMI_MAX_INFOFRAME_SIZE 29

static ssize_t
audio_infoframe_read(struct file *filp, char __user *ubuf, size_t count, loff_t *ppos)
{
Expand Down Expand Up @@ -579,7 +577,7 @@ static ssize_t _f##_read_infoframe(struct file *filp, \
struct drm_connector *connector; \
union hdmi_infoframe *frame; \
struct drm_device *dev; \
u8 buf[HDMI_MAX_INFOFRAME_SIZE]; \
u8 buf[HDMI_INFOFRAME_SIZE(MAX)]; \
ssize_t len = 0; \
\
connector = filp->private_data; \
Expand Down
9 changes: 9 additions & 0 deletions include/linux/hdmi.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,15 @@ enum hdmi_infoframe_type {
#define HDMI_DRM_INFOFRAME_SIZE 26
#define HDMI_VENDOR_INFOFRAME_SIZE 4

/*
* HDMI 1.3a table 5-14 states that the largest InfoFrame_length is 27,
* not including the packet header or checksum byte. We include the
* checksum byte in HDMI_INFOFRAME_HEADER_SIZE, so this should allow
* HDMI_INFOFRAME_SIZE(MAX) to be the largest buffer we could ever need
* for any HDMI infoframe.
*/
#define HDMI_MAX_INFOFRAME_SIZE 27

#define HDMI_INFOFRAME_SIZE(type) \
(HDMI_INFOFRAME_HEADER_SIZE + HDMI_ ## type ## _INFOFRAME_SIZE)

Expand Down

0 comments on commit f0fa69b

Please sign in to comment.