summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/omapdrm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/omapdrm')
-rw-r--r--drivers/gpu/drm/omapdrm/displays/Kconfig17
-rw-r--r--drivers/gpu/drm/omapdrm/displays/Makefile3
-rw-r--r--drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c45
-rw-r--r--drivers/gpu/drm/omapdrm/displays/connector-dvi.c330
-rw-r--r--drivers/gpu/drm/omapdrm/displays/connector-hdmi.c45
-rw-r--r--drivers/gpu/drm/omapdrm/displays/encoder-opa362.c39
-rw-r--r--drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c170
-rw-r--r--drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c40
-rw-r--r--drivers/gpu/drm/omapdrm/displays/panel-dpi.c221
-rw-r--r--drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c140
-rw-r--r--drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c41
-rw-r--r--drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c41
-rw-r--r--drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c61
-rw-r--r--drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c55
-rw-r--r--drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c58
-rw-r--r--drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c48
-rw-r--r--drivers/gpu/drm/omapdrm/dss/base.c144
-rw-r--r--drivers/gpu/drm/omapdrm/dss/display.c24
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dpi.c64
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dsi.c110
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dss-of.c60
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dss.c2
-rw-r--r--drivers/gpu/drm/omapdrm/dss/hdmi4.c54
-rw-r--r--drivers/gpu/drm/omapdrm/dss/hdmi5.c54
-rw-r--r--drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c18
-rw-r--r--drivers/gpu/drm/omapdrm/dss/omapdss.h76
-rw-r--r--drivers/gpu/drm/omapdrm/dss/output.c36
-rw-r--r--drivers/gpu/drm/omapdrm/dss/sdi.c68
-rw-r--r--drivers/gpu/drm/omapdrm/dss/venc.c229
-rw-r--r--drivers/gpu/drm/omapdrm/omap_connector.c181
-rw-r--r--drivers/gpu/drm/omapdrm/omap_connector.h8
-rw-r--r--drivers/gpu/drm/omapdrm/omap_crtc.c13
-rw-r--r--drivers/gpu/drm/omapdrm/omap_drv.c236
-rw-r--r--drivers/gpu/drm/omapdrm/omap_drv.h2
-rw-r--r--drivers/gpu/drm/omapdrm/omap_encoder.c211
-rw-r--r--drivers/gpu/drm/omapdrm/omap_encoder.h3
-rw-r--r--drivers/gpu/drm/omapdrm/omap_fbdev.c6
37 files changed, 926 insertions, 2027 deletions
diff --git a/drivers/gpu/drm/omapdrm/displays/Kconfig b/drivers/gpu/drm/omapdrm/displays/Kconfig
index a349cb61961e..7b0bcb494b5c 100644
--- a/drivers/gpu/drm/omapdrm/displays/Kconfig
+++ b/drivers/gpu/drm/omapdrm/displays/Kconfig
@@ -6,23 +6,12 @@ config DRM_OMAP_ENCODER_OPA362
Driver for OPA362 external analog TV amplifier controlled
through a GPIO.
-config DRM_OMAP_ENCODER_TFP410
- tristate "TFP410 DPI to DVI Encoder"
- help
- Driver for TFP410 DPI to DVI encoder.
-
config DRM_OMAP_ENCODER_TPD12S015
tristate "TPD12S015 HDMI ESD protection and level shifter"
help
Driver for TPD12S015, which offers HDMI ESD protection and level
shifting.
-config DRM_OMAP_CONNECTOR_DVI
- tristate "DVI Connector"
- depends on I2C
- help
- Driver for a generic DVI connector.
-
config DRM_OMAP_CONNECTOR_HDMI
tristate "HDMI Connector"
help
@@ -33,12 +22,6 @@ config DRM_OMAP_CONNECTOR_ANALOG_TV
help
Driver for a generic analog TV connector.
-config DRM_OMAP_PANEL_DPI
- tristate "Generic DPI panel"
- depends on BACKLIGHT_CLASS_DEVICE
- help
- Driver for generic DPI panels.
-
config DRM_OMAP_PANEL_DSI_CM
tristate "Generic DSI Command Mode Panel"
depends on BACKLIGHT_CLASS_DEVICE
diff --git a/drivers/gpu/drm/omapdrm/displays/Makefile b/drivers/gpu/drm/omapdrm/displays/Makefile
index d99659e1381b..1db34d4fed64 100644
--- a/drivers/gpu/drm/omapdrm/displays/Makefile
+++ b/drivers/gpu/drm/omapdrm/displays/Makefile
@@ -1,11 +1,8 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_DRM_OMAP_ENCODER_OPA362) += encoder-opa362.o
-obj-$(CONFIG_DRM_OMAP_ENCODER_TFP410) += encoder-tfp410.o
obj-$(CONFIG_DRM_OMAP_ENCODER_TPD12S015) += encoder-tpd12s015.o
-obj-$(CONFIG_DRM_OMAP_CONNECTOR_DVI) += connector-dvi.o
obj-$(CONFIG_DRM_OMAP_CONNECTOR_HDMI) += connector-hdmi.o
obj-$(CONFIG_DRM_OMAP_CONNECTOR_ANALOG_TV) += connector-analog-tv.o
-obj-$(CONFIG_DRM_OMAP_PANEL_DPI) += panel-dpi.o
obj-$(CONFIG_DRM_OMAP_PANEL_DSI_CM) += panel-dsi-cm.o
obj-$(CONFIG_DRM_OMAP_PANEL_SONY_ACX565AKM) += panel-sony-acx565akm.o
obj-$(CONFIG_DRM_OMAP_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o
diff --git a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c
index 28a3ce8f88d2..6c0561101874 100644
--- a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c
+++ b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c
@@ -35,50 +35,9 @@ static void tvc_disconnect(struct omap_dss_device *src,
{
}
-static int tvc_enable(struct omap_dss_device *dssdev)
-{
- struct panel_drv_data *ddata = to_panel_data(dssdev);
- struct omap_dss_device *src = dssdev->src;
- int r;
-
- dev_dbg(ddata->dev, "enable\n");
-
- if (!omapdss_device_is_connected(dssdev))
- return -ENODEV;
-
- if (omapdss_device_is_enabled(dssdev))
- return 0;
-
- r = src->ops->enable(src);
- if (r)
- return r;
-
- dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
- return r;
-}
-
-static void tvc_disable(struct omap_dss_device *dssdev)
-{
- struct panel_drv_data *ddata = to_panel_data(dssdev);
- struct omap_dss_device *src = dssdev->src;
-
- dev_dbg(ddata->dev, "disable\n");
-
- if (!omapdss_device_is_enabled(dssdev))
- return;
-
- src->ops->disable(src);
-
- dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-}
-
static const struct omap_dss_device_ops tvc_ops = {
.connect = tvc_connect,
.disconnect = tvc_disconnect,
-
- .enable = tvc_enable,
- .disable = tvc_disable,
};
static int tvc_probe(struct platform_device *pdev)
@@ -97,6 +56,7 @@ static int tvc_probe(struct platform_device *pdev)
dssdev->ops = &tvc_ops;
dssdev->dev = &pdev->dev;
dssdev->type = OMAP_DISPLAY_TYPE_VENC;
+ dssdev->display = true;
dssdev->owner = THIS_MODULE;
dssdev->of_ports = BIT(0);
@@ -109,12 +69,9 @@ static int tvc_probe(struct platform_device *pdev)
static int __exit tvc_remove(struct platform_device *pdev)
{
struct panel_drv_data *ddata = platform_get_drvdata(pdev);
- struct omap_dss_device *dssdev = &ddata->dssdev;
omapdss_device_unregister(&ddata->dssdev);
- tvc_disable(dssdev);
-
return 0;
}
diff --git a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c
deleted file mode 100644
index 24b14f44248e..000000000000
--- a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c
+++ /dev/null
@@ -1,330 +0,0 @@
-/*
- * Generic DVI Connector driver
- *
- * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
- * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- */
-
-#include <linux/gpio/consumer.h>
-#include <linux/i2c.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-
-#include <drm/drm_edid.h>
-
-#include "../dss/omapdss.h"
-
-struct panel_drv_data {
- struct omap_dss_device dssdev;
-
- struct i2c_adapter *i2c_adapter;
-
- struct gpio_desc *hpd_gpio;
-
- void (*hpd_cb)(void *cb_data, enum drm_connector_status status);
- void *hpd_cb_data;
- bool hpd_enabled;
- /* mutex for hpd fields above */
- struct mutex hpd_lock;
-};
-
-#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
-
-static int dvic_connect(struct omap_dss_device *src,
- struct omap_dss_device *dst)
-{
- return 0;
-}
-
-static void dvic_disconnect(struct omap_dss_device *src,
- struct omap_dss_device *dst)
-{
-}
-
-static int dvic_enable(struct omap_dss_device *dssdev)
-{
- struct omap_dss_device *src = dssdev->src;
- int r;
-
- if (!omapdss_device_is_connected(dssdev))
- return -ENODEV;
-
- if (omapdss_device_is_enabled(dssdev))
- return 0;
-
- r = src->ops->enable(src);
- if (r)
- return r;
-
- dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
- return 0;
-}
-
-static void dvic_disable(struct omap_dss_device *dssdev)
-{
- struct omap_dss_device *src = dssdev->src;
-
- if (!omapdss_device_is_enabled(dssdev))
- return;
-
- src->ops->disable(src);
-
- dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-}
-
-static int dvic_ddc_read(struct i2c_adapter *adapter,
- unsigned char *buf, u16 count, u8 offset)
-{
- int r, retries;
-
- for (retries = 3; retries > 0; retries--) {
- struct i2c_msg msgs[] = {
- {
- .addr = DDC_ADDR,
- .flags = 0,
- .len = 1,
- .buf = &offset,
- }, {
- .addr = DDC_ADDR,
- .flags = I2C_M_RD,
- .len = count,
- .buf = buf,
- }
- };
-
- r = i2c_transfer(adapter, msgs, 2);
- if (r == 2)
- return 0;
-
- if (r != -EAGAIN)
- break;
- }
-
- return r < 0 ? r : -EIO;
-}
-
-static int dvic_read_edid(struct omap_dss_device *dssdev,
- u8 *edid, int len)
-{
- struct panel_drv_data *ddata = to_panel_data(dssdev);
- int r, l, bytes_read;
-
- l = min(EDID_LENGTH, len);
- r = dvic_ddc_read(ddata->i2c_adapter, edid, l, 0);
- if (r)
- return r;
-
- bytes_read = l;
-
- /* if there are extensions, read second block */
- if (len > EDID_LENGTH && edid[0x7e] > 0) {
- l = min(EDID_LENGTH, len - EDID_LENGTH);
-
- r = dvic_ddc_read(ddata->i2c_adapter, edid + EDID_LENGTH,
- l, EDID_LENGTH);
- if (r)
- return r;
-
- bytes_read += l;
- }
-
- return bytes_read;
-}
-
-static bool dvic_detect(struct omap_dss_device *dssdev)
-{
- struct panel_drv_data *ddata = to_panel_data(dssdev);
- unsigned char out;
- int r;
-
- if (ddata->hpd_gpio)
- return gpiod_get_value_cansleep(ddata->hpd_gpio);
-
- if (!ddata->i2c_adapter)
- return true;
-
- r = dvic_ddc_read(ddata->i2c_adapter, &out, 1, 0);
-
- return r == 0;
-}
-
-static void dvic_register_hpd_cb(struct omap_dss_device *dssdev,
- void (*cb)(void *cb_data,
- enum drm_connector_status status),
- void *cb_data)
-{
- struct panel_drv_data *ddata = to_panel_data(dssdev);
-
- mutex_lock(&ddata->hpd_lock);
- ddata->hpd_cb = cb;
- ddata->hpd_cb_data = cb_data;
- mutex_unlock(&ddata->hpd_lock);
-}
-
-static void dvic_unregister_hpd_cb(struct omap_dss_device *dssdev)
-{
- struct panel_drv_data *ddata = to_panel_data(dssdev);
-
- mutex_lock(&ddata->hpd_lock);
- ddata->hpd_cb = NULL;
- ddata->hpd_cb_data = NULL;
- mutex_unlock(&ddata->hpd_lock);
-}
-
-static const struct omap_dss_device_ops dvic_ops = {
- .connect = dvic_connect,
- .disconnect = dvic_disconnect,
-
- .enable = dvic_enable,
- .disable = dvic_disable,
-
- .read_edid = dvic_read_edid,
- .detect = dvic_detect,
-
- .register_hpd_cb = dvic_register_hpd_cb,
- .unregister_hpd_cb = dvic_unregister_hpd_cb,
-};
-
-static irqreturn_t dvic_hpd_isr(int irq, void *data)
-{
- struct panel_drv_data *ddata = data;
-
- mutex_lock(&ddata->hpd_lock);
- if (ddata->hpd_enabled && ddata->hpd_cb) {
- enum drm_connector_status status;
-
- if (dvic_detect(&ddata->dssdev))
- status = connector_status_connected;
- else
- status = connector_status_disconnected;
-
- ddata->hpd_cb(ddata->hpd_cb_data, status);
- }
- mutex_unlock(&ddata->hpd_lock);
-
- return IRQ_HANDLED;
-}
-
-static int dvic_probe_of(struct platform_device *pdev)
-{
- struct panel_drv_data *ddata = platform_get_drvdata(pdev);
- struct device_node *node = pdev->dev.of_node;
- struct device_node *adapter_node;
- struct i2c_adapter *adapter;
- struct gpio_desc *gpio;
- int r;
-
- gpio = devm_gpiod_get_optional(&pdev->dev, "hpd", GPIOD_IN);
- if (IS_ERR(gpio)) {
- dev_err(&pdev->dev, "failed to parse HPD gpio\n");
- return PTR_ERR(gpio);
- }
-
- ddata->hpd_gpio = gpio;
-
- mutex_init(&ddata->hpd_lock);
-
- if (ddata->hpd_gpio) {
- r = devm_request_threaded_irq(&pdev->dev,
- gpiod_to_irq(ddata->hpd_gpio), NULL, dvic_hpd_isr,
- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- "DVI HPD", ddata);
- if (r)
- return r;
- }
-
- adapter_node = of_parse_phandle(node, "ddc-i2c-bus", 0);
- if (adapter_node) {
- adapter = of_get_i2c_adapter_by_node(adapter_node);
- of_node_put(adapter_node);
- if (adapter == NULL) {
- dev_err(&pdev->dev, "failed to parse ddc-i2c-bus\n");
- return -EPROBE_DEFER;
- }
-
- ddata->i2c_adapter = adapter;
- }
-
- return 0;
-}
-
-static int dvic_probe(struct platform_device *pdev)
-{
- struct panel_drv_data *ddata;
- struct omap_dss_device *dssdev;
- int r;
-
- ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
- if (!ddata)
- return -ENOMEM;
-
- platform_set_drvdata(pdev, ddata);
-
- r = dvic_probe_of(pdev);
- if (r)
- return r;
-
- dssdev = &ddata->dssdev;
- dssdev->ops = &dvic_ops;
- dssdev->dev = &pdev->dev;
- dssdev->type = OMAP_DISPLAY_TYPE_DVI;
- dssdev->owner = THIS_MODULE;
- dssdev->of_ports = BIT(0);
-
- if (ddata->hpd_gpio)
- dssdev->ops_flags |= OMAP_DSS_DEVICE_OP_DETECT
- | OMAP_DSS_DEVICE_OP_HPD;
- if (ddata->i2c_adapter)
- dssdev->ops_flags |= OMAP_DSS_DEVICE_OP_DETECT
- | OMAP_DSS_DEVICE_OP_EDID;
-
- omapdss_display_init(dssdev);
- omapdss_device_register(dssdev);
-
- return 0;
-}
-
-static int __exit dvic_remove(struct platform_device *pdev)
-{
- struct panel_drv_data *ddata = platform_get_drvdata(pdev);
- struct omap_dss_device *dssdev = &ddata->dssdev;
-
- omapdss_device_unregister(&ddata->dssdev);
-
- dvic_disable(dssdev);
-
- i2c_put_adapter(ddata->i2c_adapter);
-
- mutex_destroy(&ddata->hpd_lock);
-
- return 0;
-}
-
-static const struct of_device_id dvic_of_match[] = {
- { .compatible = "omapdss,dvi-connector", },
- {},
-};
-
-MODULE_DEVICE_TABLE(of, dvic_of_match);
-
-static struct platform_driver dvi_connector_driver = {
- .probe = dvic_probe,
- .remove = __exit_p(dvic_remove),
- .driver = {
- .name = "connector-dvi",
- .of_match_table = dvic_of_match,
- .suppress_bind_attrs = true,
- },
-};
-
-module_platform_driver(dvi_connector_driver);
-
-MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
-MODULE_DESCRIPTION("Generic DVI Connector driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c
index e602fa4a50a4..68d6f6e44b03 100644
--- a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c
+++ b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c
@@ -41,44 +41,6 @@ static void hdmic_disconnect(struct omap_dss_device *src,
{
}
-static int hdmic_enable(struct omap_dss_device *dssdev)
-{
- struct panel_drv_data *ddata = to_panel_data(dssdev);
- struct omap_dss_device *src = dssdev->src;
- int r;
-
- dev_dbg(ddata->dev, "enable\n");
-
- if (!omapdss_device_is_connected(dssdev))
- return -ENODEV;
-
- if (omapdss_device_is_enabled(dssdev))
- return 0;
-
- r = src->ops->enable(src);
- if (r)
- return r;
-
- dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
- return r;
-}
-
-static void hdmic_disable(struct omap_dss_device *dssdev)
-{
- struct panel_drv_data *ddata = to_panel_data(dssdev);
- struct omap_dss_device *src = dssdev->src;
-
- dev_dbg(ddata->dev, "disable\n");
-
- if (!omapdss_device_is_enabled(dssdev))
- return;
-
- src->ops->disable(src);
-
- dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-}
-
static bool hdmic_detect(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
@@ -113,9 +75,6 @@ static const struct omap_dss_device_ops hdmic_ops = {
.connect = hdmic_connect,
.disconnect = hdmic_disconnect,
- .enable = hdmic_enable,
- .disable = hdmic_disable,
-
.detect = hdmic_detect,
.register_hpd_cb = hdmic_register_hpd_cb,
.unregister_hpd_cb = hdmic_unregister_hpd_cb,
@@ -181,6 +140,7 @@ static int hdmic_probe(struct platform_device *pdev)
dssdev->ops = &hdmic_ops;
dssdev->dev = &pdev->dev;
dssdev->type = OMAP_DISPLAY_TYPE_HDMI;
+ dssdev->display = true;
dssdev->owner = THIS_MODULE;
dssdev->of_ports = BIT(0);
dssdev->ops_flags = ddata->hpd_gpio
@@ -196,12 +156,9 @@ static int hdmic_probe(struct platform_device *pdev)
static int __exit hdmic_remove(struct platform_device *pdev)
{
struct panel_drv_data *ddata = platform_get_drvdata(pdev);
- struct omap_dss_device *dssdev = &ddata->dssdev;
omapdss_device_unregister(&ddata->dssdev);
- hdmic_disable(dssdev);
-
return 0;
}
diff --git a/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c b/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c
index 4fefd80f53bb..29a5a130ebd1 100644
--- a/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c
+++ b/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c
@@ -41,48 +41,20 @@ static void opa362_disconnect(struct omap_dss_device *src,
omapdss_device_disconnect(dst, dst->next);
}
-static int opa362_enable(struct omap_dss_device *dssdev)
+static void opa362_enable(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- struct omap_dss_device *src = dssdev->src;
- int r;
-
- dev_dbg(dssdev->dev, "enable\n");
-
- if (!omapdss_device_is_connected(dssdev))
- return -ENODEV;
-
- if (omapdss_device_is_enabled(dssdev))
- return 0;
-
- r = src->ops->enable(src);
- if (r)
- return r;
if (ddata->enable_gpio)
gpiod_set_value_cansleep(ddata->enable_gpio, 1);
-
- dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
- return 0;
}
static void opa362_disable(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- struct omap_dss_device *src = dssdev->src;
-
- dev_dbg(dssdev->dev, "disable\n");
-
- if (!omapdss_device_is_enabled(dssdev))
- return;
if (ddata->enable_gpio)
gpiod_set_value_cansleep(ddata->enable_gpio, 0);
-
- src->ops->disable(src);
-
- dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
}
static const struct omap_dss_device_ops opa362_ops = {
@@ -116,7 +88,6 @@ static int opa362_probe(struct platform_device *pdev)
dssdev->ops = &opa362_ops;
dssdev->dev = &pdev->dev;
dssdev->type = OMAP_DISPLAY_TYPE_VENC;
- dssdev->output_type = OMAP_DISPLAY_TYPE_VENC;
dssdev->owner = THIS_MODULE;
dssdev->of_ports = BIT(1) | BIT(0);
@@ -141,13 +112,7 @@ static int __exit opa362_remove(struct platform_device *pdev)
omapdss_device_put(dssdev->next);
omapdss_device_unregister(&ddata->dssdev);
- WARN_ON(omapdss_device_is_enabled(dssdev));
- if (omapdss_device_is_enabled(dssdev))
- opa362_disable(dssdev);
-
- WARN_ON(omapdss_device_is_connected(dssdev));
- if (omapdss_device_is_connected(dssdev))
- omapdss_device_disconnect(NULL, dssdev);
+ opa362_disable(dssdev);
return 0;
}
diff --git a/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c b/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c
deleted file mode 100644
index f1a748353279..000000000000
--- a/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * TFP410 DPI-to-DVI encoder driver
- *
- * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
- * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- */
-
-#include <linux/gpio/consumer.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-
-#include "../dss/omapdss.h"
-
-struct panel_drv_data {
- struct omap_dss_device dssdev;
-
- struct gpio_desc *pd_gpio;
-};
-
-#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
-
-static int tfp410_connect(struct omap_dss_device *src,
- struct omap_dss_device *dst)
-{
- return omapdss_device_connect(dst->dss, dst, dst->next);
-}
-
-static void tfp410_disconnect(struct omap_dss_device *src,
- struct omap_dss_device *dst)
-{
- omapdss_device_disconnect(dst, dst->next);
-}
-
-static int tfp410_enable(struct omap_dss_device *dssdev)
-{
- struct panel_drv_data *ddata = to_panel_data(dssdev);
- struct omap_dss_device *src = dssdev->src;
- int r;
-
- if (!omapdss_device_is_connected(dssdev))
- return -ENODEV;
-
- if (omapdss_device_is_enabled(dssdev))
- return 0;
-
- r = src->ops->enable(src);
- if (r)
- return r;
-
- if (ddata->pd_gpio)
- gpiod_set_value_cansleep(ddata->pd_gpio, 0);
-
- dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
- return 0;
-}
-
-static void tfp410_disable(struct omap_dss_device *dssdev)
-{
- struct panel_drv_data *ddata = to_panel_data(dssdev);
- struct omap_dss_device *src = dssdev->src;
-
- if (!omapdss_device_is_enabled(dssdev))
- return;
-
- if (ddata->pd_gpio)
- gpiod_set_value_cansleep(ddata->pd_gpio, 0);
-
- src->ops->disable(src);
-
- dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-}
-
-static const struct omap_dss_device_ops tfp410_ops = {
- .connect = tfp410_connect,
- .disconnect = tfp410_disconnect,
- .enable = tfp410_enable,
- .disable = tfp410_disable,
-};
-
-static int tfp410_probe(struct platform_device *pdev)
-{
- struct panel_drv_data *ddata;
- struct omap_dss_device *dssdev;
- struct gpio_desc *gpio;
-
- ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
- if (!ddata)
- return -ENOMEM;
-
- platform_set_drvdata(pdev, ddata);
-
- /* Powerdown GPIO */
- gpio = devm_gpiod_get_optional(&pdev->dev, "powerdown", GPIOD_OUT_HIGH);
- if (IS_ERR(gpio)) {
- dev_err(&pdev->dev, "failed to parse powerdown gpio\n");
- return PTR_ERR(gpio);
- }
-
- ddata->pd_gpio = gpio;
-
- dssdev = &ddata->dssdev;
- dssdev->ops = &tfp410_ops;
- dssdev->dev = &pdev->dev;
- dssdev->type = OMAP_DISPLAY_TYPE_DPI;
- dssdev->output_type = OMAP_DISPLAY_TYPE_DVI;
- dssdev->owner = THIS_MODULE;
- dssdev->of_ports = BIT(1) | BIT(0);
- dssdev->bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_SYNC_POSEDGE
- | DRM_BUS_FLAG_PIXDATA_POSEDGE;
-
- dssdev->next = omapdss_of_find_connected_device(pdev->dev.of_node, 1);
- if (IS_ERR(dssdev->next)) {
- if (PTR_ERR(dssdev->next) != -EPROBE_DEFER)
- dev_err(&pdev->dev, "failed to find video sink\n");
- return PTR_ERR(dssdev->next);
- }
-
- omapdss_device_register(dssdev);
-
- return 0;
-}
-
-static int __exit tfp410_remove(struct platform_device *pdev)
-{
- struct panel_drv_data *ddata = platform_get_drvdata(pdev);
- struct omap_dss_device *dssdev = &ddata->dssdev;
-
- if (dssdev->next)
- omapdss_device_put(dssdev->next);
- omapdss_device_unregister(&ddata->dssdev);
-
- WARN_ON(omapdss_device_is_enabled(dssdev));
- if (omapdss_device_is_enabled(dssdev))
- tfp410_disable(dssdev);
-
- WARN_ON(omapdss_device_is_connected(dssdev));
- if (omapdss_device_is_connected(dssdev))
- omapdss_device_disconnect(NULL, dssdev);
-
- return 0;
-}
-
-static const struct of_device_id tfp410_of_match[] = {
- { .compatible = "omapdss,ti,tfp410", },
- {},
-};
-
-MODULE_DEVICE_TABLE(of, tfp410_of_match);
-
-static struct platform_driver tfp410_driver = {
- .probe = tfp410_probe,
- .remove = __exit_p(tfp410_remove),
- .driver = {
- .name = "tfp410",
- .of_match_table = tfp410_of_match,
- .suppress_bind_attrs = true,
- },
-};
-
-module_platform_driver(tfp410_driver);
-
-MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
-MODULE_DESCRIPTION("TFP410 DPI to DVI encoder driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c b/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c
index 94de55fd8884..bc03752d2762 100644
--- a/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c
+++ b/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c
@@ -62,35 +62,6 @@ static void tpd_disconnect(struct omap_dss_device *src,
omapdss_device_disconnect(dst, dst->next);
}
-static int tpd_enable(struct omap_dss_device *dssdev)
-{
- struct omap_dss_device *src = dssdev->src;
- int r;
-
- if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
- return 0;
-
- r = src->ops->enable(src);
- if (r)
- return r;
-
- dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
- return r;
-}
-
-static void tpd_disable(struct omap_dss_device *dssdev)
-{
- struct omap_dss_device *src = dssdev->src;
-
- if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
- return;
-
- src->ops->disable(src);
-
- dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-}
-
static bool tpd_detect(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
@@ -124,8 +95,6 @@ static void tpd_unregister_hpd_cb(struct omap_dss_device *dssdev)
static const struct omap_dss_device_ops tpd_ops = {
.connect = tpd_connect,
.disconnect = tpd_disconnect,
- .enable = tpd_enable,
- .disable = tpd_disable,
.detect = tpd_detect,
.register_hpd_cb = tpd_register_hpd_cb,
.unregister_hpd_cb = tpd_unregister_hpd_cb,
@@ -198,7 +167,6 @@ static int tpd_probe(struct platform_device *pdev)
dssdev->ops = &tpd_ops;
dssdev->dev = &pdev->dev;
dssdev->type = OMAP_DISPLAY_TYPE_HDMI;
- dssdev->output_type = OMAP_DISPLAY_TYPE_HDMI;
dssdev->owner = THIS_MODULE;
dssdev->of_ports = BIT(1) | BIT(0);
dssdev->ops_flags = OMAP_DSS_DEVICE_OP_DETECT
@@ -225,14 +193,6 @@ static int __exit tpd_remove(struct platform_device *pdev)
omapdss_device_put(dssdev->next);
omapdss_device_unregister(&ddata->dssdev);
- WARN_ON(omapdss_device_is_enabled(dssdev));
- if (omapdss_device_is_enabled(dssdev))
- tpd_disable(dssdev);
-
- WARN_ON(omapdss_device_is_connected(dssdev));
- if (omapdss_device_is_connected(dssdev))
- omapdss_device_disconnect(NULL, dssdev);
-
return 0;
}
diff --git a/drivers/gpu/drm/omapdrm/displays/panel-dpi.c b/drivers/gpu/drm/omapdrm/displays/panel-dpi.c
deleted file mode 100644
index 465120809eb3..000000000000
--- a/drivers/gpu/drm/omapdrm/displays/panel-dpi.c
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Generic MIPI DPI Panel Driver
- *
- * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
- * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- */
-
-#include <linux/gpio/consumer.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/of.h>
-#include <linux/regulator/consumer.h>
-#include <linux/backlight.h>
-
-#include <video/of_display_timing.h>
-
-#include "../dss/omapdss.h"
-
-struct panel_drv_data {
- struct omap_dss_device dssdev;
-
- struct videomode vm;
-
- struct backlight_device *backlight;
-
- struct gpio_desc *enable_gpio;
- struct regulator *vcc_supply;
-};
-
-#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
-
-static int panel_dpi_connect(struct omap_dss_device *src,
- struct omap_dss_device *dst)
-{
- return 0;
-}
-
-static void panel_dpi_disconnect(struct omap_dss_device *src,
- struct omap_dss_device *dst)
-{
-}
-
-static int panel_dpi_enable(struct omap_dss_device *dssdev)
-{
- struct panel_drv_data *ddata = to_panel_data(dssdev);
- struct omap_dss_device *src = dssdev->src;
- int r;
-
- if (!omapdss_device_is_connected(dssdev))
- return -ENODEV;
-
- if (omapdss_device_is_enabled(dssdev))
- return 0;
-
- r = src->ops->enable(src);
- if (r)
- return r;
-
- r = regulator_enable(ddata->vcc_supply);
- if (r) {
- src->ops->disable(src);
- return r;
- }
-
- gpiod_set_value_cansleep(ddata->enable_gpio, 1);
- backlight_enable(ddata->backlight);
-
- dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
- return 0;
-}
-
-static void panel_dpi_disable(struct omap_dss_device *dssdev)
-{
- struct panel_drv_data *ddata = to_panel_data(dssdev);
- struct omap_dss_device *src = dssdev->src;
-
- if (!omapdss_device_is_enabled(dssdev))
- return;
-
- backlight_disable(ddata->backlight);
-
- gpiod_set_value_cansleep(ddata->enable_gpio, 0);
- regulator_disable(ddata->vcc_supply);
-
- src->ops->disable(src);
-
- dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-}
-
-static void panel_dpi_get_timings(struct omap_dss_device *dssdev,
- struct videomode *vm)
-{
- struct panel_drv_data *ddata = to_panel_data(dssdev);
-
- *vm = ddata->vm;
-}
-
-static const struct omap_dss_device_ops panel_dpi_ops = {
- .connect = panel_dpi_connect,
- .disconnect = panel_dpi_disconnect,
-
- .enable = panel_dpi_enable,
- .disable = panel_dpi_disable,
-
- .get_timings = panel_dpi_get_timings,
-};
-
-static int panel_dpi_probe_of(struct platform_device *pdev)
-{
- struct panel_drv_data *ddata = platform_get_drvdata(pdev);
- struct device_node *node = pdev->dev.of_node;
- int r;
- struct display_timing timing;
- struct gpio_desc *gpio;
-
- gpio = devm_gpiod_get_optional(&pdev->dev, "enable", GPIOD_OUT_LOW);
- if (IS_ERR(gpio))
- return PTR_ERR(gpio);
-
- ddata->enable_gpio = gpio;
-
- /*
- * Many different panels are supported by this driver and there are
- * probably very different needs for their reset pins in regards to
- * timing and order relative to the enable gpio. So for now it's just
- * ensured that the reset line isn't active.
- */
- gpio = devm_gpiod_get_optional(&pdev->dev, "reset", GPIOD_OUT_LOW);
- if (IS_ERR(gpio))
- return PTR_ERR(gpio);
-
- ddata->vcc_supply = devm_regulator_get(&pdev->dev, "vcc");
- if (IS_ERR(ddata->vcc_supply))
- return PTR_ERR(ddata->vcc_supply);
-
- ddata->backlight = devm_of_find_backlight(&pdev->dev);
-
- if (IS_ERR(ddata->backlight))
- return PTR_ERR(ddata->backlight);
-
- r = of_get_display_timing(node, "panel-timing", &timing);
- if (r) {
- dev_err(&pdev->dev, "failed to get video timing\n");
- return r;
- }
-
- videomode_from_timing(&timing, &ddata->vm);
-
- return 0;
-}
-
-static int panel_dpi_probe(struct platform_device *pdev)
-{
- struct panel_drv_data *ddata;
- struct omap_dss_device *dssdev;
- int r;
-
- ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
- if (ddata == NULL)
- return -ENOMEM;
-
- platform_set_drvdata(pdev, ddata);
-
- r = panel_dpi_probe_of(pdev);
- if (r)
- return r;
-
- dssdev = &ddata->dssdev;
- dssdev->dev = &pdev->dev;
- dssdev->ops = &panel_dpi_ops;
- dssdev->type = OMAP_DISPLAY_TYPE_DPI;
- dssdev->owner = THIS_MODULE;
- dssdev->of_ports = BIT(0);
- drm_bus_flags_from_videomode(&ddata->vm, &dssdev->bus_flags);
-
- omapdss_display_init(dssdev);
- omapdss_device_register(dssdev);
-
- return 0;
-}
-
-static int __exit panel_dpi_remove(struct platform_device *pdev)
-{
- struct panel_drv_data *ddata = platform_get_drvdata(pdev);
- struct omap_dss_device *dssdev = &ddata->dssdev;
-
- omapdss_device_unregister(dssdev);
-
- panel_dpi_disable(dssdev);
-
- return 0;
-}
-
-static const struct of_device_id panel_dpi_of_match[] = {
- { .compatible = "omapdss,panel-dpi", },
- {},
-};
-
-MODULE_DEVICE_TABLE(of, panel_dpi_of_match);
-
-static struct platform_driver panel_dpi_driver = {
- .probe = panel_dpi_probe,
- .remove = __exit_p(panel_dpi_remove),
- .driver = {
- .name = "panel-dpi",
- .of_match_table = panel_dpi_of_match,
- .suppress_bind_attrs = true,
- },
-};
-
-module_platform_driver(panel_dpi_driver);
-
-MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
-MODULE_DESCRIPTION("Generic MIPI DPI Panel Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
index 29692a5217c5..741a5e324767 100644
--- a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
+++ b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
@@ -24,6 +24,8 @@
#include <linux/of_device.h>
#include <linux/regulator/consumer.h>
+#include <drm/drm_connector.h>
+
#include <video/mipi_display.h>
#include <video/of_display_timing.h>
@@ -41,6 +43,7 @@
struct panel_drv_data {
struct omap_dss_device dssdev;
+ struct omap_dss_device *src;
struct videomode vm;
@@ -141,7 +144,7 @@ static void hw_guard_wait(struct panel_drv_data *ddata)
static int dsicm_dcs_read_1(struct panel_drv_data *ddata, u8 dcs_cmd, u8 *data)
{
- struct omap_dss_device *src = ddata->dssdev.src;
+ struct omap_dss_device *src = ddata->src;
int r;
u8 buf[1];
@@ -157,14 +160,14 @@ static int dsicm_dcs_read_1(struct panel_drv_data *ddata, u8 dcs_cmd, u8 *data)
static int dsicm_dcs_write_0(struct panel_drv_data *ddata, u8 dcs_cmd)
{
- struct omap_dss_device *src = ddata->dssdev.src;
+ struct omap_dss_device *src = ddata->src;
return src->ops->dsi.dcs_write(src, ddata->channel, &dcs_cmd, 1);
}
static int dsicm_dcs_write_1(struct panel_drv_data *ddata, u8 dcs_cmd, u8 param)
{
- struct omap_dss_device *src = ddata->dssdev.src;
+ struct omap_dss_device *src = ddata->src;
u8 buf[2] = { dcs_cmd, param };
return src->ops->dsi.dcs_write(src, ddata->channel, buf, 2);
@@ -173,7 +176,7 @@ static int dsicm_dcs_write_1(struct panel_drv_data *ddata, u8 dcs_cmd, u8 param)
static int dsicm_sleep_in(struct panel_drv_data *ddata)
{
- struct omap_dss_device *src = ddata->dssdev.src;
+ struct omap_dss_device *src = ddata->src;
u8 cmd;
int r;
@@ -228,7 +231,7 @@ static int dsicm_get_id(struct panel_drv_data *ddata, u8 *id1, u8 *id2, u8 *id3)
static int dsicm_set_update_window(struct panel_drv_data *ddata,
u16 x, u16 y, u16 w, u16 h)
{
- struct omap_dss_device *src = ddata->dssdev.src;
+ struct omap_dss_device *src = ddata->src;
int r;
u16 x1 = x;
u16 x2 = x + w - 1;
@@ -275,7 +278,7 @@ static void dsicm_cancel_ulps_work(struct panel_drv_data *ddata)
static int dsicm_enter_ulps(struct panel_drv_data *ddata)
{
- struct omap_dss_device *src = ddata->dssdev.src;
+ struct omap_dss_device *src = ddata->src;
int r;
if (ddata->ulps_enabled)
@@ -309,18 +312,13 @@ err:
static int dsicm_exit_ulps(struct panel_drv_data *ddata)
{
- struct omap_dss_device *src = ddata->dssdev.src;
+ struct omap_dss_device *src = ddata->src;
int r;
if (!ddata->ulps_enabled)
return 0;
- r = src->ops->enable(src);
- if (r) {
- dev_err(&ddata->pdev->dev, "failed to enable DSI\n");
- goto err1;
- }
-
+ src->ops->enable(src);
src->ops->dsi.enable_hs(src, ddata->channel, true);
r = _dsicm_enable_te(ddata, true);
@@ -347,7 +345,7 @@ err2:
enable_irq(gpiod_to_irq(ddata->ext_te_gpio));
ddata->ulps_enabled = false;
}
-err1:
+
dsicm_queue_ulps_work(ddata);
return r;
@@ -366,7 +364,7 @@ static int dsicm_wake_up(struct panel_drv_data *ddata)
static int dsicm_bl_update_status(struct backlight_device *dev)
{
struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev);
- struct omap_dss_device *src = ddata->dssdev.src;
+ struct omap_dss_device *src = ddata->src;
int r = 0;
int level;
@@ -414,7 +412,7 @@ static ssize_t dsicm_num_errors_show(struct device *dev,
{
struct platform_device *pdev = to_platform_device(dev);
struct panel_drv_data *ddata = platform_get_drvdata(pdev);
- struct omap_dss_device *src = ddata->dssdev.src;
+ struct omap_dss_device *src = ddata->src;
u8 errors = 0;
int r;
@@ -446,7 +444,7 @@ static ssize_t dsicm_hw_revision_show(struct device *dev,
{
struct platform_device *pdev = to_platform_device(dev);
struct panel_drv_data *ddata = platform_get_drvdata(pdev);
- struct omap_dss_device *src = ddata->dssdev.src;
+ struct omap_dss_device *src = ddata->src;
u8 id1, id2, id3;
int r;
@@ -478,7 +476,7 @@ static ssize_t dsicm_store_ulps(struct device *dev,
{
struct platform_device *pdev = to_platform_device(dev);
struct panel_drv_data *ddata = platform_get_drvdata(pdev);
- struct omap_dss_device *src = ddata->dssdev.src;
+ struct omap_dss_device *src = ddata->src;
unsigned long t;
int r;
@@ -528,7 +526,7 @@ static ssize_t dsicm_store_ulps_timeout(struct device *dev,
{
struct platform_device *pdev = to_platform_device(dev);
struct panel_drv_data *ddata = platform_get_drvdata(pdev);
- struct omap_dss_device *src = ddata->dssdev.src;
+ struct omap_dss_device *src = ddata->src;
unsigned long t;
int r;
@@ -603,7 +601,7 @@ static void dsicm_hw_reset(struct panel_drv_data *ddata)
static int dsicm_power_on(struct panel_drv_data *ddata)
{
- struct omap_dss_device *src = ddata->dssdev.src;
+ struct omap_dss_device *src = ddata->src;
u8 id1, id2, id3;
int r;
struct omap_dss_dsi_config dsi_config = {
@@ -649,11 +647,7 @@ static int dsicm_power_on(struct panel_drv_data *ddata)
goto err_vddi;
}
- r = src->ops->enable(src);
- if (r) {
- dev_err(&ddata->pdev->dev, "failed to enable DSI\n");
- goto err_vddi;
- }
+ src->ops->enable(src);
dsicm_hw_reset(ddata);
@@ -722,7 +716,7 @@ err_vpnl:
static void dsicm_power_off(struct panel_drv_data *ddata)
{
- struct omap_dss_device *src = ddata->dssdev.src;
+ struct omap_dss_device *src = ddata->src;
int r;
src->ops->dsi.disable_video_output(src, ddata->channel);
@@ -776,6 +770,7 @@ static int dsicm_connect(struct omap_dss_device *src,
return r;
}
+ ddata->src = src;
return 0;
}
@@ -785,28 +780,17 @@ static void dsicm_disconnect(struct omap_dss_device *src,
struct panel_drv_data *ddata = to_panel_data(dst);
src->ops->dsi.release_vc(src, ddata->channel);
+ ddata->src = NULL;
}
-static int dsicm_enable(struct omap_dss_device *dssdev)
+static void dsicm_enable(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- struct omap_dss_device *src = dssdev->src;
+ struct omap_dss_device *src = ddata->src;
int r;
- dev_dbg(&ddata->pdev->dev, "enable\n");
-
mutex_lock(&ddata->lock);
- if (!omapdss_device_is_connected(dssdev)) {
- r = -ENODEV;
- goto err;
- }
-
- if (omapdss_device_is_enabled(dssdev)) {
- r = 0;
- goto err;
- }
-
src->ops->dsi.bus_lock(src);
r = dsicm_power_on(ddata);
@@ -816,27 +800,22 @@ static int dsicm_enable(struct omap_dss_device *dssdev)
if (r)
goto err;
- dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
mutex_unlock(&ddata->lock);
dsicm_bl_power(ddata, true);
- return 0;
+ return;
err:
- dev_dbg(&ddata->pdev->dev, "enable failed\n");
+ dev_dbg(&ddata->pdev->dev, "enable failed (%d)\n", r);
mutex_unlock(&ddata->lock);
- return r;
}
static void dsicm_disable(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- struct omap_dss_device *src = dssdev->src;
+ struct omap_dss_device *src = ddata->src;
int r;
- dev_dbg(&ddata->pdev->dev, "disable\n");
-
dsicm_bl_power(ddata, false);
mutex_lock(&ddata->lock);
@@ -845,23 +824,19 @@ static void dsicm_disable(struct omap_dss_device *dssdev)
src->ops->dsi.bus_lock(src);
- if (omapdss_device_is_enabled(dssdev)) {
- r = dsicm_wake_up(ddata);
- if (!r)
- dsicm_power_off(ddata);
- }
+ r = dsicm_wake_up(ddata);
+ if (!r)
+ dsicm_power_off(ddata);
src->ops->dsi.bus_unlock(src);
- dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-
mutex_unlock(&ddata->lock);
}
static void dsicm_framedone_cb(int err, void *data)
{
struct panel_drv_data *ddata = data;
- struct omap_dss_device *src = ddata->dssdev.src;
+ struct omap_dss_device *src = ddata->src;
dev_dbg(&ddata->pdev->dev, "framedone, err %d\n", err);
src->ops->dsi.bus_unlock(src);
@@ -870,7 +845,7 @@ static void dsicm_framedone_cb(int err, void *data)
static irqreturn_t dsicm_te_isr(int irq, void *data)
{
struct panel_drv_data *ddata = data;
- struct omap_dss_device *src = ddata->dssdev.src;
+ struct omap_dss_device *src = ddata->src;
int old;
int r;
@@ -896,7 +871,7 @@ static void dsicm_te_timeout_work_callback(struct work_struct *work)
{
struct panel_drv_data *ddata = container_of(work, struct panel_drv_data,
te_timeout_work.work);
- struct omap_dss_device *src = ddata->dssdev.src;
+ struct omap_dss_device *src = ddata->src;
dev_err(&ddata->pdev->dev, "TE not received for 250ms!\n");
@@ -908,7 +883,7 @@ static int dsicm_update(struct omap_dss_device *dssdev,
u16 x, u16 y, u16 w, u16 h)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- struct omap_dss_device *src = dssdev->src;
+ struct omap_dss_device *src = ddata->src;
int r;
dev_dbg(&ddata->pdev->dev, "update %d, %d, %d x %d\n", x, y, w, h);
@@ -954,7 +929,7 @@ err:
static int dsicm_sync(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- struct omap_dss_device *src = dssdev->src;
+ struct omap_dss_device *src = ddata->src;
dev_dbg(&ddata->pdev->dev, "sync\n");
@@ -970,7 +945,7 @@ static int dsicm_sync(struct omap_dss_device *dssdev)
static int _dsicm_enable_te(struct panel_drv_data *ddata, bool enable)
{
- struct omap_dss_device *src = ddata->dssdev.src;
+ struct omap_dss_device *src = ddata->src;
int r;
if (enable)
@@ -990,7 +965,7 @@ static int _dsicm_enable_te(struct panel_drv_data *ddata, bool enable)
static int dsicm_enable_te(struct omap_dss_device *dssdev, bool enable)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- struct omap_dss_device *src = dssdev->src;
+ struct omap_dss_device *src = ddata->src;
int r;
mutex_lock(&ddata->lock);
@@ -1041,7 +1016,7 @@ static int dsicm_memory_read(struct omap_dss_device *dssdev,
u16 x, u16 y, u16 w, u16 h)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- struct omap_dss_device *src = dssdev->src;
+ struct omap_dss_device *src = ddata->src;
int r;
int first = 1;
int plen;
@@ -1123,7 +1098,7 @@ static void dsicm_ulps_work(struct work_struct *work)
struct panel_drv_data *ddata = container_of(work, struct panel_drv_data,
ulps_work.work);
struct omap_dss_device *dssdev = &ddata->dssdev;
- struct omap_dss_device *src = dssdev->src;
+ struct omap_dss_device *src = ddata->src;
mutex_lock(&ddata->lock);
@@ -1140,29 +1115,32 @@ static void dsicm_ulps_work(struct work_struct *work)
mutex_unlock(&ddata->lock);
}
-static void dsicm_get_timings(struct omap_dss_device *dssdev,
- struct videomode *vm)
+static int dsicm_get_modes(struct omap_dss_device *dssdev,
+ struct drm_connector *connector)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- *vm = ddata->vm;
+ connector->display_info.width_mm = ddata->width_mm;
+ connector->display_info.height_mm = ddata->height_mm;
+
+ return omapdss_display_get_modes(connector, &ddata->vm);
}
static int dsicm_check_timings(struct omap_dss_device *dssdev,
- struct videomode *vm)
+ struct drm_display_mode *mode)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
int ret = 0;
- if (vm->hactive != ddata->vm.hactive)
+ if (mode->hdisplay != ddata->vm.hactive)
ret = -EINVAL;
- if (vm->vactive != ddata->vm.vactive)
+ if (mode->vdisplay != ddata->vm.vactive)
ret = -EINVAL;
if (ret) {
dev_warn(dssdev->dev, "wrong resolution: %d x %d",
- vm->hactive, vm->vactive);
+ mode->hdisplay, mode->vdisplay);
dev_warn(dssdev->dev, "panel resolution: %d x %d",
ddata->vm.hactive, ddata->vm.vactive);
}
@@ -1170,15 +1148,6 @@ static int dsicm_check_timings(struct omap_dss_device *dssdev,
return ret;
}
-static void dsicm_get_size(struct omap_dss_device *dssdev,
- unsigned int *width, unsigned int *height)
-{
- struct panel_drv_data *ddata = to_panel_data(dssdev);
-
- *width = ddata->width_mm;
- *height = ddata->height_mm;
-}
-
static const struct omap_dss_device_ops dsicm_ops = {
.connect = dsicm_connect,
.disconnect = dsicm_disconnect,
@@ -1186,7 +1155,7 @@ static const struct omap_dss_device_ops dsicm_ops = {
.enable = dsicm_enable,
.disable = dsicm_disable,
- .get_timings = dsicm_get_timings,
+ .get_modes = dsicm_get_modes,
.check_timings = dsicm_check_timings,
};
@@ -1194,8 +1163,6 @@ static const struct omap_dss_driver dsicm_dss_driver = {
.update = dsicm_update,
.sync = dsicm_sync,
- .get_size = dsicm_get_size,
-
.enable_te = dsicm_enable_te,
.get_te = dsicm_get_te,
@@ -1305,8 +1272,10 @@ static int dsicm_probe(struct platform_device *pdev)
dssdev->ops = &dsicm_ops;
dssdev->driver = &dsicm_dss_driver;
dssdev->type = OMAP_DISPLAY_TYPE_DSI;
+ dssdev->display = true;
dssdev->owner = THIS_MODULE;
dssdev->of_ports = BIT(0);
+ dssdev->ops_flags = OMAP_DSS_DEVICE_OP_MODES;
dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
@@ -1385,8 +1354,9 @@ static int __exit dsicm_remove(struct platform_device *pdev)
omapdss_device_unregister(dssdev);
- dsicm_disable(dssdev);
- omapdss_device_disconnect(dssdev->src, dssdev);
+ if (omapdss_device_is_enabled(dssdev))
+ dsicm_disable(dssdev);
+ omapdss_device_disconnect(ddata->src, dssdev);
sysfs_remove_group(&pdev->dev.kobj, &dsicm_attr_group);
diff --git a/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c b/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c
index f6ef8ff964dd..99f2350d462c 100644
--- a/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c
+++ b/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c
@@ -123,52 +123,28 @@ static void lb035q02_disconnect(struct omap_dss_device *src,
{
}
-static int lb035q02_enable(struct omap_dss_device *dssdev)
+static void lb035q02_enable(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- struct omap_dss_device *src = dssdev->src;
- int r;
-
- if (!omapdss_device_is_connected(dssdev))
- return -ENODEV;
-
- if (omapdss_device_is_enabled(dssdev))
- return 0;
-
- r = src->ops->enable(src);
- if (r)
- return r;
if (ddata->enable_gpio)
gpiod_set_value_cansleep(ddata->enable_gpio, 1);
-
- dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
- return 0;
}
static void lb035q02_disable(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- struct omap_dss_device *src = dssdev->src;
-
- if (!omapdss_device_is_enabled(dssdev))
- return;
if (ddata->enable_gpio)
gpiod_set_value_cansleep(ddata->enable_gpio, 0);
-
- src->ops->disable(src);
-
- dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
}
-static void lb035q02_get_timings(struct omap_dss_device *dssdev,
- struct videomode *vm)
+static int lb035q02_get_modes(struct omap_dss_device *dssdev,
+ struct drm_connector *connector)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- *vm = ddata->vm;
+ return omapdss_display_get_modes(connector, &ddata->vm);
}
static const struct omap_dss_device_ops lb035q02_ops = {
@@ -178,7 +154,7 @@ static const struct omap_dss_device_ops lb035q02_ops = {
.enable = lb035q02_enable,
.disable = lb035q02_disable,
- .get_timings = lb035q02_get_timings,
+ .get_modes = lb035q02_get_modes,
};
static int lb035q02_probe_of(struct spi_device *spi)
@@ -221,16 +197,19 @@ static int lb035q02_panel_spi_probe(struct spi_device *spi)
dssdev->dev = &spi->dev;
dssdev->ops = &lb035q02_ops;
dssdev->type = OMAP_DISPLAY_TYPE_DPI;
+ dssdev->display = true;
dssdev->owner = THIS_MODULE;
dssdev->of_ports = BIT(0);
+ dssdev->ops_flags = OMAP_DSS_DEVICE_OP_MODES;
/*
* Note: According to the panel documentation:
* DE is active LOW
* DATA needs to be driven on the FALLING edge
*/
- dssdev->bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_SYNC_NEGEDGE
- | DRM_BUS_FLAG_PIXDATA_POSEDGE;
+ dssdev->bus_flags = DRM_BUS_FLAG_DE_HIGH
+ | DRM_BUS_FLAG_SYNC_DRIVE_NEGEDGE
+ | DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE;
omapdss_display_init(dssdev);
omapdss_device_register(dssdev);
diff --git a/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c b/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c
index f445de6369f7..c2409815a204 100644
--- a/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c
+++ b/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c
@@ -118,50 +118,26 @@ static void nec_8048_disconnect(struct omap_dss_device *src,
{
}
-static int nec_8048_enable(struct omap_dss_device *dssdev)
+static void nec_8048_enable(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- struct omap_dss_device *src = dssdev->src;
- int r;
-
- if (!omapdss_device_is_connected(dssdev))
- return -ENODEV;
-
- if (omapdss_device_is_enabled(dssdev))
- return 0;
-
- r = src->ops->enable(src);
- if (r)
- return r;
gpiod_set_value_cansleep(ddata->res_gpio, 1);
-
- dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
- return 0;
}
static void nec_8048_disable(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- struct omap_dss_device *src = dssdev->src;
-
- if (!omapdss_device_is_enabled(dssdev))
- return;
gpiod_set_value_cansleep(ddata->res_gpio, 0);
-
- src->ops->disable(src);
-
- dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
}
-static void nec_8048_get_timings(struct omap_dss_device *dssdev,
- struct videomode *vm)
+static int nec_8048_get_modes(struct omap_dss_device *dssdev,
+ struct drm_connector *connector)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- *vm = ddata->vm;
+ return omapdss_display_get_modes(connector, &ddata->vm);
}
static const struct omap_dss_device_ops nec_8048_ops = {
@@ -171,7 +147,7 @@ static const struct omap_dss_device_ops nec_8048_ops = {
.enable = nec_8048_enable,
.disable = nec_8048_disable,
- .get_timings = nec_8048_get_timings,
+ .get_modes = nec_8048_get_modes,
};
static int nec_8048_probe(struct spi_device *spi)
@@ -216,10 +192,13 @@ static int nec_8048_probe(struct spi_device *spi)
dssdev->dev = &spi->dev;
dssdev->ops = &nec_8048_ops;
dssdev->type = OMAP_DISPLAY_TYPE_DPI;
+ dssdev->display = true;
dssdev->owner = THIS_MODULE;
dssdev->of_ports = BIT(0);
- dssdev->bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_SYNC_POSEDGE
- | DRM_BUS_FLAG_PIXDATA_POSEDGE;
+ dssdev->ops_flags = OMAP_DSS_DEVICE_OP_MODES;
+ dssdev->bus_flags = DRM_BUS_FLAG_DE_HIGH
+ | DRM_BUS_FLAG_SYNC_DRIVE_POSEDGE
+ | DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE;
omapdss_display_init(dssdev);
omapdss_device_register(dssdev);
diff --git a/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c b/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c
index 64b1369cb274..9c545de430f6 100644
--- a/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c
+++ b/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c
@@ -62,29 +62,22 @@ static void sharp_ls_disconnect(struct omap_dss_device *src,
{
}
-static int sharp_ls_enable(struct omap_dss_device *dssdev)
+static void sharp_ls_pre_enable(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- struct omap_dss_device *src = dssdev->src;
int r;
- if (!omapdss_device_is_connected(dssdev))
- return -ENODEV;
-
- if (omapdss_device_is_enabled(dssdev))
- return 0;
-
if (ddata->vcc) {
r = regulator_enable(ddata->vcc);
- if (r != 0)
- return r;
+ if (r)
+ dev_err(dssdev->dev, "%s: failed to enable regulator\n",
+ __func__);
}
+}
- r = src->ops->enable(src);
- if (r) {
- regulator_disable(ddata->vcc);
- return r;
- }
+static void sharp_ls_enable(struct omap_dss_device *dssdev)
+{
+ struct panel_drv_data *ddata = to_panel_data(dssdev);
/* wait couple of vsyncs until enabling the LCD */
msleep(50);
@@ -94,19 +87,11 @@ static int sharp_ls_enable(struct omap_dss_device *dssdev)
if (ddata->ini_gpio)
gpiod_set_value_cansleep(ddata->ini_gpio, 1);
-
- dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
- return 0;
}
static void sharp_ls_disable(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- struct omap_dss_device *src = dssdev->src;
-
- if (!omapdss_device_is_enabled(dssdev))
- return;
if (ddata->ini_gpio)
gpiod_set_value_cansleep(ddata->ini_gpio, 0);
@@ -115,33 +100,35 @@ static void sharp_ls_disable(struct omap_dss_device *dssdev)
gpiod_set_value_cansleep(ddata->resb_gpio, 0);
/* wait at least 5 vsyncs after disabling the LCD */
-
msleep(100);
+}
- src->ops->disable(src);
+static void sharp_ls_post_disable(struct omap_dss_device *dssdev)
+{
+ struct panel_drv_data *ddata = to_panel_data(dssdev);
if (ddata->vcc)
regulator_disable(ddata->vcc);
-
- dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
}
-static void sharp_ls_get_timings(struct omap_dss_device *dssdev,
- struct videomode *vm)
+static int sharp_ls_get_modes(struct omap_dss_device *dssdev,
+ struct drm_connector *connector)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- *vm = ddata->vm;
+ return omapdss_display_get_modes(connector, &ddata->vm);
}
static const struct omap_dss_device_ops sharp_ls_ops = {
.connect = sharp_ls_connect,
.disconnect = sharp_ls_disconnect,
+ .pre_enable = sharp_ls_pre_enable,
.enable = sharp_ls_enable,
.disable = sharp_ls_disable,
+ .post_disable = sharp_ls_post_disable,
- .get_timings = sharp_ls_get_timings,
+ .get_modes = sharp_ls_get_modes,
};
static int sharp_ls_get_gpio_of(struct device *dev, int index, int val,
@@ -220,15 +207,18 @@ static int sharp_ls_probe(struct platform_device *pdev)
dssdev->dev = &pdev->dev;
dssdev->ops = &sharp_ls_ops;
dssdev->type = OMAP_DISPLAY_TYPE_DPI;
+ dssdev->display = true;
dssdev->owner = THIS_MODULE;
dssdev->of_ports = BIT(0);
+ dssdev->ops_flags = OMAP_DSS_DEVICE_OP_MODES;
/*
* Note: According to the panel documentation:
* DATA needs to be driven on the FALLING edge
*/
- dssdev->bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_SYNC_NEGEDGE
- | DRM_BUS_FLAG_PIXDATA_POSEDGE;
+ dssdev->bus_flags = DRM_BUS_FLAG_DE_HIGH
+ | DRM_BUS_FLAG_SYNC_DRIVE_NEGEDGE
+ | DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE;
omapdss_display_init(dssdev);
omapdss_device_register(dssdev);
@@ -243,7 +233,10 @@ static int __exit sharp_ls_remove(struct platform_device *pdev)
omapdss_device_unregister(dssdev);
- sharp_ls_disable(dssdev);
+ if (omapdss_device_is_enabled(dssdev)) {
+ sharp_ls_disable(dssdev);
+ sharp_ls_post_disable(dssdev);
+ }
return 0;
}
diff --git a/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c b/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c
index e04663856b31..2038def14ba1 100644
--- a/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c
+++ b/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c
@@ -516,17 +516,9 @@ static void acx565akm_disconnect(struct omap_dss_device *src,
static int acx565akm_panel_power_on(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- struct omap_dss_device *src = dssdev->src;
- int r;
dev_dbg(&ddata->spi->dev, "%s\n", __func__);
- r = src->ops->enable(src);
- if (r) {
- pr_err("%s sdi enable failed\n", __func__);
- return r;
- }
-
/*FIXME tweak me */
msleep(50);
@@ -562,7 +554,6 @@ static int acx565akm_panel_power_on(struct omap_dss_device *dssdev)
static void acx565akm_panel_power_off(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- struct omap_dss_device *src = dssdev->src;
dev_dbg(dssdev->dev, "%s\n", __func__);
@@ -585,56 +576,32 @@ static void acx565akm_panel_power_off(struct omap_dss_device *dssdev)
/* FIXME need to tweak this delay */
msleep(100);
-
- src->ops->disable(src);
}
-static int acx565akm_enable(struct omap_dss_device *dssdev)
+static void acx565akm_enable(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- int r;
-
- dev_dbg(dssdev->dev, "%s\n", __func__);
-
- if (!omapdss_device_is_connected(dssdev))
- return -ENODEV;
-
- if (omapdss_device_is_enabled(dssdev))
- return 0;
mutex_lock(&ddata->mutex);
- r = acx565akm_panel_power_on(dssdev);
+ acx565akm_panel_power_on(dssdev);
mutex_unlock(&ddata->mutex);
- if (r)
- return r;
-
- dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
- return 0;
}
static void acx565akm_disable(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- dev_dbg(dssdev->dev, "%s\n", __func__);
-
- if (!omapdss_device_is_enabled(dssdev))
- return;
-
mutex_lock(&ddata->mutex);
acx565akm_panel_power_off(dssdev);
mutex_unlock(&ddata->mutex);
-
- dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
}
-static void acx565akm_get_timings(struct omap_dss_device *dssdev,
- struct videomode *vm)
+static int acx565akm_get_modes(struct omap_dss_device *dssdev,
+ struct drm_connector *connector)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- *vm = ddata->vm;
+ return omapdss_display_get_modes(connector, &ddata->vm);
}
static const struct omap_dss_device_ops acx565akm_ops = {
@@ -644,7 +611,7 @@ static const struct omap_dss_device_ops acx565akm_ops = {
.enable = acx565akm_enable,
.disable = acx565akm_disable,
- .get_timings = acx565akm_get_timings,
+ .get_modes = acx565akm_get_modes,
};
static int acx565akm_probe(struct spi_device *spi)
@@ -739,10 +706,13 @@ static int acx565akm_probe(struct spi_device *spi)
dssdev->dev = &spi->dev;
dssdev->ops = &acx565akm_ops;
dssdev->type = OMAP_DISPLAY_TYPE_SDI;
+ dssdev->display = true;
dssdev->owner = THIS_MODULE;
dssdev->of_ports = BIT(0);
- dssdev->bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_SYNC_NEGEDGE
- | DRM_BUS_FLAG_PIXDATA_POSEDGE;
+ dssdev->ops_flags = OMAP_DSS_DEVICE_OP_MODES;
+ dssdev->bus_flags = DRM_BUS_FLAG_DE_HIGH
+ | DRM_BUS_FLAG_SYNC_DRIVE_NEGEDGE
+ | DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE;
omapdss_display_init(dssdev);
omapdss_device_register(dssdev);
@@ -766,7 +736,8 @@ static int acx565akm_remove(struct spi_device *spi)
omapdss_device_unregister(dssdev);
- acx565akm_disable(dssdev);
+ if (omapdss_device_is_enabled(dssdev))
+ acx565akm_disable(dssdev);
return 0;
}
diff --git a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c
index 7ddc8c574a61..2ad161e33106 100644
--- a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c
+++ b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c
@@ -35,6 +35,8 @@ struct panel_drv_data {
struct videomode vm;
+ struct backlight_device *backlight;
+
struct spi_device *spi_dev;
};
@@ -169,24 +171,12 @@ static void td028ttec1_panel_disconnect(struct omap_dss_device *src,
{
}
-static int td028ttec1_panel_enable(struct omap_dss_device *dssdev)
+static void td028ttec1_panel_enable(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- struct omap_dss_device *src = dssdev->src;
- int r;
-
- if (!omapdss_device_is_connected(dssdev))
- return -ENODEV;
-
- if (omapdss_device_is_enabled(dssdev))
- return 0;
-
- r = src->ops->enable(src);
- if (r)
- return r;
+ int r = 0;
- dev_dbg(dssdev->dev, "td028ttec1_panel_enable() - state %d\n",
- dssdev->state);
+ dev_dbg(dssdev->dev, "%s: state %d\n", __func__, dssdev->state);
/* three times command zero */
r |= jbt_ret_write_0(ddata, 0x00);
@@ -197,8 +187,8 @@ static int td028ttec1_panel_enable(struct omap_dss_device *dssdev)
usleep_range(1000, 2000);
if (r) {
- dev_warn(dssdev->dev, "transfer error\n");
- goto transfer_err;
+ dev_warn(dssdev->dev, "%s: transfer error\n", __func__);
+ return;
}
/* deep standby out */
@@ -268,20 +258,17 @@ static int td028ttec1_panel_enable(struct omap_dss_device *dssdev)
r |= jbt_ret_write_0(ddata, JBT_REG_DISPLAY_ON);
- dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-transfer_err:
+ if (r)
+ dev_err(dssdev->dev, "%s: write error\n", __func__);
- return r ? -EIO : 0;
+ backlight_enable(ddata->backlight);
}
static void td028ttec1_panel_disable(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- struct omap_dss_device *src = dssdev->src;
- if (!omapdss_device_is_enabled(dssdev))
- return;
+ backlight_disable(ddata->backlight);
dev_dbg(dssdev->dev, "td028ttec1_panel_disable()\n");
@@ -289,18 +276,14 @@ static void td028ttec1_panel_disable(struct omap_dss_device *dssdev)
jbt_reg_write_2(ddata, JBT_REG_OUTPUT_CONTROL, 0x8002);
jbt_ret_write_0(ddata, JBT_REG_SLEEP_IN);
jbt_reg_write_1(ddata, JBT_REG_POWER_ON_OFF, 0x00);
-
- src->ops->disable(src);
-
- dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
}
-static void td028ttec1_panel_get_timings(struct omap_dss_device *dssdev,
- struct videomode *vm)
+static int td028ttec1_panel_get_modes(struct omap_dss_device *dssdev,
+ struct drm_connector *connector)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- *vm = ddata->vm;
+ return omapdss_display_get_modes(connector, &ddata->vm);
}
static const struct omap_dss_device_ops td028ttec1_ops = {
@@ -310,7 +293,7 @@ static const struct omap_dss_device_ops td028ttec1_ops = {
.enable = td028ttec1_panel_enable,
.disable = td028ttec1_panel_disable,
- .get_timings = td028ttec1_panel_get_timings,
+ .get_modes = td028ttec1_panel_get_modes,
};
static int td028ttec1_panel_probe(struct spi_device *spi)
@@ -334,6 +317,10 @@ static int td028ttec1_panel_probe(struct spi_device *spi)
if (ddata == NULL)
return -ENOMEM;
+ ddata->backlight = devm_of_find_backlight(&spi->dev);
+ if (IS_ERR(ddata->backlight))
+ return PTR_ERR(ddata->backlight);
+
dev_set_drvdata(&spi->dev, ddata);
ddata->spi_dev = spi;
@@ -344,15 +331,18 @@ static int td028ttec1_panel_probe(struct spi_device *spi)
dssdev->dev = &spi->dev;
dssdev->ops = &td028ttec1_ops;
dssdev->type = OMAP_DISPLAY_TYPE_DPI;
+ dssdev->display = true;
dssdev->owner = THIS_MODULE;
dssdev->of_ports = BIT(0);
+ dssdev->ops_flags = OMAP_DSS_DEVICE_OP_MODES;
/*
* Note: According to the panel documentation:
* SYNC needs to be driven on the FALLING edge
*/
- dssdev->bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_SYNC_POSEDGE
- | DRM_BUS_FLAG_PIXDATA_NEGEDGE;
+ dssdev->bus_flags = DRM_BUS_FLAG_DE_HIGH
+ | DRM_BUS_FLAG_SYNC_DRIVE_POSEDGE
+ | DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE;
omapdss_display_init(dssdev);
omapdss_device_register(dssdev);
diff --git a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c
index 8440fcb744d9..0b692fc7e5ea 100644
--- a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c
+++ b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c
@@ -320,22 +320,11 @@ static void tpo_td043_disconnect(struct omap_dss_device *src,
{
}
-static int tpo_td043_enable(struct omap_dss_device *dssdev)
+static void tpo_td043_enable(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- struct omap_dss_device *src = dssdev->src;
int r;
- if (!omapdss_device_is_connected(dssdev))
- return -ENODEV;
-
- if (omapdss_device_is_enabled(dssdev))
- return 0;
-
- r = src->ops->enable(src);
- if (r)
- return r;
-
/*
* If we are resuming from system suspend, SPI clocks might not be
* enabled yet, so we'll program the LCD from SPI PM resume callback.
@@ -343,38 +332,27 @@ static int tpo_td043_enable(struct omap_dss_device *dssdev)
if (!ddata->spi_suspended) {
r = tpo_td043_power_on(ddata);
if (r) {
- src->ops->disable(src);
- return r;
+ dev_err(&ddata->spi->dev, "%s: power on failed (%d)\n",
+ __func__, r);
+ return;
}
}
-
- dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
- return 0;
}
static void tpo_td043_disable(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- struct omap_dss_device *src = dssdev->src;
-
- if (!omapdss_device_is_enabled(dssdev))
- return;
-
- src->ops->disable(src);
if (!ddata->spi_suspended)
tpo_td043_power_off(ddata);
-
- dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
}
-static void tpo_td043_get_timings(struct omap_dss_device *dssdev,
- struct videomode *vm)
+static int tpo_td043_get_modes(struct omap_dss_device *dssdev,
+ struct drm_connector *connector)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
- *vm = ddata->vm;
+ return omapdss_display_get_modes(connector, &ddata->vm);
}
static const struct omap_dss_device_ops tpo_td043_ops = {
@@ -384,7 +362,7 @@ static const struct omap_dss_device_ops tpo_td043_ops = {
.enable = tpo_td043_enable,
.disable = tpo_td043_disable,
- .get_timings = tpo_td043_get_timings,
+ .get_modes = tpo_td043_get_modes,
};
static int tpo_td043_probe(struct spi_device *spi)
@@ -442,15 +420,18 @@ static int tpo_td043_probe(struct spi_device *spi)
dssdev->dev = &spi->dev;
dssdev->ops = &tpo_td043_ops;
dssdev->type = OMAP_DISPLAY_TYPE_DPI;
+ dssdev->display = true;
dssdev->owner = THIS_MODULE;
dssdev->of_ports = BIT(0);
+ dssdev->ops_flags = OMAP_DSS_DEVICE_OP_MODES;
/*
* Note: According to the panel documentation:
* SYNC needs to be driven on the FALLING edge
*/
- dssdev->bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_SYNC_POSEDGE
- | DRM_BUS_FLAG_PIXDATA_NEGEDGE;
+ dssdev->bus_flags = DRM_BUS_FLAG_DE_HIGH
+ | DRM_BUS_FLAG_SYNC_DRIVE_POSEDGE
+ | DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE;
omapdss_display_init(dssdev);
omapdss_device_register(dssdev);
@@ -467,7 +448,8 @@ static int tpo_td043_remove(struct spi_device *spi)
omapdss_device_unregister(dssdev);
- tpo_td043_disable(dssdev);
+ if (omapdss_device_is_enabled(dssdev))
+ tpo_td043_disable(dssdev);
sysfs_remove_group(&spi->dev.kobj, &tpo_td043_attr_group);
diff --git a/drivers/gpu/drm/omapdrm/dss/base.c b/drivers/gpu/drm/omapdrm/dss/base.c
index 472f56e3de70..f8dad99013e8 100644
--- a/drivers/gpu/drm/omapdrm/dss/base.c
+++ b/drivers/gpu/drm/omapdrm/dss/base.c
@@ -19,6 +19,7 @@
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/of_graph.h>
+#include <linux/platform_device.h>
#include "dss.h"
#include "omapdss.h"
@@ -112,13 +113,12 @@ void omapdss_device_put(struct omap_dss_device *dssdev)
}
EXPORT_SYMBOL(omapdss_device_put);
-struct omap_dss_device *omapdss_find_device_by_port(struct device_node *src,
- unsigned int port)
+struct omap_dss_device *omapdss_find_device_by_node(struct device_node *node)
{
struct omap_dss_device *dssdev;
list_for_each_entry(dssdev, &omapdss_devices_list, list) {
- if (dssdev->dev->of_node == src && dssdev->of_ports & BIT(port))
+ if (dssdev->dev->of_node == node)
return omapdss_device_get(dssdev);
}
@@ -126,13 +126,10 @@ struct omap_dss_device *omapdss_find_device_by_port(struct device_node *src,
}
/*
- * Search for the next device starting at @from. The type argument specfies
- * which device types to consider when searching. Searching for multiple types
- * is supported by and'ing their type flags. Release the reference to the @from
- * device, and acquire a reference to the returned device if found.
+ * Search for the next output device starting at @from. Release the reference to
+ * the @from device, and acquire a reference to the returned device if found.
*/
-struct omap_dss_device *omapdss_device_get_next(struct omap_dss_device *from,
- enum omap_dss_device_type type)
+struct omap_dss_device *omapdss_device_next_output(struct omap_dss_device *from)
{
struct omap_dss_device *dssdev;
struct list_head *list;
@@ -160,15 +157,8 @@ struct omap_dss_device *omapdss_device_get_next(struct omap_dss_device *from,
goto done;
}
- /*
- * Accept display entities if the display type is requested,
- * and output entities if the output type is requested.
- */
- if ((type & OMAP_DSS_DEVICE_TYPE_DISPLAY) &&
- !dssdev->output_type)
- goto done;
- if ((type & OMAP_DSS_DEVICE_TYPE_OUTPUT) && dssdev->id &&
- dssdev->next)
+ if (dssdev->id &&
+ (dssdev->next || dssdev->bridge || dssdev->panel))
goto done;
}
@@ -183,7 +173,12 @@ done:
mutex_unlock(&omapdss_devices_lock);
return dssdev;
}
-EXPORT_SYMBOL(omapdss_device_get_next);
+EXPORT_SYMBOL(omapdss_device_next_output);
+
+static bool omapdss_device_is_connected(struct omap_dss_device *dssdev)
+{
+ return dssdev->dss;
+}
int omapdss_device_connect(struct dss_device *dss,
struct omap_dss_device *src,
@@ -191,7 +186,19 @@ int omapdss_device_connect(struct dss_device *dss,
{
int ret;
- dev_dbg(dst->dev, "connect\n");
+ dev_dbg(&dss->pdev->dev, "connect(%s, %s)\n",
+ src ? dev_name(src->dev) : "NULL",
+ dst ? dev_name(dst->dev) : "NULL");
+
+ if (!dst) {
+ /*
+ * The destination is NULL when the source is connected to a
+ * bridge or panel instead of a DSS device. Stop here, we will
+ * attach the bridge or panel later when we will have a DRM
+ * encoder.
+ */
+ return src && (src->bridge || src->panel) ? 0 : -EINVAL;
+ }
if (omapdss_device_is_connected(dst))
return -EBUSY;
@@ -204,12 +211,6 @@ int omapdss_device_connect(struct dss_device *dss,
return ret;
}
- if (src) {
- WARN_ON(src->dst);
- dst->src = src;
- src->dst = dst;
- }
-
return 0;
}
EXPORT_SYMBOL_GPL(omapdss_device_connect);
@@ -217,19 +218,20 @@ EXPORT_SYMBOL_GPL(omapdss_device_connect);
void omapdss_device_disconnect(struct omap_dss_device *src,
struct omap_dss_device *dst)
{
- dev_dbg(dst->dev, "disconnect\n");
+ struct dss_device *dss = src ? src->dss : dst->dss;
- if (!dst->id && !omapdss_device_is_connected(dst)) {
- WARN_ON(dst->output_type);
+ dev_dbg(&dss->pdev->dev, "disconnect(%s, %s)\n",
+ src ? dev_name(src->dev) : "NULL",
+ dst ? dev_name(dst->dev) : "NULL");
+
+ if (!dst) {
+ WARN_ON(!src->bridge && !src->panel);
return;
}
- if (src) {
- if (WARN_ON(dst != src->dst))
- return;
-
- dst->src = NULL;
- src->dst = NULL;
+ if (!dst->id && !omapdss_device_is_connected(dst)) {
+ WARN_ON(!dst->display);
+ return;
}
WARN_ON(dst->state != OMAP_DSS_DISPLAY_DISABLED);
@@ -239,6 +241,58 @@ void omapdss_device_disconnect(struct omap_dss_device *src,
}
EXPORT_SYMBOL_GPL(omapdss_device_disconnect);
+void omapdss_device_pre_enable(struct omap_dss_device *dssdev)
+{
+ if (!dssdev)
+ return;
+
+ omapdss_device_pre_enable(dssdev->next);
+
+ if (dssdev->ops->pre_enable)
+ dssdev->ops->pre_enable(dssdev);
+}
+EXPORT_SYMBOL_GPL(omapdss_device_pre_enable);
+
+void omapdss_device_enable(struct omap_dss_device *dssdev)
+{
+ if (!dssdev)
+ return;
+
+ if (dssdev->ops->enable)
+ dssdev->ops->enable(dssdev);
+
+ omapdss_device_enable(dssdev->next);
+
+ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+}
+EXPORT_SYMBOL_GPL(omapdss_device_enable);
+
+void omapdss_device_disable(struct omap_dss_device *dssdev)
+{
+ if (!dssdev)
+ return;
+
+ omapdss_device_disable(dssdev->next);
+
+ if (dssdev->ops->disable)
+ dssdev->ops->disable(dssdev);
+}
+EXPORT_SYMBOL_GPL(omapdss_device_disable);
+
+void omapdss_device_post_disable(struct omap_dss_device *dssdev)
+{
+ if (!dssdev)
+ return;
+
+ if (dssdev->ops->post_disable)
+ dssdev->ops->post_disable(dssdev);
+
+ omapdss_device_post_disable(dssdev->next);
+
+ dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+}
+EXPORT_SYMBOL_GPL(omapdss_device_post_disable);
+
/* -----------------------------------------------------------------------------
* Components Handling
*/
@@ -249,6 +303,7 @@ struct omapdss_comp_node {
struct list_head list;
struct device_node *node;
bool dss_core_component;
+ const char *compat;
};
static bool omapdss_list_contains(const struct device_node *node)
@@ -266,13 +321,20 @@ static bool omapdss_list_contains(const struct device_node *node)
static void omapdss_walk_device(struct device *dev, struct device_node *node,
bool dss_core)
{
+ struct omapdss_comp_node *comp;
struct device_node *n;
- struct omapdss_comp_node *comp = devm_kzalloc(dev, sizeof(*comp),
- GFP_KERNEL);
+ const char *compat;
+ int ret;
+ ret = of_property_read_string(node, "compatible", &compat);
+ if (ret < 0)
+ return;
+
+ comp = devm_kzalloc(dev, sizeof(*comp), GFP_KERNEL);
if (comp) {
comp->node = node;
comp->dss_core_component = dss_core;
+ comp->compat = compat;
list_add(&comp->list, &omapdss_comp_list);
}
@@ -312,12 +374,8 @@ void omapdss_gather_components(struct device *dev)
omapdss_walk_device(dev, dev->of_node, true);
- for_each_available_child_of_node(dev->of_node, child) {
- if (!of_find_property(child, "compatible", NULL))
- continue;
-
+ for_each_available_child_of_node(dev->of_node, child)
omapdss_walk_device(dev, child, true);
- }
}
EXPORT_SYMBOL(omapdss_gather_components);
@@ -325,6 +383,8 @@ static bool omapdss_component_is_loaded(struct omapdss_comp_node *comp)
{
if (comp->dss_core_component)
return true;
+ if (!strstarts(comp->compat, "omapdss,"))
+ return true;
if (omapdss_device_is_registered(comp->node))
return true;
diff --git a/drivers/gpu/drm/omapdrm/dss/display.c b/drivers/gpu/drm/omapdrm/dss/display.c
index 34b2a4ef63a4..e93f61a567a8 100644
--- a/drivers/gpu/drm/omapdrm/dss/display.c
+++ b/drivers/gpu/drm/omapdrm/dss/display.c
@@ -23,6 +23,9 @@
#include <linux/kernel.h>
#include <linux/of.h>
+#include <drm/drm_connector.h>
+#include <drm/drm_modes.h>
+
#include "omapdss.h"
static int disp_num_counter;
@@ -39,8 +42,6 @@ void omapdss_display_init(struct omap_dss_device *dssdev)
if (id < 0)
id = disp_num_counter++;
- dssdev->alias_id = id;
-
/* Use 'label' property for name, if it exists */
of_property_read_string(dssdev->dev->of_node, "label", &dssdev->name);
@@ -58,3 +59,22 @@ struct omap_dss_device *omapdss_display_get(struct omap_dss_device *output)
return omapdss_device_get(output);
}
EXPORT_SYMBOL_GPL(omapdss_display_get);
+
+int omapdss_display_get_modes(struct drm_connector *connector,
+ const struct videomode *vm)
+{
+ struct drm_display_mode *mode;
+
+ mode = drm_mode_create(connector->dev);
+ if (!mode)
+ return 0;
+
+ drm_display_mode_from_videomode(vm, mode);
+
+ mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+ drm_mode_set_name(mode);
+ drm_mode_probed_add(connector, mode);
+
+ return 1;
+}
+EXPORT_SYMBOL_GPL(omapdss_display_get_modes);
diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c b/drivers/gpu/drm/omapdrm/dss/dpi.c
index ca4f3c4c6318..cc78dfa07f04 100644
--- a/drivers/gpu/drm/omapdrm/dss/dpi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dpi.c
@@ -47,8 +47,8 @@ struct dpi_data {
struct mutex lock;
- struct videomode vm;
struct dss_lcd_mgr_config mgr_config;
+ unsigned long pixelclock;
int data_lines;
struct omap_dss_device output;
@@ -347,16 +347,15 @@ static int dpi_set_dispc_clk(struct dpi_data *dpi, unsigned long pck_req,
static int dpi_set_mode(struct dpi_data *dpi)
{
- const struct videomode *vm = &dpi->vm;
int lck_div = 0, pck_div = 0;
unsigned long fck = 0;
int r = 0;
if (dpi->pll)
r = dpi_set_pll_clk(dpi, dpi->output.dispc_channel,
- vm->pixelclock, &fck, &lck_div, &pck_div);
+ dpi->pixelclock, &fck, &lck_div, &pck_div);
else
- r = dpi_set_dispc_clk(dpi, vm->pixelclock, &fck,
+ r = dpi_set_dispc_clk(dpi, dpi->pixelclock, &fck,
&lck_div, &pck_div);
if (r)
return r;
@@ -378,7 +377,7 @@ static void dpi_config_lcd_manager(struct dpi_data *dpi)
dss_mgr_set_lcd_config(&dpi->output, &dpi->mgr_config);
}
-static int dpi_display_enable(struct omap_dss_device *dssdev)
+static void dpi_display_enable(struct omap_dss_device *dssdev)
{
struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
struct omap_dss_device *out = &dpi->output;
@@ -386,12 +385,6 @@ static int dpi_display_enable(struct omap_dss_device *dssdev)
mutex_lock(&dpi->lock);
- if (!out->dispc_channel_connected) {
- DSSERR("failed to enable display: no output/manager\n");
- r = -ENODEV;
- goto err_no_out_mgr;
- }
-
if (dpi->vdds_dsi_reg) {
r = regulator_enable(dpi->vdds_dsi_reg);
if (r)
@@ -426,7 +419,7 @@ static int dpi_display_enable(struct omap_dss_device *dssdev)
mutex_unlock(&dpi->lock);
- return 0;
+ return;
err_mgr_enable:
err_set_mode:
@@ -439,9 +432,7 @@ err_get_dispc:
if (dpi->vdds_dsi_reg)
regulator_disable(dpi->vdds_dsi_reg);
err_reg_enable:
-err_no_out_mgr:
mutex_unlock(&dpi->lock);
- return r;
}
static void dpi_display_disable(struct omap_dss_device *dssdev)
@@ -467,7 +458,7 @@ static void dpi_display_disable(struct omap_dss_device *dssdev)
}
static void dpi_set_timings(struct omap_dss_device *dssdev,
- const struct videomode *vm)
+ const struct drm_display_mode *mode)
{
struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
@@ -475,13 +466,13 @@ static void dpi_set_timings(struct omap_dss_device *dssdev,
mutex_lock(&dpi->lock);
- dpi->vm = *vm;
+ dpi->pixelclock = mode->clock * 1000;
mutex_unlock(&dpi->lock);
}
static int dpi_check_timings(struct omap_dss_device *dssdev,
- struct videomode *vm)
+ struct drm_display_mode *mode)
{
struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
int lck_div, pck_div;
@@ -490,20 +481,20 @@ static int dpi_check_timings(struct omap_dss_device *dssdev,
struct dpi_clk_calc_ctx ctx;
bool ok;
- if (vm->hactive % 8 != 0)
+ if (mode->hdisplay % 8 != 0)
return -EINVAL;
- if (vm->pixelclock == 0)
+ if (mode->clock == 0)
return -EINVAL;
if (dpi->pll) {
- ok = dpi_pll_clk_calc(dpi, vm->pixelclock, &ctx);
+ ok = dpi_pll_clk_calc(dpi, mode->clock * 1000, &ctx);
if (!ok)
return -EINVAL;
fck = ctx.pll_cinfo.clkout[ctx.clkout_idx];
} else {
- ok = dpi_dss_clk_calc(dpi, vm->pixelclock, &ctx);
+ ok = dpi_dss_clk_calc(dpi, mode->clock * 1000, &ctx);
if (!ok)
return -EINVAL;
@@ -515,7 +506,7 @@ static int dpi_check_timings(struct omap_dss_device *dssdev,
pck = fck / lck_div / pck_div;
- vm->pixelclock = pck;
+ mode->clock = pck / 1000;
return 0;
}
@@ -596,23 +587,15 @@ static int dpi_connect(struct omap_dss_device *src,
struct omap_dss_device *dst)
{
struct dpi_data *dpi = dpi_get_data_from_dssdev(dst);
- int r;
dpi_init_pll(dpi);
- r = omapdss_device_connect(dst->dss, dst, dst->next);
- if (r)
- return r;
-
- dst->dispc_channel_connected = true;
- return 0;
+ return omapdss_device_connect(dst->dss, dst, dst->next);
}
static void dpi_disconnect(struct omap_dss_device *src,
struct omap_dss_device *dst)
{
- dst->dispc_channel_connected = false;
-
omapdss_device_disconnect(dst, dst->next);
}
@@ -651,25 +634,15 @@ static int dpi_init_output_port(struct dpi_data *dpi, struct device_node *port)
out->dev = &dpi->pdev->dev;
out->id = OMAP_DSS_OUTPUT_DPI;
- out->output_type = OMAP_DISPLAY_TYPE_DPI;
+ out->type = OMAP_DISPLAY_TYPE_DPI;
out->dispc_channel = dpi_get_channel(dpi);
out->of_ports = BIT(port_num);
out->ops = &dpi_ops;
out->owner = THIS_MODULE;
- out->next = omapdss_of_find_connected_device(out->dev->of_node, 0);
- if (IS_ERR(out->next)) {
- if (PTR_ERR(out->next) != -EPROBE_DEFER)
- dev_err(out->dev, "failed to find video sink\n");
- return PTR_ERR(out->next);
- }
-
- r = omapdss_output_validate(out);
- if (r) {
- omapdss_device_put(out->next);
- out->next = NULL;
+ r = omapdss_device_init_output(out);
+ if (r < 0)
return r;
- }
omapdss_device_register(out);
@@ -681,9 +654,8 @@ static void dpi_uninit_output_port(struct device_node *port)
struct dpi_data *dpi = port->data;
struct omap_dss_device *out = &dpi->output;
- if (out->next)
- omapdss_device_put(out->next);
omapdss_device_unregister(out);
+ omapdss_device_cleanup_output(out);
}
static const struct soc_device_attribute dpi_soc_devices[] = {
diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c
index 64fb788b6647..5202862d89b5 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -1342,12 +1342,9 @@ static int dsi_pll_enable(struct dss_pll *pll)
*/
dsi_enable_scp_clk(dsi);
- if (!dsi->vdds_dsi_enabled) {
- r = regulator_enable(dsi->vdds_dsi_reg);
- if (r)
- goto err0;
- dsi->vdds_dsi_enabled = true;
- }
+ r = regulator_enable(dsi->vdds_dsi_reg);
+ if (r)
+ goto err0;
/* XXX PLL does not come out of reset without this... */
dispc_pck_free_enable(dsi->dss->dispc, 1);
@@ -1372,36 +1369,25 @@ static int dsi_pll_enable(struct dss_pll *pll)
return 0;
err1:
- if (dsi->vdds_dsi_enabled) {
- regulator_disable(dsi->vdds_dsi_reg);
- dsi->vdds_dsi_enabled = false;
- }
+ regulator_disable(dsi->vdds_dsi_reg);
err0:
dsi_disable_scp_clk(dsi);
dsi_runtime_put(dsi);
return r;
}
-static void dsi_pll_uninit(struct dsi_data *dsi, bool disconnect_lanes)
+static void dsi_pll_disable(struct dss_pll *pll)
{
+ struct dsi_data *dsi = container_of(pll, struct dsi_data, pll);
+
dsi_pll_power(dsi, DSI_PLL_POWER_OFF);
- if (disconnect_lanes) {
- WARN_ON(!dsi->vdds_dsi_enabled);
- regulator_disable(dsi->vdds_dsi_reg);
- dsi->vdds_dsi_enabled = false;
- }
+
+ regulator_disable(dsi->vdds_dsi_reg);
dsi_disable_scp_clk(dsi);
dsi_runtime_put(dsi);
- DSSDBG("PLL uninit done\n");
-}
-
-static void dsi_pll_disable(struct dss_pll *pll)
-{
- struct dsi_data *dsi = container_of(pll, struct dsi_data, pll);
-
- dsi_pll_uninit(dsi, true);
+ DSSDBG("PLL disable done\n");
}
static int dsi_dump_dsi_clocks(struct seq_file *s, void *p)
@@ -3753,19 +3739,13 @@ static int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
{
struct dsi_data *dsi = to_dsi_data(dssdev);
int bpp = dsi_get_pixel_size(dsi->pix_fmt);
- struct omap_dss_device *out = &dsi->output;
u8 data_type;
u16 word_count;
int r;
- if (!out->dispc_channel_connected) {
- DSSERR("failed to enable display: no output/manager\n");
- return -ENODEV;
- }
-
r = dsi_display_init_dispc(dsi);
if (r)
- goto err_init_dispc;
+ return r;
if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
switch (dsi->pix_fmt) {
@@ -3814,7 +3794,6 @@ err_mgr_enable:
}
err_pix_fmt:
dsi_display_uninit_dispc(dsi);
-err_init_dispc:
return r;
}
@@ -4096,11 +4075,11 @@ static int dsi_display_init_dsi(struct dsi_data *dsi)
r = dss_pll_enable(&dsi->pll);
if (r)
- goto err0;
+ return r;
r = dsi_configure_dsi_clocks(dsi);
if (r)
- goto err1;
+ goto err0;
dss_select_dsi_clk_source(dsi->dss, dsi->module_id,
dsi->module_id == 0 ?
@@ -4108,6 +4087,14 @@ static int dsi_display_init_dsi(struct dsi_data *dsi)
DSSDBG("PLL OK\n");
+ if (!dsi->vdds_dsi_enabled) {
+ r = regulator_enable(dsi->vdds_dsi_reg);
+ if (r)
+ goto err1;
+
+ dsi->vdds_dsi_enabled = true;
+ }
+
r = dsi_cio_init(dsi);
if (r)
goto err2;
@@ -4136,10 +4123,13 @@ static int dsi_display_init_dsi(struct dsi_data *dsi)
err3:
dsi_cio_uninit(dsi);
err2:
- dss_select_dsi_clk_source(dsi->dss, dsi->module_id, DSS_CLK_SRC_FCK);
+ regulator_disable(dsi->vdds_dsi_reg);
+ dsi->vdds_dsi_enabled = false;
err1:
- dss_pll_disable(&dsi->pll);
+ dss_select_dsi_clk_source(dsi->dss, dsi->module_id, DSS_CLK_SRC_FCK);
err0:
+ dss_pll_disable(&dsi->pll);
+
return r;
}
@@ -4158,13 +4148,18 @@ static void dsi_display_uninit_dsi(struct dsi_data *dsi, bool disconnect_lanes,
dss_select_dsi_clk_source(dsi->dss, dsi->module_id, DSS_CLK_SRC_FCK);
dsi_cio_uninit(dsi);
- dsi_pll_uninit(dsi, disconnect_lanes);
+ dss_pll_disable(&dsi->pll);
+
+ if (disconnect_lanes) {
+ regulator_disable(dsi->vdds_dsi_reg);
+ dsi->vdds_dsi_enabled = false;
+ }
}
-static int dsi_display_enable(struct omap_dss_device *dssdev)
+static void dsi_display_enable(struct omap_dss_device *dssdev)
{
struct dsi_data *dsi = to_dsi_data(dssdev);
- int r = 0;
+ int r;
DSSDBG("dsi_display_enable\n");
@@ -4184,14 +4179,13 @@ static int dsi_display_enable(struct omap_dss_device *dssdev)
mutex_unlock(&dsi->lock);
- return 0;
+ return;
err_init_dsi:
dsi_runtime_put(dsi);
err_get_dsi:
mutex_unlock(&dsi->lock);
DSSDBG("dsi_display_enable FAILED\n");
- return r;
}
static void dsi_display_disable(struct omap_dss_device *dssdev,
@@ -4888,21 +4882,12 @@ static int dsi_get_clocks(struct dsi_data *dsi)
static int dsi_connect(struct omap_dss_device *src,
struct omap_dss_device *dst)
{
- int r;
-
- r = omapdss_device_connect(dst->dss, dst, dst->next);
- if (r)
- return r;
-
- dst->dispc_channel_connected = true;
- return 0;
+ return omapdss_device_connect(dst->dss, dst, dst->next);
}
static void dsi_disconnect(struct omap_dss_device *src,
struct omap_dss_device *dst)
{
- dst->dispc_channel_connected = false;
-
omapdss_device_disconnect(dst, dst->next);
}
@@ -5138,29 +5123,19 @@ static int dsi_init_output(struct dsi_data *dsi)
out->id = dsi->module_id == 0 ?
OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2;
- out->output_type = OMAP_DISPLAY_TYPE_DSI;
+ out->type = OMAP_DISPLAY_TYPE_DSI;
out->name = dsi->module_id == 0 ? "dsi.0" : "dsi.1";
out->dispc_channel = dsi_get_channel(dsi);
out->ops = &dsi_ops;
out->owner = THIS_MODULE;
out->of_ports = BIT(0);
- out->bus_flags = DRM_BUS_FLAG_PIXDATA_POSEDGE
+ out->bus_flags = DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE
| DRM_BUS_FLAG_DE_HIGH
- | DRM_BUS_FLAG_SYNC_NEGEDGE;
-
- out->next = omapdss_of_find_connected_device(out->dev->of_node, 0);
- if (IS_ERR(out->next)) {
- if (PTR_ERR(out->next) != -EPROBE_DEFER)
- dev_err(out->dev, "failed to find video sink\n");
- return PTR_ERR(out->next);
- }
+ | DRM_BUS_FLAG_SYNC_DRIVE_NEGEDGE;
- r = omapdss_output_validate(out);
- if (r) {
- omapdss_device_put(out->next);
- out->next = NULL;
+ r = omapdss_device_init_output(out);
+ if (r < 0)
return r;
- }
omapdss_device_register(out);
@@ -5171,9 +5146,8 @@ static void dsi_uninit_output(struct dsi_data *dsi)
{
struct omap_dss_device *out = &dsi->output;
- if (out->next)
- omapdss_device_put(out->next);
omapdss_device_unregister(out);
+ omapdss_device_cleanup_output(out);
}
static int dsi_probe_of(struct dsi_data *dsi)
diff --git a/drivers/gpu/drm/omapdrm/dss/dss-of.c b/drivers/gpu/drm/omapdrm/dss/dss-of.c
index 0422597ac6b0..b2094055c5fc 100644
--- a/drivers/gpu/drm/omapdrm/dss/dss-of.c
+++ b/drivers/gpu/drm/omapdrm/dss/dss-of.c
@@ -12,71 +12,25 @@
* more details.
*/
-#include <linux/device.h>
#include <linux/err.h>
-#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_graph.h>
-#include <linux/seq_file.h>
#include "omapdss.h"
-static struct device_node *
-dss_of_port_get_parent_device(struct device_node *port)
-{
- struct device_node *np;
- int i;
-
- if (!port)
- return NULL;
-
- np = of_get_parent(port);
-
- for (i = 0; i < 2 && np; ++i) {
- struct property *prop;
-
- prop = of_find_property(np, "compatible", NULL);
-
- if (prop)
- return np;
-
- np = of_get_next_parent(np);
- }
-
- return NULL;
-}
-
struct omap_dss_device *
omapdss_of_find_connected_device(struct device_node *node, unsigned int port)
{
- struct device_node *src_node;
- struct device_node *src_port;
- struct device_node *ep;
- struct omap_dss_device *src;
- u32 port_number = 0;
+ struct device_node *remote_node;
+ struct omap_dss_device *dssdev;
- /* Get the endpoint... */
- ep = of_graph_get_endpoint_by_regs(node, port, 0);
- if (!ep)
+ remote_node = of_graph_get_remote_node(node, port, 0);
+ if (!remote_node)
return NULL;
- /* ... and its remote port... */
- src_port = of_graph_get_remote_port(ep);
- of_node_put(ep);
- if (!src_port)
- return NULL;
-
- /* ... and the remote port's number and parent... */
- of_property_read_u32(src_port, "reg", &port_number);
- src_node = dss_of_port_get_parent_device(src_port);
- of_node_put(src_port);
- if (!src_node)
- return ERR_PTR(-EINVAL);
-
- /* ... and finally the connected device. */
- src = omapdss_find_device_by_port(src_node, port_number);
- of_node_put(src_node);
+ dssdev = omapdss_find_device_by_node(remote_node);
+ of_node_put(remote_node);
- return src ? src : ERR_PTR(-EPROBE_DEFER);
+ return dssdev ? dssdev : ERR_PTR(-EPROBE_DEFER);
}
EXPORT_SYMBOL_GPL(omapdss_of_find_connected_device);
diff --git a/drivers/gpu/drm/omapdrm/dss/dss.c b/drivers/gpu/drm/omapdrm/dss/dss.c
index 7553c7fc1c45..55e68863ef15 100644
--- a/drivers/gpu/drm/omapdrm/dss/dss.c
+++ b/drivers/gpu/drm/omapdrm/dss/dss.c
@@ -1560,7 +1560,7 @@ static void dss_shutdown(struct platform_device *pdev)
DSSDBG("shutdown\n");
- for_each_dss_display(dssdev) {
+ for_each_dss_output(dssdev) {
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
dssdev->ops->disable(dssdev);
}
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index aabdda394c9c..6339e2756b34 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -249,15 +249,15 @@ static void hdmi_power_off_full(struct omap_hdmi *hdmi)
}
static void hdmi_display_set_timings(struct omap_dss_device *dssdev,
- const struct videomode *vm)
+ const struct drm_display_mode *mode)
{
struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
mutex_lock(&hdmi->lock);
- hdmi->cfg.vm = *vm;
+ drm_display_mode_to_videomode(mode, &hdmi->cfg.vm);
- dispc_set_tv_pclk(hdmi->dss->dispc, vm->pixelclock);
+ dispc_set_tv_pclk(hdmi->dss->dispc, mode->clock * 1000);
mutex_unlock(&hdmi->lock);
}
@@ -312,26 +312,20 @@ static void hdmi_stop_audio_stream(struct omap_hdmi *hd)
hdmi_wp_audio_enable(&hd->wp, false);
}
-static int hdmi_display_enable(struct omap_dss_device *dssdev)
+static void hdmi_display_enable(struct omap_dss_device *dssdev)
{
struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
unsigned long flags;
- int r = 0;
+ int r;
DSSDBG("ENTER hdmi_display_enable\n");
mutex_lock(&hdmi->lock);
- if (!dssdev->dispc_channel_connected) {
- DSSERR("failed to enable display: no output/manager\n");
- r = -ENODEV;
- goto err0;
- }
-
r = hdmi_power_on_full(hdmi);
if (r) {
DSSERR("failed to power on device\n");
- goto err0;
+ goto done;
}
if (hdmi->audio_configured) {
@@ -351,12 +345,8 @@ static int hdmi_display_enable(struct omap_dss_device *dssdev)
hdmi->display_enabled = true;
spin_unlock_irqrestore(&hdmi->audio_playing_lock, flags);
+done:
mutex_unlock(&hdmi->lock);
- return 0;
-
-err0:
- mutex_unlock(&hdmi->lock);
- return r;
}
static void hdmi_display_disable(struct omap_dss_device *dssdev)
@@ -417,21 +407,12 @@ void hdmi4_core_disable(struct hdmi_core_data *core)
static int hdmi_connect(struct omap_dss_device *src,
struct omap_dss_device *dst)
{
- int r;
-
- r = omapdss_device_connect(dst->dss, dst, dst->next);
- if (r)
- return r;
-
- dst->dispc_channel_connected = true;
- return 0;
+ return omapdss_device_connect(dst->dss, dst, dst->next);
}
static void hdmi_disconnect(struct omap_dss_device *src,
struct omap_dss_device *dst)
{
- dst->dispc_channel_connected = false;
-
omapdss_device_disconnect(dst, dst->next);
}
@@ -698,7 +679,7 @@ static int hdmi4_init_output(struct omap_hdmi *hdmi)
out->dev = &hdmi->pdev->dev;
out->id = OMAP_DSS_OUTPUT_HDMI;
- out->output_type = OMAP_DISPLAY_TYPE_HDMI;
+ out->type = OMAP_DISPLAY_TYPE_HDMI;
out->name = "hdmi.0";
out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
out->ops = &hdmi_ops;
@@ -706,19 +687,9 @@ static int hdmi4_init_output(struct omap_hdmi *hdmi)
out->of_ports = BIT(0);
out->ops_flags = OMAP_DSS_DEVICE_OP_EDID;
- out->next = omapdss_of_find_connected_device(out->dev->of_node, 0);
- if (IS_ERR(out->next)) {
- if (PTR_ERR(out->next) != -EPROBE_DEFER)
- dev_err(out->dev, "failed to find video sink\n");
- return PTR_ERR(out->next);
- }
-
- r = omapdss_output_validate(out);
- if (r) {
- omapdss_device_put(out->next);
- out->next = NULL;
+ r = omapdss_device_init_output(out);
+ if (r < 0)
return r;
- }
omapdss_device_register(out);
@@ -729,9 +700,8 @@ static void hdmi4_uninit_output(struct omap_hdmi *hdmi)
{
struct omap_dss_device *out = &hdmi->output;
- if (out->next)
- omapdss_device_put(out->next);
omapdss_device_unregister(out);
+ omapdss_device_cleanup_output(out);
}
static int hdmi4_probe_of(struct omap_hdmi *hdmi)
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
index 9e8556f67a29..2955bbad13bb 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
@@ -248,15 +248,15 @@ static void hdmi_power_off_full(struct omap_hdmi *hdmi)
}
static void hdmi_display_set_timings(struct omap_dss_device *dssdev,
- const struct videomode *vm)
+ const struct drm_display_mode *mode)
{
struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
mutex_lock(&hdmi->lock);
- hdmi->cfg.vm = *vm;
+ drm_display_mode_to_videomode(mode, &hdmi->cfg.vm);
- dispc_set_tv_pclk(hdmi->dss->dispc, vm->pixelclock);
+ dispc_set_tv_pclk(hdmi->dss->dispc, mode->clock * 1000);
mutex_unlock(&hdmi->lock);
}
@@ -320,26 +320,20 @@ static void hdmi_stop_audio_stream(struct omap_hdmi *hd)
REG_FLD_MOD(hd->wp.base, HDMI_WP_SYSCONFIG, hd->wp_idlemode, 3, 2);
}
-static int hdmi_display_enable(struct omap_dss_device *dssdev)
+static void hdmi_display_enable(struct omap_dss_device *dssdev)
{
struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
unsigned long flags;
- int r = 0;
+ int r;
DSSDBG("ENTER hdmi_display_enable\n");
mutex_lock(&hdmi->lock);
- if (!dssdev->dispc_channel_connected) {
- DSSERR("failed to enable display: no output/manager\n");
- r = -ENODEV;
- goto err0;
- }
-
r = hdmi_power_on_full(hdmi);
if (r) {
DSSERR("failed to power on device\n");
- goto err0;
+ goto done;
}
if (hdmi->audio_configured) {
@@ -359,12 +353,8 @@ static int hdmi_display_enable(struct omap_dss_device *dssdev)
hdmi->display_enabled = true;
spin_unlock_irqrestore(&hdmi->audio_playing_lock, flags);
+done:
mutex_unlock(&hdmi->lock);
- return 0;
-
-err0:
- mutex_unlock(&hdmi->lock);
- return r;
}
static void hdmi_display_disable(struct omap_dss_device *dssdev)
@@ -422,21 +412,12 @@ static void hdmi_core_disable(struct omap_hdmi *hdmi)
static int hdmi_connect(struct omap_dss_device *src,
struct omap_dss_device *dst)
{
- int r;
-
- r = omapdss_device_connect(dst->dss, dst, dst->next);
- if (r)
- return r;
-
- dst->dispc_channel_connected = true;
- return 0;
+ return omapdss_device_connect(dst->dss, dst, dst->next);
}
static void hdmi_disconnect(struct omap_dss_device *src,
struct omap_dss_device *dst)
{
- dst->dispc_channel_connected = false;
-
omapdss_device_disconnect(dst, dst->next);
}
@@ -682,7 +663,7 @@ static int hdmi5_init_output(struct omap_hdmi *hdmi)
out->dev = &hdmi->pdev->dev;
out->id = OMAP_DSS_OUTPUT_HDMI;
- out->output_type = OMAP_DISPLAY_TYPE_HDMI;
+ out->type = OMAP_DISPLAY_TYPE_HDMI;
out->name = "hdmi.0";
out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
out->ops = &hdmi_ops;
@@ -690,19 +671,9 @@ static int hdmi5_init_output(struct omap_hdmi *hdmi)
out->of_ports = BIT(0);
out->ops_flags = OMAP_DSS_DEVICE_OP_EDID;
- out->next = omapdss_of_find_connected_device(out->dev->of_node, 0);
- if (IS_ERR(out->next)) {
- if (PTR_ERR(out->next) != -EPROBE_DEFER)
- dev_err(out->dev, "failed to find video sink\n");
- return PTR_ERR(out->next);
- }
-
- r = omapdss_output_validate(out);
- if (r) {
- omapdss_device_put(out->next);
- out->next = NULL;
+ r = omapdss_device_init_output(out);
+ if (r < 0)
return r;
- }
omapdss_device_register(out);
@@ -713,9 +684,8 @@ static void hdmi5_uninit_output(struct omap_hdmi *hdmi)
{
struct omap_dss_device *out = &hdmi->output;
- if (out->next)
- omapdss_device_put(out->next);
omapdss_device_unregister(out);
+ omapdss_device_cleanup_output(out);
}
static int hdmi5_probe_of(struct omap_hdmi *hdmi)
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c b/drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c
index 3bfb95d230e0..2b41c75ce988 100644
--- a/drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c
@@ -184,6 +184,22 @@ static const struct of_device_id omapdss_of_match[] __initconst = {
{},
};
+static const struct of_device_id omapdss_of_fixups_whitelist[] __initconst = {
+ { .compatible = "composite-video-connector" },
+ { .compatible = "hdmi-connector" },
+ { .compatible = "lgphilips,lb035q02" },
+ { .compatible = "nec,nl8048hl11" },
+ { .compatible = "panel-dsi-cm" },
+ { .compatible = "sharp,ls037v7dw01" },
+ { .compatible = "sony,acx565akm" },
+ { .compatible = "svideo-connector" },
+ { .compatible = "ti,opa362" },
+ { .compatible = "ti,tpd12s015" },
+ { .compatible = "toppoly,td028ttec1" },
+ { .compatible = "tpo,td028ttec1" },
+ { .compatible = "tpo,td043mtea1" },
+};
+
static int __init omapdss_boot_init(void)
{
struct device_node *dss, *child;
@@ -210,7 +226,7 @@ static int __init omapdss_boot_init(void)
n = list_first_entry(&dss_conv_list, struct dss_conv_node,
list);
- if (!n->root)
+ if (of_match_node(omapdss_of_fixups_whitelist, n->node))
omapdss_omapify_node(n->node);
list_del(&n->list);
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h
index 33e15cb77efa..0c734d1f89e1 100644
--- a/drivers/gpu/drm/omapdrm/dss/omapdss.h
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h
@@ -19,7 +19,6 @@
#define __OMAP_DRM_DSS_H
#include <linux/list.h>
-#include <linux/kobject.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <video/videomode.h>
@@ -68,6 +67,7 @@ struct dss_lcd_mgr_config;
struct snd_aes_iec958;
struct snd_cea_861_aud_if;
struct hdmi_avi_infoframe;
+struct drm_connector;
enum omap_display_type {
OMAP_DISPLAY_TYPE_NONE = 0,
@@ -360,15 +360,15 @@ struct omap_dss_device_ops {
void (*disconnect)(struct omap_dss_device *dssdev,
struct omap_dss_device *dst);
- int (*enable)(struct omap_dss_device *dssdev);
+ void (*pre_enable)(struct omap_dss_device *dssdev);
+ void (*enable)(struct omap_dss_device *dssdev);
void (*disable)(struct omap_dss_device *dssdev);
+ void (*post_disable)(struct omap_dss_device *dssdev);
int (*check_timings)(struct omap_dss_device *dssdev,
- struct videomode *vm);
- void (*get_timings)(struct omap_dss_device *dssdev,
- struct videomode *vm);
+ struct drm_display_mode *mode);
void (*set_timings)(struct omap_dss_device *dssdev,
- const struct videomode *vm);
+ const struct drm_display_mode *mode);
bool (*detect)(struct omap_dss_device *dssdev);
@@ -380,6 +380,9 @@ struct omap_dss_device_ops {
int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len);
+ int (*get_modes)(struct omap_dss_device *dssdev,
+ struct drm_connector *connector);
+
union {
const struct omapdss_hdmi_ops hdmi;
const struct omapdss_dsi_ops dsi;
@@ -390,42 +393,40 @@ struct omap_dss_device_ops {
* enum omap_dss_device_ops_flag - Indicates which device ops are supported
* @OMAP_DSS_DEVICE_OP_DETECT: The device supports output connection detection
* @OMAP_DSS_DEVICE_OP_HPD: The device supports all hot-plug-related operations
- * @OMAP_DSS_DEVICE_OP_EDID: The device supports readind EDID
+ * @OMAP_DSS_DEVICE_OP_EDID: The device supports reading EDID
+ * @OMAP_DSS_DEVICE_OP_MODES: The device supports reading modes
*/
enum omap_dss_device_ops_flag {
OMAP_DSS_DEVICE_OP_DETECT = BIT(0),
OMAP_DSS_DEVICE_OP_HPD = BIT(1),
OMAP_DSS_DEVICE_OP_EDID = BIT(2),
-};
-
-enum omap_dss_device_type {
- OMAP_DSS_DEVICE_TYPE_OUTPUT = (1 << 0),
- OMAP_DSS_DEVICE_TYPE_DISPLAY = (1 << 1),
+ OMAP_DSS_DEVICE_OP_MODES = BIT(3),
};
struct omap_dss_device {
- struct kobject kobj;
struct device *dev;
struct module *owner;
struct dss_device *dss;
- struct omap_dss_device *src;
- struct omap_dss_device *dst;
struct omap_dss_device *next;
+ struct drm_bridge *bridge;
+ struct drm_panel *panel;
struct list_head list;
- unsigned int alias_id;
-
+ /*
+ * DSS type that this device generates (for DSS internal devices) or
+ * requires (for external encoders, connectors and panels). Must be a
+ * non-zero (different than OMAP_DISPLAY_TYPE_NONE) value.
+ */
enum omap_display_type type;
+
/*
- * DSS output type that this device generates (for DSS internal devices)
- * or requires (for external encoders). Must be OMAP_DISPLAY_TYPE_NONE
- * for display devices (connectors and panels) and to non-zero value for
- * all other devices.
+ * True if the device is a display (panel or connector) at the end of
+ * the pipeline, false otherwise.
*/
- enum omap_display_type output_type;
+ bool display;
const char *name;
@@ -434,9 +435,6 @@ struct omap_dss_device {
unsigned long ops_flags;
u32 bus_flags;
- /* helper variable for driver suspend/resume */
- bool activate_after_resume;
-
enum omap_display_caps caps;
enum omap_dss_display_state state;
@@ -445,7 +443,6 @@ struct omap_dss_device {
/* DISPC channel for this output */
enum omap_channel dispc_channel;
- bool dispc_channel_connected;
/* output instance */
enum omap_dss_output_id id;
@@ -465,9 +462,6 @@ struct omap_dss_driver {
int (*memory_read)(struct omap_dss_device *dssdev,
void *buf, size_t size,
u16 x, u16 y, u16 w, u16 h);
-
- void (*get_size)(struct omap_dss_device *dssdev,
- unsigned int *width, unsigned int *height);
};
struct dss_device *omapdss_get_dss(void);
@@ -477,32 +471,35 @@ static inline bool omapdss_is_initialized(void)
return !!omapdss_get_dss();
}
-#define for_each_dss_display(d) \
- while ((d = omapdss_device_get_next(d, OMAP_DSS_DEVICE_TYPE_DISPLAY)) != NULL)
void omapdss_display_init(struct omap_dss_device *dssdev);
struct omap_dss_device *omapdss_display_get(struct omap_dss_device *output);
+int omapdss_display_get_modes(struct drm_connector *connector,
+ const struct videomode *vm);
void omapdss_device_register(struct omap_dss_device *dssdev);
void omapdss_device_unregister(struct omap_dss_device *dssdev);
struct omap_dss_device *omapdss_device_get(struct omap_dss_device *dssdev);
void omapdss_device_put(struct omap_dss_device *dssdev);
-struct omap_dss_device *omapdss_find_device_by_port(struct device_node *src,
- unsigned int port);
-struct omap_dss_device *omapdss_device_get_next(struct omap_dss_device *from,
- enum omap_dss_device_type type);
+struct omap_dss_device *omapdss_find_device_by_node(struct device_node *node);
int omapdss_device_connect(struct dss_device *dss,
struct omap_dss_device *src,
struct omap_dss_device *dst);
void omapdss_device_disconnect(struct omap_dss_device *src,
struct omap_dss_device *dst);
+void omapdss_device_pre_enable(struct omap_dss_device *dssdev);
+void omapdss_device_enable(struct omap_dss_device *dssdev);
+void omapdss_device_disable(struct omap_dss_device *dssdev);
+void omapdss_device_post_disable(struct omap_dss_device *dssdev);
int omap_dss_get_num_overlay_managers(void);
int omap_dss_get_num_overlays(void);
#define for_each_dss_output(d) \
- while ((d = omapdss_device_get_next(d, OMAP_DSS_DEVICE_TYPE_OUTPUT)) != NULL)
-int omapdss_output_validate(struct omap_dss_device *out);
+ while ((d = omapdss_device_next_output(d)) != NULL)
+struct omap_dss_device *omapdss_device_next_output(struct omap_dss_device *from);
+int omapdss_device_init_output(struct omap_dss_device *out);
+void omapdss_device_cleanup_output(struct omap_dss_device *out);
typedef void (*omap_dispc_isr_t) (void *arg, u32 mask);
int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
@@ -511,11 +508,6 @@ int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
int omapdss_compat_init(void);
void omapdss_compat_uninit(void);
-static inline bool omapdss_device_is_connected(struct omap_dss_device *dssdev)
-{
- return dssdev->src;
-}
-
static inline bool omapdss_device_is_enabled(struct omap_dss_device *dssdev)
{
return dssdev->state == OMAP_DSS_DISPLAY_ACTIVE;
diff --git a/drivers/gpu/drm/omapdrm/dss/output.c b/drivers/gpu/drm/omapdrm/dss/output.c
index 18505bc70f7e..10a9ee5cdc61 100644
--- a/drivers/gpu/drm/omapdrm/dss/output.c
+++ b/drivers/gpu/drm/omapdrm/dss/output.c
@@ -20,20 +20,48 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/of.h>
+#include <linux/of_graph.h>
+
+#include <drm/drm_panel.h>
#include "dss.h"
#include "omapdss.h"
-int omapdss_output_validate(struct omap_dss_device *out)
+int omapdss_device_init_output(struct omap_dss_device *out)
{
- if (out->next && out->output_type != out->next->type) {
+ struct device_node *remote_node;
+
+ remote_node = of_graph_get_remote_node(out->dev->of_node, 0, 0);
+ if (!remote_node) {
+ dev_dbg(out->dev, "failed to find video sink\n");
+ return 0;
+ }
+
+ out->next = omapdss_find_device_by_node(remote_node);
+ out->bridge = of_drm_find_bridge(remote_node);
+ out->panel = of_drm_find_panel(remote_node);
+ if (IS_ERR(out->panel))
+ out->panel = NULL;
+
+ of_node_put(remote_node);
+
+ if (out->next && out->type != out->next->type) {
dev_err(out->dev, "output type and display type don't match\n");
+ omapdss_device_put(out->next);
+ out->next = NULL;
return -EINVAL;
}
- return 0;
+ return out->next || out->bridge || out->panel ? 0 : -EPROBE_DEFER;
+}
+EXPORT_SYMBOL(omapdss_device_init_output);
+
+void omapdss_device_cleanup_output(struct omap_dss_device *out)
+{
+ if (out->next)
+ omapdss_device_put(out->next);
}
-EXPORT_SYMBOL(omapdss_output_validate);
+EXPORT_SYMBOL(omapdss_device_cleanup_output);
int dss_install_mgr_ops(struct dss_device *dss,
const struct dss_mgr_ops *mgr_ops,
diff --git a/drivers/gpu/drm/omapdrm/dss/sdi.c b/drivers/gpu/drm/omapdrm/dss/sdi.c
index b2fe2387037a..7aae52984fed 100644
--- a/drivers/gpu/drm/omapdrm/dss/sdi.c
+++ b/drivers/gpu/drm/omapdrm/dss/sdi.c
@@ -37,7 +37,7 @@ struct sdi_device {
struct regulator *vdds_sdi_reg;
struct dss_lcd_mgr_config mgr_config;
- struct videomode vm;
+ unsigned long pixelclock;
int datapairs;
struct omap_dss_device output;
@@ -129,27 +129,22 @@ static void sdi_config_lcd_manager(struct sdi_device *sdi)
dss_mgr_set_lcd_config(&sdi->output, &sdi->mgr_config);
}
-static int sdi_display_enable(struct omap_dss_device *dssdev)
+static void sdi_display_enable(struct omap_dss_device *dssdev)
{
struct sdi_device *sdi = dssdev_to_sdi(dssdev);
struct dispc_clock_info dispc_cinfo;
unsigned long fck;
int r;
- if (!sdi->output.dispc_channel_connected) {
- DSSERR("failed to enable display: no output/manager\n");
- return -ENODEV;
- }
-
r = regulator_enable(sdi->vdds_sdi_reg);
if (r)
- goto err_reg_enable;
+ return;
r = dispc_runtime_get(sdi->dss->dispc);
if (r)
goto err_get_dispc;
- r = sdi_calc_clock_div(sdi, sdi->vm.pixelclock, &fck, &dispc_cinfo);
+ r = sdi_calc_clock_div(sdi, sdi->pixelclock, &fck, &dispc_cinfo);
if (r)
goto err_calc_clock_div;
@@ -185,7 +180,7 @@ static int sdi_display_enable(struct omap_dss_device *dssdev)
if (r)
goto err_mgr_enable;
- return 0;
+ return;
err_mgr_enable:
dss_sdi_disable(sdi->dss);
@@ -195,8 +190,6 @@ err_calc_clock_div:
dispc_runtime_put(sdi->dss->dispc);
err_get_dispc:
regulator_disable(sdi->vdds_sdi_reg);
-err_reg_enable:
- return r;
}
static void sdi_display_disable(struct omap_dss_device *dssdev)
@@ -213,36 +206,37 @@ static void sdi_display_disable(struct omap_dss_device *dssdev)
}
static void sdi_set_timings(struct omap_dss_device *dssdev,
- const struct videomode *vm)
+ const struct drm_display_mode *mode)
{
struct sdi_device *sdi = dssdev_to_sdi(dssdev);
- sdi->vm = *vm;
+ sdi->pixelclock = mode->clock * 1000;
}
static int sdi_check_timings(struct omap_dss_device *dssdev,
- struct videomode *vm)
+ struct drm_display_mode *mode)
{
struct sdi_device *sdi = dssdev_to_sdi(dssdev);
struct dispc_clock_info dispc_cinfo;
+ unsigned long pixelclock = mode->clock * 1000;
unsigned long fck;
unsigned long pck;
int r;
- if (vm->pixelclock == 0)
+ if (pixelclock == 0)
return -EINVAL;
- r = sdi_calc_clock_div(sdi, vm->pixelclock, &fck, &dispc_cinfo);
+ r = sdi_calc_clock_div(sdi, pixelclock, &fck, &dispc_cinfo);
if (r)
return r;
pck = fck / dispc_cinfo.lck_div / dispc_cinfo.pck_div;
- if (pck != vm->pixelclock) {
+ if (pck != pixelclock) {
DSSWARN("Pixel clock adjusted from %lu Hz to %lu Hz\n",
- vm->pixelclock, pck);
+ pixelclock, pck);
- vm->pixelclock = pck;
+ mode->clock = pck / 1000;
}
return 0;
@@ -251,21 +245,12 @@ static int sdi_check_timings(struct omap_dss_device *dssdev,
static int sdi_connect(struct omap_dss_device *src,
struct omap_dss_device *dst)
{
- int r;
-
- r = omapdss_device_connect(dst->dss, dst, dst->next);
- if (r)
- return r;
-
- dst->dispc_channel_connected = true;
- return 0;
+ return omapdss_device_connect(dst->dss, dst, dst->next);
}
static void sdi_disconnect(struct omap_dss_device *src,
struct omap_dss_device *dst)
{
- dst->dispc_channel_connected = false;
-
omapdss_device_disconnect(dst, dst->next);
}
@@ -287,29 +272,19 @@ static int sdi_init_output(struct sdi_device *sdi)
out->dev = &sdi->pdev->dev;
out->id = OMAP_DSS_OUTPUT_SDI;
- out->output_type = OMAP_DISPLAY_TYPE_SDI;
+ out->type = OMAP_DISPLAY_TYPE_SDI;
out->name = "sdi.0";
out->dispc_channel = OMAP_DSS_CHANNEL_LCD;
/* We have SDI only on OMAP3, where it's on port 1 */
out->of_ports = BIT(1);
out->ops = &sdi_ops;
out->owner = THIS_MODULE;
- out->bus_flags = DRM_BUS_FLAG_PIXDATA_POSEDGE /* 15.5.9.1.2 */
- | DRM_BUS_FLAG_SYNC_POSEDGE;
-
- out->next = omapdss_of_find_connected_device(out->dev->of_node, 1);
- if (IS_ERR(out->next)) {
- if (PTR_ERR(out->next) != -EPROBE_DEFER)
- dev_err(out->dev, "failed to find video sink\n");
- return PTR_ERR(out->next);
- }
+ out->bus_flags = DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE /* 15.5.9.1.2 */
+ | DRM_BUS_FLAG_SYNC_DRIVE_POSEDGE;
- r = omapdss_output_validate(out);
- if (r) {
- omapdss_device_put(out->next);
- out->next = NULL;
+ r = omapdss_device_init_output(out);
+ if (r < 0)
return r;
- }
omapdss_device_register(out);
@@ -318,9 +293,8 @@ static int sdi_init_output(struct sdi_device *sdi)
static void sdi_uninit_output(struct sdi_device *sdi)
{
- if (sdi->output.next)
- omapdss_device_put(sdi->output.next);
omapdss_device_unregister(&sdi->output);
+ omapdss_device_cleanup_output(&sdi->output);
}
int sdi_init_port(struct dss_device *dss, struct platform_device *pdev,
diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c
index b5f52727f8b1..da43b865d973 100644
--- a/drivers/gpu/drm/omapdrm/dss/venc.c
+++ b/drivers/gpu/drm/omapdrm/dss/venc.c
@@ -267,63 +267,40 @@ enum venc_videomode {
VENC_MODE_NTSC,
};
-static const struct videomode omap_dss_pal_vm = {
- .hactive = 720,
- .vactive = 574,
- .pixelclock = 13500000,
- .hsync_len = 64,
- .hfront_porch = 12,
- .hback_porch = 68,
- .vsync_len = 5,
- .vfront_porch = 5,
- .vback_porch = 41,
-
- .flags = DISPLAY_FLAGS_INTERLACED | DISPLAY_FLAGS_HSYNC_LOW |
- DISPLAY_FLAGS_VSYNC_LOW | DISPLAY_FLAGS_DE_HIGH |
- DISPLAY_FLAGS_PIXDATA_POSEDGE |
- DISPLAY_FLAGS_SYNC_NEGEDGE,
+static const struct drm_display_mode omap_dss_pal_mode = {
+ .hdisplay = 720,
+ .hsync_start = 732,
+ .hsync_end = 796,
+ .htotal = 864,
+ .vdisplay = 574,
+ .vsync_start = 579,
+ .vsync_end = 584,
+ .vtotal = 625,
+ .clock = 13500,
+
+ .flags = DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_NHSYNC |
+ DRM_MODE_FLAG_NVSYNC,
};
-static const struct videomode omap_dss_ntsc_vm = {
- .hactive = 720,
- .vactive = 482,
- .pixelclock = 13500000,
- .hsync_len = 64,
- .hfront_porch = 16,
- .hback_porch = 58,
- .vsync_len = 6,
- .vfront_porch = 6,
- .vback_porch = 31,
-
- .flags = DISPLAY_FLAGS_INTERLACED | DISPLAY_FLAGS_HSYNC_LOW |
- DISPLAY_FLAGS_VSYNC_LOW | DISPLAY_FLAGS_DE_HIGH |
- DISPLAY_FLAGS_PIXDATA_POSEDGE |
- DISPLAY_FLAGS_SYNC_NEGEDGE,
+static const struct drm_display_mode omap_dss_ntsc_mode = {
+ .hdisplay = 720,
+ .hsync_start = 736,
+ .hsync_end = 800,
+ .htotal = 858,
+ .vdisplay = 482,
+ .vsync_start = 488,
+ .vsync_end = 494,
+ .vtotal = 525,
+ .clock = 13500,
+
+ .flags = DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_NHSYNC |
+ DRM_MODE_FLAG_NVSYNC,
};
-static enum venc_videomode venc_get_videomode(const struct videomode *vm)
-{
- if (!(vm->flags & DISPLAY_FLAGS_INTERLACED))
- return VENC_MODE_UNKNOWN;
-
- if (vm->pixelclock == omap_dss_pal_vm.pixelclock &&
- vm->hactive == omap_dss_pal_vm.hactive &&
- vm->vactive == omap_dss_pal_vm.vactive)
- return VENC_MODE_PAL;
-
- if (vm->pixelclock == omap_dss_ntsc_vm.pixelclock &&
- vm->hactive == omap_dss_ntsc_vm.hactive &&
- vm->vactive == omap_dss_ntsc_vm.vactive)
- return VENC_MODE_NTSC;
-
- return VENC_MODE_UNKNOWN;
-}
-
struct venc_device {
struct platform_device *pdev;
void __iomem *base;
struct mutex venc_lock;
- u32 wss_data;
struct regulator *vdda_dac_reg;
struct dss_device *dss;
@@ -331,7 +308,7 @@ struct venc_device {
struct clk *tv_dac_clk;
- struct videomode vm;
+ const struct venc_config *config;
enum omap_dss_venc_type type;
bool invert_polarity;
bool requires_tv_dac_clk;
@@ -367,8 +344,7 @@ static void venc_write_config(struct venc_device *venc,
venc_write_reg(venc, VENC_BLACK_LEVEL, config->black_level);
venc_write_reg(venc, VENC_BLANK_LEVEL, config->blank_level);
venc_write_reg(venc, VENC_M_CONTROL, config->m_control);
- venc_write_reg(venc, VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data |
- venc->wss_data);
+ venc_write_reg(venc, VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data);
venc_write_reg(venc, VENC_S_CARR, config->s_carr);
venc_write_reg(venc, VENC_L21__WC_CTL, config->l21__wc_ctl);
venc_write_reg(venc, VENC_SAVID__EAVID, config->savid__eavid);
@@ -452,18 +428,6 @@ static void venc_runtime_put(struct venc_device *venc)
WARN_ON(r < 0 && r != -ENOSYS);
}
-static const struct venc_config *venc_timings_to_config(const struct videomode *vm)
-{
- switch (venc_get_videomode(vm)) {
- default:
- WARN_ON_ONCE(1);
- case VENC_MODE_PAL:
- return &venc_config_pal_trm;
- case VENC_MODE_NTSC:
- return &venc_config_ntsc_trm;
- }
-}
-
static int venc_power_on(struct venc_device *venc)
{
u32 l;
@@ -474,7 +438,7 @@ static int venc_power_on(struct venc_device *venc)
goto err0;
venc_reset(venc);
- venc_write_config(venc, venc_timings_to_config(&venc->vm));
+ venc_write_config(venc, venc->config);
dss_set_venc_output(venc->dss, venc->type);
dss_set_dac_pwrdn_bgz(venc->dss, 1);
@@ -524,33 +488,17 @@ static void venc_power_off(struct venc_device *venc)
venc_runtime_put(venc);
}
-static int venc_display_enable(struct omap_dss_device *dssdev)
+static void venc_display_enable(struct omap_dss_device *dssdev)
{
struct venc_device *venc = dssdev_to_venc(dssdev);
- int r;
DSSDBG("venc_display_enable\n");
mutex_lock(&venc->venc_lock);
- if (!dssdev->dispc_channel_connected) {
- DSSERR("Failed to enable display: no output/manager\n");
- r = -ENODEV;
- goto err0;
- }
-
- r = venc_power_on(venc);
- if (r)
- goto err0;
-
- venc->wss_data = 0;
+ venc_power_on(venc);
mutex_unlock(&venc->venc_lock);
-
- return 0;
-err0:
- mutex_unlock(&venc->venc_lock);
- return r;
}
static void venc_display_disable(struct omap_dss_device *dssdev)
@@ -566,30 +514,70 @@ static void venc_display_disable(struct omap_dss_device *dssdev)
mutex_unlock(&venc->venc_lock);
}
-static void venc_get_timings(struct omap_dss_device *dssdev,
- struct videomode *vm)
+static int venc_get_modes(struct omap_dss_device *dssdev,
+ struct drm_connector *connector)
{
- struct venc_device *venc = dssdev_to_venc(dssdev);
+ static const struct drm_display_mode *modes[] = {
+ &omap_dss_pal_mode,
+ &omap_dss_ntsc_mode,
+ };
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(modes); ++i) {
+ struct drm_display_mode *mode;
+
+ mode = drm_mode_duplicate(connector->dev, modes[i]);
+ if (!mode)
+ return i;
+
+ mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+ drm_mode_set_name(mode);
+ drm_mode_probed_add(connector, mode);
+ }
- mutex_lock(&venc->venc_lock);
- *vm = venc->vm;
- mutex_unlock(&venc->venc_lock);
+ return ARRAY_SIZE(modes);
+}
+
+static enum venc_videomode venc_get_videomode(const struct drm_display_mode *mode)
+{
+ if (!(mode->flags & DRM_MODE_FLAG_INTERLACE))
+ return VENC_MODE_UNKNOWN;
+
+ if (mode->clock == omap_dss_pal_mode.clock &&
+ mode->hdisplay == omap_dss_pal_mode.hdisplay &&
+ mode->vdisplay == omap_dss_pal_mode.vdisplay)
+ return VENC_MODE_PAL;
+
+ if (mode->clock == omap_dss_ntsc_mode.clock &&
+ mode->hdisplay == omap_dss_ntsc_mode.hdisplay &&
+ mode->vdisplay == omap_dss_ntsc_mode.vdisplay)
+ return VENC_MODE_NTSC;
+
+ return VENC_MODE_UNKNOWN;
}
static void venc_set_timings(struct omap_dss_device *dssdev,
- const struct videomode *vm)
+ const struct drm_display_mode *mode)
{
struct venc_device *venc = dssdev_to_venc(dssdev);
+ enum venc_videomode venc_mode = venc_get_videomode(mode);
DSSDBG("venc_set_timings\n");
mutex_lock(&venc->venc_lock);
- /* Reset WSS data when the TV standard changes. */
- if (memcmp(&venc->vm, vm, sizeof(*vm)))
- venc->wss_data = 0;
+ switch (venc_mode) {
+ default:
+ WARN_ON_ONCE(1);
+ /* Fall-through */
+ case VENC_MODE_PAL:
+ venc->config = &venc_config_pal_trm;
+ break;
- venc->vm = *vm;
+ case VENC_MODE_NTSC:
+ venc->config = &venc_config_ntsc_trm;
+ break;
+ }
dispc_set_tv_pclk(venc->dss->dispc, 13500000);
@@ -597,22 +585,26 @@ static void venc_set_timings(struct omap_dss_device *dssdev,
}
static int venc_check_timings(struct omap_dss_device *dssdev,
- struct videomode *vm)
+ struct drm_display_mode *mode)
{
DSSDBG("venc_check_timings\n");
- switch (venc_get_videomode(vm)) {
+ switch (venc_get_videomode(mode)) {
case VENC_MODE_PAL:
- *vm = omap_dss_pal_vm;
- return 0;
+ drm_mode_copy(mode, &omap_dss_pal_mode);
+ break;
case VENC_MODE_NTSC:
- *vm = omap_dss_ntsc_vm;
- return 0;
+ drm_mode_copy(mode, &omap_dss_ntsc_mode);
+ break;
default:
return -EINVAL;
}
+
+ drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
+ drm_mode_set_name(mode);
+ return 0;
}
static int venc_dump_regs(struct seq_file *s, void *p)
@@ -695,21 +687,12 @@ static int venc_get_clocks(struct venc_device *venc)
static int venc_connect(struct omap_dss_device *src,
struct omap_dss_device *dst)
{
- int r;
-
- r = omapdss_device_connect(dst->dss, dst, dst->next);
- if (r)
- return r;
-
- dst->dispc_channel_connected = true;
- return 0;
+ return omapdss_device_connect(dst->dss, dst, dst->next);
}
static void venc_disconnect(struct omap_dss_device *src,
struct omap_dss_device *dst)
{
- dst->dispc_channel_connected = false;
-
omapdss_device_disconnect(dst, dst->next);
}
@@ -721,8 +704,9 @@ static const struct omap_dss_device_ops venc_ops = {
.disable = venc_display_disable,
.check_timings = venc_check_timings,
- .get_timings = venc_get_timings,
.set_timings = venc_set_timings,
+
+ .get_modes = venc_get_modes,
};
/* -----------------------------------------------------------------------------
@@ -776,26 +760,17 @@ static int venc_init_output(struct venc_device *venc)
out->dev = &venc->pdev->dev;
out->id = OMAP_DSS_OUTPUT_VENC;
- out->output_type = OMAP_DISPLAY_TYPE_VENC;
+ out->type = OMAP_DISPLAY_TYPE_VENC;
out->name = "venc.0";
out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
out->ops = &venc_ops;
out->owner = THIS_MODULE;
out->of_ports = BIT(0);
+ out->ops_flags = OMAP_DSS_DEVICE_OP_MODES;
- out->next = omapdss_of_find_connected_device(out->dev->of_node, 0);
- if (IS_ERR(out->next)) {
- if (PTR_ERR(out->next) != -EPROBE_DEFER)
- dev_err(out->dev, "failed to find video sink\n");
- return PTR_ERR(out->next);
- }
-
- r = omapdss_output_validate(out);
- if (r) {
- omapdss_device_put(out->next);
- out->next = NULL;
+ r = omapdss_device_init_output(out);
+ if (r < 0)
return r;
- }
omapdss_device_register(out);
@@ -804,9 +779,8 @@ static int venc_init_output(struct venc_device *venc)
static void venc_uninit_output(struct venc_device *venc)
{
- if (venc->output.next)
- omapdss_device_put(venc->output.next);
omapdss_device_unregister(&venc->output);
+ omapdss_device_cleanup_output(&venc->output);
}
static int venc_probe_of(struct venc_device *venc)
@@ -878,8 +852,7 @@ static int venc_probe(struct platform_device *pdev)
mutex_init(&venc->venc_lock);
- venc->wss_data = 0;
- venc->vm = omap_dss_pal_vm;
+ venc->config = &venc_config_pal_trm;
venc_mem = platform_get_resource(venc->pdev, IORESOURCE_MEM, 0);
venc->base = devm_ioremap_resource(&pdev->dev, venc_mem);
diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c
index 9da94d10782a..5967283934e1 100644
--- a/drivers/gpu/drm/omapdrm/omap_connector.c
+++ b/drivers/gpu/drm/omapdrm/omap_connector.c
@@ -17,6 +17,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
+#include <drm/drm_panel.h>
#include <drm/drm_probe_helper.h>
#include "omap_drv.h"
@@ -30,24 +31,27 @@
struct omap_connector {
struct drm_connector base;
struct omap_dss_device *output;
- struct omap_dss_device *display;
struct omap_dss_device *hpd;
bool hdmi_mode;
};
static void omap_connector_hpd_notify(struct drm_connector *connector,
- struct omap_dss_device *src,
enum drm_connector_status status)
{
- if (status == connector_status_disconnected) {
- /*
- * If the source is an HDMI encoder, notify it of disconnection.
- * This is required to let the HDMI encoder reset any internal
- * state related to connection status, such as the CEC address.
- */
- if (src && src->type == OMAP_DISPLAY_TYPE_HDMI &&
- src->ops->hdmi.lost_hotplug)
- src->ops->hdmi.lost_hotplug(src);
+ struct omap_connector *omap_connector = to_omap_connector(connector);
+ struct omap_dss_device *dssdev;
+
+ if (status != connector_status_disconnected)
+ return;
+
+ /*
+ * Notify all devics in the pipeline of disconnection. This is required
+ * to let the HDMI encoders reset their internal state related to
+ * connection status, such as the CEC address.
+ */
+ for (dssdev = omap_connector->output; dssdev; dssdev = dssdev->next) {
+ if (dssdev->ops && dssdev->ops->hdmi.lost_hotplug)
+ dssdev->ops->hdmi.lost_hotplug(dssdev);
}
}
@@ -67,7 +71,7 @@ static void omap_connector_hpd_cb(void *cb_data,
if (old_status == status)
return;
- omap_connector_hpd_notify(connector, omap_connector->hpd, status);
+ omap_connector_hpd_notify(connector, status);
drm_kms_helper_hotplug_event(dev);
}
@@ -103,20 +107,20 @@ omap_connector_find_device(struct drm_connector *connector,
enum omap_dss_device_ops_flag op)
{
struct omap_connector *omap_connector = to_omap_connector(connector);
- struct omap_dss_device *dssdev;
+ struct omap_dss_device *dssdev = NULL;
+ struct omap_dss_device *d;
- for (dssdev = omap_connector->display; dssdev; dssdev = dssdev->src) {
- if (dssdev->ops_flags & op)
- return dssdev;
+ for (d = omap_connector->output; d; d = d->next) {
+ if (d->ops_flags & op)
+ dssdev = d;
}
- return NULL;
+ return dssdev;
}
static enum drm_connector_status omap_connector_detect(
struct drm_connector *connector, bool force)
{
- struct omap_connector *omap_connector = to_omap_connector(connector);
struct omap_dss_device *dssdev;
enum drm_connector_status status;
@@ -128,13 +132,12 @@ static enum drm_connector_status omap_connector_detect(
? connector_status_connected
: connector_status_disconnected;
- omap_connector_hpd_notify(connector, dssdev->src, status);
+ omap_connector_hpd_notify(connector, status);
} else {
- switch (omap_connector->display->type) {
- case OMAP_DISPLAY_TYPE_DPI:
- case OMAP_DISPLAY_TYPE_DBI:
- case OMAP_DISPLAY_TYPE_SDI:
- case OMAP_DISPLAY_TYPE_DSI:
+ switch (connector->connector_type) {
+ case DRM_MODE_CONNECTOR_DPI:
+ case DRM_MODE_CONNECTOR_LVDS:
+ case DRM_MODE_CONNECTOR_DSI:
status = connector_status_connected;
break;
default:
@@ -143,7 +146,7 @@ static enum drm_connector_status omap_connector_detect(
}
}
- VERB("%s: %d (force=%d)", omap_connector->display->name, status, force);
+ VERB("%s: %d (force=%d)", connector->name, status, force);
return status;
}
@@ -152,7 +155,7 @@ static void omap_connector_destroy(struct drm_connector *connector)
{
struct omap_connector *omap_connector = to_omap_connector(connector);
- DBG("%s", omap_connector->display->name);
+ DBG("%s", connector->name);
if (omap_connector->hpd) {
struct omap_dss_device *hpd = omap_connector->hpd;
@@ -166,7 +169,6 @@ static void omap_connector_destroy(struct drm_connector *connector)
drm_connector_cleanup(connector);
omapdss_device_put(omap_connector->output);
- omapdss_device_put(omap_connector->display);
kfree(omap_connector);
}
@@ -212,10 +214,8 @@ static int omap_connector_get_modes(struct drm_connector *connector)
{
struct omap_connector *omap_connector = to_omap_connector(connector);
struct omap_dss_device *dssdev;
- struct drm_display_mode *mode;
- struct videomode vm = {0};
- DBG("%s", omap_connector->display->name);
+ DBG("%s", connector->name);
/*
* If display exposes EDID, then we parse that in the normal way to
@@ -227,89 +227,71 @@ static int omap_connector_get_modes(struct drm_connector *connector)
return omap_connector_get_modes_edid(connector, dssdev);
/*
- * Otherwise we have either a fixed resolution panel or an output that
- * doesn't support modes discovery (e.g. DVI or VGA with the DDC bus
- * unconnected, or analog TV). Start by querying the size.
+ * Otherwise if the display pipeline reports modes (e.g. with a fixed
+ * resolution panel or an analog TV output), query it.
*/
- dssdev = omap_connector->display;
- if (dssdev->driver && dssdev->driver->get_size)
- dssdev->driver->get_size(dssdev,
- &connector->display_info.width_mm,
- &connector->display_info.height_mm);
+ dssdev = omap_connector_find_device(connector,
+ OMAP_DSS_DEVICE_OP_MODES);
+ if (dssdev)
+ return dssdev->ops->get_modes(dssdev, connector);
/*
- * Iterate over the pipeline to find the first device that can provide
- * timing information. If we can't find any, we just let the KMS core
- * add the default modes.
+ * Otherwise if the display pipeline uses a drm_panel, we delegate the
+ * operation to the panel API.
*/
- for (dssdev = omap_connector->display; dssdev; dssdev = dssdev->src) {
- if (dssdev->ops->get_timings)
- break;
- }
- if (!dssdev)
- return 0;
+ if (omap_connector->output->panel)
+ return drm_panel_get_modes(omap_connector->output->panel);
- /* Add a single mode corresponding to the fixed panel timings. */
- mode = drm_mode_create(connector->dev);
- if (!mode)
- return 0;
+ /*
+ * We can't retrieve modes, which can happen for instance for a DVI or
+ * VGA output with the DDC bus unconnected. The KMS core will add the
+ * default modes.
+ */
+ return 0;
+}
- dssdev->ops->get_timings(dssdev, &vm);
+enum drm_mode_status omap_connector_mode_fixup(struct omap_dss_device *dssdev,
+ const struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ int ret;
- drm_display_mode_from_videomode(&vm, mode);
+ drm_mode_copy(adjusted_mode, mode);
- mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
- drm_mode_set_name(mode);
- drm_mode_probed_add(connector, mode);
+ for (; dssdev; dssdev = dssdev->next) {
+ if (!dssdev->ops->check_timings)
+ continue;
+
+ ret = dssdev->ops->check_timings(dssdev, adjusted_mode);
+ if (ret)
+ return MODE_BAD;
+ }
- return 1;
+ return MODE_OK;
}
-static int omap_connector_mode_valid(struct drm_connector *connector,
+static enum drm_mode_status omap_connector_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
struct omap_connector *omap_connector = to_omap_connector(connector);
- enum omap_channel channel = omap_connector->output->dispc_channel;
- struct omap_drm_private *priv = connector->dev->dev_private;
- struct omap_dss_device *dssdev;
- struct videomode vm = {0};
- struct drm_device *dev = connector->dev;
- struct drm_display_mode *new_mode;
- int r, ret = MODE_BAD;
-
- drm_display_mode_to_videomode(mode, &vm);
- mode->vrefresh = drm_mode_vrefresh(mode);
+ struct drm_display_mode new_mode = { { 0 } };
+ enum drm_mode_status status;
- r = priv->dispc_ops->mgr_check_timings(priv->dispc, channel, &vm);
- if (r)
+ status = omap_connector_mode_fixup(omap_connector->output, mode,
+ &new_mode);
+ if (status != MODE_OK)
goto done;
- for (dssdev = omap_connector->output; dssdev; dssdev = dssdev->next) {
- if (!dssdev->ops->check_timings)
- continue;
-
- r = dssdev->ops->check_timings(dssdev, &vm);
- if (r)
- goto done;
- }
-
- /* check if vrefresh is still valid */
- new_mode = drm_mode_duplicate(dev, mode);
- if (!new_mode)
- return MODE_BAD;
-
- new_mode->clock = vm.pixelclock / 1000;
- new_mode->vrefresh = 0;
- if (mode->vrefresh == drm_mode_vrefresh(new_mode))
- ret = MODE_OK;
- drm_mode_destroy(dev, new_mode);
+ /* Check if vrefresh is still valid. */
+ if (drm_mode_vrefresh(mode) != drm_mode_vrefresh(&new_mode))
+ status = MODE_NOCLOCK;
done:
DBG("connector: mode %s: " DRM_MODE_FMT,
- (ret == MODE_OK) ? "valid" : "invalid",
+ (status == MODE_OK) ? "valid" : "invalid",
DRM_MODE_ARG(mode));
- return ret;
+ return status;
}
static const struct drm_connector_funcs omap_connector_funcs = {
@@ -326,9 +308,16 @@ static const struct drm_connector_helper_funcs omap_connector_helper_funcs = {
.mode_valid = omap_connector_mode_valid,
};
-static int omap_connector_get_type(struct omap_dss_device *display)
+static int omap_connector_get_type(struct omap_dss_device *output)
{
- switch (display->type) {
+ struct omap_dss_device *display;
+ enum omap_display_type type;
+
+ display = omapdss_display_get(output);
+ type = display->type;
+ omapdss_device_put(display);
+
+ switch (type) {
case OMAP_DISPLAY_TYPE_HDMI:
return DRM_MODE_CONNECTOR_HDMIA;
case OMAP_DISPLAY_TYPE_DVI:
@@ -351,28 +340,26 @@ static int omap_connector_get_type(struct omap_dss_device *display)
/* initialize connector */
struct drm_connector *omap_connector_init(struct drm_device *dev,
struct omap_dss_device *output,
- struct omap_dss_device *display,
struct drm_encoder *encoder)
{
struct drm_connector *connector = NULL;
struct omap_connector *omap_connector;
struct omap_dss_device *dssdev;
- DBG("%s", display->name);
+ DBG("%s", output->name);
omap_connector = kzalloc(sizeof(*omap_connector), GFP_KERNEL);
if (!omap_connector)
goto fail;
omap_connector->output = omapdss_device_get(output);
- omap_connector->display = omapdss_device_get(display);
connector = &omap_connector->base;
connector->interlace_allowed = 1;
connector->doublescan_allowed = 0;
drm_connector_init(dev, connector, &omap_connector_funcs,
- omap_connector_get_type(display));
+ omap_connector_get_type(output));
drm_connector_helper_add(connector, &omap_connector_helper_funcs);
/*
diff --git a/drivers/gpu/drm/omapdrm/omap_connector.h b/drivers/gpu/drm/omapdrm/omap_connector.h
index 854099801649..608085219336 100644
--- a/drivers/gpu/drm/omapdrm/omap_connector.h
+++ b/drivers/gpu/drm/omapdrm/omap_connector.h
@@ -22,6 +22,8 @@
#include <linux/types.h>
+enum drm_mode_status;
+
struct drm_connector;
struct drm_device;
struct drm_encoder;
@@ -29,12 +31,12 @@ struct omap_dss_device;
struct drm_connector *omap_connector_init(struct drm_device *dev,
struct omap_dss_device *output,
- struct omap_dss_device *display,
struct drm_encoder *encoder);
-struct drm_encoder *omap_connector_attached_encoder(
- struct drm_connector *connector);
bool omap_connector_get_hdmi_mode(struct drm_connector *connector);
void omap_connector_enable_hpd(struct drm_connector *connector);
void omap_connector_disable_hpd(struct drm_connector *connector);
+enum drm_mode_status omap_connector_mode_fixup(struct omap_dss_device *dssdev,
+ const struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode);
#endif /* __OMAPDRM_CONNECTOR_H__ */
diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index d99e24dcc0bf..5a29bf01c0e8 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -128,7 +128,7 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable)
if (WARN_ON(omap_crtc->enabled == enable))
return;
- if (omap_crtc->pipe->output->output_type == OMAP_DISPLAY_TYPE_HDMI) {
+ if (omap_crtc->pipe->output->type == OMAP_DISPLAY_TYPE_HDMI) {
priv->dispc_ops->mgr_enable(priv->dispc, channel, enable);
omap_crtc->enabled = enable;
return;
@@ -390,6 +390,15 @@ static enum drm_mode_status omap_crtc_mode_valid(struct drm_crtc *crtc,
const struct drm_display_mode *mode)
{
struct omap_drm_private *priv = crtc->dev->dev_private;
+ struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+ struct videomode vm = {0};
+ int r;
+
+ drm_display_mode_to_videomode(mode, &vm);
+ r = priv->dispc_ops->mgr_check_timings(priv->dispc, omap_crtc->channel,
+ &vm);
+ if (r)
+ return r;
/* Check for bandwidth limit */
if (priv->max_bandwidth) {
@@ -657,7 +666,7 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev,
&omap_crtc_funcs, NULL);
if (ret < 0) {
dev_err(dev->dev, "%s(): could not init crtc for: %s\n",
- __func__, pipe->display->name);
+ __func__, pipe->output->name);
kfree(omap_crtc);
return ERR_PTR(ret);
}
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index f8292278f57d..1b9b6f5e48e1 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -23,6 +23,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_probe_helper.h>
+#include <drm/drm_panel.h>
#include "omap_dmm_tiler.h"
#include "omap_drv.h"
@@ -137,12 +138,13 @@ static void omap_disconnect_pipelines(struct drm_device *ddev)
for (i = 0; i < priv->num_pipes; i++) {
struct omap_drm_pipeline *pipe = &priv->pipes[i];
+ if (pipe->output->panel)
+ drm_panel_detach(pipe->output->panel);
+
omapdss_device_disconnect(NULL, pipe->output);
omapdss_device_put(pipe->output);
- omapdss_device_put(pipe->display);
pipe->output = NULL;
- pipe->display = NULL;
}
memset(&priv->channels, 0, sizeof(priv->channels));
@@ -150,33 +152,17 @@ static void omap_disconnect_pipelines(struct drm_device *ddev)
priv->num_pipes = 0;
}
-static int omap_compare_pipes(const void *a, const void *b)
-{
- const struct omap_drm_pipeline *pipe1 = a;
- const struct omap_drm_pipeline *pipe2 = b;
-
- if (pipe1->display->alias_id > pipe2->display->alias_id)
- return 1;
- else if (pipe1->display->alias_id < pipe2->display->alias_id)
- return -1;
- return 0;
-}
-
static int omap_connect_pipelines(struct drm_device *ddev)
{
struct omap_drm_private *priv = ddev->dev_private;
struct omap_dss_device *output = NULL;
- unsigned int i;
int r;
- if (!omapdss_stack_is_ready())
- return -EPROBE_DEFER;
-
for_each_dss_output(output) {
r = omapdss_device_connect(priv->dss, NULL, output);
if (r == -EPROBE_DEFER) {
omapdss_device_put(output);
- goto cleanup;
+ return r;
} else if (r) {
dev_warn(output->dev, "could not connect output %s\n",
output->name);
@@ -185,7 +171,6 @@ static int omap_connect_pipelines(struct drm_device *ddev)
pipe = &priv->pipes[priv->num_pipes++];
pipe->output = omapdss_device_get(output);
- pipe->display = omapdss_display_get(output);
if (priv->num_pipes == ARRAY_SIZE(priv->pipes)) {
/* To balance the 'for_each_dss_output' loop */
@@ -195,36 +180,19 @@ static int omap_connect_pipelines(struct drm_device *ddev)
}
}
- /* Sort the list by DT aliases */
- sort(priv->pipes, priv->num_pipes, sizeof(priv->pipes[0]),
- omap_compare_pipes, NULL);
-
- /*
- * Populate the pipeline lookup table by DISPC channel. Only one display
- * is allowed per channel.
- */
- for (i = 0; i < priv->num_pipes; ++i) {
- struct omap_drm_pipeline *pipe = &priv->pipes[i];
- enum omap_channel channel = pipe->output->dispc_channel;
-
- if (WARN_ON(priv->channels[channel] != NULL)) {
- r = -EINVAL;
- goto cleanup;
- }
-
- priv->channels[channel] = pipe;
- }
-
return 0;
+}
-cleanup:
- /*
- * if we are deferring probe, we disconnect the devices we previously
- * connected
- */
- omap_disconnect_pipelines(ddev);
+static int omap_compare_pipelines(const void *a, const void *b)
+{
+ const struct omap_drm_pipeline *pipe1 = a;
+ const struct omap_drm_pipeline *pipe2 = b;
- return r;
+ if (pipe1->alias_id > pipe2->alias_id)
+ return 1;
+ else if (pipe1->alias_id < pipe2->alias_id)
+ return -1;
+ return 0;
}
static int omap_modeset_init_properties(struct drm_device *dev)
@@ -240,6 +208,30 @@ static int omap_modeset_init_properties(struct drm_device *dev)
return 0;
}
+static int omap_display_id(struct omap_dss_device *output)
+{
+ struct device_node *node = NULL;
+
+ if (output->next) {
+ struct omap_dss_device *display;
+
+ display = omapdss_display_get(output);
+ node = display->dev->of_node;
+ omapdss_device_put(display);
+ } else if (output->bridge) {
+ struct drm_bridge *bridge = output->bridge;
+
+ while (bridge->next)
+ bridge = bridge->next;
+
+ node = bridge->of_node;
+ } else if (output->panel) {
+ node = output->panel->dev->of_node;
+ }
+
+ return node ? of_alias_get_id(node, "display") : -ENODEV;
+}
+
static int omap_modeset_init(struct drm_device *dev)
{
struct omap_drm_private *priv = dev->dev_private;
@@ -249,6 +241,9 @@ static int omap_modeset_init(struct drm_device *dev)
int ret;
u32 plane_crtc_mask;
+ if (!omapdss_stack_is_ready())
+ return -EPROBE_DEFER;
+
drm_mode_config_init(dev);
ret = omap_modeset_init_properties(dev);
@@ -263,6 +258,10 @@ static int omap_modeset_init(struct drm_device *dev)
* configuration does not match the expectations or exceeds
* the available resources, the configuration is rejected.
*/
+ ret = omap_connect_pipelines(dev);
+ if (ret < 0)
+ return ret;
+
if (priv->num_pipes > num_mgrs || priv->num_pipes > num_ovls) {
dev_err(dev->dev, "%s(): Too many connected displays\n",
__func__);
@@ -288,33 +287,75 @@ static int omap_modeset_init(struct drm_device *dev)
priv->planes[priv->num_planes++] = plane;
}
- /* Create the CRTCs, encoders and connectors. */
+ /*
+ * Create the encoders, attach the bridges and get the pipeline alias
+ * IDs.
+ */
for (i = 0; i < priv->num_pipes; i++) {
struct omap_drm_pipeline *pipe = &priv->pipes[i];
- struct omap_dss_device *display = pipe->display;
- struct drm_connector *connector;
- struct drm_encoder *encoder;
- struct drm_crtc *crtc;
+ int id;
- encoder = omap_encoder_init(dev, pipe->output, display);
- if (!encoder)
+ pipe->encoder = omap_encoder_init(dev, pipe->output);
+ if (!pipe->encoder)
return -ENOMEM;
- connector = omap_connector_init(dev, pipe->output, display,
- encoder);
- if (!connector)
- return -ENOMEM;
+ if (pipe->output->bridge) {
+ ret = drm_bridge_attach(pipe->encoder,
+ pipe->output->bridge, NULL);
+ if (ret < 0)
+ return ret;
+ }
+
+ id = omap_display_id(pipe->output);
+ pipe->alias_id = id >= 0 ? id : i;
+ }
+
+ /* Sort the pipelines by DT aliases. */
+ sort(priv->pipes, priv->num_pipes, sizeof(priv->pipes[0]),
+ omap_compare_pipelines, NULL);
+
+ /*
+ * Populate the pipeline lookup table by DISPC channel. Only one display
+ * is allowed per channel.
+ */
+ for (i = 0; i < priv->num_pipes; ++i) {
+ struct omap_drm_pipeline *pipe = &priv->pipes[i];
+ enum omap_channel channel = pipe->output->dispc_channel;
+
+ if (WARN_ON(priv->channels[channel] != NULL))
+ return -EINVAL;
+
+ priv->channels[channel] = pipe;
+ }
+
+ /* Create the connectors and CRTCs. */
+ for (i = 0; i < priv->num_pipes; i++) {
+ struct omap_drm_pipeline *pipe = &priv->pipes[i];
+ struct drm_encoder *encoder = pipe->encoder;
+ struct drm_crtc *crtc;
+
+ if (!pipe->output->bridge) {
+ pipe->connector = omap_connector_init(dev, pipe->output,
+ encoder);
+ if (!pipe->connector)
+ return -ENOMEM;
+
+ drm_connector_attach_encoder(pipe->connector, encoder);
+
+ if (pipe->output->panel) {
+ ret = drm_panel_attach(pipe->output->panel,
+ pipe->connector);
+ if (ret < 0)
+ return ret;
+ }
+ }
crtc = omap_crtc_init(dev, pipe, priv->planes[i]);
if (IS_ERR(crtc))
return PTR_ERR(crtc);
- drm_connector_attach_encoder(connector, encoder);
encoder->possible_crtcs = 1 << i;
-
pipe->crtc = crtc;
- pipe->encoder = encoder;
- pipe->connector = connector;
}
DBG("registered %u planes, %u crtcs/encoders/connectors\n",
@@ -351,10 +392,12 @@ static int omap_modeset_init(struct drm_device *dev)
static void omap_modeset_enable_external_hpd(struct drm_device *ddev)
{
struct omap_drm_private *priv = ddev->dev_private;
- int i;
+ unsigned int i;
- for (i = 0; i < priv->num_pipes; i++)
- omap_connector_enable_hpd(priv->pipes[i].connector);
+ for (i = 0; i < priv->num_pipes; i++) {
+ if (priv->pipes[i].connector)
+ omap_connector_enable_hpd(priv->pipes[i].connector);
+ }
}
/*
@@ -363,10 +406,12 @@ static void omap_modeset_enable_external_hpd(struct drm_device *ddev)
static void omap_modeset_disable_external_hpd(struct drm_device *ddev)
{
struct omap_drm_private *priv = ddev->dev_private;
- int i;
+ unsigned int i;
- for (i = 0; i < priv->num_pipes; i++)
- omap_connector_disable_hpd(priv->pipes[i].connector);
+ for (i = 0; i < priv->num_pipes; i++) {
+ if (priv->pipes[i].connector)
+ omap_connector_disable_hpd(priv->pipes[i].connector);
+ }
}
/*
@@ -551,10 +596,6 @@ static int omapdrm_init(struct omap_drm_private *priv, struct device *dev)
omap_crtc_pre_init(priv);
- ret = omap_connect_pipelines(ddev);
- if (ret)
- goto err_crtc_uninit;
-
soc = soc_device_match(omapdrm_soc_devices);
priv->omaprev = soc ? (unsigned int)soc->data : 0;
priv->wq = alloc_ordered_workqueue("omapdrm", 0);
@@ -612,7 +653,6 @@ err_gem_deinit:
omap_gem_deinit(ddev);
destroy_workqueue(priv->wq);
omap_disconnect_pipelines(ddev);
-err_crtc_uninit:
omap_crtc_pre_uninit(priv);
drm_dev_put(ddev);
return ret;
@@ -685,54 +725,12 @@ static int pdev_remove(struct platform_device *pdev)
}
#ifdef CONFIG_PM_SLEEP
-static int omap_drm_suspend_all_displays(struct drm_device *ddev)
-{
- struct omap_drm_private *priv = ddev->dev_private;
- int i;
-
- for (i = 0; i < priv->num_pipes; i++) {
- struct omap_dss_device *display = priv->pipes[i].display;
-
- if (display->state == OMAP_DSS_DISPLAY_ACTIVE) {
- display->ops->disable(display);
- display->activate_after_resume = true;
- } else {
- display->activate_after_resume = false;
- }
- }
-
- return 0;
-}
-
-static int omap_drm_resume_all_displays(struct drm_device *ddev)
-{
- struct omap_drm_private *priv = ddev->dev_private;
- int i;
-
- for (i = 0; i < priv->num_pipes; i++) {
- struct omap_dss_device *display = priv->pipes[i].display;
-
- if (display->activate_after_resume) {
- display->ops->enable(display);
- display->activate_after_resume = false;
- }
- }
-
- return 0;
-}
-
static int omap_drm_suspend(struct device *dev)
{
struct omap_drm_private *priv = dev_get_drvdata(dev);
struct drm_device *drm_dev = priv->ddev;
- drm_kms_helper_poll_disable(drm_dev);
-
- drm_modeset_lock_all(drm_dev);
- omap_drm_suspend_all_displays(drm_dev);
- drm_modeset_unlock_all(drm_dev);
-
- return 0;
+ return drm_mode_config_helper_suspend(drm_dev);
}
static int omap_drm_resume(struct device *dev)
@@ -740,11 +738,7 @@ static int omap_drm_resume(struct device *dev)
struct omap_drm_private *priv = dev_get_drvdata(dev);
struct drm_device *drm_dev = priv->ddev;
- drm_modeset_lock_all(drm_dev);
- omap_drm_resume_all_displays(drm_dev);
- drm_modeset_unlock_all(drm_dev);
-
- drm_kms_helper_poll_enable(drm_dev);
+ drm_mode_config_helper_resume(drm_dev);
return omap_gem_resume(drm_dev);
}
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index 0c57d2814c51..3cca45cb25f3 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -49,7 +49,7 @@ struct omap_drm_pipeline {
struct drm_encoder *encoder;
struct drm_connector *connector;
struct omap_dss_device *output;
- struct omap_dss_device *display;
+ unsigned int alias_id;
};
struct omap_drm_private {
diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c b/drivers/gpu/drm/omapdrm/omap_encoder.c
index 0d85b3a35767..40512419642b 100644
--- a/drivers/gpu/drm/omapdrm/omap_encoder.c
+++ b/drivers/gpu/drm/omapdrm/omap_encoder.c
@@ -20,6 +20,7 @@
#include <drm/drm_crtc.h>
#include <drm/drm_modeset_helper_vtables.h>
#include <drm/drm_edid.h>
+#include <drm/drm_panel.h>
#include "omap_drv.h"
@@ -37,7 +38,6 @@
struct omap_encoder {
struct drm_encoder base;
struct omap_dss_device *output;
- struct omap_dss_device *display;
};
static void omap_encoder_destroy(struct drm_encoder *encoder)
@@ -52,22 +52,43 @@ static const struct drm_encoder_funcs omap_encoder_funcs = {
.destroy = omap_encoder_destroy,
};
-static void omap_encoder_hdmi_mode_set(struct drm_encoder *encoder,
+static void omap_encoder_update_videomode_flags(struct videomode *vm,
+ u32 bus_flags)
+{
+ if (!(vm->flags & (DISPLAY_FLAGS_DE_LOW |
+ DISPLAY_FLAGS_DE_HIGH))) {
+ if (bus_flags & DRM_BUS_FLAG_DE_LOW)
+ vm->flags |= DISPLAY_FLAGS_DE_LOW;
+ else if (bus_flags & DRM_BUS_FLAG_DE_HIGH)
+ vm->flags |= DISPLAY_FLAGS_DE_HIGH;
+ }
+
+ if (!(vm->flags & (DISPLAY_FLAGS_PIXDATA_POSEDGE |
+ DISPLAY_FLAGS_PIXDATA_NEGEDGE))) {
+ if (bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE)
+ vm->flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE;
+ else if (bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE)
+ vm->flags |= DISPLAY_FLAGS_PIXDATA_NEGEDGE;
+ }
+
+ if (!(vm->flags & (DISPLAY_FLAGS_SYNC_POSEDGE |
+ DISPLAY_FLAGS_SYNC_NEGEDGE))) {
+ if (bus_flags & DRM_BUS_FLAG_SYNC_DRIVE_POSEDGE)
+ vm->flags |= DISPLAY_FLAGS_SYNC_POSEDGE;
+ else if (bus_flags & DRM_BUS_FLAG_SYNC_DRIVE_NEGEDGE)
+ vm->flags |= DISPLAY_FLAGS_SYNC_NEGEDGE;
+ }
+}
+
+static void omap_encoder_hdmi_mode_set(struct drm_connector *connector,
+ struct drm_encoder *encoder,
struct drm_display_mode *adjusted_mode)
{
- struct drm_device *dev = encoder->dev;
struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
struct omap_dss_device *dssdev = omap_encoder->output;
- struct drm_connector *connector;
bool hdmi_mode;
- hdmi_mode = false;
- list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
- if (connector->encoder == encoder) {
- hdmi_mode = omap_connector_get_hdmi_mode(connector);
- break;
- }
- }
+ hdmi_mode = omap_connector_get_hdmi_mode(connector);
if (dssdev->ops->hdmi.set_hdmi_mode)
dssdev->ops->hdmi.set_hdmi_mode(dssdev, hdmi_mode);
@@ -88,8 +109,18 @@ static void omap_encoder_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *adjusted_mode)
{
struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
+ struct omap_dss_device *output = omap_encoder->output;
struct omap_dss_device *dssdev;
+ struct drm_device *dev = encoder->dev;
+ struct drm_connector *connector;
+ struct drm_bridge *bridge;
struct videomode vm = { 0 };
+ u32 bus_flags;
+
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+ if (connector->encoder == encoder)
+ break;
+ }
drm_display_mode_to_videomode(adjusted_mode, &vm);
@@ -102,66 +133,102 @@ static void omap_encoder_mode_set(struct drm_encoder *encoder,
*
* A better solution is to use DRM's bus-flags through the whole driver.
*/
- for (dssdev = omap_encoder->output; dssdev; dssdev = dssdev->next) {
- unsigned long bus_flags = dssdev->bus_flags;
-
- if (!(vm.flags & (DISPLAY_FLAGS_DE_LOW |
- DISPLAY_FLAGS_DE_HIGH))) {
- if (bus_flags & DRM_BUS_FLAG_DE_LOW)
- vm.flags |= DISPLAY_FLAGS_DE_LOW;
- else if (bus_flags & DRM_BUS_FLAG_DE_HIGH)
- vm.flags |= DISPLAY_FLAGS_DE_HIGH;
- }
-
- if (!(vm.flags & (DISPLAY_FLAGS_PIXDATA_POSEDGE |
- DISPLAY_FLAGS_PIXDATA_NEGEDGE))) {
- if (bus_flags & DRM_BUS_FLAG_PIXDATA_POSEDGE)
- vm.flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE;
- else if (bus_flags & DRM_BUS_FLAG_PIXDATA_NEGEDGE)
- vm.flags |= DISPLAY_FLAGS_PIXDATA_NEGEDGE;
- }
-
- if (!(vm.flags & (DISPLAY_FLAGS_SYNC_POSEDGE |
- DISPLAY_FLAGS_SYNC_NEGEDGE))) {
- if (bus_flags & DRM_BUS_FLAG_SYNC_POSEDGE)
- vm.flags |= DISPLAY_FLAGS_SYNC_POSEDGE;
- else if (bus_flags & DRM_BUS_FLAG_SYNC_NEGEDGE)
- vm.flags |= DISPLAY_FLAGS_SYNC_NEGEDGE;
- }
+ for (dssdev = output; dssdev; dssdev = dssdev->next)
+ omap_encoder_update_videomode_flags(&vm, dssdev->bus_flags);
+
+ for (bridge = output->bridge; bridge; bridge = bridge->next) {
+ if (!bridge->timings)
+ continue;
+
+ bus_flags = bridge->timings->input_bus_flags;
+ omap_encoder_update_videomode_flags(&vm, bus_flags);
}
+ bus_flags = connector->display_info.bus_flags;
+ omap_encoder_update_videomode_flags(&vm, bus_flags);
+
/* Set timings for all devices in the display pipeline. */
- dss_mgr_set_timings(omap_encoder->output, &vm);
+ dss_mgr_set_timings(output, &vm);
- for (dssdev = omap_encoder->output; dssdev; dssdev = dssdev->next) {
+ for (dssdev = output; dssdev; dssdev = dssdev->next) {
if (dssdev->ops->set_timings)
- dssdev->ops->set_timings(dssdev, &vm);
+ dssdev->ops->set_timings(dssdev, adjusted_mode);
}
/* Set the HDMI mode and HDMI infoframe if applicable. */
- if (omap_encoder->output->output_type == OMAP_DISPLAY_TYPE_HDMI)
- omap_encoder_hdmi_mode_set(encoder, adjusted_mode);
+ if (output->type == OMAP_DISPLAY_TYPE_HDMI)
+ omap_encoder_hdmi_mode_set(connector, encoder, adjusted_mode);
}
static void omap_encoder_disable(struct drm_encoder *encoder)
{
struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
- struct omap_dss_device *dssdev = omap_encoder->display;
+ struct omap_dss_device *dssdev = omap_encoder->output;
+ struct drm_device *dev = encoder->dev;
+
+ dev_dbg(dev->dev, "disable(%s)\n", dssdev->name);
+
+ /* Disable the panel if present. */
+ if (dssdev->panel) {
+ drm_panel_disable(dssdev->panel);
+ drm_panel_unprepare(dssdev->panel);
+ }
+
+ /*
+ * Disable the chain of external devices, starting at the one at the
+ * internal encoder's output.
+ */
+ omapdss_device_disable(dssdev->next);
+
+ /*
+ * Disable the internal encoder. This will disable the DSS output. The
+ * DSI is treated as an exception as DSI pipelines still use the legacy
+ * flow where the pipeline output controls the encoder.
+ */
+ if (dssdev->type != OMAP_DISPLAY_TYPE_DSI) {
+ dssdev->ops->disable(dssdev);
+ dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+ }
- dssdev->ops->disable(dssdev);
+ /*
+ * Perform the post-disable operations on the chain of external devices
+ * to complete the display pipeline disable.
+ */
+ omapdss_device_post_disable(dssdev->next);
}
static void omap_encoder_enable(struct drm_encoder *encoder)
{
struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
- struct omap_dss_device *dssdev = omap_encoder->display;
- int r;
-
- r = dssdev->ops->enable(dssdev);
- if (r)
- dev_err(encoder->dev->dev,
- "Failed to enable display '%s': %d\n",
- dssdev->name, r);
+ struct omap_dss_device *dssdev = omap_encoder->output;
+ struct drm_device *dev = encoder->dev;
+
+ dev_dbg(dev->dev, "enable(%s)\n", dssdev->name);
+
+ /* Prepare the chain of external devices for pipeline enable. */
+ omapdss_device_pre_enable(dssdev->next);
+
+ /*
+ * Enable the internal encoder. This will enable the DSS output. The
+ * DSI is treated as an exception as DSI pipelines still use the legacy
+ * flow where the pipeline output controls the encoder.
+ */
+ if (dssdev->type != OMAP_DISPLAY_TYPE_DSI) {
+ dssdev->ops->enable(dssdev);
+ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+ }
+
+ /*
+ * Enable the chain of external devices, starting at the one at the
+ * internal encoder's output.
+ */
+ omapdss_device_enable(dssdev->next);
+
+ /* Enable the panel if present. */
+ if (dssdev->panel) {
+ drm_panel_prepare(dssdev->panel);
+ drm_panel_enable(dssdev->panel);
+ }
}
static int omap_encoder_atomic_check(struct drm_encoder *encoder,
@@ -169,35 +236,17 @@ static int omap_encoder_atomic_check(struct drm_encoder *encoder,
struct drm_connector_state *conn_state)
{
struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
- enum omap_channel channel = omap_encoder->output->dispc_channel;
- struct drm_device *dev = encoder->dev;
- struct omap_drm_private *priv = dev->dev_private;
- struct omap_dss_device *dssdev;
- struct videomode vm = { 0 };
- int ret;
-
- drm_display_mode_to_videomode(&crtc_state->mode, &vm);
-
- ret = priv->dispc_ops->mgr_check_timings(priv->dispc, channel, &vm);
- if (ret)
- goto done;
-
- for (dssdev = omap_encoder->output; dssdev; dssdev = dssdev->next) {
- if (!dssdev->ops->check_timings)
- continue;
-
- ret = dssdev->ops->check_timings(dssdev, &vm);
- if (ret)
- goto done;
+ enum drm_mode_status status;
+
+ status = omap_connector_mode_fixup(omap_encoder->output,
+ &crtc_state->mode,
+ &crtc_state->adjusted_mode);
+ if (status != MODE_OK) {
+ dev_err(encoder->dev->dev, "invalid timings: %d\n", status);
+ return -EINVAL;
}
- drm_display_mode_from_videomode(&vm, &crtc_state->adjusted_mode);
-
-done:
- if (ret)
- dev_err(dev->dev, "invalid timings: %d\n", ret);
-
- return ret;
+ return 0;
}
static const struct drm_encoder_helper_funcs omap_encoder_helper_funcs = {
@@ -209,8 +258,7 @@ static const struct drm_encoder_helper_funcs omap_encoder_helper_funcs = {
/* initialize encoder */
struct drm_encoder *omap_encoder_init(struct drm_device *dev,
- struct omap_dss_device *output,
- struct omap_dss_device *display)
+ struct omap_dss_device *output)
{
struct drm_encoder *encoder = NULL;
struct omap_encoder *omap_encoder;
@@ -220,7 +268,6 @@ struct drm_encoder *omap_encoder_init(struct drm_device *dev,
goto fail;
omap_encoder->output = output;
- omap_encoder->display = display;
encoder = &omap_encoder->base;
diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.h b/drivers/gpu/drm/omapdrm/omap_encoder.h
index a7b5dde63ecb..4aefb3142886 100644
--- a/drivers/gpu/drm/omapdrm/omap_encoder.h
+++ b/drivers/gpu/drm/omapdrm/omap_encoder.h
@@ -25,7 +25,6 @@ struct drm_encoder;
struct omap_dss_device;
struct drm_encoder *omap_encoder_init(struct drm_device *dev,
- struct omap_dss_device *output,
- struct omap_dss_device *display);
+ struct omap_dss_device *output);
#endif /* __OMAPDRM_ENCODER_H__ */
diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c
index 851c59f07eb1..50aabd854f4d 100644
--- a/drivers/gpu/drm/omapdrm/omap_fbdev.c
+++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c
@@ -183,13 +183,9 @@ static int omap_fbdev_create(struct drm_fb_helper *helper,
fbdev->fb = fb;
helper->fb = fb;
- fbi->par = helper;
fbi->fbops = &omap_fb_ops;
- strcpy(fbi->fix.id, MODULE_NAME);
-
- drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->format->depth);
- drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height);
+ drm_fb_helper_fill_info(fbi, helper, sizes);
dev->mode_config.fb_base = dma_addr;