Commit 988dbd25 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'du-next-20210728' of git://linuxtv.org/pinchartl/media into drm-next

- R-Car DU shutdown fixes
- R-Car DU conversion to bridge connector helper
- Misc small fixes
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Link: https://patchwork.freedesktop.org/patch/msgid/YQGHjOSOw2G4+A3x@pendragon.ideasonboard.com
parents 15d27b15 6571a76a
...@@ -1583,7 +1583,6 @@ static int analogix_dp_create_bridge(struct drm_device *drm_dev, ...@@ -1583,7 +1583,6 @@ static int analogix_dp_create_bridge(struct drm_device *drm_dev,
struct analogix_dp_device *dp) struct analogix_dp_device *dp)
{ {
struct drm_bridge *bridge; struct drm_bridge *bridge;
int ret;
bridge = devm_kzalloc(drm_dev->dev, sizeof(*bridge), GFP_KERNEL); bridge = devm_kzalloc(drm_dev->dev, sizeof(*bridge), GFP_KERNEL);
if (!bridge) { if (!bridge) {
...@@ -1596,13 +1595,7 @@ static int analogix_dp_create_bridge(struct drm_device *drm_dev, ...@@ -1596,13 +1595,7 @@ static int analogix_dp_create_bridge(struct drm_device *drm_dev,
bridge->driver_private = dp; bridge->driver_private = dp;
bridge->funcs = &analogix_dp_bridge_funcs; bridge->funcs = &analogix_dp_bridge_funcs;
ret = drm_bridge_attach(dp->encoder, bridge, NULL, 0); return drm_bridge_attach(dp->encoder, bridge, NULL, 0);
if (ret) {
DRM_ERROR("failed to attach drm bridge\n");
return -EINVAL;
}
return 0;
} }
static int analogix_dp_dt_parse_pdata(struct analogix_dp_device *dp) static int analogix_dp_dt_parse_pdata(struct analogix_dp_device *dp)
......
...@@ -1359,12 +1359,9 @@ static int anx7625_bridge_attach(struct drm_bridge *bridge, ...@@ -1359,12 +1359,9 @@ static int anx7625_bridge_attach(struct drm_bridge *bridge,
err = drm_bridge_attach(bridge->encoder, err = drm_bridge_attach(bridge->encoder,
ctx->pdata.panel_bridge, ctx->pdata.panel_bridge,
&ctx->bridge, flags); &ctx->bridge, flags);
if (err) { if (err)
DRM_DEV_ERROR(dev,
"Fail to attach panel bridge: %d\n", err);
return err; return err;
} }
}
ctx->bridge_attached = 1; ctx->bridge_attached = 1;
......
...@@ -143,6 +143,7 @@ struct dw_hdmi_phy_data { ...@@ -143,6 +143,7 @@ struct dw_hdmi_phy_data {
struct dw_hdmi { struct dw_hdmi {
struct drm_connector connector; struct drm_connector connector;
struct drm_bridge bridge; struct drm_bridge bridge;
struct drm_bridge *next_bridge;
unsigned int version; unsigned int version;
...@@ -2775,7 +2776,8 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge, ...@@ -2775,7 +2776,8 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge,
struct dw_hdmi *hdmi = bridge->driver_private; struct dw_hdmi *hdmi = bridge->driver_private;
if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
return 0; return drm_bridge_attach(bridge->encoder, hdmi->next_bridge,
bridge, flags);
return dw_hdmi_connector_create(hdmi); return dw_hdmi_connector_create(hdmi);
} }
...@@ -3160,6 +3162,52 @@ static void dw_hdmi_init_hw(struct dw_hdmi *hdmi) ...@@ -3160,6 +3162,52 @@ static void dw_hdmi_init_hw(struct dw_hdmi *hdmi)
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* Probe/remove API, used from platforms based on the DRM bridge API. * Probe/remove API, used from platforms based on the DRM bridge API.
*/ */
static int dw_hdmi_parse_dt(struct dw_hdmi *hdmi)
{
struct device_node *endpoint;
struct device_node *remote;
if (!hdmi->plat_data->output_port)
return 0;
endpoint = of_graph_get_endpoint_by_regs(hdmi->dev->of_node,
hdmi->plat_data->output_port,
-1);
if (!endpoint) {
/*
* On platforms whose bindings don't make the output port
* mandatory (such as Rockchip) the plat_data->output_port
* field isn't set, so it's safe to make this a fatal error.
*/
dev_err(hdmi->dev, "Missing endpoint in port@%u\n",
hdmi->plat_data->output_port);
return -ENODEV;
}
remote = of_graph_get_remote_port_parent(endpoint);
of_node_put(endpoint);
if (!remote) {
dev_err(hdmi->dev, "Endpoint in port@%u unconnected\n",
hdmi->plat_data->output_port);
return -ENODEV;
}
if (!of_device_is_available(remote)) {
dev_err(hdmi->dev, "port@%u remote device is disabled\n",
hdmi->plat_data->output_port);
of_node_put(remote);
return -ENODEV;
}
hdmi->next_bridge = of_drm_find_bridge(remote);
of_node_put(remote);
if (!hdmi->next_bridge)
return -EPROBE_DEFER;
return 0;
}
struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev, struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
const struct dw_hdmi_plat_data *plat_data) const struct dw_hdmi_plat_data *plat_data)
{ {
...@@ -3196,6 +3244,10 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev, ...@@ -3196,6 +3244,10 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
mutex_init(&hdmi->cec_notifier_mutex); mutex_init(&hdmi->cec_notifier_mutex);
spin_lock_init(&hdmi->audio_lock); spin_lock_init(&hdmi->audio_lock);
ret = dw_hdmi_parse_dt(hdmi);
if (ret < 0)
return ERR_PTR(ret);
ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0); ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
if (ddc_node) { if (ddc_node) {
hdmi->ddc = of_get_i2c_adapter_by_node(ddc_node); hdmi->ddc = of_get_i2c_adapter_by_node(ddc_node);
...@@ -3474,7 +3526,6 @@ struct dw_hdmi *dw_hdmi_bind(struct platform_device *pdev, ...@@ -3474,7 +3526,6 @@ struct dw_hdmi *dw_hdmi_bind(struct platform_device *pdev,
ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL, 0); ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL, 0);
if (ret) { if (ret) {
dw_hdmi_remove(hdmi); dw_hdmi_remove(hdmi);
DRM_ERROR("Failed to initialize bridge with drm\n");
return ERR_PTR(ret); return ERR_PTR(ret);
} }
......
...@@ -1229,15 +1229,7 @@ EXPORT_SYMBOL_GPL(dw_mipi_dsi_remove); ...@@ -1229,15 +1229,7 @@ EXPORT_SYMBOL_GPL(dw_mipi_dsi_remove);
*/ */
int dw_mipi_dsi_bind(struct dw_mipi_dsi *dsi, struct drm_encoder *encoder) int dw_mipi_dsi_bind(struct dw_mipi_dsi *dsi, struct drm_encoder *encoder)
{ {
int ret; return drm_bridge_attach(encoder, &dsi->bridge, NULL, 0);
ret = drm_bridge_attach(encoder, &dsi->bridge, NULL, 0);
if (ret) {
DRM_ERROR("Failed to initialize bridge with drm\n");
return ret;
}
return ret;
} }
EXPORT_SYMBOL_GPL(dw_mipi_dsi_bind); EXPORT_SYMBOL_GPL(dw_mipi_dsi_bind);
......
...@@ -291,7 +291,7 @@ static int tc358768_calc_pll(struct tc358768_priv *priv, ...@@ -291,7 +291,7 @@ static int tc358768_calc_pll(struct tc358768_priv *priv,
const struct drm_display_mode *mode, const struct drm_display_mode *mode,
bool verify_only) bool verify_only)
{ {
const u32 frs_limits[] = { static const u32 frs_limits[] = {
1000000000, 1000000000,
500000000, 500000000,
250000000, 250000000,
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <drm/drm_atomic_state_helper.h> #include <drm/drm_atomic_state_helper.h>
#include <drm/drm_bridge.h> #include <drm/drm_bridge.h>
#include <drm/drm_encoder.h> #include <drm/drm_encoder.h>
#include <drm/drm_print.h>
#include "drm_crtc_internal.h" #include "drm_crtc_internal.h"
...@@ -225,6 +226,15 @@ int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge, ...@@ -225,6 +226,15 @@ int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
bridge->dev = NULL; bridge->dev = NULL;
bridge->encoder = NULL; bridge->encoder = NULL;
list_del(&bridge->chain_node); list_del(&bridge->chain_node);
#ifdef CONFIG_OF
DRM_ERROR("failed to attach bridge %pOF to encoder %s: %d\n",
bridge->of_node, encoder->name, ret);
#else
DRM_ERROR("failed to attach bridge to encoder %s: %d\n",
encoder->name, ret);
#endif
return ret; return ret;
} }
EXPORT_SYMBOL(drm_bridge_attach); EXPORT_SYMBOL(drm_bridge_attach);
......
...@@ -109,12 +109,9 @@ static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data, ...@@ -109,12 +109,9 @@ static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data,
if (dp->ptn_bridge) { if (dp->ptn_bridge) {
ret = drm_bridge_attach(&dp->encoder, dp->ptn_bridge, bridge, ret = drm_bridge_attach(&dp->encoder, dp->ptn_bridge, bridge,
0); 0);
if (ret) { if (ret)
DRM_DEV_ERROR(dp->dev,
"Failed to attach bridge to drm\n");
return ret; return ret;
} }
}
return 0; return 0;
} }
......
...@@ -970,11 +970,8 @@ static int hdmi_create_connector(struct drm_encoder *encoder) ...@@ -970,11 +970,8 @@ static int hdmi_create_connector(struct drm_encoder *encoder)
drm_connector_helper_add(connector, &hdmi_connector_helper_funcs); drm_connector_helper_add(connector, &hdmi_connector_helper_funcs);
drm_connector_attach_encoder(connector, encoder); drm_connector_attach_encoder(connector, encoder);
if (hdata->bridge) { if (hdata->bridge)
ret = drm_bridge_attach(encoder, hdata->bridge, NULL, 0); ret = drm_bridge_attach(encoder, hdata->bridge, NULL, 0);
if (ret)
DRM_DEV_ERROR(hdata->dev, "Failed to attach bridge\n");
}
cec_fill_conn_info_from_drm(&conn_info, connector); cec_fill_conn_info_from_drm(&conn_info, connector);
......
...@@ -769,16 +769,9 @@ static int dsi_bridge_init(struct drm_device *dev, struct dw_dsi *dsi) ...@@ -769,16 +769,9 @@ static int dsi_bridge_init(struct drm_device *dev, struct dw_dsi *dsi)
{ {
struct drm_encoder *encoder = &dsi->encoder; struct drm_encoder *encoder = &dsi->encoder;
struct drm_bridge *bridge = dsi->bridge; struct drm_bridge *bridge = dsi->bridge;
int ret;
/* associate the bridge to dsi encoder */ /* associate the bridge to dsi encoder */
ret = drm_bridge_attach(encoder, bridge, NULL, 0); return drm_bridge_attach(encoder, bridge, NULL, 0);
if (ret) {
DRM_ERROR("failed to attach external bridge\n");
return ret;
}
return 0;
} }
static int dsi_bind(struct device *dev, struct device *master, void *data) static int dsi_bind(struct device *dev, struct device *master, void *data)
......
...@@ -93,11 +93,8 @@ static int dcss_kms_bridge_connector_init(struct dcss_kms_dev *kms) ...@@ -93,11 +93,8 @@ static int dcss_kms_bridge_connector_init(struct dcss_kms_dev *kms)
ret = drm_bridge_attach(encoder, bridge, NULL, ret = drm_bridge_attach(encoder, bridge, NULL,
DRM_BRIDGE_ATTACH_NO_CONNECTOR); DRM_BRIDGE_ATTACH_NO_CONNECTOR);
if (ret < 0) { if (ret < 0)
dev_err(ddev->dev, "Unable to attach bridge %pOF\n",
bridge->of_node);
return ret; return ret;
}
kms->connector = drm_bridge_connector_init(ddev, encoder); kms->connector = drm_bridge_connector_init(ddev, encoder);
if (IS_ERR(kms->connector)) { if (IS_ERR(kms->connector)) {
......
...@@ -465,10 +465,8 @@ static int imx_ldb_register(struct drm_device *drm, ...@@ -465,10 +465,8 @@ static int imx_ldb_register(struct drm_device *drm,
if (imx_ldb_ch->bridge) { if (imx_ldb_ch->bridge) {
ret = drm_bridge_attach(encoder, imx_ldb_ch->bridge, NULL, 0); ret = drm_bridge_attach(encoder, imx_ldb_ch->bridge, NULL, 0);
if (ret) { if (ret)
DRM_ERROR("Failed to initialize bridge with drm\n");
return ret; return ret;
}
} else { } else {
/* /*
* We want to add the connector whenever there is no bridge * We want to add the connector whenever there is no bridge
......
...@@ -294,11 +294,8 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data) ...@@ -294,11 +294,8 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data)
if (imxpd->next_bridge) { if (imxpd->next_bridge) {
ret = drm_bridge_attach(encoder, imxpd->next_bridge, bridge, 0); ret = drm_bridge_attach(encoder, imxpd->next_bridge, bridge, 0);
if (ret < 0) { if (ret < 0)
dev_err(imxpd->dev, "failed to attach bridge: %d\n",
ret);
return ret; return ret;
}
} else { } else {
drm_connector_helper_add(connector, drm_connector_helper_add(connector,
&imx_pd_connector_helper_funcs); &imx_pd_connector_helper_funcs);
......
...@@ -1081,11 +1081,9 @@ static int ingenic_drm_bind(struct device *dev, bool has_components) ...@@ -1081,11 +1081,9 @@ static int ingenic_drm_bind(struct device *dev, bool has_components)
drm_encoder_helper_add(encoder, &ingenic_drm_encoder_helper_funcs); drm_encoder_helper_add(encoder, &ingenic_drm_encoder_helper_funcs);
ret = drm_bridge_attach(encoder, bridge, NULL, 0); ret = drm_bridge_attach(encoder, bridge, NULL, 0);
if (ret) { if (ret)
dev_err(dev, "Unable to attach bridge\n");
return ret; return ret;
} }
}
drm_for_each_encoder(encoder, drm) { drm_for_each_encoder(encoder, drm) {
clone_mask |= BIT(drm_encoder_index(encoder)); clone_mask |= BIT(drm_encoder_index(encoder));
......
...@@ -1441,7 +1441,6 @@ int kmb_dsi_encoder_init(struct drm_device *dev, struct kmb_dsi *kmb_dsi) ...@@ -1441,7 +1441,6 @@ int kmb_dsi_encoder_init(struct drm_device *dev, struct kmb_dsi *kmb_dsi)
ret = drm_bridge_attach(encoder, adv_bridge, NULL, ret = drm_bridge_attach(encoder, adv_bridge, NULL,
DRM_BRIDGE_ATTACH_NO_CONNECTOR); DRM_BRIDGE_ATTACH_NO_CONNECTOR);
if (ret) { if (ret) {
DRM_ERROR("failed to attach bridge to MIPI\n");
drm_encoder_cleanup(encoder); drm_encoder_cleanup(encoder);
return ret; return ret;
} }
......
...@@ -1052,7 +1052,6 @@ static int mcde_dsi_bridge_attach(struct drm_bridge *bridge, ...@@ -1052,7 +1052,6 @@ static int mcde_dsi_bridge_attach(struct drm_bridge *bridge,
{ {
struct mcde_dsi *d = bridge_to_mcde_dsi(bridge); struct mcde_dsi *d = bridge_to_mcde_dsi(bridge);
struct drm_device *drm = bridge->dev; struct drm_device *drm = bridge->dev;
int ret;
if (!drm_core_check_feature(drm, DRIVER_ATOMIC)) { if (!drm_core_check_feature(drm, DRIVER_ATOMIC)) {
dev_err(d->dev, "we need atomic updates\n"); dev_err(d->dev, "we need atomic updates\n");
...@@ -1060,13 +1059,7 @@ static int mcde_dsi_bridge_attach(struct drm_bridge *bridge, ...@@ -1060,13 +1059,7 @@ static int mcde_dsi_bridge_attach(struct drm_bridge *bridge,
} }
/* Attach the DSI bridge to the output (panel etc) bridge */ /* Attach the DSI bridge to the output (panel etc) bridge */
ret = drm_bridge_attach(bridge->encoder, d->bridge_out, bridge, flags); return drm_bridge_attach(bridge->encoder, d->bridge_out, bridge, flags);
if (ret) {
dev_err(d->dev, "failed to attach the DSI bridge\n");
return ret;
}
return 0;
} }
static const struct drm_bridge_funcs mcde_dsi_bridge_funcs = { static const struct drm_bridge_funcs mcde_dsi_bridge_funcs = {
......
...@@ -714,10 +714,8 @@ static int mtk_dpi_bind(struct device *dev, struct device *master, void *data) ...@@ -714,10 +714,8 @@ static int mtk_dpi_bind(struct device *dev, struct device *master, void *data)
ret = drm_bridge_attach(&dpi->encoder, &dpi->bridge, NULL, ret = drm_bridge_attach(&dpi->encoder, &dpi->bridge, NULL,
DRM_BRIDGE_ATTACH_NO_CONNECTOR); DRM_BRIDGE_ATTACH_NO_CONNECTOR);
if (ret) { if (ret)
dev_err(dev, "Failed to attach bridge: %d\n", ret);
goto err_cleanup; goto err_cleanup;
}
dpi->connector = drm_bridge_connector_init(drm_dev, &dpi->encoder); dpi->connector = drm_bridge_connector_init(drm_dev, &dpi->encoder);
if (IS_ERR(dpi->connector)) { if (IS_ERR(dpi->connector)) {
......
...@@ -1293,12 +1293,9 @@ static int mtk_hdmi_bridge_attach(struct drm_bridge *bridge, ...@@ -1293,12 +1293,9 @@ static int mtk_hdmi_bridge_attach(struct drm_bridge *bridge,
if (hdmi->next_bridge) { if (hdmi->next_bridge) {
ret = drm_bridge_attach(bridge->encoder, hdmi->next_bridge, ret = drm_bridge_attach(bridge->encoder, hdmi->next_bridge,
bridge, flags); bridge, flags);
if (ret) { if (ret)
dev_err(hdmi->dev,
"Failed to attach external bridge: %d\n", ret);
return ret; return ret;
} }
}
mtk_cec_set_hpd_event(hdmi->cec_dev, mtk_hdmi_hpd_event, hdmi->dev); mtk_cec_set_hpd_event(hdmi->cec_dev, mtk_hdmi_hpd_event, hdmi->dev);
......
...@@ -290,13 +290,9 @@ static int omap_modeset_init(struct drm_device *dev) ...@@ -290,13 +290,9 @@ static int omap_modeset_init(struct drm_device *dev)
ret = drm_bridge_attach(pipe->encoder, ret = drm_bridge_attach(pipe->encoder,
pipe->output->bridge, NULL, pipe->output->bridge, NULL,
DRM_BRIDGE_ATTACH_NO_CONNECTOR); DRM_BRIDGE_ATTACH_NO_CONNECTOR);
if (ret < 0) { if (ret < 0)
dev_err(priv->dev,
"unable to attach bridge %pOF\n",
pipe->output->bridge->of_node);
return ret; return ret;
} }
}
id = omap_display_id(pipe->output); id = omap_display_id(pipe->output);
pipe->alias_id = id >= 0 ? id : i; pipe->alias_id = id >= 0 ? id : i;
......
...@@ -553,14 +553,20 @@ static int rcar_du_remove(struct platform_device *pdev) ...@@ -553,14 +553,20 @@ static int rcar_du_remove(struct platform_device *pdev)
struct drm_device *ddev = &rcdu->ddev; struct drm_device *ddev = &rcdu->ddev;
drm_dev_unregister(ddev); drm_dev_unregister(ddev);
drm_atomic_helper_shutdown(ddev);
drm_kms_helper_poll_fini(ddev); drm_kms_helper_poll_fini(ddev);
drm_dev_put(ddev);
return 0; return 0;
} }
static void rcar_du_shutdown(struct platform_device *pdev)
{
struct rcar_du_device *rcdu = platform_get_drvdata(pdev);
drm_atomic_helper_shutdown(&rcdu->ddev);
}
static int rcar_du_probe(struct platform_device *pdev) static int rcar_du_probe(struct platform_device *pdev)
{ {
struct rcar_du_device *rcdu; struct rcar_du_device *rcdu;
...@@ -615,6 +621,7 @@ static int rcar_du_probe(struct platform_device *pdev) ...@@ -615,6 +621,7 @@ static int rcar_du_probe(struct platform_device *pdev)
static struct platform_driver rcar_du_platform_driver = { static struct platform_driver rcar_du_platform_driver = {
.probe = rcar_du_probe, .probe = rcar_du_probe,
.remove = rcar_du_remove, .remove = rcar_du_remove,
.shutdown = rcar_du_shutdown,
.driver = { .driver = {
.name = "rcar-du", .name = "rcar-du",
.pm = &rcar_du_pm_ops, .pm = &rcar_du_pm_ops,
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <drm/drm_bridge.h> #include <drm/drm_bridge.h>
#include <drm/drm_bridge_connector.h>
#include <drm/drm_crtc.h> #include <drm/drm_crtc.h>
#include <drm/drm_managed.h> #include <drm/drm_managed.h>
#include <drm/drm_modeset_helper_vtables.h> #include <drm/drm_modeset_helper_vtables.h>
...@@ -53,7 +54,9 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu, ...@@ -53,7 +54,9 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
struct device_node *enc_node) struct device_node *enc_node)
{ {
struct rcar_du_encoder *renc; struct rcar_du_encoder *renc;
struct drm_connector *connector;
struct drm_bridge *bridge; struct drm_bridge *bridge;
int ret;
/* /*
* Locate the DRM bridge from the DT node. For the DPAD outputs, if the * Locate the DRM bridge from the DT node. For the DPAD outputs, if the
...@@ -103,9 +106,22 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu, ...@@ -103,9 +106,22 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
renc->output = output; renc->output = output;
/* /* Attach the bridge to the encoder. */
* Attach the bridge to the encoder. The bridge will create the ret = drm_bridge_attach(&renc->base, bridge, NULL,
* connector. DRM_BRIDGE_ATTACH_NO_CONNECTOR);
*/ if (ret) {
return drm_bridge_attach(&renc->base, bridge, NULL, 0); dev_err(rcdu->dev, "failed to attach bridge for output %u\n",
output);
return ret;
}
/* Create the connector for the chain of bridges. */
connector = drm_bridge_connector_init(&rcdu->ddev, &renc->base);
if (IS_ERR(connector)) {
dev_err(rcdu->dev,
"failed to created connector for output %u\n", output);
return PTR_ERR(connector);
}
return drm_connector_attach_encoder(connector, &renc->base);
} }
...@@ -75,6 +75,7 @@ static int rcar_hdmi_phy_configure(struct dw_hdmi *hdmi, void *data, ...@@ -75,6 +75,7 @@ static int rcar_hdmi_phy_configure(struct dw_hdmi *hdmi, void *data,
} }
static const struct dw_hdmi_plat_data rcar_dw_hdmi_plat_data = { static const struct dw_hdmi_plat_data rcar_dw_hdmi_plat_data = {
.output_port = 1,
.mode_valid = rcar_hdmi_mode_valid, .mode_valid = rcar_hdmi_mode_valid,
.configure_phy = rcar_hdmi_phy_configure, .configure_phy = rcar_hdmi_phy_configure,
}; };
......
...@@ -63,7 +63,6 @@ struct rcar_lvds { ...@@ -63,7 +63,6 @@ struct rcar_lvds {
struct drm_bridge bridge; struct drm_bridge bridge;
struct drm_bridge *next_bridge; struct drm_bridge *next_bridge;
struct drm_connector connector;
struct drm_panel *panel; struct drm_panel *panel;
void __iomem *mmio; void __iomem *mmio;
...@@ -80,73 +79,11 @@ struct rcar_lvds { ...@@ -80,73 +79,11 @@ struct rcar_lvds {
#define bridge_to_rcar_lvds(b) \ #define bridge_to_rcar_lvds(b) \
container_of(b, struct rcar_lvds, bridge) container_of(b, struct rcar_lvds, bridge)
#define connector_to_rcar_lvds(c) \
container_of(c, struct rcar_lvds, connector)
static void rcar_lvds_write(struct rcar_lvds *lvds, u32 reg, u32 data) static void rcar_lvds_write(struct rcar_lvds *lvds, u32 reg, u32 data)
{ {
iowrite32(data, lvds->mmio + reg); iowrite32(data, lvds->mmio + reg);
} }
/* -----------------------------------------------------------------------------
* Connector & Panel
*/
static int rcar_lvds_connector_get_modes(struct drm_connector *connector)
{
struct rcar_lvds *lvds = connector_to_rcar_lvds(connector);
return drm_panel_get_modes(lvds->panel, connector);
}
static int rcar_lvds_connector_atomic_check(struct drm_connector *connector,
struct drm_atomic_state *state)
{
struct rcar_lvds *lvds = connector_to_rcar_lvds(connector);
const struct drm_display_mode *panel_mode;
struct drm_connector_state *conn_state;
struct drm_crtc_state *crtc_state;
conn_state = drm_atomic_get_new_connector_state(state, connector);
if (!conn_state->crtc)
return 0;
if (list_empty(&connector->modes)) {
dev_dbg(lvds->dev, "connector: empty modes list\n");
return -EINVAL;
}
panel_mode = list_first_entry(&connector->modes,
struct drm_display_mode, head);
/* We're not allowed to modify the resolution. */
crtc_state = drm_atomic_get_crtc_state(state, conn_state->crtc);
if (IS_ERR(crtc_state))
return PTR_ERR(crtc_state);
if (crtc_state->mode.hdisplay != panel_mode->hdisplay ||
crtc_state->mode.vdisplay != panel_mode->vdisplay)
return -EINVAL;
/* The flat panel mode is fixed, just copy it to the adjusted mode. */
drm_mode_copy(&crtc_state->adjusted_mode, panel_mode);
return 0;
}
static const struct drm_connector_helper_funcs rcar_lvds_conn_helper_funcs = {
.get_modes = rcar_lvds_connector_get_modes,
.atomic_check = rcar_lvds_connector_atomic_check,
};
static const struct drm_connector_funcs rcar_lvds_conn_funcs = {
.reset = drm_atomic_helper_connector_reset,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = drm_connector_cleanup,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* PLL Setup * PLL Setup
*/ */
...@@ -583,11 +520,6 @@ static void __rcar_lvds_atomic_enable(struct drm_bridge *bridge, ...@@ -583,11 +520,6 @@ static void __rcar_lvds_atomic_enable(struct drm_bridge *bridge,
/* Turn the output on. */ /* Turn the output on. */
lvdcr0 |= LVDCR0_LVRES; lvdcr0 |= LVDCR0_LVRES;
rcar_lvds_write(lvds, LVDCR0, lvdcr0); rcar_lvds_write(lvds, LVDCR0, lvdcr0);
if (lvds->panel) {
drm_panel_prepare(lvds->panel);
drm_panel_enable(lvds->panel);
}
} }
static void rcar_lvds_atomic_enable(struct drm_bridge *bridge, static void rcar_lvds_atomic_enable(struct drm_bridge *bridge,
...@@ -609,11 +541,6 @@ static void rcar_lvds_atomic_disable(struct drm_bridge *bridge, ...@@ -609,11 +541,6 @@ static void rcar_lvds_atomic_disable(struct drm_bridge *bridge,
{ {
struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge); struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
if (lvds->panel) {
drm_panel_disable(lvds->panel);
drm_panel_unprepare(lvds->panel);
}
rcar_lvds_write(lvds, LVDCR0, 0); rcar_lvds_write(lvds, LVDCR0, 0);
rcar_lvds_write(lvds, LVDCR1, 0); rcar_lvds_write(lvds, LVDCR1, 0);
rcar_lvds_write(lvds, LVDPLLCR, 0); rcar_lvds_write(lvds, LVDPLLCR, 0);
...@@ -648,45 +575,13 @@ static int rcar_lvds_attach(struct drm_bridge *bridge, ...@@ -648,45 +575,13 @@ static int rcar_lvds_attach(struct drm_bridge *bridge,
enum drm_bridge_attach_flags flags) enum drm_bridge_attach_flags flags)
{ {
struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge); struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
struct drm_connector *connector = &lvds->connector;
struct drm_encoder *encoder = bridge->encoder;
int ret;
/* If we have a next bridge just attach it. */
if (lvds->next_bridge)
return drm_bridge_attach(bridge->encoder, lvds->next_bridge,
bridge, flags);
if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) {
DRM_ERROR("Fix bridge driver to make connector optional!");
return -EINVAL;
}
/* Otherwise if we have a panel, create a connector. */
if (!lvds->panel)
return 0;
ret = drm_connector_init(bridge->dev, connector, &rcar_lvds_conn_funcs,
DRM_MODE_CONNECTOR_LVDS);
if (ret < 0)
return ret;
drm_connector_helper_add(connector, &rcar_lvds_conn_helper_funcs);
ret = drm_connector_attach_encoder(connector, encoder);
if (ret < 0)
return ret;
return 0;
}
static void rcar_lvds_detach(struct drm_bridge *bridge) return drm_bridge_attach(bridge->encoder, lvds->next_bridge, bridge,
{ flags);
} }
static const struct drm_bridge_funcs rcar_lvds_bridge_ops = { static const struct drm_bridge_funcs rcar_lvds_bridge_ops = {
.attach = rcar_lvds_attach, .attach = rcar_lvds_attach,
.detach = rcar_lvds_detach,
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
.atomic_reset = drm_atomic_helper_bridge_reset, .atomic_reset = drm_atomic_helper_bridge_reset,
...@@ -759,7 +654,7 @@ static int rcar_lvds_parse_dt_companion(struct rcar_lvds *lvds) ...@@ -759,7 +654,7 @@ static int rcar_lvds_parse_dt_companion(struct rcar_lvds *lvds)
* that we are expected to generate even pixels from the primary * that we are expected to generate even pixels from the primary
* encoder, and odd pixels from the companion encoder. * encoder, and odd pixels from the companion encoder.
*/ */
if (lvds->next_bridge && lvds->next_bridge->timings && if (lvds->next_bridge->timings &&
lvds->next_bridge->timings->dual_link) lvds->next_bridge->timings->dual_link)
lvds->link_type = RCAR_LVDS_DUAL_LINK_EVEN_ODD_PIXELS; lvds->link_type = RCAR_LVDS_DUAL_LINK_EVEN_ODD_PIXELS;
else else
...@@ -811,6 +706,15 @@ static int rcar_lvds_parse_dt(struct rcar_lvds *lvds) ...@@ -811,6 +706,15 @@ static int rcar_lvds_parse_dt(struct rcar_lvds *lvds)
if (ret) if (ret)
goto done; goto done;
if (lvds->panel) {
lvds->next_bridge = devm_drm_panel_bridge_add(lvds->dev,
lvds->panel);
if (IS_ERR_OR_NULL(lvds->next_bridge)) {
ret = -EINVAL;
goto done;
}
}
if (lvds->info->quirks & RCAR_LVDS_QUIRK_DUAL_LINK) if (lvds->info->quirks & RCAR_LVDS_QUIRK_DUAL_LINK)
ret = rcar_lvds_parse_dt_companion(lvds); ret = rcar_lvds_parse_dt_companion(lvds);
...@@ -839,8 +743,7 @@ static struct clk *rcar_lvds_get_clock(struct rcar_lvds *lvds, const char *name, ...@@ -839,8 +743,7 @@ static struct clk *rcar_lvds_get_clock(struct rcar_lvds *lvds, const char *name,
if (PTR_ERR(clk) == -ENOENT && optional) if (PTR_ERR(clk) == -ENOENT && optional)
return NULL; return NULL;
if (PTR_ERR(clk) != -EPROBE_DEFER) dev_err_probe(lvds->dev, PTR_ERR(clk), "failed to get %s clock\n",
dev_err(lvds->dev, "failed to get %s clock\n",
name ? name : "module"); name ? name : "module");
return clk; return clk;
...@@ -919,7 +822,6 @@ static int rcar_lvds_probe(struct platform_device *pdev) ...@@ -919,7 +822,6 @@ static int rcar_lvds_probe(struct platform_device *pdev)
if (ret < 0) if (ret < 0)
return ret; return ret;
lvds->bridge.driver_private = lvds;
lvds->bridge.funcs = &rcar_lvds_bridge_ops; lvds->bridge.funcs = &rcar_lvds_bridge_ops;
lvds->bridge.of_node = pdev->dev.of_node; lvds->bridge.of_node = pdev->dev.of_node;
......
...@@ -636,12 +636,9 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master, ...@@ -636,12 +636,9 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
} }
} else { } else {
ret = drm_bridge_attach(encoder, lvds->bridge, NULL, 0); ret = drm_bridge_attach(encoder, lvds->bridge, NULL, 0);
if (ret) { if (ret)
DRM_DEV_ERROR(drm_dev->dev,
"failed to attach bridge: %d\n", ret);
goto err_free_encoder; goto err_free_encoder;
} }
}
pm_runtime_enable(dev); pm_runtime_enable(dev);
of_node_put(remote); of_node_put(remote);
......
...@@ -143,11 +143,8 @@ struct rockchip_rgb *rockchip_rgb_init(struct device *dev, ...@@ -143,11 +143,8 @@ struct rockchip_rgb *rockchip_rgb_init(struct device *dev,
rgb->bridge = bridge; rgb->bridge = bridge;
ret = drm_bridge_attach(encoder, rgb->bridge, NULL, 0); ret = drm_bridge_attach(encoder, rgb->bridge, NULL, 0);
if (ret) { if (ret)
DRM_DEV_ERROR(drm_dev->dev,
"failed to attach bridge: %d\n", ret);
goto err_free_encoder; goto err_free_encoder;
}
return rgb; return rgb;
......
...@@ -463,10 +463,8 @@ static int sti_dvo_bind(struct device *dev, struct device *master, void *data) ...@@ -463,10 +463,8 @@ static int sti_dvo_bind(struct device *dev, struct device *master, void *data)
drm_bridge_add(bridge); drm_bridge_add(bridge);
err = drm_bridge_attach(encoder, bridge, NULL, 0); err = drm_bridge_attach(encoder, bridge, NULL, 0);
if (err) { if (err)
DRM_ERROR("Failed to attach bridge\n");
return err; return err;
}
dvo->bridge = bridge; dvo->bridge = bridge;
connector->encoder = encoder; connector->encoder = encoder;
......
...@@ -142,11 +142,9 @@ int sun4i_lvds_init(struct drm_device *drm, struct sun4i_tcon *tcon) ...@@ -142,11 +142,9 @@ int sun4i_lvds_init(struct drm_device *drm, struct sun4i_tcon *tcon)
if (bridge) { if (bridge) {
ret = drm_bridge_attach(encoder, bridge, NULL, 0); ret = drm_bridge_attach(encoder, bridge, NULL, 0);
if (ret) { if (ret)
dev_err(drm->dev, "Couldn't attach our bridge\n");
goto err_cleanup_connector; goto err_cleanup_connector;
} }
}
return 0; return 0;
......
...@@ -234,11 +234,9 @@ int sun4i_rgb_init(struct drm_device *drm, struct sun4i_tcon *tcon) ...@@ -234,11 +234,9 @@ int sun4i_rgb_init(struct drm_device *drm, struct sun4i_tcon *tcon)
if (rgb->bridge) { if (rgb->bridge) {
ret = drm_bridge_attach(encoder, rgb->bridge, NULL, 0); ret = drm_bridge_attach(encoder, rgb->bridge, NULL, 0);
if (ret) { if (ret)
dev_err(drm->dev, "Couldn't attach our bridge\n");
goto err_cleanup_connector; goto err_cleanup_connector;
} }
}
return 0; return 0;
......
...@@ -275,11 +275,8 @@ int tegra_dc_rgb_init(struct drm_device *drm, struct tegra_dc *dc) ...@@ -275,11 +275,8 @@ int tegra_dc_rgb_init(struct drm_device *drm, struct tegra_dc *dc)
if (output->bridge) { if (output->bridge) {
err = drm_bridge_attach(&output->encoder, output->bridge, err = drm_bridge_attach(&output->encoder, output->bridge,
NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR); NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR);
if (err) { if (err)
dev_err(output->dev, "failed to attach bridge: %d\n",
err);
return err; return err;
}
connector = drm_bridge_connector_init(drm, &output->encoder); connector = drm_bridge_connector_init(drm, &output->encoder);
if (IS_ERR(connector)) { if (IS_ERR(connector)) {
......
...@@ -227,11 +227,9 @@ static int tidss_dispc_modeset_init(struct tidss_device *tidss) ...@@ -227,11 +227,9 @@ static int tidss_dispc_modeset_init(struct tidss_device *tidss)
} }
ret = drm_bridge_attach(enc, pipes[i].bridge, NULL, 0); ret = drm_bridge_attach(enc, pipes[i].bridge, NULL, 0);
if (ret) { if (ret)
dev_err(tidss->dev, "bridge attach failed: %d\n", ret);
return ret; return ret;
} }
}
/* create overlay planes of the leftover planes */ /* create overlay planes of the leftover planes */
......
...@@ -93,10 +93,8 @@ int tilcdc_attach_bridge(struct drm_device *ddev, struct drm_bridge *bridge) ...@@ -93,10 +93,8 @@ int tilcdc_attach_bridge(struct drm_device *ddev, struct drm_bridge *bridge)
priv->external_encoder->possible_crtcs = BIT(0); priv->external_encoder->possible_crtcs = BIT(0);
ret = drm_bridge_attach(priv->external_encoder, bridge, NULL, 0); ret = drm_bridge_attach(priv->external_encoder, bridge, NULL, 0);
if (ret) { if (ret)
dev_err(ddev->dev, "drm_bridge_attach() failed %d\n", ret);
return ret; return ret;
}
tilcdc_crtc_set_panel_info(priv->crtc, &panel_info_default); tilcdc_crtc_set_panel_info(priv->crtc, &panel_info_default);
......
...@@ -1646,10 +1646,8 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) ...@@ -1646,10 +1646,8 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data)
drm_encoder_helper_add(dsi->encoder, &vc4_dsi_encoder_helper_funcs); drm_encoder_helper_add(dsi->encoder, &vc4_dsi_encoder_helper_funcs);
ret = drm_bridge_attach(dsi->encoder, dsi->bridge, NULL, 0); ret = drm_bridge_attach(dsi->encoder, dsi->bridge, NULL, 0);
if (ret) { if (ret)
dev_err(dev, "bridge attach failed: %d\n", ret);
return ret; return ret;
}
/* Disable the atomic helper calls into the bridge. We /* Disable the atomic helper calls into the bridge. We
* manually call the bridge pre_enable / enable / etc. calls * manually call the bridge pre_enable / enable / etc. calls
* from our driver, since we need to sequence them within the * from our driver, since we need to sequence them within the
......
...@@ -126,6 +126,8 @@ struct dw_hdmi_phy_ops { ...@@ -126,6 +126,8 @@ struct dw_hdmi_phy_ops {
struct dw_hdmi_plat_data { struct dw_hdmi_plat_data {
struct regmap *regm; struct regmap *regm;
unsigned int output_port;
unsigned long input_bus_encoding; unsigned long input_bus_encoding;
bool use_drm_infoframe; bool use_drm_infoframe;
bool ycbcr_420_allowed; bool ycbcr_420_allowed;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment