return MODE_OK;
}
-static int drm_bridge_connector_clear_infoframe(struct drm_connector *connector,
- enum hdmi_infoframe_type type)
+static int drm_bridge_connector_clear_avi_infoframe(struct drm_connector *connector)
{
struct drm_bridge_connector *bridge_connector =
to_drm_bridge_connector(connector);
if (!bridge)
return -EINVAL;
- switch (type) {
- case HDMI_INFOFRAME_TYPE_AVI:
- /* required */
- return bridge->funcs->hdmi_clear_avi_infoframe(bridge);
- case HDMI_INFOFRAME_TYPE_VENDOR:
- /* required */
- return bridge->funcs->hdmi_clear_hdmi_infoframe(bridge);
- case HDMI_INFOFRAME_TYPE_AUDIO:
- if (bridge->ops & DRM_BRIDGE_OP_HDMI_AUDIO)
- return bridge->funcs->hdmi_clear_audio_infoframe(bridge);
- break;
- case HDMI_INFOFRAME_TYPE_DRM:
- if (bridge->ops & DRM_BRIDGE_OP_HDMI_HDR_DRM_INFOFRAME)
- return bridge->funcs->hdmi_clear_hdr_drm_infoframe(bridge);
- break;
- case HDMI_INFOFRAME_TYPE_SPD:
- if (bridge->ops & DRM_BRIDGE_OP_HDMI_SPD_INFOFRAME)
- return bridge->funcs->hdmi_clear_spd_infoframe(bridge);
- break;
- }
+ return bridge->funcs->hdmi_clear_avi_infoframe(bridge);
+}
+
+static int drm_bridge_connector_write_avi_infoframe(struct drm_connector *connector,
+ const u8 *buffer, size_t len)
+{
+ struct drm_bridge_connector *bridge_connector =
+ to_drm_bridge_connector(connector);
+ struct drm_bridge *bridge;
+
+ bridge = bridge_connector->bridge_hdmi;
+ if (!bridge)
+ return -EINVAL;
+
+ return bridge->funcs->hdmi_write_avi_infoframe(bridge, buffer, len);
+}
- drm_dbg_driver(connector->dev, "Unsupported HDMI InfoFrame %x\n", type);
+static int drm_bridge_connector_clear_hdmi_infoframe(struct drm_connector *connector)
+{
+ struct drm_bridge_connector *bridge_connector =
+ to_drm_bridge_connector(connector);
+ struct drm_bridge *bridge;
+
+ bridge = bridge_connector->bridge_hdmi;
+ if (!bridge)
+ return -EINVAL;
+
+ return bridge->funcs->hdmi_clear_hdmi_infoframe(bridge);
+}
+
+static int drm_bridge_connector_write_hdmi_infoframe(struct drm_connector *connector,
+ const u8 *buffer, size_t len)
+{
+ struct drm_bridge_connector *bridge_connector =
+ to_drm_bridge_connector(connector);
+ struct drm_bridge *bridge;
+
+ bridge = bridge_connector->bridge_hdmi;
+ if (!bridge)
+ return -EINVAL;
+
+ return bridge->funcs->hdmi_write_hdmi_infoframe(bridge, buffer, len);
+}
+
+static int drm_bridge_connector_clear_audio_infoframe(struct drm_connector *connector)
+{
+ struct drm_bridge_connector *bridge_connector =
+ to_drm_bridge_connector(connector);
+ struct drm_bridge *bridge;
+
+ bridge = bridge_connector->bridge_hdmi;
+ if (!bridge)
+ return -EINVAL;
+
+ if (bridge->ops & DRM_BRIDGE_OP_HDMI_AUDIO)
+ return bridge->funcs->hdmi_clear_audio_infoframe(bridge);
+
+ drm_dbg_driver(connector->dev, "Unsupported HDMI Audio InfoFrame\n");
return 0;
}
-static int drm_bridge_connector_write_infoframe(struct drm_connector *connector,
- enum hdmi_infoframe_type type,
- const u8 *buffer, size_t len)
+static int drm_bridge_connector_write_audio_infoframe(struct drm_connector *connector,
+ const u8 *buffer, size_t len)
{
struct drm_bridge_connector *bridge_connector =
to_drm_bridge_connector(connector);
if (!bridge)
return -EINVAL;
- switch (type) {
- case HDMI_INFOFRAME_TYPE_AVI:
- /* required */
- return bridge->funcs->hdmi_write_avi_infoframe(bridge, buffer, len);
- case HDMI_INFOFRAME_TYPE_VENDOR:
- /* required */
- return bridge->funcs->hdmi_write_hdmi_infoframe(bridge, buffer, len);
- case HDMI_INFOFRAME_TYPE_AUDIO:
- if (bridge->ops & DRM_BRIDGE_OP_HDMI_AUDIO)
- return bridge->funcs->hdmi_write_audio_infoframe(bridge, buffer, len);
- break;
- case HDMI_INFOFRAME_TYPE_DRM:
- if (bridge->ops & DRM_BRIDGE_OP_HDMI_HDR_DRM_INFOFRAME)
- return bridge->funcs->hdmi_write_hdr_drm_infoframe(bridge, buffer, len);
- break;
- case HDMI_INFOFRAME_TYPE_SPD:
- if (bridge->ops & DRM_BRIDGE_OP_HDMI_SPD_INFOFRAME)
- return bridge->funcs->hdmi_write_spd_infoframe(bridge, buffer, len);
- break;
- }
+ if (bridge->ops & DRM_BRIDGE_OP_HDMI_AUDIO)
+ return bridge->funcs->hdmi_write_audio_infoframe(bridge, buffer, len);
+
+ drm_dbg_driver(connector->dev, "Unsupported HDMI Audio InfoFrame\n");
+
+ return 0;
+}
+
+static int drm_bridge_connector_clear_hdr_drm_infoframe(struct drm_connector *connector)
+{
+ struct drm_bridge_connector *bridge_connector =
+ to_drm_bridge_connector(connector);
+ struct drm_bridge *bridge;
+
+ bridge = bridge_connector->bridge_hdmi;
+ if (!bridge)
+ return -EINVAL;
+
+ if (bridge->ops & DRM_BRIDGE_OP_HDMI_HDR_DRM_INFOFRAME)
+ return bridge->funcs->hdmi_clear_hdr_drm_infoframe(bridge);
+
+ drm_dbg_driver(connector->dev, "Unsupported HDMI HDR DRM InfoFrame\n");
+
+ return 0;
+}
+
+static int drm_bridge_connector_write_hdr_drm_infoframe(struct drm_connector *connector,
+ const u8 *buffer, size_t len)
+{
+ struct drm_bridge_connector *bridge_connector =
+ to_drm_bridge_connector(connector);
+ struct drm_bridge *bridge;
+
+ bridge = bridge_connector->bridge_hdmi;
+ if (!bridge)
+ return -EINVAL;
+
+ if (bridge->ops & DRM_BRIDGE_OP_HDMI_HDR_DRM_INFOFRAME)
+ return bridge->funcs->hdmi_write_hdr_drm_infoframe(bridge, buffer, len);
+
+ drm_dbg_driver(connector->dev, "Unsupported HDMI HDR DRM InfoFrame\n");
+
+ return 0;
+}
+
+static int drm_bridge_connector_clear_spd_infoframe(struct drm_connector *connector)
+{
+ struct drm_bridge_connector *bridge_connector =
+ to_drm_bridge_connector(connector);
+ struct drm_bridge *bridge;
+
+ bridge = bridge_connector->bridge_hdmi;
+ if (!bridge)
+ return -EINVAL;
+
+ if (bridge->ops & DRM_BRIDGE_OP_HDMI_SPD_INFOFRAME)
+ return bridge->funcs->hdmi_clear_spd_infoframe(bridge);
+
+ drm_dbg_driver(connector->dev, "Unsupported HDMI SPD InfoFrame\n");
+
+ return 0;
+}
+
+static int drm_bridge_connector_write_spd_infoframe(struct drm_connector *connector,
+ const u8 *buffer, size_t len)
+{
+ struct drm_bridge_connector *bridge_connector =
+ to_drm_bridge_connector(connector);
+ struct drm_bridge *bridge;
+
+ bridge = bridge_connector->bridge_hdmi;
+ if (!bridge)
+ return -EINVAL;
+
+ if (bridge->ops & DRM_BRIDGE_OP_HDMI_SPD_INFOFRAME)
+ return bridge->funcs->hdmi_write_spd_infoframe(bridge, buffer, len);
- drm_dbg_driver(connector->dev, "Unsupported HDMI InfoFrame %x\n", type);
+ drm_dbg_driver(connector->dev, "Unsupported HDMI SPD InfoFrame\n");
return 0;
}
static const struct drm_connector_hdmi_funcs drm_bridge_connector_hdmi_funcs = {
.tmds_char_rate_valid = drm_bridge_connector_tmds_char_rate_valid,
- .clear_infoframe = drm_bridge_connector_clear_infoframe,
- .write_infoframe = drm_bridge_connector_write_infoframe,
.read_edid = drm_bridge_connector_read_edid,
+ .avi = {
+ .clear_infoframe = drm_bridge_connector_clear_avi_infoframe,
+ .write_infoframe = drm_bridge_connector_write_avi_infoframe,
+ },
+ .hdmi = {
+ .clear_infoframe = drm_bridge_connector_clear_hdmi_infoframe,
+ .write_infoframe = drm_bridge_connector_write_hdmi_infoframe,
+ },
+ .audio = {
+ .clear_infoframe = drm_bridge_connector_clear_audio_infoframe,
+ .write_infoframe = drm_bridge_connector_write_audio_infoframe,
+ },
+ .hdr_drm = {
+ .clear_infoframe = drm_bridge_connector_clear_hdr_drm_infoframe,
+ .write_infoframe = drm_bridge_connector_write_hdr_drm_infoframe,
+ },
+ .spd = {
+ .clear_infoframe = drm_bridge_connector_clear_spd_infoframe,
+ .write_infoframe = drm_bridge_connector_write_spd_infoframe,
+ },
};
static int drm_bridge_connector_audio_startup(struct drm_connector *connector)
}
EXPORT_SYMBOL(drm_hdmi_connector_mode_valid);
-static int clear_device_infoframe(struct drm_connector *connector,
- enum hdmi_infoframe_type type)
+static int clear_infoframe(struct drm_connector *connector,
+ const struct drm_connector_infoframe_funcs *funcs,
+ const char *type)
{
- const struct drm_connector_hdmi_funcs *funcs = connector->hdmi.funcs;
struct drm_device *dev = connector->dev;
int ret;
- drm_dbg_kms(dev, "Clearing infoframe type 0x%x\n", type);
+ drm_dbg_kms(dev, "Clearing %s InfoFrame\n", type);
- if (!funcs || !funcs->clear_infoframe) {
+ if (!funcs->clear_infoframe) {
drm_dbg_kms(dev, "Function not implemented, bailing.\n");
return 0;
}
- ret = funcs->clear_infoframe(connector, type);
+ ret = funcs->clear_infoframe(connector);
if (ret) {
drm_dbg_kms(dev, "Call failed: %d\n", ret);
return ret;
return 0;
}
-static int clear_infoframe(struct drm_connector *connector,
- struct drm_connector_hdmi_infoframe *old_frame)
-{
- int ret;
-
- ret = clear_device_infoframe(connector, old_frame->data.any.type);
- if (ret)
- return ret;
-
- return 0;
-}
-
-static int write_device_infoframe(struct drm_connector *connector,
- union hdmi_infoframe *frame)
+static int write_infoframe(struct drm_connector *connector,
+ const struct drm_connector_infoframe_funcs *funcs,
+ const char *type,
+ struct drm_connector_hdmi_infoframe *new_frame)
{
- const struct drm_connector_hdmi_funcs *funcs = connector->hdmi.funcs;
struct drm_device *dev = connector->dev;
u8 buffer[HDMI_INFOFRAME_SIZE(MAX)];
int ret;
int len;
- drm_dbg_kms(dev, "Writing infoframe type %x\n", frame->any.type);
+ drm_dbg_kms(dev, "Writing %s InfoFrame\n", type);
- if (!funcs || !funcs->write_infoframe) {
+ if (!funcs->write_infoframe) {
drm_dbg_kms(dev, "Function not implemented, bailing.\n");
- return -EINVAL;
+ return 0; /* XXX: temporal until we stop generating unsupported frames */
}
- len = hdmi_infoframe_pack(frame, buffer, sizeof(buffer));
+ len = hdmi_infoframe_pack(&new_frame->data, buffer, sizeof(buffer));
if (len < 0)
return len;
- ret = funcs->write_infoframe(connector, frame->any.type, buffer, len);
+ ret = funcs->write_infoframe(connector, buffer, len);
if (ret) {
drm_dbg_kms(dev, "Call failed: %d\n", ret);
return ret;
return 0;
}
-static int write_infoframe(struct drm_connector *connector,
- struct drm_connector_hdmi_infoframe *new_frame)
-{
- int ret;
-
- ret = write_device_infoframe(connector, &new_frame->data);
- if (ret)
- return ret;
-
- return 0;
-}
-
static int write_or_clear_infoframe(struct drm_connector *connector,
+ const struct drm_connector_infoframe_funcs *funcs,
+ const char *type,
struct drm_connector_hdmi_infoframe *old_frame,
struct drm_connector_hdmi_infoframe *new_frame)
{
if (new_frame->set)
- return write_infoframe(connector, new_frame);
+ return write_infoframe(connector, funcs, type, new_frame);
if (old_frame->set && !new_frame->set)
- return clear_infoframe(connector, old_frame);
+ return clear_infoframe(connector, funcs, type);
return 0;
}
int drm_atomic_helper_connector_hdmi_update_infoframes(struct drm_connector *connector,
struct drm_atomic_state *state)
{
+ const struct drm_connector_hdmi_funcs *funcs = connector->hdmi.funcs;
struct drm_connector_state *old_conn_state =
drm_atomic_get_old_connector_state(state, connector);
struct drm_connector_state *new_conn_state =
if (!info->is_hdmi)
return 0;
+ if (!funcs) {
+ drm_dbg_kms(connector->dev, "Function not implemented, bailing.\n");
+ return -EINVAL;
+ }
+
mutex_lock(&connector->hdmi.infoframes.lock);
ret = write_or_clear_infoframe(connector,
+ &funcs->avi, "AVI",
&old_conn_state->hdmi.infoframes.avi,
&new_conn_state->hdmi.infoframes.avi);
if (ret)
if (connector->hdmi.infoframes.audio.set) {
ret = write_infoframe(connector,
+ &funcs->audio, "Audio",
&connector->hdmi.infoframes.audio);
if (ret)
goto out;
}
ret = write_or_clear_infoframe(connector,
+ &funcs->hdr_drm, "HDR DRM",
&old_conn_state->hdmi.infoframes.hdr_drm,
&new_conn_state->hdmi.infoframes.hdr_drm);
if (ret)
goto out;
ret = write_or_clear_infoframe(connector,
+ &funcs->spd, "SPD",
&old_conn_state->hdmi.infoframes.spd,
&new_conn_state->hdmi.infoframes.spd);
if (ret)
if (info->has_hdmi_infoframe) {
ret = write_or_clear_infoframe(connector,
+ &funcs->hdmi, "HDMI-VS",
&old_conn_state->hdmi.infoframes.hdmi,
&new_conn_state->hdmi.infoframes.hdmi);
if (ret)
drm_atomic_helper_connector_hdmi_update_audio_infoframe(struct drm_connector *connector,
struct hdmi_audio_infoframe *frame)
{
+ const struct drm_connector_hdmi_funcs *funcs = connector->hdmi.funcs;
struct drm_connector_hdmi_infoframe *infoframe =
&connector->hdmi.infoframes.audio;
struct drm_display_info *info = &connector->display_info;
if (!info->is_hdmi)
return 0;
+ if (!funcs) {
+ drm_dbg_kms(connector->dev, "Function not implemented, bailing.\n");
+ return -EINVAL;
+ }
+
mutex_lock(&connector->hdmi.infoframes.lock);
memcpy(&infoframe->data, frame, sizeof(infoframe->data));
infoframe->set = true;
- ret = write_infoframe(connector, infoframe);
+ ret = write_infoframe(connector, &funcs->audio, "Audio", infoframe);
mutex_unlock(&connector->hdmi.infoframes.lock);
int
drm_atomic_helper_connector_hdmi_clear_audio_infoframe(struct drm_connector *connector)
{
+ const struct drm_connector_hdmi_funcs *funcs = connector->hdmi.funcs;
struct drm_connector_hdmi_infoframe *infoframe =
&connector->hdmi.infoframes.audio;
struct drm_display_info *info = &connector->display_info;
if (!info->is_hdmi)
return 0;
+ if (!funcs) {
+ drm_dbg_kms(connector->dev, "Function not implemented, bailing.\n");
+ return -EINVAL;
+ }
+
mutex_lock(&connector->hdmi.infoframes.lock);
infoframe->set = false;
- ret = clear_infoframe(connector, infoframe);
+ ret = clear_infoframe(connector, &funcs->audio, "Audio");
memset(&infoframe->data, 0, sizeof(infoframe->data));
if (!(max_bpc == 8 || max_bpc == 10 || max_bpc == 12))
return -EINVAL;
- if (!hdmi_funcs->clear_infoframe ||
- !hdmi_funcs->write_infoframe)
+ if (!hdmi_funcs->avi.clear_infoframe ||
+ !hdmi_funcs->avi.write_infoframe ||
+ !hdmi_funcs->hdmi.clear_infoframe ||
+ !hdmi_funcs->hdmi.write_infoframe)
return -EINVAL;
ret = drmm_connector_init(dev, connector, funcs, connector_type, ddc);
#define drm_connector_to_sun4i_hdmi(c) \
container_of_const(c, struct sun4i_hdmi, connector)
-static int sun4i_hdmi_clear_infoframe(struct drm_connector *connector,
- enum hdmi_infoframe_type type)
+static int sun4i_hdmi_clear_avi_infoframe(struct drm_connector *connector)
{
drm_warn_once(connector->dev, "clearing of AVI infoframe is not implemented\n");
return 0;
}
-static int sun4i_hdmi_write_infoframe(struct drm_connector *connector,
- enum hdmi_infoframe_type type,
- const u8 *buffer, size_t len)
+static int sun4i_hdmi_write_avi_infoframe(struct drm_connector *connector,
+ const u8 *buffer, size_t len)
{
struct sun4i_hdmi *hdmi = drm_connector_to_sun4i_hdmi(connector);
int i;
- if (type != HDMI_INFOFRAME_TYPE_AVI) {
- drm_err(connector->dev,
- "Unsupported infoframe type: %u\n", type);
- return 0;
- }
-
for (i = 0; i < len; i++)
writeb(buffer[i], hdmi->base + SUN4I_HDMI_AVI_INFOFRAME_REG(i));
}
+static int sun4i_hdmi_clear_hdmi_infoframe(struct drm_connector *connector)
+{
+ drm_warn_once(connector->dev, "HDMI VSI not implemented\n");
+
+ return 0;
+}
+
+static int sun4i_hdmi_write_hdmi_infoframe(struct drm_connector *connector,
+ const u8 *buffer, size_t len)
+{
+ drm_warn_once(connector->dev, "HDMI VSI not implemented\n");
+
+ return 0;
+}
+
static void sun4i_hdmi_disable(struct drm_encoder *encoder,
struct drm_atomic_state *state)
{
static const struct drm_connector_hdmi_funcs sun4i_hdmi_hdmi_connector_funcs = {
.tmds_char_rate_valid = sun4i_hdmi_connector_clock_valid,
- .clear_infoframe = sun4i_hdmi_clear_infoframe,
- .write_infoframe = sun4i_hdmi_write_infoframe,
+ .avi = {
+ .clear_infoframe = sun4i_hdmi_clear_avi_infoframe,
+ .write_infoframe = sun4i_hdmi_write_avi_infoframe,
+ },
+ .hdmi = {
+ .clear_infoframe = sun4i_hdmi_clear_hdmi_infoframe,
+ .write_infoframe = sun4i_hdmi_write_hdmi_infoframe,
+ },
};
static const struct drm_connector_helper_funcs sun4i_hdmi_connector_helper_funcs = {
struct i2c_adapter ddc;
};
-static int accept_infoframe_clear_infoframe(struct drm_connector *connector,
- enum hdmi_infoframe_type type)
+static int accept_infoframe_clear_infoframe(struct drm_connector *connector)
{
return 0;
}
static int accept_infoframe_write_infoframe(struct drm_connector *connector,
- enum hdmi_infoframe_type type,
const u8 *buffer, size_t len)
{
return 0;
}
static const struct drm_connector_hdmi_funcs dummy_hdmi_funcs = {
- .clear_infoframe = accept_infoframe_clear_infoframe,
- .write_infoframe = accept_infoframe_write_infoframe,
+ .avi = {
+ .clear_infoframe = accept_infoframe_clear_infoframe,
+ .write_infoframe = accept_infoframe_write_infoframe,
+ },
+ .hdmi = {
+ .clear_infoframe = accept_infoframe_clear_infoframe,
+ .write_infoframe = accept_infoframe_write_infoframe,
+ },
};
static const struct drm_connector_funcs dummy_funcs = {
return ret;
}
-static int accept_infoframe_clear_infoframe(struct drm_connector *connector,
- enum hdmi_infoframe_type type)
+static int accept_infoframe_clear_infoframe(struct drm_connector *connector)
{
return 0;
}
static int accept_infoframe_write_infoframe(struct drm_connector *connector,
- enum hdmi_infoframe_type type,
const u8 *buffer, size_t len)
{
return 0;
}
static const struct drm_connector_hdmi_funcs dummy_connector_hdmi_funcs = {
- .clear_infoframe = accept_infoframe_clear_infoframe,
- .write_infoframe = accept_infoframe_write_infoframe,
+ .avi = {
+ .clear_infoframe = accept_infoframe_clear_infoframe,
+ .write_infoframe = accept_infoframe_write_infoframe,
+ },
+ .hdmi = {
+ .clear_infoframe = accept_infoframe_clear_infoframe,
+ .write_infoframe = accept_infoframe_write_infoframe,
+ },
};
static enum drm_mode_status
static const struct drm_connector_hdmi_funcs reject_connector_hdmi_funcs = {
.tmds_char_rate_valid = reject_connector_tmds_char_rate_valid,
- .clear_infoframe = accept_infoframe_clear_infoframe,
- .write_infoframe = accept_infoframe_write_infoframe,
+ .avi = {
+ .clear_infoframe = accept_infoframe_clear_infoframe,
+ .write_infoframe = accept_infoframe_write_infoframe,
+ },
+ .hdmi = {
+ .clear_infoframe = accept_infoframe_clear_infoframe,
+ .write_infoframe = accept_infoframe_write_infoframe,
+ },
};
static enum drm_mode_status
static const struct drm_connector_hdmi_funcs reject_100mhz_connector_hdmi_funcs = {
.tmds_char_rate_valid = reject_100mhz_connector_tmds_char_rate_valid,
- .clear_infoframe = accept_infoframe_clear_infoframe,
- .write_infoframe = accept_infoframe_write_infoframe,
+ .avi = {
+ .clear_infoframe = accept_infoframe_clear_infoframe,
+ .write_infoframe = accept_infoframe_write_infoframe,
+ },
+ .hdmi = {
+ .clear_infoframe = accept_infoframe_clear_infoframe,
+ .write_infoframe = accept_infoframe_write_infoframe,
+ },
};
static int dummy_connector_get_modes(struct drm_connector *connector)
drm_modeset_acquire_fini(&ctx);
}
-static int reject_avi_infoframe_write_infoframe(struct drm_connector *connector,
- enum hdmi_infoframe_type type,
- const u8 *buffer, size_t len)
+static int reject_infoframe_write_infoframe(struct drm_connector *connector,
+ const u8 *buffer, size_t len)
{
- if (type == HDMI_INFOFRAME_TYPE_AVI)
- return -EOPNOTSUPP;
-
- return 0;
+ return -EOPNOTSUPP;
}
static const struct drm_connector_hdmi_funcs reject_avi_infoframe_hdmi_funcs = {
- .clear_infoframe = accept_infoframe_clear_infoframe,
- .write_infoframe = reject_avi_infoframe_write_infoframe,
+ .avi = {
+ .clear_infoframe = accept_infoframe_clear_infoframe,
+ .write_infoframe = reject_infoframe_write_infoframe,
+ },
+ .hdmi = {
+ .clear_infoframe = accept_infoframe_clear_infoframe,
+ .write_infoframe = accept_infoframe_write_infoframe,
+ },
};
/*
drm_modeset_acquire_fini(&ctx);
}
-static int reject_hdr_infoframe_write_infoframe(struct drm_connector *connector,
- enum hdmi_infoframe_type type,
- const u8 *buffer, size_t len)
-{
- if (type == HDMI_INFOFRAME_TYPE_DRM)
- return -EOPNOTSUPP;
-
- return 0;
-}
-
static const struct drm_connector_hdmi_funcs reject_hdr_infoframe_hdmi_funcs = {
- .clear_infoframe = accept_infoframe_clear_infoframe,
- .write_infoframe = reject_hdr_infoframe_write_infoframe,
+ .avi = {
+ .clear_infoframe = accept_infoframe_clear_infoframe,
+ .write_infoframe = accept_infoframe_write_infoframe,
+ },
+ .hdmi = {
+ .clear_infoframe = accept_infoframe_clear_infoframe,
+ .write_infoframe = accept_infoframe_write_infoframe,
+ },
+ .hdr_drm = {
+ .clear_infoframe = accept_infoframe_clear_infoframe,
+ .write_infoframe = reject_infoframe_write_infoframe,
+ },
};
/*
drm_modeset_acquire_fini(&ctx);
}
-static int reject_audio_infoframe_write_infoframe(struct drm_connector *connector,
- enum hdmi_infoframe_type type,
- const u8 *buffer, size_t len)
-{
- if (type == HDMI_INFOFRAME_TYPE_AUDIO)
- return -EOPNOTSUPP;
-
- return 0;
-}
-
static const struct drm_connector_hdmi_funcs reject_audio_infoframe_hdmi_funcs = {
- .clear_infoframe = accept_infoframe_clear_infoframe,
- .write_infoframe = reject_audio_infoframe_write_infoframe,
+ .avi = {
+ .clear_infoframe = accept_infoframe_clear_infoframe,
+ .write_infoframe = accept_infoframe_write_infoframe,
+ },
+ .hdmi = {
+ .clear_infoframe = accept_infoframe_clear_infoframe,
+ .write_infoframe = accept_infoframe_write_infoframe,
+ },
+ .audio = {
+ .clear_infoframe = accept_infoframe_clear_infoframe,
+ .write_infoframe = reject_infoframe_write_infoframe,
+ },
};
/*
return ret;
}
+static int vc4_hdmi_clear_avi_infoframe(struct drm_connector *connector)
+{
+ return vc4_hdmi_clear_infoframe(connector, HDMI_INFOFRAME_TYPE_AVI);
+}
+
+static int vc4_hdmi_clear_hdmi_infoframe(struct drm_connector *connector)
+{
+ return vc4_hdmi_clear_infoframe(connector, HDMI_INFOFRAME_TYPE_VENDOR);
+}
+
+static int vc4_hdmi_clear_audio_infoframe(struct drm_connector *connector)
+{
+ return vc4_hdmi_clear_infoframe(connector, HDMI_INFOFRAME_TYPE_AUDIO);
+}
+
+static int vc4_hdmi_clear_hdr_drm_infoframe(struct drm_connector *connector)
+{
+ return vc4_hdmi_clear_infoframe(connector, HDMI_INFOFRAME_TYPE_DRM);
+}
+
+static int vc4_hdmi_clear_spd_infoframe(struct drm_connector *connector)
+{
+ return vc4_hdmi_clear_infoframe(connector, HDMI_INFOFRAME_TYPE_SPD);
+}
+
+static int vc4_hdmi_write_avi_infoframe(struct drm_connector *connector,
+ const u8 *buffer, size_t len)
+{
+ return vc4_hdmi_write_infoframe(connector, HDMI_INFOFRAME_TYPE_AVI,
+ buffer, len);
+}
+
+static int vc4_hdmi_write_hdmi_infoframe(struct drm_connector *connector,
+ const u8 *buffer, size_t len)
+{
+ return vc4_hdmi_write_infoframe(connector, HDMI_INFOFRAME_TYPE_VENDOR,
+ buffer, len);
+}
+
+static int vc4_hdmi_write_audio_infoframe(struct drm_connector *connector,
+ const u8 *buffer, size_t len)
+{
+ return vc4_hdmi_write_infoframe(connector, HDMI_INFOFRAME_TYPE_AUDIO,
+ buffer, len);
+}
+
+static int vc4_hdmi_write_hdr_drm_infoframe(struct drm_connector *connector,
+ const u8 *buffer, size_t len)
+{
+ return vc4_hdmi_write_infoframe(connector, HDMI_INFOFRAME_TYPE_DRM,
+ buffer, len);
+}
+
+static int vc4_hdmi_write_spd_infoframe(struct drm_connector *connector,
+ const u8 *buffer, size_t len)
+{
+ return vc4_hdmi_write_infoframe(connector, HDMI_INFOFRAME_TYPE_SPD,
+ buffer, len);
+}
+
#define SCRAMBLING_POLLING_DELAY_MS 1000
static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder)
static const struct drm_connector_hdmi_funcs vc4_hdmi_hdmi_connector_funcs = {
.tmds_char_rate_valid = vc4_hdmi_connector_clock_valid,
- .clear_infoframe = vc4_hdmi_clear_infoframe,
- .write_infoframe = vc4_hdmi_write_infoframe,
+ .avi = {
+ .clear_infoframe = vc4_hdmi_clear_avi_infoframe,
+ .write_infoframe = vc4_hdmi_write_avi_infoframe,
+ },
+ .hdmi = {
+ .clear_infoframe = vc4_hdmi_clear_hdmi_infoframe,
+ .write_infoframe = vc4_hdmi_write_hdmi_infoframe,
+ },
+ .audio = {
+ .clear_infoframe = vc4_hdmi_clear_audio_infoframe,
+ .write_infoframe = vc4_hdmi_write_audio_infoframe,
+ },
+ .hdr_drm = {
+ .clear_infoframe = vc4_hdmi_clear_hdr_drm_infoframe,
+ .write_infoframe = vc4_hdmi_write_hdr_drm_infoframe,
+ },
+ .spd = {
+ .clear_infoframe = vc4_hdmi_clear_spd_infoframe,
+ .write_infoframe = vc4_hdmi_write_spd_infoframe,
+ },
};
#define WIFI_2_4GHz_CH1_MIN_FREQ 2400000000ULL
};
/**
- * struct drm_connector_hdmi_funcs - drm_hdmi_connector control functions
+ * struct drm_connector_infoframe_funcs - InfoFrame-related functions
*/
-struct drm_connector_hdmi_funcs {
- /**
- * @tmds_char_rate_valid:
- *
- * This callback is invoked at atomic_check time to figure out
- * whether a particular TMDS character rate is supported by the
- * driver.
- *
- * The @tmds_char_rate_valid callback is optional.
- *
- * Returns:
- *
- * Either &drm_mode_status.MODE_OK or one of the failure reasons
- * in &enum drm_mode_status.
- */
- enum drm_mode_status
- (*tmds_char_rate_valid)(const struct drm_connector *connector,
- const struct drm_display_mode *mode,
- unsigned long long tmds_rate);
-
+struct drm_connector_infoframe_funcs {
/**
* @clear_infoframe:
*
* This callback is invoked through
* @drm_atomic_helper_connector_hdmi_update_infoframes during a
* commit to clear the infoframes into the hardware. It will be
- * called multiple times, once for every disabled infoframe
- * type.
+ * called once for each frame type to be disabled.
*
- * The @clear_infoframe callback is mandatory.
+ * The @clear_infoframe callback is mandatory for AVI and HDMI-VS
+ * InfoFrame types.
*
* Returns:
* 0 on success, a negative error code otherwise
*/
- int (*clear_infoframe)(struct drm_connector *connector,
- enum hdmi_infoframe_type type);
+ int (*clear_infoframe)(struct drm_connector *connector);
/**
* @write_infoframe:
* This callback is invoked through
* @drm_atomic_helper_connector_hdmi_update_infoframes during a
* commit to program the infoframes into the hardware. It will
- * be called multiple times, once for every updated infoframe
- * type.
+ * be called for every updated infoframe type.
*
- * The @write_infoframe callback is mandatory.
+ * The @write_infoframe callback is mandatory for AVI and HDMI-VS
+ * InfoFrame types.
*
* Returns:
* 0 on success, a negative error code otherwise
*/
int (*write_infoframe)(struct drm_connector *connector,
- enum hdmi_infoframe_type type,
const u8 *buffer, size_t len);
+};
+
+/**
+ * struct drm_connector_hdmi_funcs - drm_hdmi_connector control functions
+ */
+struct drm_connector_hdmi_funcs {
+ /**
+ * @tmds_char_rate_valid:
+ *
+ * This callback is invoked at atomic_check time to figure out
+ * whether a particular TMDS character rate is supported by the
+ * driver.
+ *
+ * The @tmds_char_rate_valid callback is optional.
+ *
+ * Returns:
+ *
+ * Either &drm_mode_status.MODE_OK or one of the failure reasons
+ * in &enum drm_mode_status.
+ */
+ enum drm_mode_status
+ (*tmds_char_rate_valid)(const struct drm_connector *connector,
+ const struct drm_display_mode *mode,
+ unsigned long long tmds_rate);
+
/**
* @read_edid:
*
* Valid EDID on success, NULL in case of failure.
*/
const struct drm_edid *(*read_edid)(struct drm_connector *connector);
+
+ /**
+ * @avi:
+ *
+ * Set of callbacks for handling the AVI InfoFrame. These callbacks are
+ * mandatory.
+ */
+ struct drm_connector_infoframe_funcs avi;
+
+ /**
+ * @hdmi:
+ *
+ * Set of callbacks for handling the HDMI Vendor-Specific InfoFrame.
+ * These callbacks are mandatory.
+ */
+ struct drm_connector_infoframe_funcs hdmi;
+
+ /**
+ * @audio:
+ *
+ * Set of callbacks for handling the Audio InfoFrame. These callbacks
+ * are optional, but they are required for drivers which use
+ * drm_atomic_helper_connector_hdmi_update_audio_infoframe().
+ */
+ struct drm_connector_infoframe_funcs audio;
+
+ /**
+ * @hdr_drm:
+ *
+ * Set of callbacks for handling the HDR DRM InfoFrame. These callbacks
+ * are mandatory if HDR output is to be supported.
+ */
+ struct drm_connector_infoframe_funcs hdr_drm;
+
+ /**
+ * @spd:
+ *
+ * Set of callbacks for handling the SPD InfoFrame. These callbacks are
+ * optional.
+ */
+ struct drm_connector_infoframe_funcs spd;
};
/**