summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/rcar-du
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/rcar-du')
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_drv.c13
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_encoder.c26
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c1
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_lvds.c126
4 files changed, 45 insertions, 121 deletions
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index bfbff90588cb..4ac26d08ebb4 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -553,14 +553,20 @@ static int rcar_du_remove(struct platform_device *pdev)
struct drm_device *ddev = &rcdu->ddev;
drm_dev_unregister(ddev);
+ drm_atomic_helper_shutdown(ddev);
drm_kms_helper_poll_fini(ddev);
- drm_dev_put(ddev);
-
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)
{
struct rcar_du_device *rcdu;
@@ -593,8 +599,6 @@ static int rcar_du_probe(struct platform_device *pdev)
goto error;
}
- rcdu->ddev.irq_enabled = 1;
-
/*
* Register the DRM device with the core and the connectors with
* sysfs.
@@ -617,6 +621,7 @@ error:
static struct platform_driver rcar_du_platform_driver = {
.probe = rcar_du_probe,
.remove = rcar_du_remove,
+ .shutdown = rcar_du_shutdown,
.driver = {
.name = "rcar-du",
.pm = &rcar_du_pm_ops,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
index ca3761772211..0daa8bba50f5 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
@@ -11,6 +11,7 @@
#include <linux/slab.h>
#include <drm/drm_bridge.h>
+#include <drm/drm_bridge_connector.h>
#include <drm/drm_crtc.h>
#include <drm/drm_managed.h>
#include <drm/drm_modeset_helper_vtables.h>
@@ -53,7 +54,9 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
struct device_node *enc_node)
{
struct rcar_du_encoder *renc;
+ struct drm_connector *connector;
struct drm_bridge *bridge;
+ int ret;
/*
* 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,
renc->output = output;
- /*
- * Attach the bridge to the encoder. The bridge will create the
- * connector.
- */
- return drm_bridge_attach(&renc->base, bridge, NULL, 0);
+ /* Attach the bridge to the encoder. */
+ ret = drm_bridge_attach(&renc->base, bridge, NULL,
+ DRM_BRIDGE_ATTACH_NO_CONNECTOR);
+ if (ret) {
+ 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);
}
diff --git a/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c b/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c
index 7b8ec8310699..18ed14911b98 100644
--- a/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c
+++ b/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c
@@ -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 = {
+ .output_port = 1,
.mode_valid = rcar_hdmi_mode_valid,
.configure_phy = rcar_hdmi_phy_configure,
};
diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c b/drivers/gpu/drm/rcar-du/rcar_lvds.c
index 70dbbe44bb23..d061b8de748f 100644
--- a/drivers/gpu/drm/rcar-du/rcar_lvds.c
+++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c
@@ -63,7 +63,6 @@ struct rcar_lvds {
struct drm_bridge bridge;
struct drm_bridge *next_bridge;
- struct drm_connector connector;
struct drm_panel *panel;
void __iomem *mmio;
@@ -80,74 +79,12 @@ struct rcar_lvds {
#define bridge_to_rcar_lvds(b) \
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)
{
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
*/
@@ -583,11 +520,6 @@ static void __rcar_lvds_atomic_enable(struct drm_bridge *bridge,
/* Turn the output on. */
lvdcr0 |= LVDCR0_LVRES;
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,
@@ -609,11 +541,6 @@ static void rcar_lvds_atomic_disable(struct drm_bridge *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, LVDCR1, 0);
rcar_lvds_write(lvds, LVDPLLCR, 0);
@@ -648,45 +575,13 @@ static int rcar_lvds_attach(struct drm_bridge *bridge,
enum drm_bridge_attach_flags flags)
{
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 = {
.attach = rcar_lvds_attach,
- .detach = rcar_lvds_detach,
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
.atomic_reset = drm_atomic_helper_bridge_reset,
@@ -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
* 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->link_type = RCAR_LVDS_DUAL_LINK_EVEN_ODD_PIXELS;
else
@@ -811,6 +706,15 @@ static int rcar_lvds_parse_dt(struct rcar_lvds *lvds)
if (ret)
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)
ret = rcar_lvds_parse_dt_companion(lvds);
@@ -839,9 +743,8 @@ static struct clk *rcar_lvds_get_clock(struct rcar_lvds *lvds, const char *name,
if (PTR_ERR(clk) == -ENOENT && optional)
return NULL;
- if (PTR_ERR(clk) != -EPROBE_DEFER)
- dev_err(lvds->dev, "failed to get %s clock\n",
- name ? name : "module");
+ dev_err_probe(lvds->dev, PTR_ERR(clk), "failed to get %s clock\n",
+ name ? name : "module");
return clk;
}
@@ -919,7 +822,6 @@ static int rcar_lvds_probe(struct platform_device *pdev)
if (ret < 0)
return ret;
- lvds->bridge.driver_private = lvds;
lvds->bridge.funcs = &rcar_lvds_bridge_ops;
lvds->bridge.of_node = pdev->dev.of_node;