diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index 65a8cf1ddfb9..145ace790976 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -2600,6 +2600,50 @@ static int dw_hdmi_connector_atomic_check(struct drm_connector *connector, return 0; } +static int +dw_hdmi_atomic_connector_set_property(struct drm_connector *connector, + struct drm_connector_state *state, + struct drm_property *property, + uint64_t val) +{ + struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, + connector); + const struct dw_hdmi_property_ops *ops = + hdmi->plat_data->property_ops; + + if (ops && ops->set_property) + return ops->set_property(connector, state, property, + val, hdmi->plat_data->phy_data); + else + return -EINVAL; +} + +static int +dw_hdmi_atomic_connector_get_property(struct drm_connector *connector, + const struct drm_connector_state *state, + struct drm_property *property, + uint64_t *val) +{ + struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, + connector); + const struct dw_hdmi_property_ops *ops = + hdmi->plat_data->property_ops; + + if (ops && ops->get_property) + return ops->get_property(connector, state, property, + val, hdmi->plat_data->phy_data); + else + return -EINVAL; +} + +static int +dw_hdmi_connector_set_property(struct drm_connector *connector, + struct drm_property *property, uint64_t val) +{ + return dw_hdmi_atomic_connector_set_property(connector, NULL, + property, val); +} + static void dw_hdmi_connector_force(struct drm_connector *connector) { struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, @@ -2618,8 +2662,11 @@ static const struct drm_connector_funcs dw_hdmi_connector_funcs = { .destroy = drm_connector_cleanup, .force = dw_hdmi_connector_force, .reset = drm_atomic_helper_connector_reset, + .set_property = dw_hdmi_connector_set_property, .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, + .atomic_set_property = dw_hdmi_atomic_connector_set_property, + .atomic_get_property = dw_hdmi_atomic_connector_get_property, }; static const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = { @@ -2628,6 +2675,27 @@ static const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = .atomic_check = dw_hdmi_connector_atomic_check, }; +static void dw_hdmi_attach_properties(struct dw_hdmi *hdmi) +{ + const struct dw_hdmi_property_ops *ops = + hdmi->plat_data->property_ops; + + if (ops && ops->attach_properties) + return ops->attach_properties(&hdmi->connector, + hdmi->version, + hdmi->plat_data->phy_data); +} + +static void dw_hdmi_destroy_properties(struct dw_hdmi *hdmi) +{ + const struct dw_hdmi_property_ops *ops = + hdmi->plat_data->property_ops; + + if (ops && ops->destroy_properties) + return ops->destroy_properties(&hdmi->connector, + hdmi->plat_data->phy_data); +} + static int dw_hdmi_connector_create(struct dw_hdmi *hdmi) { struct drm_connector *connector = &hdmi->connector; @@ -2664,6 +2732,8 @@ static int dw_hdmi_connector_create(struct dw_hdmi *hdmi) drm_connector_attach_encoder(connector, hdmi->bridge.encoder); + dw_hdmi_attach_properties(hdmi); + cec_fill_conn_info_from_drm(&conn_info, connector); notifier = cec_notifier_conn_register(hdmi->dev, NULL, &conn_info); @@ -3628,6 +3698,8 @@ void dw_hdmi_remove(struct dw_hdmi *hdmi) /* Disable all interrupts */ hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0); + dw_hdmi_destroy_properties(hdmi); + clk_disable_unprepare(hdmi->iahb_clk); clk_disable_unprepare(hdmi->isfr_clk); if (hdmi->cec_clk) diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h index 8b8d73a58474..204fbf4615ac 100644 --- a/include/drm/bridge/dw_hdmi.h +++ b/include/drm/bridge/dw_hdmi.h @@ -6,6 +6,7 @@ #ifndef __DW_HDMI__ #define __DW_HDMI__ +#include #include struct drm_display_info; @@ -130,6 +131,24 @@ struct dw_hdmi_phy_ops { void (*setup_hpd)(struct dw_hdmi *hdmi, void *data); }; +struct dw_hdmi_property_ops { + void (*attach_properties)(struct drm_connector *connector, + int version, + void *data); + void (*destroy_properties)(struct drm_connector *connector, + void *data); + int (*set_property)(struct drm_connector *connector, + struct drm_connector_state *state, + struct drm_property *property, + u64 val, + void *data); + int (*get_property)(struct drm_connector *connector, + const struct drm_connector_state *state, + struct drm_property *property, + u64 *val, + void *data); +}; + struct dw_hdmi_plat_data { struct regmap *regm; @@ -172,6 +191,9 @@ struct dw_hdmi_plat_data { unsigned long (*get_output_bus_format)(void *data); unsigned long (*get_enc_in_encoding)(void *data); unsigned long (*get_enc_out_encoding)(void *data); + + /* Vendor Property support */ + const struct dw_hdmi_property_ops *property_ops; }; struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,