Skip to content

Commit

Permalink
drm/connector: hdmi: Add support for output format
Browse files Browse the repository at this point in the history
Just like BPC, we'll add support for automatic selection of the output
format for HDMI connectors.

Let's add the needed defaults and fields for now.

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20240527-kms-hdmi-connector-state-v15-7-c5af16c3aae2@kernel.org
Signed-off-by: Maxime Ripard <mripard@kernel.org>
  • Loading branch information
Maxime Ripard committed May 28, 2024
1 parent eb66d34 commit 948f01d
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 6 deletions.
3 changes: 2 additions & 1 deletion drivers/gpu/drm/display/drm_hdmi_state_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ int drm_atomic_helper_connector_hdmi_check(struct drm_connector *connector,
struct drm_connector_state *new_conn_state =
drm_atomic_get_new_connector_state(state, connector);

if (old_conn_state->hdmi.output_bpc != new_conn_state->hdmi.output_bpc) {
if (old_conn_state->hdmi.output_bpc != new_conn_state->hdmi.output_bpc ||
old_conn_state->hdmi.output_format != new_conn_state->hdmi.output_format) {
struct drm_crtc *crtc = new_conn_state->crtc;
struct drm_crtc_state *crtc_state;

Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/drm_atomic.c
Original file line number Diff line number Diff line change
Expand Up @@ -1146,6 +1146,8 @@ static void drm_atomic_connector_print_state(struct drm_printer *p,
if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA ||
connector->connector_type == DRM_MODE_CONNECTOR_HDMIB) {
drm_printf(p, "\toutput_bpc=%u\n", state->hdmi.output_bpc);
drm_printf(p, "\toutput_format=%s\n",
drm_hdmi_connector_get_output_format_name(state->hdmi.output_format));
}

if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
Expand Down
31 changes: 31 additions & 0 deletions drivers/gpu/drm/drm_connector.c
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,7 @@ EXPORT_SYMBOL(drmm_connector_init);
* @funcs: callbacks for this connector
* @connector_type: user visible type of the connector
* @ddc: optional pointer to the associated ddc adapter
* @supported_formats: Bitmask of @hdmi_colorspace listing supported output formats
* @max_bpc: Maximum bits per char the HDMI connector supports
*
* Initialises a preallocated HDMI connector. Connectors can be
Expand All @@ -477,6 +478,7 @@ int drmm_connector_hdmi_init(struct drm_device *dev,
const struct drm_connector_funcs *funcs,
int connector_type,
struct i2c_adapter *ddc,
unsigned long supported_formats,
unsigned int max_bpc)
{
int ret;
Expand All @@ -485,13 +487,18 @@ int drmm_connector_hdmi_init(struct drm_device *dev,
connector_type == DRM_MODE_CONNECTOR_HDMIB))
return -EINVAL;

if (!supported_formats || !(supported_formats & BIT(HDMI_COLORSPACE_RGB)))
return -EINVAL;

if (!(max_bpc == 8 || max_bpc == 10 || max_bpc == 12))
return -EINVAL;

ret = drmm_connector_init(dev, connector, funcs, connector_type, ddc);
if (ret)
return ret;

connector->hdmi.supported_formats = supported_formats;

/*
* drm_connector_attach_max_bpc_property() requires the
* connector to have a state.
Expand Down Expand Up @@ -1201,6 +1208,30 @@ static const u32 dp_colorspaces =
BIT(DRM_MODE_COLORIMETRY_BT2020_CYCC) |
BIT(DRM_MODE_COLORIMETRY_BT2020_YCC);

static const char * const output_format_str[] = {
[HDMI_COLORSPACE_RGB] = "RGB",
[HDMI_COLORSPACE_YUV420] = "YUV 4:2:0",
[HDMI_COLORSPACE_YUV422] = "YUV 4:2:2",
[HDMI_COLORSPACE_YUV444] = "YUV 4:4:4",
};

/*
* drm_hdmi_connector_get_output_format_name() - Return a string for HDMI connector output format
* @fmt: Output format to compute name of
*
* Returns: the name of the output format, or NULL if the type is not
* valid.
*/
const char *
drm_hdmi_connector_get_output_format_name(enum hdmi_colorspace fmt)
{
if (fmt >= ARRAY_SIZE(output_format_str))
return NULL;

return output_format_str[fmt];
}
EXPORT_SYMBOL(drm_hdmi_connector_get_output_format_name);

/**
* DOC: standard connector properties
*
Expand Down
9 changes: 9 additions & 0 deletions drivers/gpu/drm/tests/drm_connector_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ static void drm_test_connector_hdmi_init_valid(struct kunit *test)
&dummy_funcs,
DRM_MODE_CONNECTOR_HDMIA,
&priv->ddc,
BIT(HDMI_COLORSPACE_RGB),
8);
KUNIT_EXPECT_EQ(test, ret, 0);
}
Expand All @@ -204,6 +205,7 @@ static void drm_test_connector_hdmi_init_null_ddc(struct kunit *test)
&dummy_funcs,
DRM_MODE_CONNECTOR_HDMIA,
NULL,
BIT(HDMI_COLORSPACE_RGB),
8);
KUNIT_EXPECT_EQ(test, ret, 0);
}
Expand All @@ -221,6 +223,7 @@ static void drm_test_connector_hdmi_init_bpc_invalid(struct kunit *test)
&dummy_funcs,
DRM_MODE_CONNECTOR_HDMIA,
&priv->ddc,
BIT(HDMI_COLORSPACE_RGB),
9);
KUNIT_EXPECT_LT(test, ret, 0);
}
Expand All @@ -238,6 +241,7 @@ static void drm_test_connector_hdmi_init_bpc_null(struct kunit *test)
&dummy_funcs,
DRM_MODE_CONNECTOR_HDMIA,
&priv->ddc,
BIT(HDMI_COLORSPACE_RGB),
0);
KUNIT_EXPECT_LT(test, ret, 0);
}
Expand All @@ -260,6 +264,7 @@ static void drm_test_connector_hdmi_init_bpc_8(struct kunit *test)
&dummy_funcs,
DRM_MODE_CONNECTOR_HDMIA,
&priv->ddc,
BIT(HDMI_COLORSPACE_RGB),
8);
KUNIT_EXPECT_EQ(test, ret, 0);

Expand Down Expand Up @@ -298,6 +303,7 @@ static void drm_test_connector_hdmi_init_bpc_10(struct kunit *test)
&dummy_funcs,
DRM_MODE_CONNECTOR_HDMIA,
&priv->ddc,
BIT(HDMI_COLORSPACE_RGB),
10);
KUNIT_EXPECT_EQ(test, ret, 0);

Expand Down Expand Up @@ -336,6 +342,7 @@ static void drm_test_connector_hdmi_init_bpc_12(struct kunit *test)
&dummy_funcs,
DRM_MODE_CONNECTOR_HDMIA,
&priv->ddc,
BIT(HDMI_COLORSPACE_RGB),
12);
KUNIT_EXPECT_EQ(test, ret, 0);

Expand Down Expand Up @@ -370,6 +377,7 @@ static void drm_test_connector_hdmi_init_type_valid(struct kunit *test)
&dummy_funcs,
connector_type,
&priv->ddc,
BIT(HDMI_COLORSPACE_RGB),
8);
KUNIT_EXPECT_EQ(test, ret, 0);
}
Expand Down Expand Up @@ -402,6 +410,7 @@ static void drm_test_connector_hdmi_init_type_invalid(struct kunit *test)
&dummy_funcs,
connector_type,
&priv->ddc,
BIT(HDMI_COLORSPACE_RGB),
8);
KUNIT_EXPECT_LT(test, ret, 0);
}
Expand Down
22 changes: 17 additions & 5 deletions drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ static const struct drm_connector_funcs dummy_connector_funcs = {
static
struct drm_atomic_helper_connector_hdmi_priv *
drm_atomic_helper_connector_hdmi_init(struct kunit *test,
unsigned int formats,
unsigned int max_bpc)
{
struct drm_atomic_helper_connector_hdmi_priv *priv;
Expand Down Expand Up @@ -192,6 +193,7 @@ drm_atomic_helper_connector_hdmi_init(struct kunit *test,
&dummy_connector_funcs,
DRM_MODE_CONNECTOR_HDMIA,
NULL,
formats,
max_bpc);
KUNIT_ASSERT_EQ(test, ret, 0);

Expand Down Expand Up @@ -227,7 +229,9 @@ static void drm_test_check_output_bpc_crtc_mode_changed(struct kunit *test)
struct drm_crtc *crtc;
int ret;

priv = drm_atomic_helper_connector_hdmi_init(test, 10);
priv = drm_atomic_helper_connector_hdmi_init(test,
BIT(HDMI_COLORSPACE_RGB),
10);
KUNIT_ASSERT_NOT_NULL(test, priv);

ctx = drm_kunit_helper_acquire_ctx_alloc(test);
Expand Down Expand Up @@ -294,7 +298,9 @@ static void drm_test_check_output_bpc_crtc_mode_not_changed(struct kunit *test)
struct drm_crtc *crtc;
int ret;

priv = drm_atomic_helper_connector_hdmi_init(test, 10);
priv = drm_atomic_helper_connector_hdmi_init(test,
BIT(HDMI_COLORSPACE_RGB),
10);
KUNIT_ASSERT_NOT_NULL(test, priv);

ctx = drm_kunit_helper_acquire_ctx_alloc(test);
Expand Down Expand Up @@ -363,7 +369,9 @@ static void drm_test_check_bpc_8_value(struct kunit *test)
struct drm_connector_state *conn_state;
struct drm_connector *conn;

priv = drm_atomic_helper_connector_hdmi_init(test, 8);
priv = drm_atomic_helper_connector_hdmi_init(test,
BIT(HDMI_COLORSPACE_RGB),
8);
KUNIT_ASSERT_NOT_NULL(test, priv);

conn = &priv->connector;
Expand All @@ -385,7 +393,9 @@ static void drm_test_check_bpc_10_value(struct kunit *test)
struct drm_connector_state *conn_state;
struct drm_connector *conn;

priv = drm_atomic_helper_connector_hdmi_init(test, 10);
priv = drm_atomic_helper_connector_hdmi_init(test,
BIT(HDMI_COLORSPACE_RGB),
10);
KUNIT_ASSERT_NOT_NULL(test, priv);

conn = &priv->connector;
Expand All @@ -407,7 +417,9 @@ static void drm_test_check_bpc_12_value(struct kunit *test)
struct drm_connector_state *conn_state;
struct drm_connector *conn;

priv = drm_atomic_helper_connector_hdmi_init(test, 12);
priv = drm_atomic_helper_connector_hdmi_init(test,
BIT(HDMI_COLORSPACE_RGB),
12);
KUNIT_ASSERT_NOT_NULL(test, priv);

conn = &priv->connector;
Expand Down
20 changes: 20 additions & 0 deletions include/drm/drm_connector.h
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,9 @@ enum drm_panel_orientation {
DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
};

const char *
drm_hdmi_connector_get_output_format_name(enum hdmi_colorspace fmt);

/**
* struct drm_monitor_range_info - Panel's Monitor range in EDID for
* &drm_display_info
Expand Down Expand Up @@ -1041,6 +1044,11 @@ struct drm_connector_state {
* @output_bpc: Bits per color channel to output.
*/
unsigned int output_bpc;

/**
* @output_format: Pixel format to output in.
*/
enum hdmi_colorspace output_format;
} hdmi;
};

Expand Down Expand Up @@ -1906,6 +1914,17 @@ struct drm_connector {

/** @hdr_sink_metadata: HDR Metadata Information read from sink */
struct hdr_sink_metadata hdr_sink_metadata;

/**
* @hdmi: HDMI-related variable and properties.
*/
struct {
/**
* @supported_formats: Bitmask of @hdmi_colorspace
* supported by the controller.
*/
unsigned long supported_formats;
} hdmi;
};

#define obj_to_connector(x) container_of(x, struct drm_connector, base)
Expand All @@ -1929,6 +1948,7 @@ int drmm_connector_hdmi_init(struct drm_device *dev,
const struct drm_connector_funcs *funcs,
int connector_type,
struct i2c_adapter *ddc,
unsigned long supported_formats,
unsigned int max_bpc);
void drm_connector_attach_edid_property(struct drm_connector *connector);
int drm_connector_register(struct drm_connector *connector);
Expand Down

0 comments on commit 948f01d

Please sign in to comment.