summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/omapdrm/dss
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/omapdrm/dss')
-rw-r--r--drivers/gpu/drm/omapdrm/dss/base.c217
-rw-r--r--drivers/gpu/drm/omapdrm/dss/core.c26
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dispc.c61
-rw-r--r--drivers/gpu/drm/omapdrm/dss/display.c134
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dpi.c192
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dsi.c569
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dss-of.c47
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dss.c47
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dss.h11
-rw-r--r--drivers/gpu/drm/omapdrm/dss/hdmi.h8
-rw-r--r--drivers/gpu/drm/omapdrm/dss/hdmi4.c351
-rw-r--r--drivers/gpu/drm/omapdrm/dss/hdmi5.c334
-rw-r--r--drivers/gpu/drm/omapdrm/dss/hdmi5_core.c6
-rw-r--r--drivers/gpu/drm/omapdrm/dss/hdmi_wp.c8
-rw-r--r--drivers/gpu/drm/omapdrm/dss/omapdss.h306
-rw-r--r--drivers/gpu/drm/omapdrm/dss/output.c208
-rw-r--r--drivers/gpu/drm/omapdrm/dss/sdi.c149
-rw-r--r--drivers/gpu/drm/omapdrm/dss/venc.c291
18 files changed, 1288 insertions, 1677 deletions
diff --git a/drivers/gpu/drm/omapdrm/dss/base.c b/drivers/gpu/drm/omapdrm/dss/base.c
index 99e8cb8dc65b..472f56e3de70 100644
--- a/drivers/gpu/drm/omapdrm/dss/base.c
+++ b/drivers/gpu/drm/omapdrm/dss/base.c
@@ -14,24 +14,17 @@
*/
#include <linux/kernel.h>
+#include <linux/list.h>
#include <linux/module.h>
+#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/of_graph.h>
-#include <linux/list.h>
#include "dss.h"
#include "omapdss.h"
static struct dss_device *dss_device;
-static struct list_head omapdss_comp_list;
-
-struct omapdss_comp_node {
- struct list_head list;
- struct device_node *node;
- bool dss_core_component;
-};
-
struct dss_device *omapdss_get_dss(void)
{
return dss_device;
@@ -56,6 +49,208 @@ const struct dispc_ops *dispc_get_ops(struct dss_device *dss)
}
EXPORT_SYMBOL(dispc_get_ops);
+
+/* -----------------------------------------------------------------------------
+ * OMAP DSS Devices Handling
+ */
+
+static LIST_HEAD(omapdss_devices_list);
+static DEFINE_MUTEX(omapdss_devices_lock);
+
+void omapdss_device_register(struct omap_dss_device *dssdev)
+{
+ mutex_lock(&omapdss_devices_lock);
+ list_add_tail(&dssdev->list, &omapdss_devices_list);
+ mutex_unlock(&omapdss_devices_lock);
+}
+EXPORT_SYMBOL_GPL(omapdss_device_register);
+
+void omapdss_device_unregister(struct omap_dss_device *dssdev)
+{
+ mutex_lock(&omapdss_devices_lock);
+ list_del(&dssdev->list);
+ mutex_unlock(&omapdss_devices_lock);
+}
+EXPORT_SYMBOL_GPL(omapdss_device_unregister);
+
+static bool omapdss_device_is_registered(struct device_node *node)
+{
+ struct omap_dss_device *dssdev;
+ bool found = false;
+
+ mutex_lock(&omapdss_devices_lock);
+
+ list_for_each_entry(dssdev, &omapdss_devices_list, list) {
+ if (dssdev->dev->of_node == node) {
+ found = true;
+ break;
+ }
+ }
+
+ mutex_unlock(&omapdss_devices_lock);
+ return found;
+}
+
+struct omap_dss_device *omapdss_device_get(struct omap_dss_device *dssdev)
+{
+ if (!try_module_get(dssdev->owner))
+ return NULL;
+
+ if (get_device(dssdev->dev) == NULL) {
+ module_put(dssdev->owner);
+ return NULL;
+ }
+
+ return dssdev;
+}
+EXPORT_SYMBOL(omapdss_device_get);
+
+void omapdss_device_put(struct omap_dss_device *dssdev)
+{
+ put_device(dssdev->dev);
+ module_put(dssdev->owner);
+}
+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 *dssdev;
+
+ list_for_each_entry(dssdev, &omapdss_devices_list, list) {
+ if (dssdev->dev->of_node == src && dssdev->of_ports & BIT(port))
+ return omapdss_device_get(dssdev);
+ }
+
+ return NULL;
+}
+
+/*
+ * 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.
+ */
+struct omap_dss_device *omapdss_device_get_next(struct omap_dss_device *from,
+ enum omap_dss_device_type type)
+{
+ struct omap_dss_device *dssdev;
+ struct list_head *list;
+
+ mutex_lock(&omapdss_devices_lock);
+
+ if (list_empty(&omapdss_devices_list)) {
+ dssdev = NULL;
+ goto done;
+ }
+
+ /*
+ * Start from the from entry if given or from omapdss_devices_list
+ * otherwise.
+ */
+ list = from ? &from->list : &omapdss_devices_list;
+
+ list_for_each_entry(dssdev, list, list) {
+ /*
+ * Stop if we reach the omapdss_devices_list, that's the end of
+ * the list.
+ */
+ if (&dssdev->list == &omapdss_devices_list) {
+ dssdev = NULL;
+ 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)
+ goto done;
+ }
+
+ dssdev = NULL;
+
+done:
+ if (from)
+ omapdss_device_put(from);
+ if (dssdev)
+ omapdss_device_get(dssdev);
+
+ mutex_unlock(&omapdss_devices_lock);
+ return dssdev;
+}
+EXPORT_SYMBOL(omapdss_device_get_next);
+
+int omapdss_device_connect(struct dss_device *dss,
+ struct omap_dss_device *src,
+ struct omap_dss_device *dst)
+{
+ int ret;
+
+ dev_dbg(dst->dev, "connect\n");
+
+ if (omapdss_device_is_connected(dst))
+ return -EBUSY;
+
+ dst->dss = dss;
+
+ ret = dst->ops->connect(src, dst);
+ if (ret < 0) {
+ dst->dss = NULL;
+ return ret;
+ }
+
+ if (src) {
+ WARN_ON(src->dst);
+ dst->src = src;
+ src->dst = dst;
+ }
+
+ return 0;
+}
+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");
+
+ if (!dst->id && !omapdss_device_is_connected(dst)) {
+ WARN_ON(dst->output_type);
+ return;
+ }
+
+ if (src) {
+ if (WARN_ON(dst != src->dst))
+ return;
+
+ dst->src = NULL;
+ src->dst = NULL;
+ }
+
+ WARN_ON(dst->state != OMAP_DSS_DISPLAY_DISABLED);
+
+ dst->ops->disconnect(src, dst);
+ dst->dss = NULL;
+}
+EXPORT_SYMBOL_GPL(omapdss_device_disconnect);
+
+/* -----------------------------------------------------------------------------
+ * Components Handling
+ */
+
+static struct list_head omapdss_comp_list;
+
+struct omapdss_comp_node {
+ struct list_head list;
+ struct device_node *node;
+ bool dss_core_component;
+};
+
static bool omapdss_list_contains(const struct device_node *node)
{
struct omapdss_comp_node *comp;
@@ -130,9 +325,7 @@ static bool omapdss_component_is_loaded(struct omapdss_comp_node *comp)
{
if (comp->dss_core_component)
return true;
- if (omapdss_component_is_display(comp->node))
- return true;
- if (omapdss_component_is_output(comp->node))
+ if (omapdss_device_is_registered(comp->node))
return true;
return false;
diff --git a/drivers/gpu/drm/omapdrm/dss/core.c b/drivers/gpu/drm/omapdrm/dss/core.c
index 07d00a186f15..a2edabc9f6b3 100644
--- a/drivers/gpu/drm/omapdrm/dss/core.c
+++ b/drivers/gpu/drm/omapdrm/dss/core.c
@@ -45,36 +45,14 @@ static struct platform_driver * const omap_dss_drivers[] = {
#endif
};
-static struct platform_device *omap_drm_device;
-
static int __init omap_dss_init(void)
{
- int r;
-
- r = platform_register_drivers(omap_dss_drivers,
- ARRAY_SIZE(omap_dss_drivers));
- if (r)
- goto err_reg;
-
- omap_drm_device = platform_device_register_simple("omapdrm", 0, NULL, 0);
- if (IS_ERR(omap_drm_device)) {
- r = PTR_ERR(omap_drm_device);
- goto err_reg;
- }
-
- return 0;
-
-err_reg:
- platform_unregister_drivers(omap_dss_drivers,
- ARRAY_SIZE(omap_dss_drivers));
-
- return r;
+ return platform_register_drivers(omap_dss_drivers,
+ ARRAY_SIZE(omap_dss_drivers));
}
static void __exit omap_dss_exit(void)
{
- platform_device_unregister(omap_drm_device);
-
platform_unregister_drivers(omap_dss_drivers,
ARRAY_SIZE(omap_dss_drivers));
}
diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c
index 84f274c4a4cb..ba82d916719c 100644
--- a/drivers/gpu/drm/omapdrm/dss/dispc.c
+++ b/drivers/gpu/drm/omapdrm/dss/dispc.c
@@ -1140,18 +1140,6 @@ static void dispc_ovl_set_color_mode(struct dispc_device *dispc,
REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), m, 4, 1);
}
-static bool format_is_yuv(u32 fourcc)
-{
- switch (fourcc) {
- case DRM_FORMAT_YUYV:
- case DRM_FORMAT_UYVY:
- case DRM_FORMAT_NV12:
- return true;
- default:
- return false;
- }
-}
-
static void dispc_ovl_configure_burst_type(struct dispc_device *dispc,
enum omap_plane_id plane,
enum omap_dss_rotation_type rotation)
@@ -1910,11 +1898,14 @@ static void dispc_ovl_set_scaling_uv(struct dispc_device *dispc,
int scale_x = out_width != orig_width;
int scale_y = out_height != orig_height;
bool chroma_upscale = plane != OMAP_DSS_WB;
+ const struct drm_format_info *info;
+
+ info = drm_format_info(fourcc);
if (!dispc_has_feature(dispc, FEAT_HANDLE_UV_SEPARATE))
return;
- if (!format_is_yuv(fourcc)) {
+ if (!info->is_yuv) {
/* reset chroma resampling for RGB formats */
if (plane != OMAP_DSS_WB)
REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES2(plane),
@@ -2624,7 +2615,7 @@ static int dispc_ovl_setup_common(struct dispc_device *dispc,
unsigned int offset0, offset1;
s32 row_inc;
s32 pix_inc;
- u16 frame_width, frame_height;
+ u16 frame_width;
unsigned int field_offset = 0;
u16 in_height = height;
u16 in_width = width;
@@ -2632,6 +2623,9 @@ static int dispc_ovl_setup_common(struct dispc_device *dispc,
bool ilace = !!(vm->flags & DISPLAY_FLAGS_INTERLACED);
unsigned long pclk = dispc_plane_pclk_rate(dispc, plane);
unsigned long lclk = dispc_plane_lclk_rate(dispc, plane);
+ const struct drm_format_info *info;
+
+ info = drm_format_info(fourcc);
/* when setting up WB, dispc_plane_pclk_rate() returns 0 */
if (plane == OMAP_DSS_WB)
@@ -2640,7 +2634,7 @@ static int dispc_ovl_setup_common(struct dispc_device *dispc,
if (paddr == 0 && rotation_type != OMAP_DSS_ROT_TILER)
return -EINVAL;
- if (format_is_yuv(fourcc) && (in_width & 1)) {
+ if (info->is_yuv && (in_width & 1)) {
DSSERR("input width %d is not even for YUV format\n", in_width);
return -EINVAL;
}
@@ -2680,7 +2674,7 @@ static int dispc_ovl_setup_common(struct dispc_device *dispc,
DSSDBG("predecimation %d x %x, new input size %d x %d\n",
x_predecim, y_predecim, in_width, in_height);
- if (format_is_yuv(fourcc) && (in_width & 1)) {
+ if (info->is_yuv && (in_width & 1)) {
DSSDBG("predecimated input width is not even for YUV format\n");
DSSDBG("adjusting input width %d -> %d\n",
in_width, in_width & ~1);
@@ -2688,7 +2682,7 @@ static int dispc_ovl_setup_common(struct dispc_device *dispc,
in_width &= ~1;
}
- if (format_is_yuv(fourcc))
+ if (info->is_yuv)
cconv = 1;
if (ilace && !fieldmode) {
@@ -2714,13 +2708,10 @@ static int dispc_ovl_setup_common(struct dispc_device *dispc,
row_inc = 0;
pix_inc = 0;
- if (plane == OMAP_DSS_WB) {
+ if (plane == OMAP_DSS_WB)
frame_width = out_width;
- frame_height = out_height;
- } else {
+ else
frame_width = in_width;
- frame_height = height;
- }
calc_offset(screen_width, frame_width,
fourcc, fieldmode, field_offset,
@@ -2904,13 +2895,6 @@ static int dispc_ovl_enable(struct dispc_device *dispc,
return 0;
}
-static enum omap_dss_output_id
-dispc_mgr_get_supported_outputs(struct dispc_device *dispc,
- enum omap_channel channel)
-{
- return dss_get_supported_outputs(dispc->dss, channel);
-}
-
static void dispc_lcd_enable_signal_polarity(struct dispc_device *dispc,
bool act_high)
{
@@ -3120,28 +3104,29 @@ static bool _dispc_mgr_pclk_ok(struct dispc_device *dispc,
return pclk <= dispc->feat->max_tv_pclk;
}
-bool dispc_mgr_timings_ok(struct dispc_device *dispc, enum omap_channel channel,
- const struct videomode *vm)
+static int dispc_mgr_check_timings(struct dispc_device *dispc,
+ enum omap_channel channel,
+ const struct videomode *vm)
{
if (!_dispc_mgr_size_ok(dispc, vm->hactive, vm->vactive))
- return false;
+ return MODE_BAD;
if (!_dispc_mgr_pclk_ok(dispc, channel, vm->pixelclock))
- return false;
+ return MODE_BAD;
if (dss_mgr_is_lcd(channel)) {
/* TODO: OMAP4+ supports interlace for LCD outputs */
if (vm->flags & DISPLAY_FLAGS_INTERLACED)
- return false;
+ return MODE_BAD;
if (!_dispc_lcd_timings_ok(dispc, vm->hsync_len,
vm->hfront_porch, vm->hback_porch,
vm->vsync_len, vm->vfront_porch,
vm->vback_porch))
- return false;
+ return MODE_BAD;
}
- return true;
+ return MODE_OK;
}
static void _dispc_mgr_set_lcd_timings(struct dispc_device *dispc,
@@ -3243,7 +3228,7 @@ static void dispc_mgr_set_timings(struct dispc_device *dispc,
DSSDBG("channel %d xres %u yres %u\n", channel, t.hactive, t.vactive);
- if (!dispc_mgr_timings_ok(dispc, channel, &t)) {
+ if (dispc_mgr_check_timings(dispc, channel, &t)) {
BUG();
return;
}
@@ -4740,9 +4725,9 @@ static const struct dispc_ops dispc_ops = {
.mgr_go_busy = dispc_mgr_go_busy,
.mgr_go = dispc_mgr_go,
.mgr_set_lcd_config = dispc_mgr_set_lcd_config,
+ .mgr_check_timings = dispc_mgr_check_timings,
.mgr_set_timings = dispc_mgr_set_timings,
.mgr_setup = dispc_mgr_setup,
- .mgr_get_supported_outputs = dispc_mgr_get_supported_outputs,
.mgr_gamma_size = dispc_mgr_gamma_size,
.mgr_set_gamma = dispc_mgr_set_gamma,
diff --git a/drivers/gpu/drm/omapdrm/dss/display.c b/drivers/gpu/drm/omapdrm/dss/display.c
index 9e7fcbd57e52..34b2a4ef63a4 100644
--- a/drivers/gpu/drm/omapdrm/dss/display.c
+++ b/drivers/gpu/drm/omapdrm/dss/display.c
@@ -21,27 +21,14 @@
#define DSS_SUBSYS_NAME "DISPLAY"
#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/jiffies.h>
-#include <linux/platform_device.h>
#include <linux/of.h>
#include "omapdss.h"
-static void omapdss_default_get_timings(struct omap_dss_device *dssdev,
- struct videomode *vm)
-{
- *vm = dssdev->panel.vm;
-}
-
-static LIST_HEAD(panel_list);
-static DEFINE_MUTEX(panel_list_mutex);
static int disp_num_counter;
-int omapdss_register_display(struct omap_dss_device *dssdev)
+void omapdss_display_init(struct omap_dss_device *dssdev)
{
- struct omap_dss_driver *drv = dssdev->driver;
- struct list_head *cur;
int id;
/*
@@ -52,123 +39,22 @@ int omapdss_register_display(struct omap_dss_device *dssdev)
if (id < 0)
id = disp_num_counter++;
- snprintf(dssdev->alias, sizeof(dssdev->alias), "display%d", id);
+ dssdev->alias_id = id;
/* Use 'label' property for name, if it exists */
of_property_read_string(dssdev->dev->of_node, "label", &dssdev->name);
if (dssdev->name == NULL)
- dssdev->name = dssdev->alias;
-
- if (drv && drv->get_timings == NULL)
- drv->get_timings = omapdss_default_get_timings;
-
- mutex_lock(&panel_list_mutex);
- list_for_each(cur, &panel_list) {
- struct omap_dss_device *ldev = list_entry(cur,
- struct omap_dss_device,
- panel_list);
- if (strcmp(ldev->alias, dssdev->alias) > 0)
- break;
- }
- list_add_tail(&dssdev->panel_list, cur);
- mutex_unlock(&panel_list_mutex);
- return 0;
-}
-EXPORT_SYMBOL(omapdss_register_display);
-
-void omapdss_unregister_display(struct omap_dss_device *dssdev)
-{
- mutex_lock(&panel_list_mutex);
- list_del(&dssdev->panel_list);
- mutex_unlock(&panel_list_mutex);
+ dssdev->name = devm_kasprintf(dssdev->dev, GFP_KERNEL,
+ "display%u", id);
}
-EXPORT_SYMBOL(omapdss_unregister_display);
+EXPORT_SYMBOL_GPL(omapdss_display_init);
-bool omapdss_component_is_display(struct device_node *node)
+struct omap_dss_device *omapdss_display_get(struct omap_dss_device *output)
{
- struct omap_dss_device *dssdev;
- bool found = false;
-
- mutex_lock(&panel_list_mutex);
- list_for_each_entry(dssdev, &panel_list, panel_list) {
- if (dssdev->dev->of_node == node) {
- found = true;
- goto out;
- }
- }
-out:
- mutex_unlock(&panel_list_mutex);
- return found;
-}
-EXPORT_SYMBOL(omapdss_component_is_display);
-
-struct omap_dss_device *omap_dss_get_device(struct omap_dss_device *dssdev)
-{
- if (!try_module_get(dssdev->owner))
- return NULL;
-
- if (get_device(dssdev->dev) == NULL) {
- module_put(dssdev->owner);
- return NULL;
- }
-
- return dssdev;
-}
-EXPORT_SYMBOL(omap_dss_get_device);
-
-void omap_dss_put_device(struct omap_dss_device *dssdev)
-{
- put_device(dssdev->dev);
- module_put(dssdev->owner);
-}
-EXPORT_SYMBOL(omap_dss_put_device);
-
-/*
- * ref count of the found device is incremented.
- * ref count of from-device is decremented.
- */
-struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from)
-{
- struct list_head *l;
- struct omap_dss_device *dssdev;
-
- mutex_lock(&panel_list_mutex);
-
- if (list_empty(&panel_list)) {
- dssdev = NULL;
- goto out;
- }
-
- if (from == NULL) {
- dssdev = list_first_entry(&panel_list, struct omap_dss_device,
- panel_list);
- omap_dss_get_device(dssdev);
- goto out;
- }
-
- omap_dss_put_device(from);
-
- list_for_each(l, &panel_list) {
- dssdev = list_entry(l, struct omap_dss_device, panel_list);
- if (dssdev == from) {
- if (list_is_last(l, &panel_list)) {
- dssdev = NULL;
- goto out;
- }
-
- dssdev = list_entry(l->next, struct omap_dss_device,
- panel_list);
- omap_dss_get_device(dssdev);
- goto out;
- }
- }
-
- WARN(1, "'from' dssdev not found\n");
+ while (output->next)
+ output = output->next;
- dssdev = NULL;
-out:
- mutex_unlock(&panel_list_mutex);
- return dssdev;
+ return omapdss_device_get(output);
}
-EXPORT_SYMBOL(omap_dss_get_next_device);
+EXPORT_SYMBOL_GPL(omapdss_display_get);
diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c b/drivers/gpu/drm/omapdrm/dss/dpi.c
index 9fcc50217133..ca4f3c4c6318 100644
--- a/drivers/gpu/drm/omapdrm/dss/dpi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dpi.c
@@ -39,6 +39,7 @@ struct dpi_data {
struct platform_device *pdev;
enum dss_model dss_model;
struct dss_device *dss;
+ unsigned int id;
struct regulator *vdds_dsi_reg;
enum dss_clk_source clk_src;
@@ -346,10 +347,9 @@ static int dpi_set_dispc_clk(struct dpi_data *dpi, unsigned long pck_req,
static int dpi_set_mode(struct dpi_data *dpi)
{
- struct videomode *vm = &dpi->vm;
+ const struct videomode *vm = &dpi->vm;
int lck_div = 0, pck_div = 0;
unsigned long fck = 0;
- unsigned long pck;
int r = 0;
if (dpi->pll)
@@ -361,17 +361,6 @@ static int dpi_set_mode(struct dpi_data *dpi)
if (r)
return r;
- pck = fck / lck_div / pck_div;
-
- if (pck != vm->pixelclock) {
- DSSWARN("Could not find exact pixel clock. Requested %lu Hz, got %lu Hz\n",
- vm->pixelclock, pck);
-
- vm->pixelclock = pck;
- }
-
- dss_mgr_set_timings(&dpi->output, vm);
-
return 0;
}
@@ -413,7 +402,7 @@ static int dpi_display_enable(struct omap_dss_device *dssdev)
if (r)
goto err_get_dispc;
- r = dss_dpi_select_source(dpi->dss, out->port_num, out->dispc_channel);
+ r = dss_dpi_select_source(dpi->dss, dpi->id, out->dispc_channel);
if (r)
goto err_src_sel;
@@ -478,7 +467,7 @@ static void dpi_display_disable(struct omap_dss_device *dssdev)
}
static void dpi_set_timings(struct omap_dss_device *dssdev,
- struct videomode *vm)
+ const struct videomode *vm)
{
struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
@@ -491,23 +480,10 @@ static void dpi_set_timings(struct omap_dss_device *dssdev,
mutex_unlock(&dpi->lock);
}
-static void dpi_get_timings(struct omap_dss_device *dssdev,
- struct videomode *vm)
-{
- struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
-
- mutex_lock(&dpi->lock);
-
- *vm = dpi->vm;
-
- mutex_unlock(&dpi->lock);
-}
-
static int dpi_check_timings(struct omap_dss_device *dssdev,
struct videomode *vm)
{
struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
- enum omap_channel channel = dpi->output.dispc_channel;
int lck_div, pck_div;
unsigned long fck;
unsigned long pck;
@@ -517,9 +493,6 @@ static int dpi_check_timings(struct omap_dss_device *dssdev,
if (vm->hactive % 8 != 0)
return -EINVAL;
- if (!dispc_mgr_timings_ok(dpi->dss->dispc, channel, vm))
- return -EINVAL;
-
if (vm->pixelclock == 0)
return -EINVAL;
@@ -562,38 +535,6 @@ static int dpi_verify_pll(struct dss_pll *pll)
return 0;
}
-static const struct soc_device_attribute dpi_soc_devices[] = {
- { .machine = "OMAP3[456]*" },
- { .machine = "[AD]M37*" },
- { /* sentinel */ }
-};
-
-static int dpi_init_regulator(struct dpi_data *dpi)
-{
- struct regulator *vdds_dsi;
-
- /*
- * The DPI uses the DSI VDDS on OMAP34xx, OMAP35xx, OMAP36xx, AM37xx and
- * DM37xx only.
- */
- if (!soc_device_match(dpi_soc_devices))
- return 0;
-
- if (dpi->vdds_dsi_reg)
- return 0;
-
- vdds_dsi = devm_regulator_get(&dpi->pdev->dev, "vdds_dsi");
- if (IS_ERR(vdds_dsi)) {
- if (PTR_ERR(vdds_dsi) != -EPROBE_DEFER)
- DSSERR("can't get VDDS_DSI regulator\n");
- return PTR_ERR(vdds_dsi);
- }
-
- dpi->vdds_dsi_reg = vdds_dsi;
-
- return 0;
-}
-
static void dpi_init_pll(struct dpi_data *dpi)
{
struct dss_pll *pll;
@@ -621,7 +562,7 @@ static void dpi_init_pll(struct dpi_data *dpi)
* the channel in some more dynamic manner, or get the channel as a user
* parameter.
*/
-static enum omap_channel dpi_get_channel(struct dpi_data *dpi, int port_num)
+static enum omap_channel dpi_get_channel(struct dpi_data *dpi)
{
switch (dpi->dss_model) {
case DSS_MODEL_OMAP2:
@@ -629,7 +570,7 @@ static enum omap_channel dpi_get_channel(struct dpi_data *dpi, int port_num)
return OMAP_DSS_CHANNEL_LCD;
case DSS_MODEL_DRA7:
- switch (port_num) {
+ switch (dpi->id) {
case 2:
return OMAP_DSS_CHANNEL_LCD3;
case 1:
@@ -651,49 +592,31 @@ static enum omap_channel dpi_get_channel(struct dpi_data *dpi, int port_num)
}
}
-static int dpi_connect(struct omap_dss_device *dssdev,
- struct omap_dss_device *dst)
+static int dpi_connect(struct omap_dss_device *src,
+ struct omap_dss_device *dst)
{
- struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
+ struct dpi_data *dpi = dpi_get_data_from_dssdev(dst);
int r;
- r = dpi_init_regulator(dpi);
- if (r)
- return r;
-
dpi_init_pll(dpi);
- r = dss_mgr_connect(&dpi->output, dssdev);
+ r = omapdss_device_connect(dst->dss, dst, dst->next);
if (r)
return r;
- r = omapdss_output_set_device(dssdev, dst);
- if (r) {
- DSSERR("failed to connect output to new device: %s\n",
- dst->name);
- dss_mgr_disconnect(&dpi->output, dssdev);
- return r;
- }
-
+ dst->dispc_channel_connected = true;
return 0;
}
-static void dpi_disconnect(struct omap_dss_device *dssdev,
- struct omap_dss_device *dst)
+static void dpi_disconnect(struct omap_dss_device *src,
+ struct omap_dss_device *dst)
{
- struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
-
- WARN_ON(dst != dssdev->dst);
+ dst->dispc_channel_connected = false;
- if (dst != dssdev->dst)
- return;
-
- omapdss_output_unset_device(dssdev);
-
- dss_mgr_disconnect(&dpi->output, dssdev);
+ omapdss_device_disconnect(dst, dst->next);
}
-static const struct omapdss_dpi_ops dpi_ops = {
+static const struct omap_dss_device_ops dpi_ops = {
.connect = dpi_connect,
.disconnect = dpi_disconnect,
@@ -702,18 +625,16 @@ static const struct omapdss_dpi_ops dpi_ops = {
.check_timings = dpi_check_timings,
.set_timings = dpi_set_timings,
- .get_timings = dpi_get_timings,
};
-static void dpi_init_output_port(struct dpi_data *dpi, struct device_node *port)
+static int dpi_init_output_port(struct dpi_data *dpi, struct device_node *port)
{
struct omap_dss_device *out = &dpi->output;
+ u32 port_num = 0;
int r;
- u32 port_num;
- r = of_property_read_u32(port, "reg", &port_num);
- if (r)
- port_num = 0;
+ of_property_read_u32(port, "reg", &port_num);
+ dpi->id = port_num <= 2 ? port_num : 0;
switch (port_num) {
case 2:
@@ -731,12 +652,28 @@ static void 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->dispc_channel = dpi_get_channel(dpi, port_num);
- out->port_num = port_num;
- out->ops.dpi = &dpi_ops;
+ out->dispc_channel = dpi_get_channel(dpi);
+ out->of_ports = BIT(port_num);
+ out->ops = &dpi_ops;
out->owner = THIS_MODULE;
- omapdss_register_output(out);
+ 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;
+ return r;
+ }
+
+ omapdss_device_register(out);
+
+ return 0;
}
static void dpi_uninit_output_port(struct device_node *port)
@@ -744,7 +681,38 @@ static void dpi_uninit_output_port(struct device_node *port)
struct dpi_data *dpi = port->data;
struct omap_dss_device *out = &dpi->output;
- omapdss_unregister_output(out);
+ if (out->next)
+ omapdss_device_put(out->next);
+ omapdss_device_unregister(out);
+}
+
+static const struct soc_device_attribute dpi_soc_devices[] = {
+ { .machine = "OMAP3[456]*" },
+ { .machine = "[AD]M37*" },
+ { /* sentinel */ }
+};
+
+static int dpi_init_regulator(struct dpi_data *dpi)
+{
+ struct regulator *vdds_dsi;
+
+ /*
+ * The DPI uses the DSI VDDS on OMAP34xx, OMAP35xx, OMAP36xx, AM37xx and
+ * DM37xx only.
+ */
+ if (!soc_device_match(dpi_soc_devices))
+ return 0;
+
+ vdds_dsi = devm_regulator_get(&dpi->pdev->dev, "vdds_dsi");
+ if (IS_ERR(vdds_dsi)) {
+ if (PTR_ERR(vdds_dsi) != -EPROBE_DEFER)
+ DSSERR("can't get VDDS_DSI regulator\n");
+ return PTR_ERR(vdds_dsi);
+ }
+
+ dpi->vdds_dsi_reg = vdds_dsi;
+
+ return 0;
}
int dpi_init_port(struct dss_device *dss, struct platform_device *pdev,
@@ -764,15 +732,14 @@ int dpi_init_port(struct dss_device *dss, struct platform_device *pdev,
return 0;
r = of_property_read_u32(ep, "data-lines", &datalines);
+ of_node_put(ep);
if (r) {
DSSERR("failed to parse datalines\n");
- goto err_datalines;
+ return r;
}
dpi->data_lines = datalines;
- of_node_put(ep);
-
dpi->pdev = pdev;
dpi->dss_model = dss_model;
dpi->dss = dss;
@@ -780,14 +747,11 @@ int dpi_init_port(struct dss_device *dss, struct platform_device *pdev,
mutex_init(&dpi->lock);
- dpi_init_output_port(dpi, port);
-
- return 0;
-
-err_datalines:
- of_node_put(ep);
+ r = dpi_init_regulator(dpi);
+ if (r)
+ return r;
- return r;
+ return dpi_init_output_port(dpi, port);
}
void dpi_uninit_port(struct device_node *port)
diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c
index 74467b308721..394c129cfb3b 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -403,6 +403,7 @@ struct dsi_data {
struct {
struct dss_debugfs_entry *irqs;
struct dss_debugfs_entry *regs;
+ struct dss_debugfs_entry *clks;
} debugfs;
#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
@@ -442,27 +443,6 @@ static inline struct dsi_data *to_dsi_data(struct omap_dss_device *dssdev)
return dev_get_drvdata(dssdev->dev);
}
-static struct dsi_data *dsi_get_dsi_from_id(int module)
-{
- struct omap_dss_device *out;
- enum omap_dss_output_id id;
-
- switch (module) {
- case 0:
- id = OMAP_DSS_OUTPUT_DSI1;
- break;
- case 1:
- id = OMAP_DSS_OUTPUT_DSI2;
- break;
- default:
- return NULL;
- }
-
- out = omap_dss_get_output(id);
-
- return out ? to_dsi_data(out) : NULL;
-}
-
static inline void dsi_write_reg(struct dsi_data *dsi,
const struct dsi_reg idx, u32 val)
{
@@ -1157,26 +1137,6 @@ static void dsi_runtime_put(struct dsi_data *dsi)
WARN_ON(r < 0 && r != -ENOSYS);
}
-static int dsi_regulator_init(struct dsi_data *dsi)
-{
- struct regulator *vdds_dsi;
-
- if (dsi->vdds_dsi_reg != NULL)
- return 0;
-
- vdds_dsi = devm_regulator_get(dsi->dev, "vdd");
-
- if (IS_ERR(vdds_dsi)) {
- if (PTR_ERR(vdds_dsi) != -EPROBE_DEFER)
- DSSERR("can't get DSI VDD regulator\n");
- return PTR_ERR(vdds_dsi);
- }
-
- dsi->vdds_dsi_reg = vdds_dsi;
-
- return 0;
-}
-
static void _dsi_print_reset_status(struct dsi_data *dsi)
{
u32 l;
@@ -1373,10 +1333,6 @@ static int dsi_pll_enable(struct dss_pll *pll)
DSSDBG("PLL init\n");
- r = dsi_regulator_init(dsi);
- if (r)
- return r;
-
r = dsi_runtime_get(dsi);
if (r)
return r;
@@ -1448,8 +1404,9 @@ static void dsi_pll_disable(struct dss_pll *pll)
dsi_pll_uninit(dsi, true);
}
-static void dsi_dump_dsi_clocks(struct dsi_data *dsi, struct seq_file *s)
+static int dsi_dump_dsi_clocks(struct seq_file *s, void *p)
{
+ struct dsi_data *dsi = p;
struct dss_pll_clock_info *cinfo = &dsi->pll.cinfo;
enum dss_clk_source dispc_clk_src, dsi_clk_src;
int dsi_module = dsi->module_id;
@@ -1459,7 +1416,7 @@ static void dsi_dump_dsi_clocks(struct dsi_data *dsi, struct seq_file *s)
dsi_clk_src = dss_get_dsi_clk_source(dsi->dss, dsi_module);
if (dsi_runtime_get(dsi))
- return;
+ return 0;
seq_printf(s, "- DSI%d PLL -\n", dsi_module + 1);
@@ -1503,23 +1460,14 @@ static void dsi_dump_dsi_clocks(struct dsi_data *dsi, struct seq_file *s)
seq_printf(s, "LP_CLK\t\t%lu\n", dsi->current_lp_cinfo.lp_clk);
dsi_runtime_put(dsi);
-}
-
-void dsi_dump_clocks(struct seq_file *s)
-{
- struct dsi_data *dsi;
- int i;
- for (i = 0; i < MAX_NUM_DSI; i++) {
- dsi = dsi_get_dsi_from_id(i);
- if (dsi)
- dsi_dump_dsi_clocks(dsi, s);
- }
+ return 0;
}
#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
-static void dsi_dump_dsi_irqs(struct dsi_data *dsi, struct seq_file *s)
+static int dsi_dump_dsi_irqs(struct seq_file *s, void *p)
{
+ struct dsi_data *dsi = p;
unsigned long flags;
struct dsi_irq_stats stats;
@@ -1603,33 +1551,20 @@ static void dsi_dump_dsi_irqs(struct dsi_data *dsi, struct seq_file *s)
PIS(ULPSACTIVENOT_ALL0);
PIS(ULPSACTIVENOT_ALL1);
#undef PIS
-}
-static int dsi1_dump_irqs(struct seq_file *s, void *p)
-{
- struct dsi_data *dsi = dsi_get_dsi_from_id(0);
-
- dsi_dump_dsi_irqs(dsi, s);
- return 0;
-}
-
-static int dsi2_dump_irqs(struct seq_file *s, void *p)
-{
- struct dsi_data *dsi = dsi_get_dsi_from_id(1);
-
- dsi_dump_dsi_irqs(dsi, s);
return 0;
}
#endif
-static void dsi_dump_dsi_regs(struct dsi_data *dsi, struct seq_file *s)
+static int dsi_dump_dsi_regs(struct seq_file *s, void *p)
{
-#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(dsi, r))
+ struct dsi_data *dsi = p;
if (dsi_runtime_get(dsi))
- return;
+ return 0;
dsi_enable_scp_clk(dsi);
+#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(dsi, r))
DUMPREG(DSI_REVISION);
DUMPREG(DSI_SYSCONFIG);
DUMPREG(DSI_SYSSTATUS);
@@ -1699,25 +1634,11 @@ static void dsi_dump_dsi_regs(struct dsi_data *dsi, struct seq_file *s)
DUMPREG(DSI_PLL_GO);
DUMPREG(DSI_PLL_CONFIGURATION1);
DUMPREG(DSI_PLL_CONFIGURATION2);
+#undef DUMPREG
dsi_disable_scp_clk(dsi);
dsi_runtime_put(dsi);
-#undef DUMPREG
-}
-
-static int dsi1_dump_regs(struct seq_file *s, void *p)
-{
- struct dsi_data *dsi = dsi_get_dsi_from_id(0);
-
- dsi_dump_dsi_regs(dsi, s);
- return 0;
-}
-
-static int dsi2_dump_regs(struct seq_file *s, void *p)
-{
- struct dsi_data *dsi = dsi_get_dsi_from_id(1);
- dsi_dump_dsi_regs(dsi, s);
return 0;
}
@@ -3344,7 +3265,7 @@ static void dsi_config_vp_num_line_buffers(struct dsi_data *dsi)
if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
int bpp = dsi_get_pixel_size(dsi->pix_fmt);
- struct videomode *vm = &dsi->vm;
+ const struct videomode *vm = &dsi->vm;
/*
* Don't use line buffers if width is greater than the video
* port's line buffer size
@@ -3473,7 +3394,7 @@ static void dsi_config_cmd_mode_interleaving(struct dsi_data *dsi)
int ddr_clk_pre, ddr_clk_post, enter_hs_mode_lat, exit_hs_mode_lat;
int tclk_trail, ths_exit, exiths_clk;
bool ddr_alwon;
- struct videomode *vm = &dsi->vm;
+ const struct videomode *vm = &dsi->vm;
int bpp = dsi_get_pixel_size(dsi->pix_fmt);
int ndl = dsi->num_lanes_used - 1;
int dsi_fclk_hsdiv = dsi->user_dsi_cinfo.mX[HSDIV_DSI] + 1;
@@ -3723,7 +3644,7 @@ static void dsi_proto_timings(struct dsi_data *dsi)
int vbp = dsi->vm_timings.vbp;
int window_sync = dsi->vm_timings.window_sync;
bool hsync_end;
- struct videomode *vm = &dsi->vm;
+ const struct videomode *vm = &dsi->vm;
int bpp = dsi_get_pixel_size(dsi->pix_fmt);
int tl, t_he, width_bytes;
@@ -3980,8 +3901,6 @@ static void dsi_update_screen_dispc(struct dsi_data *dsi)
msecs_to_jiffies(250));
BUG_ON(r == 0);
- dss_mgr_set_timings(&dsi->output, &dsi->vm);
-
dss_mgr_start_update(&dsi->output);
if (dsi->te_enabled) {
@@ -4123,24 +4042,6 @@ static int dsi_display_init_dispc(struct dsi_data *dsi)
dsi->mgr_config.fifohandcheck = false;
}
- /*
- * override interlace, logic level and edge related parameters in
- * videomode with default values
- */
- dsi->vm.flags &= ~DISPLAY_FLAGS_INTERLACED;
- dsi->vm.flags &= ~DISPLAY_FLAGS_HSYNC_LOW;
- dsi->vm.flags |= DISPLAY_FLAGS_HSYNC_HIGH;
- dsi->vm.flags &= ~DISPLAY_FLAGS_VSYNC_LOW;
- dsi->vm.flags |= DISPLAY_FLAGS_VSYNC_HIGH;
- dsi->vm.flags &= ~DISPLAY_FLAGS_PIXDATA_NEGEDGE;
- dsi->vm.flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE;
- dsi->vm.flags &= ~DISPLAY_FLAGS_DE_LOW;
- dsi->vm.flags |= DISPLAY_FLAGS_DE_HIGH;
- dsi->vm.flags &= ~DISPLAY_FLAGS_SYNC_POSEDGE;
- dsi->vm.flags |= DISPLAY_FLAGS_SYNC_NEGEDGE;
-
- dss_mgr_set_timings(&dsi->output, &dsi->vm);
-
r = dsi_configure_dispc_clocks(dsi);
if (r)
goto err1;
@@ -4840,6 +4741,19 @@ static int dsi_set_config(struct omap_dss_device *dssdev,
dsi->user_dispc_cinfo = ctx.dispc_cinfo;
dsi->vm = ctx.vm;
+
+ /*
+ * override interlace, logic level and edge related parameters in
+ * videomode with default values
+ */
+ dsi->vm.flags &= ~DISPLAY_FLAGS_INTERLACED;
+ dsi->vm.flags &= ~DISPLAY_FLAGS_HSYNC_LOW;
+ dsi->vm.flags |= DISPLAY_FLAGS_HSYNC_HIGH;
+ dsi->vm.flags &= ~DISPLAY_FLAGS_VSYNC_LOW;
+ dsi->vm.flags |= DISPLAY_FLAGS_VSYNC_HIGH;
+
+ dss_mgr_set_timings(&dsi->output, &dsi->vm);
+
dsi->vm_timings = ctx.dsi_vm;
mutex_unlock(&dsi->lock);
@@ -4960,163 +4874,71 @@ static int dsi_get_clocks(struct dsi_data *dsi)
return 0;
}
-static int dsi_connect(struct omap_dss_device *dssdev,
- struct omap_dss_device *dst)
+static int dsi_connect(struct omap_dss_device *src,
+ struct omap_dss_device *dst)
{
- struct dsi_data *dsi = to_dsi_data(dssdev);
int r;
- r = dsi_regulator_init(dsi);
- if (r)
- return r;
-
- r = dss_mgr_connect(&dsi->output, dssdev);
+ r = omapdss_device_connect(dst->dss, dst, dst->next);
if (r)
return r;
- r = omapdss_output_set_device(dssdev, dst);
- if (r) {
- DSSERR("failed to connect output to new device: %s\n",
- dssdev->name);
- dss_mgr_disconnect(&dsi->output, dssdev);
- return r;
- }
-
+ dst->dispc_channel_connected = true;
return 0;
}
-static void dsi_disconnect(struct omap_dss_device *dssdev,
- struct omap_dss_device *dst)
+static void dsi_disconnect(struct omap_dss_device *src,
+ struct omap_dss_device *dst)
{
- struct dsi_data *dsi = to_dsi_data(dssdev);
+ dst->dispc_channel_connected = false;
- WARN_ON(dst != dssdev->dst);
-
- if (dst != dssdev->dst)
- return;
-
- omapdss_output_unset_device(dssdev);
-
- dss_mgr_disconnect(&dsi->output, dssdev);
+ omapdss_device_disconnect(dst, dst->next);
}
-static const struct omapdss_dsi_ops dsi_ops = {
+static const struct omap_dss_device_ops dsi_ops = {
.connect = dsi_connect,
.disconnect = dsi_disconnect,
-
- .bus_lock = dsi_bus_lock,
- .bus_unlock = dsi_bus_unlock,
-
.enable = dsi_display_enable,
- .disable = dsi_display_disable,
-
- .enable_hs = dsi_vc_enable_hs,
-
- .configure_pins = dsi_configure_pins,
- .set_config = dsi_set_config,
-
- .enable_video_output = dsi_enable_video_output,
- .disable_video_output = dsi_disable_video_output,
-
- .update = dsi_update,
-
- .enable_te = dsi_enable_te,
-
- .request_vc = dsi_request_vc,
- .set_vc_id = dsi_set_vc_id,
- .release_vc = dsi_release_vc,
-
- .dcs_write = dsi_vc_dcs_write,
- .dcs_write_nosync = dsi_vc_dcs_write_nosync,
- .dcs_read = dsi_vc_dcs_read,
-
- .gen_write = dsi_vc_generic_write,
- .gen_write_nosync = dsi_vc_generic_write_nosync,
- .gen_read = dsi_vc_generic_read,
-
- .bta_sync = dsi_vc_send_bta_sync,
-
- .set_max_rx_packet_size = dsi_vc_set_max_rx_packet_size,
-};
-
-static void dsi_init_output(struct dsi_data *dsi)
-{
- struct omap_dss_device *out = &dsi->output;
-
- out->dev = dsi->dev;
- out->id = dsi->module_id == 0 ?
- OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2;
-
- out->output_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 = &dsi_ops;
- out->owner = THIS_MODULE;
- omapdss_register_output(out);
-}
+ .dsi = {
+ .bus_lock = dsi_bus_lock,
+ .bus_unlock = dsi_bus_unlock,
-static void dsi_uninit_output(struct dsi_data *dsi)
-{
- struct omap_dss_device *out = &dsi->output;
+ .disable = dsi_display_disable,
- omapdss_unregister_output(out);
-}
+ .enable_hs = dsi_vc_enable_hs,
-static int dsi_probe_of(struct dsi_data *dsi)
-{
- struct device_node *node = dsi->dev->of_node;
- struct property *prop;
- u32 lane_arr[10];
- int len, num_pins;
- int r, i;
- struct device_node *ep;
- struct omap_dsi_pin_config pin_cfg;
-
- ep = of_graph_get_endpoint_by_regs(node, 0, 0);
- if (!ep)
- return 0;
+ .configure_pins = dsi_configure_pins,
+ .set_config = dsi_set_config,
- prop = of_find_property(ep, "lanes", &len);
- if (prop == NULL) {
- dev_err(dsi->dev, "failed to find lane data\n");
- r = -EINVAL;
- goto err;
- }
+ .enable_video_output = dsi_enable_video_output,
+ .disable_video_output = dsi_disable_video_output,
- num_pins = len / sizeof(u32);
+ .update = dsi_update,
- if (num_pins < 4 || num_pins % 2 != 0 ||
- num_pins > dsi->num_lanes_supported * 2) {
- dev_err(dsi->dev, "bad number of lanes\n");
- r = -EINVAL;
- goto err;
- }
+ .enable_te = dsi_enable_te,
- r = of_property_read_u32_array(ep, "lanes", lane_arr, num_pins);
- if (r) {
- dev_err(dsi->dev, "failed to read lane data\n");
- goto err;
- }
+ .request_vc = dsi_request_vc,
+ .set_vc_id = dsi_set_vc_id,
+ .release_vc = dsi_release_vc,
- pin_cfg.num_pins = num_pins;
- for (i = 0; i < num_pins; ++i)
- pin_cfg.pins[i] = (int)lane_arr[i];
+ .dcs_write = dsi_vc_dcs_write,
+ .dcs_write_nosync = dsi_vc_dcs_write_nosync,
+ .dcs_read = dsi_vc_dcs_read,
- r = dsi_configure_pins(&dsi->output, &pin_cfg);
- if (r) {
- dev_err(dsi->dev, "failed to configure pins");
- goto err;
- }
+ .gen_write = dsi_vc_generic_write,
+ .gen_write_nosync = dsi_vc_generic_write_nosync,
+ .gen_read = dsi_vc_generic_read,
- of_node_put(ep);
+ .bta_sync = dsi_vc_send_bta_sync,
- return 0;
+ .set_max_rx_packet_size = dsi_vc_set_max_rx_packet_size,
+ },
+};
-err:
- of_node_put(ep);
- return r;
-}
+/* -----------------------------------------------------------------------------
+ * PLL
+ */
static const struct dss_pll_ops dsi_pll_ops = {
.enable = dsi_pll_enable,
@@ -5231,7 +5053,175 @@ static int dsi_init_pll_data(struct dss_device *dss, struct dsi_data *dsi)
return 0;
}
-/* DSI1 HW IP initialisation */
+/* -----------------------------------------------------------------------------
+ * Component Bind & Unbind
+ */
+
+static int dsi_bind(struct device *dev, struct device *master, void *data)
+{
+ struct dss_device *dss = dss_get_device(master);
+ struct dsi_data *dsi = dev_get_drvdata(dev);
+ char name[10];
+ u32 rev;
+ int r;
+
+ dsi->dss = dss;
+
+ dsi_init_pll_data(dss, dsi);
+
+ r = dsi_runtime_get(dsi);
+ if (r)
+ return r;
+
+ rev = dsi_read_reg(dsi, DSI_REVISION);
+ dev_dbg(dev, "OMAP DSI rev %d.%d\n",
+ FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
+
+ dsi->line_buffer_size = dsi_get_line_buf_size(dsi);
+
+ dsi_runtime_put(dsi);
+
+ snprintf(name, sizeof(name), "dsi%u_regs", dsi->module_id + 1);
+ dsi->debugfs.regs = dss_debugfs_create_file(dss, name,
+ dsi_dump_dsi_regs, &dsi);
+#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
+ snprintf(name, sizeof(name), "dsi%u_irqs", dsi->module_id + 1);
+ dsi->debugfs.irqs = dss_debugfs_create_file(dss, name,
+ dsi_dump_dsi_irqs, &dsi);
+#endif
+ snprintf(name, sizeof(name), "dsi%u_clks", dsi->module_id + 1);
+ dsi->debugfs.clks = dss_debugfs_create_file(dss, name,
+ dsi_dump_dsi_clocks, &dsi);
+
+ return 0;
+}
+
+static void dsi_unbind(struct device *dev, struct device *master, void *data)
+{
+ struct dsi_data *dsi = dev_get_drvdata(dev);
+
+ dss_debugfs_remove_file(dsi->debugfs.clks);
+ dss_debugfs_remove_file(dsi->debugfs.irqs);
+ dss_debugfs_remove_file(dsi->debugfs.regs);
+
+ of_platform_depopulate(dev);
+
+ WARN_ON(dsi->scp_clk_refcount > 0);
+
+ dss_pll_unregister(&dsi->pll);
+}
+
+static const struct component_ops dsi_component_ops = {
+ .bind = dsi_bind,
+ .unbind = dsi_unbind,
+};
+
+/* -----------------------------------------------------------------------------
+ * Probe & Remove, Suspend & Resume
+ */
+
+static int dsi_init_output(struct dsi_data *dsi)
+{
+ struct omap_dss_device *out = &dsi->output;
+ int r;
+
+ out->dev = dsi->dev;
+ out->id = dsi->module_id == 0 ?
+ OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2;
+
+ out->output_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
+ | 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);
+ }
+
+ r = omapdss_output_validate(out);
+ if (r) {
+ omapdss_device_put(out->next);
+ out->next = NULL;
+ return r;
+ }
+
+ omapdss_device_register(out);
+
+ return 0;
+}
+
+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);
+}
+
+static int dsi_probe_of(struct dsi_data *dsi)
+{
+ struct device_node *node = dsi->dev->of_node;
+ struct property *prop;
+ u32 lane_arr[10];
+ int len, num_pins;
+ int r, i;
+ struct device_node *ep;
+ struct omap_dsi_pin_config pin_cfg;
+
+ ep = of_graph_get_endpoint_by_regs(node, 0, 0);
+ if (!ep)
+ return 0;
+
+ prop = of_find_property(ep, "lanes", &len);
+ if (prop == NULL) {
+ dev_err(dsi->dev, "failed to find lane data\n");
+ r = -EINVAL;
+ goto err;
+ }
+
+ num_pins = len / sizeof(u32);
+
+ if (num_pins < 4 || num_pins % 2 != 0 ||
+ num_pins > dsi->num_lanes_supported * 2) {
+ dev_err(dsi->dev, "bad number of lanes\n");
+ r = -EINVAL;
+ goto err;
+ }
+
+ r = of_property_read_u32_array(ep, "lanes", lane_arr, num_pins);
+ if (r) {
+ dev_err(dsi->dev, "failed to read lane data\n");
+ goto err;
+ }
+
+ pin_cfg.num_pins = num_pins;
+ for (i = 0; i < num_pins; ++i)
+ pin_cfg.pins[i] = (int)lane_arr[i];
+
+ r = dsi_configure_pins(&dsi->output, &pin_cfg);
+ if (r) {
+ dev_err(dsi->dev, "failed to configure pins");
+ goto err;
+ }
+
+ of_node_put(ep);
+
+ return 0;
+
+err:
+ of_node_put(ep);
+ return r;
+}
+
static const struct dsi_of_data dsi_of_data_omap34xx = {
.model = DSI_MODEL_OMAP3,
.pll_hw = &dss_omap3_dsi_pll_hw,
@@ -5297,23 +5287,21 @@ static const struct soc_device_attribute dsi_soc_devices[] = {
{ /* sentinel */ }
};
-static int dsi_bind(struct device *dev, struct device *master, void *data)
+static int dsi_probe(struct platform_device *pdev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct dss_device *dss = dss_get_device(master);
const struct soc_device_attribute *soc;
const struct dsi_module_id_data *d;
- u32 rev;
- int r, i;
+ struct device *dev = &pdev->dev;
struct dsi_data *dsi;
struct resource *dsi_mem;
struct resource *res;
+ unsigned int i;
+ int r;
dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL);
if (!dsi)
return -ENOMEM;
- dsi->dss = dss;
dsi->dev = dev;
dev_set_drvdata(dev, dsi);
@@ -5364,6 +5352,13 @@ static int dsi_bind(struct device *dev, struct device *master, void *data)
return r;
}
+ dsi->vdds_dsi_reg = devm_regulator_get(dev, "vdd");
+ if (IS_ERR(dsi->vdds_dsi_reg)) {
+ if (PTR_ERR(dsi->vdds_dsi_reg) != -EPROBE_DEFER)
+ DSSERR("can't get DSI VDD regulator\n");
+ return PTR_ERR(dsi->vdds_dsi_reg);
+ }
+
soc = soc_device_match(dsi_soc_devices);
if (soc)
dsi->data = soc->data;
@@ -5410,18 +5405,8 @@ static int dsi_bind(struct device *dev, struct device *master, void *data)
if (r)
return r;
- dsi_init_pll_data(dss, dsi);
-
pm_runtime_enable(dev);
- r = dsi_runtime_get(dsi);
- if (r)
- goto err_runtime_get;
-
- rev = dsi_read_reg(dsi, DSI_REVISION);
- dev_dbg(dev, "OMAP DSI rev %d.%d\n",
- FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
-
/* DSI on OMAP3 doesn't have register DSI_GNQ, set number
* of data to 3 by default */
if (dsi->data->quirks & DSI_QUIRK_GNQ)
@@ -5430,88 +5415,48 @@ static int dsi_bind(struct device *dev, struct device *master, void *data)
else
dsi->num_lanes_supported = 3;
- dsi->line_buffer_size = dsi_get_line_buf_size(dsi);
-
- dsi_init_output(dsi);
+ r = dsi_init_output(dsi);
+ if (r)
+ goto err_pm_disable;
r = dsi_probe_of(dsi);
if (r) {
DSSERR("Invalid DSI DT data\n");
- goto err_probe_of;
+ goto err_uninit_output;
}
r = of_platform_populate(dev->of_node, NULL, NULL, dev);
if (r)
DSSERR("Failed to populate DSI child devices: %d\n", r);
- dsi_runtime_put(dsi);
-
- if (dsi->module_id == 0)
- dsi->debugfs.regs = dss_debugfs_create_file(dss, "dsi1_regs",
- dsi1_dump_regs,
- &dsi);
- else
- dsi->debugfs.regs = dss_debugfs_create_file(dss, "dsi2_regs",
- dsi2_dump_regs,
- &dsi);
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
- if (dsi->module_id == 0)
- dsi->debugfs.irqs = dss_debugfs_create_file(dss, "dsi1_irqs",
- dsi1_dump_irqs,
- &dsi);
- else
- dsi->debugfs.irqs = dss_debugfs_create_file(dss, "dsi2_irqs",
- dsi2_dump_irqs,
- &dsi);
-#endif
+ r = component_add(&pdev->dev, &dsi_component_ops);
+ if (r)
+ goto err_uninit_output;
return 0;
-err_probe_of:
+err_uninit_output:
dsi_uninit_output(dsi);
- dsi_runtime_put(dsi);
-
-err_runtime_get:
+err_pm_disable:
pm_runtime_disable(dev);
return r;
}
-static void dsi_unbind(struct device *dev, struct device *master, void *data)
+static int dsi_remove(struct platform_device *pdev)
{
- struct dsi_data *dsi = dev_get_drvdata(dev);
+ struct dsi_data *dsi = platform_get_drvdata(pdev);
- dss_debugfs_remove_file(dsi->debugfs.irqs);
- dss_debugfs_remove_file(dsi->debugfs.regs);
-
- of_platform_depopulate(dev);
-
- WARN_ON(dsi->scp_clk_refcount > 0);
-
- dss_pll_unregister(&dsi->pll);
+ component_del(&pdev->dev, &dsi_component_ops);
dsi_uninit_output(dsi);
- pm_runtime_disable(dev);
+ pm_runtime_disable(&pdev->dev);
if (dsi->vdds_dsi_reg != NULL && dsi->vdds_dsi_enabled) {
regulator_disable(dsi->vdds_dsi_reg);
dsi->vdds_dsi_enabled = false;
}
-}
-static const struct component_ops dsi_component_ops = {
- .bind = dsi_bind,
- .unbind = dsi_unbind,
-};
-
-static int dsi_probe(struct platform_device *pdev)
-{
- return component_add(&pdev->dev, &dsi_component_ops);
-}
-
-static int dsi_remove(struct platform_device *pdev)
-{
- component_del(&pdev->dev, &dsi_component_ops);
return 0;
}
diff --git a/drivers/gpu/drm/omapdrm/dss/dss-of.c b/drivers/gpu/drm/omapdrm/dss/dss-of.c
index 4602a79c6c44..0422597ac6b0 100644
--- a/drivers/gpu/drm/omapdrm/dss/dss-of.c
+++ b/drivers/gpu/drm/omapdrm/dss/dss-of.c
@@ -21,7 +21,8 @@
#include "omapdss.h"
-struct device_node *dss_of_port_get_parent_device(struct device_node *port)
+static struct device_node *
+dss_of_port_get_parent_device(struct device_node *port)
{
struct device_node *np;
int i;
@@ -45,41 +46,37 @@ struct device_node *dss_of_port_get_parent_device(struct device_node *port)
return NULL;
}
-u32 dss_of_port_get_port_number(struct device_node *port)
-{
- int r;
- u32 reg;
-
- r = of_property_read_u32(port, "reg", &reg);
- if (r)
- reg = 0;
-
- return reg;
-}
-
struct omap_dss_device *
-omapdss_of_find_source_for_first_ep(struct device_node *node)
+omapdss_of_find_connected_device(struct device_node *node, unsigned int port)
{
- struct device_node *ep;
+ struct device_node *src_node;
struct device_node *src_port;
+ struct device_node *ep;
struct omap_dss_device *src;
+ u32 port_number = 0;
- ep = of_graph_get_endpoint_by_regs(node, 0, 0);
+ /* Get the endpoint... */
+ ep = of_graph_get_endpoint_by_regs(node, port, 0);
if (!ep)
- return ERR_PTR(-EINVAL);
+ return NULL;
+ /* ... and its remote port... */
src_port = of_graph_get_remote_port(ep);
- if (!src_port) {
- of_node_put(ep);
- return ERR_PTR(-EINVAL);
- }
-
of_node_put(ep);
+ if (!src_port)
+ return NULL;
- src = omap_dss_find_output_by_port_node(src_port);
-
+ /* ... 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);
return src ? src : ERR_PTR(-EPROBE_DEFER);
}
-EXPORT_SYMBOL_GPL(omapdss_of_find_source_for_first_ep);
+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 cb80ddaa19d2..1aaf260aa9b8 100644
--- a/drivers/gpu/drm/omapdrm/dss/dss.c
+++ b/drivers/gpu/drm/omapdrm/dss/dss.c
@@ -394,9 +394,6 @@ static int dss_debug_dump_clocks(struct seq_file *s, void *p)
dss_dump_clocks(dss, s);
dispc_dump_clocks(dss->dispc, s);
-#ifdef CONFIG_OMAP2_DSS_DSI
- dsi_dump_clocks(s);
-#endif
return 0;
}
@@ -681,12 +678,6 @@ unsigned long dss_get_max_fck_rate(struct dss_device *dss)
return dss->feat->fck_freq_max;
}
-enum omap_dss_output_id dss_get_supported_outputs(struct dss_device *dss,
- enum omap_channel channel)
-{
- return dss->feat->outputs[channel];
-}
-
static int dss_setup_default_clock(struct dss_device *dss)
{
unsigned long max_dss_fck, prate;
@@ -956,7 +947,7 @@ dss_debugfs_create_file(struct dss_device *dss, const char *name,
&dss_debug_fops);
if (IS_ERR(d)) {
kfree(entry);
- return ERR_PTR(PTR_ERR(d));
+ return ERR_CAST(d);
}
entry->dentry = d;
@@ -1183,7 +1174,8 @@ static int dss_init_ports(struct dss_device *dss)
struct platform_device *pdev = dss->pdev;
struct device_node *parent = pdev->dev.of_node;
struct device_node *port;
- int i;
+ unsigned int i;
+ int r;
for (i = 0; i < dss->feat->num_ports; i++) {
port = of_graph_get_port_by_id(parent, i);
@@ -1192,11 +1184,17 @@ static int dss_init_ports(struct dss_device *dss)
switch (dss->feat->ports[i]) {
case OMAP_DISPLAY_TYPE_DPI:
- dpi_init_port(dss, pdev, port, dss->feat->model);
+ r = dpi_init_port(dss, pdev, port, dss->feat->model);
+ if (r)
+ return r;
break;
+
case OMAP_DISPLAY_TYPE_SDI:
- sdi_init_port(dss, pdev, port);
+ r = sdi_init_port(dss, pdev, port);
+ if (r)
+ return r;
break;
+
default:
break;
}
@@ -1315,6 +1313,7 @@ static const struct soc_device_attribute dss_soc_devices[] = {
static int dss_bind(struct device *dev)
{
struct dss_device *dss = dev_get_drvdata(dev);
+ struct platform_device *drm_pdev;
int r;
r = component_bind_all(dev, NULL);
@@ -1323,14 +1322,25 @@ static int dss_bind(struct device *dev)
pm_set_vt_switch(0);
- omapdss_gather_components(dev);
omapdss_set_dss(dss);
+ drm_pdev = platform_device_register_simple("omapdrm", 0, NULL, 0);
+ if (IS_ERR(drm_pdev)) {
+ component_unbind_all(dev, NULL);
+ return PTR_ERR(drm_pdev);
+ }
+
+ dss->drm_pdev = drm_pdev;
+
return 0;
}
static void dss_unbind(struct device *dev)
{
+ struct dss_device *dss = dev_get_drvdata(dev);
+
+ platform_device_unregister(dss->drm_pdev);
+
omapdss_set_dss(NULL);
component_unbind_all(dev, NULL);
@@ -1474,6 +1484,8 @@ static int dss_probe(struct platform_device *pdev)
dss);
/* Add all the child devices as components. */
+ omapdss_gather_components(&pdev->dev);
+
device_for_each_child(&pdev->dev, &match, dss_add_child_component);
r = component_master_add_with_match(&pdev->dev, &dss_component_ops, match);
@@ -1539,12 +1551,9 @@ static void dss_shutdown(struct platform_device *pdev)
DSSDBG("shutdown\n");
- for_each_dss_dev(dssdev) {
- if (!dssdev->driver)
- continue;
-
+ for_each_dss_display(dssdev) {
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
- dssdev->driver->disable(dssdev);
+ dssdev->ops->disable(dssdev);
}
}
diff --git a/drivers/gpu/drm/omapdrm/dss/dss.h b/drivers/gpu/drm/omapdrm/dss/dss.h
index 38302631b64b..37790c363128 100644
--- a/drivers/gpu/drm/omapdrm/dss/dss.h
+++ b/drivers/gpu/drm/omapdrm/dss/dss.h
@@ -238,6 +238,8 @@ struct dss_device {
struct regmap *syscon_pll_ctrl;
u32 syscon_pll_ctrl_offset;
+ struct platform_device *drm_pdev;
+
struct clk *parent_clk;
struct clk *dss_clk;
unsigned long dss_clk_rate;
@@ -267,6 +269,8 @@ struct dss_device {
struct dispc_device *dispc;
const struct dispc_ops *dispc_ops;
+ const struct dss_mgr_ops *mgr_ops;
+ struct omap_drm_private *mgr_ops_priv;
};
/* core */
@@ -313,8 +317,6 @@ void dss_runtime_put(struct dss_device *dss);
unsigned long dss_get_dispc_clk_rate(struct dss_device *dss);
unsigned long dss_get_max_fck_rate(struct dss_device *dss);
-enum omap_dss_output_id dss_get_supported_outputs(struct dss_device *dss,
- enum omap_channel channel);
int dss_dpi_select_source(struct dss_device *dss, int port,
enum omap_channel channel);
void dss_select_hdmi_venc_clk_source(struct dss_device *dss,
@@ -374,8 +376,6 @@ static inline void sdi_uninit_port(struct device_node *port)
#ifdef CONFIG_OMAP2_DSS_DSI
-void dsi_dump_clocks(struct seq_file *s);
-
void dsi_irq_handler(void);
#endif
@@ -417,9 +417,6 @@ bool dispc_div_calc(struct dispc_device *dispc, unsigned long dispc_freq,
unsigned long pck_min, unsigned long pck_max,
dispc_div_calc_func func, void *data);
-bool dispc_mgr_timings_ok(struct dispc_device *dispc,
- enum omap_channel channel,
- const struct videomode *vm);
int dispc_calc_clock_rates(struct dispc_device *dispc,
unsigned long dispc_fclk_rate,
struct dispc_clock_info *cinfo);
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi.h b/drivers/gpu/drm/omapdrm/dss/hdmi.h
index 3aeb4cabd59f..7f0dc490a31d 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi.h
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi.h
@@ -313,13 +313,13 @@ void hdmi_wp_clear_irqenable(struct hdmi_wp_data *wp, u32 mask);
int hdmi_wp_set_phy_pwr(struct hdmi_wp_data *wp, enum hdmi_phy_pwr val);
int hdmi_wp_set_pll_pwr(struct hdmi_wp_data *wp, enum hdmi_pll_pwr val);
void hdmi_wp_video_config_format(struct hdmi_wp_data *wp,
- struct hdmi_video_format *video_fmt);
+ const struct hdmi_video_format *video_fmt);
void hdmi_wp_video_config_interface(struct hdmi_wp_data *wp,
- struct videomode *vm);
+ const struct videomode *vm);
void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp,
- struct videomode *vm);
+ const struct videomode *vm);
void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt,
- struct videomode *vm, struct hdmi_config *param);
+ struct videomode *vm, const struct hdmi_config *param);
int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp,
unsigned int version);
phys_addr_t hdmi_wp_get_audio_dma_addr(struct hdmi_wp_data *wp);
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index 5879f45f6fc9..cf6230eac31a 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -108,26 +108,6 @@ static irqreturn_t hdmi_irq_handler(int irq, void *data)
return IRQ_HANDLED;
}
-static int hdmi_init_regulator(struct omap_hdmi *hdmi)
-{
- struct regulator *reg;
-
- if (hdmi->vdda_reg != NULL)
- return 0;
-
- reg = devm_regulator_get(&hdmi->pdev->dev, "vdda");
-
- if (IS_ERR(reg)) {
- if (PTR_ERR(reg) != -EPROBE_DEFER)
- DSSERR("can't get VDDA regulator\n");
- return PTR_ERR(reg);
- }
-
- hdmi->vdda_reg = reg;
-
- return 0;
-}
-
static int hdmi_power_on_core(struct omap_hdmi *hdmi)
{
int r;
@@ -174,7 +154,7 @@ static void hdmi_power_off_core(struct omap_hdmi *hdmi)
static int hdmi_power_on_full(struct omap_hdmi *hdmi)
{
int r;
- struct videomode *vm;
+ const struct videomode *vm;
struct hdmi_wp_data *wp = &hdmi->wp;
struct dss_pll_clock_info hdmi_cinfo = { 0 };
unsigned int pc;
@@ -227,9 +207,6 @@ static int hdmi_power_on_full(struct omap_hdmi *hdmi)
hdmi4_configure(&hdmi->core, &hdmi->wp, &hdmi->cfg);
- /* tv size */
- dss_mgr_set_timings(&hdmi->output, vm);
-
r = dss_mgr_enable(&hdmi->output);
if (r)
goto err_mgr_enable;
@@ -271,19 +248,8 @@ static void hdmi_power_off_full(struct omap_hdmi *hdmi)
hdmi_power_off_core(hdmi);
}
-static int hdmi_display_check_timing(struct omap_dss_device *dssdev,
- struct videomode *vm)
-{
- struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-
- if (!dispc_mgr_timings_ok(hdmi->dss->dispc, dssdev->dispc_channel, vm))
- return -EINVAL;
-
- return 0;
-}
-
-static void hdmi_display_set_timing(struct omap_dss_device *dssdev,
- struct videomode *vm)
+static void hdmi_display_set_timings(struct omap_dss_device *dssdev,
+ const struct videomode *vm)
{
struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
@@ -296,14 +262,6 @@ static void hdmi_display_set_timing(struct omap_dss_device *dssdev,
mutex_unlock(&hdmi->lock);
}
-static void hdmi_display_get_timings(struct omap_dss_device *dssdev,
- struct videomode *vm)
-{
- struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-
- *vm = hdmi->cfg.vm;
-}
-
static int hdmi_dump_regs(struct seq_file *s, void *p)
{
struct omap_hdmi *hdmi = s->private;
@@ -456,44 +414,25 @@ void hdmi4_core_disable(struct hdmi_core_data *core)
mutex_unlock(&hdmi->lock);
}
-static int hdmi_connect(struct omap_dss_device *dssdev,
- struct omap_dss_device *dst)
+static int hdmi_connect(struct omap_dss_device *src,
+ struct omap_dss_device *dst)
{
- struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
int r;
- r = hdmi_init_regulator(hdmi);
+ r = omapdss_device_connect(dst->dss, dst, dst->next);
if (r)
return r;
- r = dss_mgr_connect(&hdmi->output, dssdev);
- if (r)
- return r;
-
- r = omapdss_output_set_device(dssdev, dst);
- if (r) {
- DSSERR("failed to connect output to new device: %s\n",
- dst->name);
- dss_mgr_disconnect(&hdmi->output, dssdev);
- return r;
- }
-
+ dst->dispc_channel_connected = true;
return 0;
}
-static void hdmi_disconnect(struct omap_dss_device *dssdev,
- struct omap_dss_device *dst)
+static void hdmi_disconnect(struct omap_dss_device *src,
+ struct omap_dss_device *dst)
{
- struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-
- WARN_ON(dst != dssdev->dst);
+ dst->dispc_channel_connected = false;
- if (dst != dssdev->dst)
- return;
-
- omapdss_output_unset_device(dssdev);
-
- dss_mgr_disconnect(&hdmi->output, dssdev);
+ omapdss_device_disconnect(dst, dst->next);
}
static int hdmi_read_edid(struct omap_dss_device *dssdev,
@@ -548,69 +487,28 @@ static int hdmi_set_hdmi_mode(struct omap_dss_device *dssdev,
return 0;
}
-static const struct omapdss_hdmi_ops hdmi_ops = {
+static const struct omap_dss_device_ops hdmi_ops = {
.connect = hdmi_connect,
.disconnect = hdmi_disconnect,
.enable = hdmi_display_enable,
.disable = hdmi_display_disable,
- .check_timings = hdmi_display_check_timing,
- .set_timings = hdmi_display_set_timing,
- .get_timings = hdmi_display_get_timings,
+ .set_timings = hdmi_display_set_timings,
.read_edid = hdmi_read_edid,
- .lost_hotplug = hdmi_lost_hotplug,
- .set_infoframe = hdmi_set_infoframe,
- .set_hdmi_mode = hdmi_set_hdmi_mode,
-};
-
-static void hdmi_init_output(struct omap_hdmi *hdmi)
-{
- struct omap_dss_device *out = &hdmi->output;
-
- out->dev = &hdmi->pdev->dev;
- out->id = OMAP_DSS_OUTPUT_HDMI;
- out->output_type = OMAP_DISPLAY_TYPE_HDMI;
- out->name = "hdmi.0";
- out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
- out->ops.hdmi = &hdmi_ops;
- out->owner = THIS_MODULE;
-
- omapdss_register_output(out);
-}
-
-static void hdmi_uninit_output(struct omap_hdmi *hdmi)
-{
- struct omap_dss_device *out = &hdmi->output;
-
- omapdss_unregister_output(out);
-}
-
-static int hdmi_probe_of(struct omap_hdmi *hdmi)
-{
- struct platform_device *pdev = hdmi->pdev;
- struct device_node *node = pdev->dev.of_node;
- struct device_node *ep;
- int r;
-
- ep = of_graph_get_endpoint_by_regs(node, 0, 0);
- if (!ep)
- return 0;
-
- r = hdmi_parse_lanes_of(pdev, ep, &hdmi->phy);
- if (r)
- goto err;
- of_node_put(ep);
- return 0;
+ .hdmi = {
+ .lost_hotplug = hdmi_lost_hotplug,
+ .set_infoframe = hdmi_set_infoframe,
+ .set_hdmi_mode = hdmi_set_hdmi_mode,
+ },
+};
-err:
- of_node_put(ep);
- return r;
-}
+/* -----------------------------------------------------------------------------
+ * Audio Callbacks
+ */
-/* Audio callbacks */
static int hdmi_audio_startup(struct device *dev,
void (*abort_cb)(struct device *dev))
{
@@ -725,27 +623,143 @@ static int hdmi_audio_register(struct omap_hdmi *hdmi)
return 0;
}
-/* HDMI HW IP initialisation */
+/* -----------------------------------------------------------------------------
+ * Component Bind & Unbind
+ */
+
static int hdmi4_bind(struct device *dev, struct device *master, void *data)
{
- struct platform_device *pdev = to_platform_device(dev);
struct dss_device *dss = dss_get_device(master);
- struct omap_hdmi *hdmi;
+ struct omap_hdmi *hdmi = dev_get_drvdata(dev);
+ int r;
+
+ hdmi->dss = dss;
+
+ r = hdmi_pll_init(dss, hdmi->pdev, &hdmi->pll, &hdmi->wp);
+ if (r)
+ return r;
+
+ r = hdmi4_cec_init(hdmi->pdev, &hdmi->core, &hdmi->wp);
+ if (r)
+ goto err_pll_uninit;
+
+ r = hdmi_audio_register(hdmi);
+ if (r) {
+ DSSERR("Registering HDMI audio failed\n");
+ goto err_cec_uninit;
+ }
+
+ hdmi->debugfs = dss_debugfs_create_file(dss, "hdmi", hdmi_dump_regs,
+ hdmi);
+
+ return 0;
+
+err_cec_uninit:
+ hdmi4_cec_uninit(&hdmi->core);
+err_pll_uninit:
+ hdmi_pll_uninit(&hdmi->pll);
+ return r;
+}
+
+static void hdmi4_unbind(struct device *dev, struct device *master, void *data)
+{
+ struct omap_hdmi *hdmi = dev_get_drvdata(dev);
+
+ dss_debugfs_remove_file(hdmi->debugfs);
+
+ if (hdmi->audio_pdev)
+ platform_device_unregister(hdmi->audio_pdev);
+
+ hdmi4_cec_uninit(&hdmi->core);
+ hdmi_pll_uninit(&hdmi->pll);
+}
+
+static const struct component_ops hdmi4_component_ops = {
+ .bind = hdmi4_bind,
+ .unbind = hdmi4_unbind,
+};
+
+/* -----------------------------------------------------------------------------
+ * Probe & Remove, Suspend & Resume
+ */
+
+static int hdmi4_init_output(struct omap_hdmi *hdmi)
+{
+ struct omap_dss_device *out = &hdmi->output;
int r;
+
+ out->dev = &hdmi->pdev->dev;
+ out->id = OMAP_DSS_OUTPUT_HDMI;
+ out->output_type = OMAP_DISPLAY_TYPE_HDMI;
+ out->name = "hdmi.0";
+ out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
+ out->ops = &hdmi_ops;
+ out->owner = THIS_MODULE;
+ 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;
+ return r;
+ }
+
+ omapdss_device_register(out);
+
+ return 0;
+}
+
+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);
+}
+
+static int hdmi4_probe_of(struct omap_hdmi *hdmi)
+{
+ struct platform_device *pdev = hdmi->pdev;
+ struct device_node *node = pdev->dev.of_node;
+ struct device_node *ep;
+ int r;
+
+ ep = of_graph_get_endpoint_by_regs(node, 0, 0);
+ if (!ep)
+ return 0;
+
+ r = hdmi_parse_lanes_of(pdev, ep, &hdmi->phy);
+ of_node_put(ep);
+ return r;
+}
+
+static int hdmi4_probe(struct platform_device *pdev)
+{
+ struct omap_hdmi *hdmi;
int irq;
+ int r;
hdmi = kzalloc(sizeof(*hdmi), GFP_KERNEL);
if (!hdmi)
return -ENOMEM;
hdmi->pdev = pdev;
- hdmi->dss = dss;
+
dev_set_drvdata(&pdev->dev, hdmi);
mutex_init(&hdmi->lock);
spin_lock_init(&hdmi->audio_playing_lock);
- r = hdmi_probe_of(hdmi);
+ r = hdmi4_probe_of(hdmi);
if (r)
goto err_free;
@@ -753,27 +767,19 @@ static int hdmi4_bind(struct device *dev, struct device *master, void *data)
if (r)
goto err_free;
- r = hdmi_pll_init(dss, pdev, &hdmi->pll, &hdmi->wp);
- if (r)
- goto err_free;
-
r = hdmi_phy_init(pdev, &hdmi->phy, 4);
if (r)
- goto err_pll;
+ goto err_free;
r = hdmi4_core_init(pdev, &hdmi->core);
if (r)
- goto err_pll;
-
- r = hdmi4_cec_init(pdev, &hdmi->core, &hdmi->wp);
- if (r)
- goto err_pll;
+ goto err_free;
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
DSSERR("platform_get_irq failed\n");
r = -ENODEV;
- goto err_pll;
+ goto err_free;
}
r = devm_request_threaded_irq(&pdev->dev, irq,
@@ -781,66 +787,49 @@ static int hdmi4_bind(struct device *dev, struct device *master, void *data)
IRQF_ONESHOT, "OMAP HDMI", hdmi);
if (r) {
DSSERR("HDMI IRQ request failed\n");
- goto err_pll;
+ goto err_free;
}
- pm_runtime_enable(&pdev->dev);
+ hdmi->vdda_reg = devm_regulator_get(&pdev->dev, "vdda");
+ if (IS_ERR(hdmi->vdda_reg)) {
+ r = PTR_ERR(hdmi->vdda_reg);
+ if (r != -EPROBE_DEFER)
+ DSSERR("can't get VDDA regulator\n");
+ goto err_free;
+ }
- hdmi_init_output(hdmi);
+ pm_runtime_enable(&pdev->dev);
- r = hdmi_audio_register(hdmi);
- if (r) {
- DSSERR("Registering HDMI audio failed\n");
- hdmi_uninit_output(hdmi);
- pm_runtime_disable(&pdev->dev);
- return r;
- }
+ r = hdmi4_init_output(hdmi);
+ if (r)
+ goto err_pm_disable;
- hdmi->debugfs = dss_debugfs_create_file(dss, "hdmi", hdmi_dump_regs,
- hdmi);
+ r = component_add(&pdev->dev, &hdmi4_component_ops);
+ if (r)
+ goto err_uninit_output;
return 0;
-err_pll:
- hdmi_pll_uninit(&hdmi->pll);
+err_uninit_output:
+ hdmi4_uninit_output(hdmi);
+err_pm_disable:
+ pm_runtime_disable(&pdev->dev);
err_free:
kfree(hdmi);
return r;
}
-static void hdmi4_unbind(struct device *dev, struct device *master, void *data)
+static int hdmi4_remove(struct platform_device *pdev)
{
- struct omap_hdmi *hdmi = dev_get_drvdata(dev);
-
- dss_debugfs_remove_file(hdmi->debugfs);
-
- if (hdmi->audio_pdev)
- platform_device_unregister(hdmi->audio_pdev);
+ struct omap_hdmi *hdmi = platform_get_drvdata(pdev);
- hdmi_uninit_output(hdmi);
-
- hdmi4_cec_uninit(&hdmi->core);
+ component_del(&pdev->dev, &hdmi4_component_ops);
- hdmi_pll_uninit(&hdmi->pll);
+ hdmi4_uninit_output(hdmi);
- pm_runtime_disable(dev);
+ pm_runtime_disable(&pdev->dev);
kfree(hdmi);
-}
-
-static const struct component_ops hdmi4_component_ops = {
- .bind = hdmi4_bind,
- .unbind = hdmi4_unbind,
-};
-
-static int hdmi4_probe(struct platform_device *pdev)
-{
- return component_add(&pdev->dev, &hdmi4_component_ops);
-}
-
-static int hdmi4_remove(struct platform_device *pdev)
-{
- component_del(&pdev->dev, &hdmi4_component_ops);
return 0;
}
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
index ae1a001d1b83..b0e4a7463f8c 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
@@ -117,24 +117,6 @@ static irqreturn_t hdmi_irq_handler(int irq, void *data)
return IRQ_HANDLED;
}
-static int hdmi_init_regulator(struct omap_hdmi *hdmi)
-{
- struct regulator *reg;
-
- if (hdmi->vdda_reg != NULL)
- return 0;
-
- reg = devm_regulator_get(&hdmi->pdev->dev, "vdda");
- if (IS_ERR(reg)) {
- DSSERR("can't get VDDA regulator\n");
- return PTR_ERR(reg);
- }
-
- hdmi->vdda_reg = reg;
-
- return 0;
-}
-
static int hdmi_power_on_core(struct omap_hdmi *hdmi)
{
int r;
@@ -171,7 +153,7 @@ static void hdmi_power_off_core(struct omap_hdmi *hdmi)
static int hdmi_power_on_full(struct omap_hdmi *hdmi)
{
int r;
- struct videomode *vm;
+ const struct videomode *vm;
struct dss_pll_clock_info hdmi_cinfo = { 0 };
unsigned int pc;
@@ -224,9 +206,6 @@ static int hdmi_power_on_full(struct omap_hdmi *hdmi)
hdmi5_configure(&hdmi->core, &hdmi->wp, &hdmi->cfg);
- /* tv size */
- dss_mgr_set_timings(&hdmi->output, vm);
-
r = dss_mgr_enable(&hdmi->output);
if (r)
goto err_mgr_enable;
@@ -268,19 +247,8 @@ static void hdmi_power_off_full(struct omap_hdmi *hdmi)
hdmi_power_off_core(hdmi);
}
-static int hdmi_display_check_timing(struct omap_dss_device *dssdev,
- struct videomode *vm)
-{
- struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-
- if (!dispc_mgr_timings_ok(hdmi->dss->dispc, dssdev->dispc_channel, vm))
- return -EINVAL;
-
- return 0;
-}
-
-static void hdmi_display_set_timing(struct omap_dss_device *dssdev,
- struct videomode *vm)
+static void hdmi_display_set_timings(struct omap_dss_device *dssdev,
+ const struct videomode *vm)
{
struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
@@ -293,14 +261,6 @@ static void hdmi_display_set_timing(struct omap_dss_device *dssdev,
mutex_unlock(&hdmi->lock);
}
-static void hdmi_display_get_timings(struct omap_dss_device *dssdev,
- struct videomode *vm)
-{
- struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-
- *vm = hdmi->cfg.vm;
-}
-
static int hdmi_dump_regs(struct seq_file *s, void *p)
{
struct omap_hdmi *hdmi = s->private;
@@ -459,44 +419,25 @@ static void hdmi_core_disable(struct omap_hdmi *hdmi)
mutex_unlock(&hdmi->lock);
}
-static int hdmi_connect(struct omap_dss_device *dssdev,
- struct omap_dss_device *dst)
+static int hdmi_connect(struct omap_dss_device *src,
+ struct omap_dss_device *dst)
{
- struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
int r;
- r = hdmi_init_regulator(hdmi);
- if (r)
- return r;
-
- r = dss_mgr_connect(&hdmi->output, dssdev);
+ r = omapdss_device_connect(dst->dss, dst, dst->next);
if (r)
return r;
- r = omapdss_output_set_device(dssdev, dst);
- if (r) {
- DSSERR("failed to connect output to new device: %s\n",
- dst->name);
- dss_mgr_disconnect(&hdmi->output, dssdev);
- return r;
- }
-
+ dst->dispc_channel_connected = true;
return 0;
}
-static void hdmi_disconnect(struct omap_dss_device *dssdev,
- struct omap_dss_device *dst)
+static void hdmi_disconnect(struct omap_dss_device *src,
+ struct omap_dss_device *dst)
{
- struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-
- WARN_ON(dst != dssdev->dst);
+ dst->dispc_channel_connected = false;
- if (dst != dssdev->dst)
- return;
-
- omapdss_output_unset_device(dssdev);
-
- dss_mgr_disconnect(&hdmi->output, dssdev);
+ omapdss_device_disconnect(dst, dst->next);
}
static int hdmi_read_edid(struct omap_dss_device *dssdev,
@@ -540,68 +481,27 @@ static int hdmi_set_hdmi_mode(struct omap_dss_device *dssdev,
return 0;
}
-static const struct omapdss_hdmi_ops hdmi_ops = {
+static const struct omap_dss_device_ops hdmi_ops = {
.connect = hdmi_connect,
.disconnect = hdmi_disconnect,
.enable = hdmi_display_enable,
.disable = hdmi_display_disable,
- .check_timings = hdmi_display_check_timing,
- .set_timings = hdmi_display_set_timing,
- .get_timings = hdmi_display_get_timings,
+ .set_timings = hdmi_display_set_timings,
.read_edid = hdmi_read_edid,
- .set_infoframe = hdmi_set_infoframe,
- .set_hdmi_mode = hdmi_set_hdmi_mode,
-};
-
-static void hdmi_init_output(struct omap_hdmi *hdmi)
-{
- struct omap_dss_device *out = &hdmi->output;
-
- out->dev = &hdmi->pdev->dev;
- out->id = OMAP_DSS_OUTPUT_HDMI;
- out->output_type = OMAP_DISPLAY_TYPE_HDMI;
- out->name = "hdmi.0";
- out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
- out->ops.hdmi = &hdmi_ops;
- out->owner = THIS_MODULE;
-
- omapdss_register_output(out);
-}
-
-static void hdmi_uninit_output(struct omap_hdmi *hdmi)
-{
- struct omap_dss_device *out = &hdmi->output;
-
- omapdss_unregister_output(out);
-}
-
-static int hdmi_probe_of(struct omap_hdmi *hdmi)
-{
- struct platform_device *pdev = hdmi->pdev;
- struct device_node *node = pdev->dev.of_node;
- struct device_node *ep;
- int r;
-
- ep = of_graph_get_endpoint_by_regs(node, 0, 0);
- if (!ep)
- return 0;
-
- r = hdmi_parse_lanes_of(pdev, ep, &hdmi->phy);
- if (r)
- goto err;
- of_node_put(ep);
- return 0;
+ .hdmi = {
+ .set_infoframe = hdmi_set_infoframe,
+ .set_hdmi_mode = hdmi_set_hdmi_mode,
+ },
+};
-err:
- of_node_put(ep);
- return r;
-}
+/* -----------------------------------------------------------------------------
+ * Audio Callbacks
+ */
-/* Audio callbacks */
static int hdmi_audio_startup(struct device *dev,
void (*abort_cb)(struct device *dev))
{
@@ -722,27 +622,136 @@ static int hdmi_audio_register(struct omap_hdmi *hdmi)
return 0;
}
-/* HDMI HW IP initialisation */
+/* -----------------------------------------------------------------------------
+ * Component Bind & Unbind
+ */
+
static int hdmi5_bind(struct device *dev, struct device *master, void *data)
{
- struct platform_device *pdev = to_platform_device(dev);
struct dss_device *dss = dss_get_device(master);
- struct omap_hdmi *hdmi;
+ struct omap_hdmi *hdmi = dev_get_drvdata(dev);
+ int r;
+
+ hdmi->dss = dss;
+
+ r = hdmi_pll_init(dss, hdmi->pdev, &hdmi->pll, &hdmi->wp);
+ if (r)
+ return r;
+
+ r = hdmi_audio_register(hdmi);
+ if (r) {
+ DSSERR("Registering HDMI audio failed %d\n", r);
+ goto err_pll_uninit;
+ }
+
+ hdmi->debugfs = dss_debugfs_create_file(dss, "hdmi", hdmi_dump_regs,
+ hdmi);
+
+ return 0;
+
+err_pll_uninit:
+ hdmi_pll_uninit(&hdmi->pll);
+ return r;
+}
+
+static void hdmi5_unbind(struct device *dev, struct device *master, void *data)
+{
+ struct omap_hdmi *hdmi = dev_get_drvdata(dev);
+
+ dss_debugfs_remove_file(hdmi->debugfs);
+
+ if (hdmi->audio_pdev)
+ platform_device_unregister(hdmi->audio_pdev);
+
+ hdmi_pll_uninit(&hdmi->pll);
+}
+
+static const struct component_ops hdmi5_component_ops = {
+ .bind = hdmi5_bind,
+ .unbind = hdmi5_unbind,
+};
+
+/* -----------------------------------------------------------------------------
+ * Probe & Remove, Suspend & Resume
+ */
+
+static int hdmi5_init_output(struct omap_hdmi *hdmi)
+{
+ struct omap_dss_device *out = &hdmi->output;
+ int r;
+
+ out->dev = &hdmi->pdev->dev;
+ out->id = OMAP_DSS_OUTPUT_HDMI;
+ out->output_type = OMAP_DISPLAY_TYPE_HDMI;
+ out->name = "hdmi.0";
+ out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
+ out->ops = &hdmi_ops;
+ out->owner = THIS_MODULE;
+ 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;
+ return r;
+ }
+
+ omapdss_device_register(out);
+
+ return 0;
+}
+
+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);
+}
+
+static int hdmi5_probe_of(struct omap_hdmi *hdmi)
+{
+ struct platform_device *pdev = hdmi->pdev;
+ struct device_node *node = pdev->dev.of_node;
+ struct device_node *ep;
int r;
+
+ ep = of_graph_get_endpoint_by_regs(node, 0, 0);
+ if (!ep)
+ return 0;
+
+ r = hdmi_parse_lanes_of(pdev, ep, &hdmi->phy);
+ of_node_put(ep);
+ return r;
+}
+
+static int hdmi5_probe(struct platform_device *pdev)
+{
+ struct omap_hdmi *hdmi;
int irq;
+ int r;
hdmi = kzalloc(sizeof(*hdmi), GFP_KERNEL);
if (!hdmi)
return -ENOMEM;
hdmi->pdev = pdev;
- hdmi->dss = dss;
+
dev_set_drvdata(&pdev->dev, hdmi);
mutex_init(&hdmi->lock);
spin_lock_init(&hdmi->audio_playing_lock);
- r = hdmi_probe_of(hdmi);
+ r = hdmi5_probe_of(hdmi);
if (r)
goto err_free;
@@ -750,23 +759,19 @@ static int hdmi5_bind(struct device *dev, struct device *master, void *data)
if (r)
goto err_free;
- r = hdmi_pll_init(dss, pdev, &hdmi->pll, &hdmi->wp);
- if (r)
- goto err_free;
-
r = hdmi_phy_init(pdev, &hdmi->phy, 5);
if (r)
- goto err_pll;
+ goto err_free;
r = hdmi5_core_init(pdev, &hdmi->core);
if (r)
- goto err_pll;
+ goto err_free;
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
DSSERR("platform_get_irq failed\n");
r = -ENODEV;
- goto err_pll;
+ goto err_free;
}
r = devm_request_threaded_irq(&pdev->dev, irq,
@@ -774,64 +779,49 @@ static int hdmi5_bind(struct device *dev, struct device *master, void *data)
IRQF_ONESHOT, "OMAP HDMI", hdmi);
if (r) {
DSSERR("HDMI IRQ request failed\n");
- goto err_pll;
+ goto err_free;
}
- pm_runtime_enable(&pdev->dev);
+ hdmi->vdda_reg = devm_regulator_get(&pdev->dev, "vdda");
+ if (IS_ERR(hdmi->vdda_reg)) {
+ r = PTR_ERR(hdmi->vdda_reg);
+ if (r != -EPROBE_DEFER)
+ DSSERR("can't get VDDA regulator\n");
+ goto err_free;
+ }
- hdmi_init_output(hdmi);
+ pm_runtime_enable(&pdev->dev);
- r = hdmi_audio_register(hdmi);
- if (r) {
- DSSERR("Registering HDMI audio failed %d\n", r);
- hdmi_uninit_output(hdmi);
- pm_runtime_disable(&pdev->dev);
- return r;
- }
+ r = hdmi5_init_output(hdmi);
+ if (r)
+ goto err_pm_disable;
- hdmi->debugfs = dss_debugfs_create_file(dss, "hdmi", hdmi_dump_regs,
- hdmi);
+ r = component_add(&pdev->dev, &hdmi5_component_ops);
+ if (r)
+ goto err_uninit_output;
return 0;
-err_pll:
- hdmi_pll_uninit(&hdmi->pll);
+err_uninit_output:
+ hdmi5_uninit_output(hdmi);
+err_pm_disable:
+ pm_runtime_disable(&pdev->dev);
err_free:
kfree(hdmi);
return r;
}
-static void hdmi5_unbind(struct device *dev, struct device *master, void *data)
+static int hdmi5_remove(struct platform_device *pdev)
{
- struct omap_hdmi *hdmi = dev_get_drvdata(dev);
-
- dss_debugfs_remove_file(hdmi->debugfs);
+ struct omap_hdmi *hdmi = platform_get_drvdata(pdev);
- if (hdmi->audio_pdev)
- platform_device_unregister(hdmi->audio_pdev);
-
- hdmi_uninit_output(hdmi);
+ component_del(&pdev->dev, &hdmi5_component_ops);
- hdmi_pll_uninit(&hdmi->pll);
+ hdmi5_uninit_output(hdmi);
- pm_runtime_disable(dev);
+ pm_runtime_disable(&pdev->dev);
kfree(hdmi);
-}
-
-static const struct component_ops hdmi5_component_ops = {
- .bind = hdmi5_bind,
- .unbind = hdmi5_unbind,
-};
-
-static int hdmi5_probe(struct platform_device *pdev)
-{
- return component_add(&pdev->dev, &hdmi5_component_ops);
-}
-
-static int hdmi5_remove(struct platform_device *pdev)
-{
- component_del(&pdev->dev, &hdmi5_component_ops);
return 0;
}
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c
index 2282e48574c6..02efabc7ed76 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c
@@ -287,7 +287,7 @@ void hdmi5_core_dump(struct hdmi_core_data *core, struct seq_file *s)
}
static void hdmi_core_init(struct hdmi_core_vid_config *video_cfg,
- struct hdmi_config *cfg)
+ const struct hdmi_config *cfg)
{
DSSDBG("hdmi_core_init\n");
@@ -325,10 +325,10 @@ static void hdmi_core_init(struct hdmi_core_vid_config *video_cfg,
/* DSS_HDMI_CORE_VIDEO_CONFIG */
static void hdmi_core_video_config(struct hdmi_core_data *core,
- struct hdmi_core_vid_config *cfg)
+ const struct hdmi_core_vid_config *cfg)
{
void __iomem *base = core->base;
- struct videomode *vm = &cfg->v_fc_config.vm;
+ const struct videomode *vm = &cfg->v_fc_config.vm;
unsigned char r = 0;
bool vsync_pol, hsync_pol;
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c
index 53bc5f78050c..100efb9f08c6 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c
@@ -131,7 +131,7 @@ void hdmi_wp_video_stop(struct hdmi_wp_data *wp)
}
void hdmi_wp_video_config_format(struct hdmi_wp_data *wp,
- struct hdmi_video_format *video_fmt)
+ const struct hdmi_video_format *video_fmt)
{
u32 l = 0;
@@ -144,7 +144,7 @@ void hdmi_wp_video_config_format(struct hdmi_wp_data *wp,
}
void hdmi_wp_video_config_interface(struct hdmi_wp_data *wp,
- struct videomode *vm)
+ const struct videomode *vm)
{
u32 r;
bool vsync_inv, hsync_inv;
@@ -164,7 +164,7 @@ void hdmi_wp_video_config_interface(struct hdmi_wp_data *wp,
}
void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp,
- struct videomode *vm)
+ const struct videomode *vm)
{
u32 timing_h = 0;
u32 timing_v = 0;
@@ -193,7 +193,7 @@ void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp,
}
void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt,
- struct videomode *vm, struct hdmi_config *param)
+ struct videomode *vm, const struct hdmi_config *param)
{
DSSDBG("Enter hdmi_wp_video_init_format\n");
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h
index 14d74adb13fb..1f698a95a94a 100644
--- a/drivers/gpu/drm/omapdrm/dss/omapdss.h
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h
@@ -296,117 +296,14 @@ struct omap_dss_writeback_info {
u8 pre_mult_alpha;
};
-struct omapdss_dpi_ops {
- int (*connect)(struct omap_dss_device *dssdev,
- struct omap_dss_device *dst);
- void (*disconnect)(struct omap_dss_device *dssdev,
- struct omap_dss_device *dst);
-
- int (*enable)(struct omap_dss_device *dssdev);
- void (*disable)(struct omap_dss_device *dssdev);
-
- int (*check_timings)(struct omap_dss_device *dssdev,
- struct videomode *vm);
- void (*set_timings)(struct omap_dss_device *dssdev,
- struct videomode *vm);
- void (*get_timings)(struct omap_dss_device *dssdev,
- struct videomode *vm);
-};
-
-struct omapdss_sdi_ops {
- int (*connect)(struct omap_dss_device *dssdev,
- struct omap_dss_device *dst);
- void (*disconnect)(struct omap_dss_device *dssdev,
- struct omap_dss_device *dst);
-
- int (*enable)(struct omap_dss_device *dssdev);
- void (*disable)(struct omap_dss_device *dssdev);
-
- int (*check_timings)(struct omap_dss_device *dssdev,
- struct videomode *vm);
- void (*set_timings)(struct omap_dss_device *dssdev,
- struct videomode *vm);
- void (*get_timings)(struct omap_dss_device *dssdev,
- struct videomode *vm);
-};
-
-struct omapdss_dvi_ops {
- int (*connect)(struct omap_dss_device *dssdev,
- struct omap_dss_device *dst);
- void (*disconnect)(struct omap_dss_device *dssdev,
- struct omap_dss_device *dst);
-
- int (*enable)(struct omap_dss_device *dssdev);
- void (*disable)(struct omap_dss_device *dssdev);
-
- int (*check_timings)(struct omap_dss_device *dssdev,
- struct videomode *vm);
- void (*set_timings)(struct omap_dss_device *dssdev,
- struct videomode *vm);
- void (*get_timings)(struct omap_dss_device *dssdev,
- struct videomode *vm);
-};
-
-struct omapdss_atv_ops {
- int (*connect)(struct omap_dss_device *dssdev,
- struct omap_dss_device *dst);
- void (*disconnect)(struct omap_dss_device *dssdev,
- struct omap_dss_device *dst);
-
- int (*enable)(struct omap_dss_device *dssdev);
- void (*disable)(struct omap_dss_device *dssdev);
-
- int (*check_timings)(struct omap_dss_device *dssdev,
- struct videomode *vm);
- void (*set_timings)(struct omap_dss_device *dssdev,
- struct videomode *vm);
- void (*get_timings)(struct omap_dss_device *dssdev,
- struct videomode *vm);
-
- int (*set_wss)(struct omap_dss_device *dssdev, u32 wss);
- u32 (*get_wss)(struct omap_dss_device *dssdev);
-};
-
struct omapdss_hdmi_ops {
- int (*connect)(struct omap_dss_device *dssdev,
- struct omap_dss_device *dst);
- void (*disconnect)(struct omap_dss_device *dssdev,
- struct omap_dss_device *dst);
-
- int (*enable)(struct omap_dss_device *dssdev);
- void (*disable)(struct omap_dss_device *dssdev);
-
- int (*check_timings)(struct omap_dss_device *dssdev,
- struct videomode *vm);
- void (*set_timings)(struct omap_dss_device *dssdev,
- struct videomode *vm);
- void (*get_timings)(struct omap_dss_device *dssdev,
- struct videomode *vm);
-
- int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len);
void (*lost_hotplug)(struct omap_dss_device *dssdev);
- bool (*detect)(struct omap_dss_device *dssdev);
-
- int (*register_hpd_cb)(struct omap_dss_device *dssdev,
- void (*cb)(void *cb_data,
- enum drm_connector_status status),
- void *cb_data);
- void (*unregister_hpd_cb)(struct omap_dss_device *dssdev);
- void (*enable_hpd)(struct omap_dss_device *dssdev);
- void (*disable_hpd)(struct omap_dss_device *dssdev);
-
int (*set_hdmi_mode)(struct omap_dss_device *dssdev, bool hdmi_mode);
int (*set_infoframe)(struct omap_dss_device *dssdev,
const struct hdmi_avi_infoframe *avi);
};
struct omapdss_dsi_ops {
- int (*connect)(struct omap_dss_device *dssdev,
- struct omap_dss_device *dst);
- void (*disconnect)(struct omap_dss_device *dssdev,
- struct omap_dss_device *dst);
-
- int (*enable)(struct omap_dss_device *dssdev);
void (*disable)(struct omap_dss_device *dssdev, bool disconnect_lanes,
bool enter_ulps);
@@ -457,53 +354,95 @@ struct omapdss_dsi_ops {
int channel, u16 plen);
};
+struct omap_dss_device_ops {
+ int (*connect)(struct omap_dss_device *dssdev,
+ struct omap_dss_device *dst);
+ void (*disconnect)(struct omap_dss_device *dssdev,
+ struct omap_dss_device *dst);
+
+ int (*enable)(struct omap_dss_device *dssdev);
+ void (*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);
+ void (*set_timings)(struct omap_dss_device *dssdev,
+ const struct videomode *vm);
+
+ bool (*detect)(struct omap_dss_device *dssdev);
+
+ void (*register_hpd_cb)(struct omap_dss_device *dssdev,
+ void (*cb)(void *cb_data,
+ enum drm_connector_status status),
+ void *cb_data);
+ void (*unregister_hpd_cb)(struct omap_dss_device *dssdev);
+
+ int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len);
+
+ union {
+ const struct omapdss_hdmi_ops hdmi;
+ const struct omapdss_dsi_ops dsi;
+ };
+};
+
+/**
+ * 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
+ */
+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),
+};
+
struct omap_dss_device {
struct kobject kobj;
struct device *dev;
struct module *owner;
- struct list_head panel_list;
+ struct dss_device *dss;
+ struct omap_dss_device *src;
+ struct omap_dss_device *dst;
+ struct omap_dss_device *next;
+
+ struct list_head list;
- /* alias in the form of "display%d" */
- char alias[16];
+ unsigned int alias_id;
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.
+ */
enum omap_display_type output_type;
- struct {
- struct videomode vm;
-
- enum omap_dss_dsi_pixel_format dsi_pix_fmt;
- enum omap_dss_dsi_mode dsi_mode;
- } panel;
-
const char *name;
- struct omap_dss_driver *driver;
-
- union {
- const struct omapdss_dpi_ops *dpi;
- const struct omapdss_sdi_ops *sdi;
- const struct omapdss_dvi_ops *dvi;
- const struct omapdss_hdmi_ops *hdmi;
- const struct omapdss_atv_ops *atv;
- const struct omapdss_dsi_ops *dsi;
- } ops;
+ const struct omap_dss_driver *driver;
+ const struct omap_dss_device_ops *ops;
+ unsigned long ops_flags;
+ unsigned long bus_flags;
/* helper variable for driver suspend/resume */
bool activate_after_resume;
enum omap_display_caps caps;
- struct omap_dss_device *src;
-
enum omap_dss_display_state state;
/* OMAP DSS output specific fields */
- struct list_head list;
-
/* DISPC channel for this output */
enum omap_channel dispc_channel;
bool dispc_channel_connected;
@@ -511,24 +450,11 @@ struct omap_dss_device {
/* output instance */
enum omap_dss_output_id id;
- /* the port number in the DT node */
- int port_num;
-
- /* dynamic fields */
- struct omap_dss_device *dst;
+ /* bitmask of port numbers in DT */
+ unsigned int of_ports;
};
struct omap_dss_driver {
- int (*probe)(struct omap_dss_device *);
- void (*remove)(struct omap_dss_device *);
-
- int (*connect)(struct omap_dss_device *dssdev);
- void (*disconnect)(struct omap_dss_device *dssdev);
-
- int (*enable)(struct omap_dss_device *display);
- void (*disable)(struct omap_dss_device *display);
- int (*run_test)(struct omap_dss_device *display, int test);
-
int (*update)(struct omap_dss_device *dssdev,
u16 x, u16 y, u16 w, u16 h);
int (*sync)(struct omap_dss_device *dssdev);
@@ -536,42 +462,12 @@ struct omap_dss_driver {
int (*enable_te)(struct omap_dss_device *dssdev, bool enable);
int (*get_te)(struct omap_dss_device *dssdev);
- u8 (*get_rotate)(struct omap_dss_device *dssdev);
- int (*set_rotate)(struct omap_dss_device *dssdev, u8 rotate);
-
- bool (*get_mirror)(struct omap_dss_device *dssdev);
- int (*set_mirror)(struct omap_dss_device *dssdev, bool enable);
-
int (*memory_read)(struct omap_dss_device *dssdev,
void *buf, size_t size,
u16 x, u16 y, u16 w, u16 h);
- int (*check_timings)(struct omap_dss_device *dssdev,
- struct videomode *vm);
- void (*set_timings)(struct omap_dss_device *dssdev,
- struct videomode *vm);
- void (*get_timings)(struct omap_dss_device *dssdev,
- struct videomode *vm);
void (*get_size)(struct omap_dss_device *dssdev,
unsigned int *width, unsigned int *height);
-
- int (*set_wss)(struct omap_dss_device *dssdev, u32 wss);
- u32 (*get_wss)(struct omap_dss_device *dssdev);
-
- int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len);
- bool (*detect)(struct omap_dss_device *dssdev);
-
- int (*register_hpd_cb)(struct omap_dss_device *dssdev,
- void (*cb)(void *cb_data,
- enum drm_connector_status status),
- void *cb_data);
- void (*unregister_hpd_cb)(struct omap_dss_device *dssdev);
- void (*enable_hpd)(struct omap_dss_device *dssdev);
- void (*disable_hpd)(struct omap_dss_device *dssdev);
-
- int (*set_hdmi_mode)(struct omap_dss_device *dssdev, bool hdmi_mode);
- int (*set_hdmi_infoframe)(struct omap_dss_device *dssdev,
- const struct hdmi_avi_infoframe *avi);
};
struct dss_device *omapdss_get_dss(void);
@@ -581,27 +477,32 @@ static inline bool omapdss_is_initialized(void)
return !!omapdss_get_dss();
}
-int omapdss_register_display(struct omap_dss_device *dssdev);
-void omapdss_unregister_display(struct omap_dss_device *dssdev);
-
-struct omap_dss_device *omap_dss_get_device(struct omap_dss_device *dssdev);
-void omap_dss_put_device(struct omap_dss_device *dssdev);
-#define for_each_dss_dev(d) while ((d = omap_dss_get_next_device(d)) != NULL)
-struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from);
+#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);
+
+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);
+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);
int omap_dss_get_num_overlay_managers(void);
int omap_dss_get_num_overlays(void);
-int omapdss_register_output(struct omap_dss_device *output);
-void omapdss_unregister_output(struct omap_dss_device *output);
-struct omap_dss_device *omap_dss_get_output(enum omap_dss_output_id id);
-struct omap_dss_device *omap_dss_find_output_by_port_node(struct device_node *port);
-int omapdss_output_set_device(struct omap_dss_device *out,
- struct omap_dss_device *dssdev);
-int omapdss_output_unset_device(struct omap_dss_device *out);
-
-struct omap_dss_device *omapdss_find_output_from_display(struct omap_dss_device *dssdev);
+#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);
typedef void (*omap_dispc_isr_t) (void *arg, u32 mask);
int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
@@ -621,10 +522,7 @@ static inline bool omapdss_device_is_enabled(struct omap_dss_device *dssdev)
}
struct omap_dss_device *
-omapdss_of_find_source_for_first_ep(struct device_node *node);
-
-struct device_node *dss_of_port_get_parent_device(struct device_node *port);
-u32 dss_of_port_get_port_number(struct device_node *port);
+omapdss_of_find_connected_device(struct device_node *node, unsigned int port);
enum dss_writeback_channel {
DSS_WB_LCD1_MGR = 0,
@@ -638,13 +536,6 @@ enum dss_writeback_channel {
};
struct dss_mgr_ops {
- int (*connect)(struct omap_drm_private *priv,
- enum omap_channel channel,
- struct omap_dss_device *dst);
- void (*disconnect)(struct omap_drm_private *priv,
- enum omap_channel channel,
- struct omap_dss_device *dst);
-
void (*start_update)(struct omap_drm_private *priv,
enum omap_channel channel);
int (*enable)(struct omap_drm_private *priv,
@@ -665,14 +556,11 @@ struct dss_mgr_ops {
void (*handler)(void *), void *data);
};
-int dss_install_mgr_ops(const struct dss_mgr_ops *mgr_ops,
+int dss_install_mgr_ops(struct dss_device *dss,
+ const struct dss_mgr_ops *mgr_ops,
struct omap_drm_private *priv);
-void dss_uninstall_mgr_ops(void);
+void dss_uninstall_mgr_ops(struct dss_device *dss);
-int dss_mgr_connect(struct omap_dss_device *dssdev,
- struct omap_dss_device *dst);
-void dss_mgr_disconnect(struct omap_dss_device *dssdev,
- struct omap_dss_device *dst);
void dss_mgr_set_timings(struct omap_dss_device *dssdev,
const struct videomode *vm);
void dss_mgr_set_lcd_config(struct omap_dss_device *dssdev,
@@ -720,13 +608,14 @@ struct dispc_ops {
void (*mgr_set_lcd_config)(struct dispc_device *dispc,
enum omap_channel channel,
const struct dss_lcd_mgr_config *config);
+ int (*mgr_check_timings)(struct dispc_device *dispc,
+ enum omap_channel channel,
+ const struct videomode *vm);
void (*mgr_set_timings)(struct dispc_device *dispc,
enum omap_channel channel,
const struct videomode *vm);
void (*mgr_setup)(struct dispc_device *dispc, enum omap_channel channel,
const struct omap_overlay_manager_info *info);
- enum omap_dss_output_id (*mgr_get_supported_outputs)(
- struct dispc_device *dispc, enum omap_channel channel);
u32 (*mgr_gamma_size)(struct dispc_device *dispc,
enum omap_channel channel);
void (*mgr_set_gamma)(struct dispc_device *dispc,
@@ -757,9 +646,6 @@ struct dispc_ops {
struct dispc_device *dispc_get_dispc(struct dss_device *dss);
const struct dispc_ops *dispc_get_ops(struct dss_device *dss);
-bool omapdss_component_is_display(struct device_node *node);
-bool omapdss_component_is_output(struct device_node *node);
-
bool omapdss_stack_is_ready(void);
void omapdss_gather_components(struct device *dev);
diff --git a/drivers/gpu/drm/omapdrm/dss/output.c b/drivers/gpu/drm/omapdrm/dss/output.c
index 96b9d4cd505f..18505bc70f7e 100644
--- a/drivers/gpu/drm/omapdrm/dss/output.c
+++ b/drivers/gpu/drm/omapdrm/dss/output.c
@@ -21,238 +21,96 @@
#include <linux/slab.h>
#include <linux/of.h>
+#include "dss.h"
#include "omapdss.h"
-static LIST_HEAD(output_list);
-static DEFINE_MUTEX(output_lock);
-
-int omapdss_output_set_device(struct omap_dss_device *out,
- struct omap_dss_device *dssdev)
+int omapdss_output_validate(struct omap_dss_device *out)
{
- int r;
-
- mutex_lock(&output_lock);
-
- if (out->dst) {
- dev_err(out->dev,
- "output already has device %s connected to it\n",
- out->dst->name);
- r = -EINVAL;
- goto err;
- }
-
- if (out->output_type != dssdev->type) {
+ if (out->next && out->output_type != out->next->type) {
dev_err(out->dev, "output type and display type don't match\n");
- r = -EINVAL;
- goto err;
- }
-
- out->dst = dssdev;
- dssdev->src = out;
-
- mutex_unlock(&output_lock);
-
- return 0;
-err:
- mutex_unlock(&output_lock);
-
- return r;
-}
-EXPORT_SYMBOL(omapdss_output_set_device);
-
-int omapdss_output_unset_device(struct omap_dss_device *out)
-{
- int r;
-
- mutex_lock(&output_lock);
-
- if (!out->dst) {
- dev_err(out->dev,
- "output doesn't have a device connected to it\n");
- r = -EINVAL;
- goto err;
+ return -EINVAL;
}
- if (out->dst->state != OMAP_DSS_DISPLAY_DISABLED) {
- dev_err(out->dev,
- "device %s is not disabled, cannot unset device\n",
- out->dst->name);
- r = -EINVAL;
- goto err;
- }
-
- out->dst->src = NULL;
- out->dst = NULL;
-
- mutex_unlock(&output_lock);
-
- return 0;
-err:
- mutex_unlock(&output_lock);
-
- return r;
-}
-EXPORT_SYMBOL(omapdss_output_unset_device);
-
-int omapdss_register_output(struct omap_dss_device *out)
-{
- list_add_tail(&out->list, &output_list);
return 0;
}
-EXPORT_SYMBOL(omapdss_register_output);
-
-void omapdss_unregister_output(struct omap_dss_device *out)
-{
- list_del(&out->list);
-}
-EXPORT_SYMBOL(omapdss_unregister_output);
-
-bool omapdss_component_is_output(struct device_node *node)
-{
- struct omap_dss_device *out;
-
- list_for_each_entry(out, &output_list, list) {
- if (out->dev->of_node == node)
- return true;
- }
+EXPORT_SYMBOL(omapdss_output_validate);
- return false;
-}
-EXPORT_SYMBOL(omapdss_component_is_output);
-
-struct omap_dss_device *omap_dss_get_output(enum omap_dss_output_id id)
-{
- struct omap_dss_device *out;
-
- list_for_each_entry(out, &output_list, list) {
- if (out->id == id)
- return out;
- }
-
- return NULL;
-}
-EXPORT_SYMBOL(omap_dss_get_output);
-
-struct omap_dss_device *omap_dss_find_output_by_port_node(struct device_node *port)
-{
- struct device_node *src_node;
- struct omap_dss_device *out;
- u32 reg;
-
- src_node = dss_of_port_get_parent_device(port);
- if (!src_node)
- return NULL;
-
- reg = dss_of_port_get_port_number(port);
-
- list_for_each_entry(out, &output_list, list) {
- if (out->dev->of_node == src_node && out->port_num == reg) {
- of_node_put(src_node);
- return omap_dss_get_device(out);
- }
- }
-
- of_node_put(src_node);
-
- return NULL;
-}
-
-struct omap_dss_device *omapdss_find_output_from_display(struct omap_dss_device *dssdev)
-{
- while (dssdev->src)
- dssdev = dssdev->src;
-
- if (dssdev->id != 0)
- return omap_dss_get_device(dssdev);
-
- return NULL;
-}
-EXPORT_SYMBOL(omapdss_find_output_from_display);
-
-static const struct dss_mgr_ops *dss_mgr_ops;
-static struct omap_drm_private *dss_mgr_ops_priv;
-
-int dss_install_mgr_ops(const struct dss_mgr_ops *mgr_ops,
+int dss_install_mgr_ops(struct dss_device *dss,
+ const struct dss_mgr_ops *mgr_ops,
struct omap_drm_private *priv)
{
- if (dss_mgr_ops)
+ if (dss->mgr_ops)
return -EBUSY;
- dss_mgr_ops = mgr_ops;
- dss_mgr_ops_priv = priv;
+ dss->mgr_ops = mgr_ops;
+ dss->mgr_ops_priv = priv;
return 0;
}
EXPORT_SYMBOL(dss_install_mgr_ops);
-void dss_uninstall_mgr_ops(void)
+void dss_uninstall_mgr_ops(struct dss_device *dss)
{
- dss_mgr_ops = NULL;
- dss_mgr_ops_priv = NULL;
+ dss->mgr_ops = NULL;
+ dss->mgr_ops_priv = NULL;
}
EXPORT_SYMBOL(dss_uninstall_mgr_ops);
-int dss_mgr_connect(struct omap_dss_device *dssdev, struct omap_dss_device *dst)
-{
- return dss_mgr_ops->connect(dss_mgr_ops_priv,
- dssdev->dispc_channel, dst);
-}
-EXPORT_SYMBOL(dss_mgr_connect);
-
-void dss_mgr_disconnect(struct omap_dss_device *dssdev,
- struct omap_dss_device *dst)
-{
- dss_mgr_ops->disconnect(dss_mgr_ops_priv, dssdev->dispc_channel, dst);
-}
-EXPORT_SYMBOL(dss_mgr_disconnect);
-
void dss_mgr_set_timings(struct omap_dss_device *dssdev,
const struct videomode *vm)
{
- dss_mgr_ops->set_timings(dss_mgr_ops_priv, dssdev->dispc_channel, vm);
+ dssdev->dss->mgr_ops->set_timings(dssdev->dss->mgr_ops_priv,
+ dssdev->dispc_channel, vm);
}
EXPORT_SYMBOL(dss_mgr_set_timings);
void dss_mgr_set_lcd_config(struct omap_dss_device *dssdev,
const struct dss_lcd_mgr_config *config)
{
- dss_mgr_ops->set_lcd_config(dss_mgr_ops_priv,
- dssdev->dispc_channel, config);
+ dssdev->dss->mgr_ops->set_lcd_config(dssdev->dss->mgr_ops_priv,
+ dssdev->dispc_channel, config);
}
EXPORT_SYMBOL(dss_mgr_set_lcd_config);
int dss_mgr_enable(struct omap_dss_device *dssdev)
{
- return dss_mgr_ops->enable(dss_mgr_ops_priv, dssdev->dispc_channel);
+ return dssdev->dss->mgr_ops->enable(dssdev->dss->mgr_ops_priv,
+ dssdev->dispc_channel);
}
EXPORT_SYMBOL(dss_mgr_enable);
void dss_mgr_disable(struct omap_dss_device *dssdev)
{
- dss_mgr_ops->disable(dss_mgr_ops_priv, dssdev->dispc_channel);
+ dssdev->dss->mgr_ops->disable(dssdev->dss->mgr_ops_priv,
+ dssdev->dispc_channel);
}
EXPORT_SYMBOL(dss_mgr_disable);
void dss_mgr_start_update(struct omap_dss_device *dssdev)
{
- dss_mgr_ops->start_update(dss_mgr_ops_priv, dssdev->dispc_channel);
+ dssdev->dss->mgr_ops->start_update(dssdev->dss->mgr_ops_priv,
+ dssdev->dispc_channel);
}
EXPORT_SYMBOL(dss_mgr_start_update);
int dss_mgr_register_framedone_handler(struct omap_dss_device *dssdev,
void (*handler)(void *), void *data)
{
- return dss_mgr_ops->register_framedone_handler(dss_mgr_ops_priv,
- dssdev->dispc_channel,
- handler, data);
+ struct dss_device *dss = dssdev->dss;
+
+ return dss->mgr_ops->register_framedone_handler(dss->mgr_ops_priv,
+ dssdev->dispc_channel,
+ handler, data);
}
EXPORT_SYMBOL(dss_mgr_register_framedone_handler);
void dss_mgr_unregister_framedone_handler(struct omap_dss_device *dssdev,
void (*handler)(void *), void *data)
{
- dss_mgr_ops->unregister_framedone_handler(dss_mgr_ops_priv,
- dssdev->dispc_channel,
- handler, data);
+ struct dss_device *dss = dssdev->dss;
+
+ dss->mgr_ops->unregister_framedone_handler(dss->mgr_ops_priv,
+ dssdev->dispc_channel,
+ handler, data);
}
EXPORT_SYMBOL(dss_mgr_unregister_framedone_handler);
diff --git a/drivers/gpu/drm/omapdrm/dss/sdi.c b/drivers/gpu/drm/omapdrm/dss/sdi.c
index 69c3b7a3d5c7..b2fe2387037a 100644
--- a/drivers/gpu/drm/omapdrm/dss/sdi.c
+++ b/drivers/gpu/drm/omapdrm/dss/sdi.c
@@ -132,10 +132,8 @@ static void sdi_config_lcd_manager(struct sdi_device *sdi)
static int sdi_display_enable(struct omap_dss_device *dssdev)
{
struct sdi_device *sdi = dssdev_to_sdi(dssdev);
- struct videomode *vm = &sdi->vm;
- unsigned long fck;
struct dispc_clock_info dispc_cinfo;
- unsigned long pck;
+ unsigned long fck;
int r;
if (!sdi->output.dispc_channel_connected) {
@@ -151,27 +149,12 @@ static int sdi_display_enable(struct omap_dss_device *dssdev)
if (r)
goto err_get_dispc;
- /* 15.5.9.1.2 */
- vm->flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE | DISPLAY_FLAGS_SYNC_POSEDGE;
-
- r = sdi_calc_clock_div(sdi, vm->pixelclock, &fck, &dispc_cinfo);
+ r = sdi_calc_clock_div(sdi, sdi->vm.pixelclock, &fck, &dispc_cinfo);
if (r)
goto err_calc_clock_div;
sdi->mgr_config.clock_info = dispc_cinfo;
- pck = fck / dispc_cinfo.lck_div / dispc_cinfo.pck_div;
-
- if (pck != vm->pixelclock) {
- DSSWARN("Could not find exact pixel clock. Requested %lu Hz, got %lu Hz\n",
- vm->pixelclock, pck);
-
- vm->pixelclock = pck;
- }
-
-
- dss_mgr_set_timings(&sdi->output, vm);
-
r = dss_set_fck_rate(sdi->dss, fck);
if (r)
goto err_set_dss_clock_div;
@@ -230,96 +213,63 @@ static void sdi_display_disable(struct omap_dss_device *dssdev)
}
static void sdi_set_timings(struct omap_dss_device *dssdev,
- struct videomode *vm)
+ const struct videomode *vm)
{
struct sdi_device *sdi = dssdev_to_sdi(dssdev);
sdi->vm = *vm;
}
-static void sdi_get_timings(struct omap_dss_device *dssdev,
- struct videomode *vm)
-{
- struct sdi_device *sdi = dssdev_to_sdi(dssdev);
-
- *vm = sdi->vm;
-}
-
static int sdi_check_timings(struct omap_dss_device *dssdev,
struct videomode *vm)
{
struct sdi_device *sdi = dssdev_to_sdi(dssdev);
- enum omap_channel channel = dssdev->dispc_channel;
-
- if (!dispc_mgr_timings_ok(sdi->dss->dispc, channel, vm))
- return -EINVAL;
+ struct dispc_clock_info dispc_cinfo;
+ unsigned long fck;
+ unsigned long pck;
+ int r;
if (vm->pixelclock == 0)
return -EINVAL;
- return 0;
-}
+ r = sdi_calc_clock_div(sdi, vm->pixelclock, &fck, &dispc_cinfo);
+ if (r)
+ return r;
-static int sdi_init_regulator(struct sdi_device *sdi)
-{
- struct regulator *vdds_sdi;
+ pck = fck / dispc_cinfo.lck_div / dispc_cinfo.pck_div;
- if (sdi->vdds_sdi_reg)
- return 0;
+ if (pck != vm->pixelclock) {
+ DSSWARN("Pixel clock adjusted from %lu Hz to %lu Hz\n",
+ vm->pixelclock, pck);
- vdds_sdi = devm_regulator_get(&sdi->pdev->dev, "vdds_sdi");
- if (IS_ERR(vdds_sdi)) {
- if (PTR_ERR(vdds_sdi) != -EPROBE_DEFER)
- DSSERR("can't get VDDS_SDI regulator\n");
- return PTR_ERR(vdds_sdi);
+ vm->pixelclock = pck;
}
- sdi->vdds_sdi_reg = vdds_sdi;
-
return 0;
}
-static int sdi_connect(struct omap_dss_device *dssdev,
- struct omap_dss_device *dst)
+static int sdi_connect(struct omap_dss_device *src,
+ struct omap_dss_device *dst)
{
- struct sdi_device *sdi = dssdev_to_sdi(dssdev);
int r;
- r = sdi_init_regulator(sdi);
+ r = omapdss_device_connect(dst->dss, dst, dst->next);
if (r)
return r;
- r = dss_mgr_connect(&sdi->output, dssdev);
- if (r)
- return r;
-
- r = omapdss_output_set_device(dssdev, dst);
- if (r) {
- DSSERR("failed to connect output to new device: %s\n",
- dst->name);
- dss_mgr_disconnect(&sdi->output, dssdev);
- return r;
- }
-
+ dst->dispc_channel_connected = true;
return 0;
}
-static void sdi_disconnect(struct omap_dss_device *dssdev,
- struct omap_dss_device *dst)
+static void sdi_disconnect(struct omap_dss_device *src,
+ struct omap_dss_device *dst)
{
- struct sdi_device *sdi = dssdev_to_sdi(dssdev);
+ dst->dispc_channel_connected = false;
- WARN_ON(dst != dssdev->dst);
-
- if (dst != dssdev->dst)
- return;
-
- omapdss_output_unset_device(dssdev);
-
- dss_mgr_disconnect(&sdi->output, dssdev);
+ omapdss_device_disconnect(dst, dst->next);
}
-static const struct omapdss_sdi_ops sdi_ops = {
+static const struct omap_dss_device_ops sdi_ops = {
.connect = sdi_connect,
.disconnect = sdi_disconnect,
@@ -328,12 +278,12 @@ static const struct omapdss_sdi_ops sdi_ops = {
.check_timings = sdi_check_timings,
.set_timings = sdi_set_timings,
- .get_timings = sdi_get_timings,
};
-static void sdi_init_output(struct sdi_device *sdi)
+static int sdi_init_output(struct sdi_device *sdi)
{
struct omap_dss_device *out = &sdi->output;
+ int r;
out->dev = &sdi->pdev->dev;
out->id = OMAP_DSS_OUTPUT_SDI;
@@ -341,16 +291,36 @@ static void sdi_init_output(struct sdi_device *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->port_num = 1;
- out->ops.sdi = &sdi_ops;
+ 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);
+ }
- omapdss_register_output(out);
+ r = omapdss_output_validate(out);
+ if (r) {
+ omapdss_device_put(out->next);
+ out->next = NULL;
+ return r;
+ }
+
+ omapdss_device_register(out);
+
+ return 0;
}
static void sdi_uninit_output(struct sdi_device *sdi)
{
- omapdss_unregister_output(&sdi->output);
+ if (sdi->output.next)
+ omapdss_device_put(sdi->output.next);
+ omapdss_device_unregister(&sdi->output);
}
int sdi_init_port(struct dss_device *dss, struct platform_device *pdev,
@@ -372,25 +342,32 @@ int sdi_init_port(struct dss_device *dss, struct platform_device *pdev,
}
r = of_property_read_u32(ep, "datapairs", &datapairs);
+ of_node_put(ep);
if (r) {
DSSERR("failed to parse datapairs\n");
- goto err_datapairs;
+ goto err_free;
}
sdi->datapairs = datapairs;
sdi->dss = dss;
- of_node_put(ep);
-
sdi->pdev = pdev;
port->data = sdi;
- sdi_init_output(sdi);
+ sdi->vdds_sdi_reg = devm_regulator_get(&pdev->dev, "vdds_sdi");
+ if (IS_ERR(sdi->vdds_sdi_reg)) {
+ r = PTR_ERR(sdi->vdds_sdi_reg);
+ if (r != -EPROBE_DEFER)
+ DSSERR("can't get VDDS_SDI regulator\n");
+ goto err_free;
+ }
+
+ r = sdi_init_output(sdi);
+ if (r)
+ goto err_free;
return 0;
-err_datapairs:
- of_node_put(ep);
err_free:
kfree(sdi);
diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c
index ac01907dcc34..ff0b18c8e4ac 100644
--- a/drivers/gpu/drm/omapdrm/dss/venc.c
+++ b/drivers/gpu/drm/omapdrm/dss/venc.c
@@ -452,7 +452,7 @@ static void venc_runtime_put(struct venc_device *venc)
WARN_ON(r < 0 && r != -ENOSYS);
}
-static const struct venc_config *venc_timings_to_config(struct videomode *vm)
+static const struct venc_config *venc_timings_to_config(const struct videomode *vm)
{
switch (venc_get_videomode(vm)) {
default:
@@ -491,8 +491,6 @@ static int venc_power_on(struct venc_device *venc)
venc_write_reg(venc, VENC_OUTPUT_CONTROL, l);
- dss_mgr_set_timings(&venc->output, &venc->vm);
-
r = regulator_enable(venc->vdda_dac_reg);
if (r)
goto err1;
@@ -568,32 +566,30 @@ static void venc_display_disable(struct omap_dss_device *dssdev)
mutex_unlock(&venc->venc_lock);
}
-static void venc_set_timings(struct omap_dss_device *dssdev,
+static void venc_get_timings(struct omap_dss_device *dssdev,
struct videomode *vm)
{
struct venc_device *venc = dssdev_to_venc(dssdev);
- struct videomode actual_vm;
+
+ mutex_lock(&venc->venc_lock);
+ *vm = venc->vm;
+ mutex_unlock(&venc->venc_lock);
+}
+
+static void venc_set_timings(struct omap_dss_device *dssdev,
+ const struct videomode *vm)
+{
+ struct venc_device *venc = dssdev_to_venc(dssdev);
DSSDBG("venc_set_timings\n");
mutex_lock(&venc->venc_lock);
- switch (venc_get_videomode(vm)) {
- default:
- WARN_ON_ONCE(1);
- case VENC_MODE_PAL:
- actual_vm = omap_dss_pal_vm;
- break;
- case VENC_MODE_NTSC:
- actual_vm = omap_dss_ntsc_vm;
- break;
- }
-
/* Reset WSS data when the TV standard changes. */
- if (memcmp(&venc->vm, &actual_vm, sizeof(actual_vm)))
+ if (memcmp(&venc->vm, vm, sizeof(*vm)))
venc->wss_data = 0;
- venc->vm = actual_vm;
+ venc->vm = *vm;
dispc_set_tv_pclk(venc->dss->dispc, 13500000);
@@ -607,80 +603,16 @@ static int venc_check_timings(struct omap_dss_device *dssdev,
switch (venc_get_videomode(vm)) {
case VENC_MODE_PAL:
- case VENC_MODE_NTSC:
+ *vm = omap_dss_pal_vm;
return 0;
- default:
- return -EINVAL;
- }
-}
-
-static void venc_get_timings(struct omap_dss_device *dssdev,
- struct videomode *vm)
-{
- struct venc_device *venc = dssdev_to_venc(dssdev);
-
- mutex_lock(&venc->venc_lock);
-
- *vm = venc->vm;
-
- mutex_unlock(&venc->venc_lock);
-}
-
-static u32 venc_get_wss(struct omap_dss_device *dssdev)
-{
- struct venc_device *venc = dssdev_to_venc(dssdev);
-
- /* Invert due to VENC_L21_WC_CTL:INV=1 */
- return (venc->wss_data >> 8) ^ 0xfffff;
-}
-
-static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
-{
- struct venc_device *venc = dssdev_to_venc(dssdev);
- const struct venc_config *config;
- int r;
- DSSDBG("venc_set_wss\n");
-
- mutex_lock(&venc->venc_lock);
-
- config = venc_timings_to_config(&venc->vm);
-
- /* Invert due to VENC_L21_WC_CTL:INV=1 */
- venc->wss_data = (wss ^ 0xfffff) << 8;
-
- r = venc_runtime_get(venc);
- if (r)
- goto err;
-
- venc_write_reg(venc, VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data |
- venc->wss_data);
-
- venc_runtime_put(venc);
-
-err:
- mutex_unlock(&venc->venc_lock);
-
- return r;
-}
-
-static int venc_init_regulator(struct venc_device *venc)
-{
- struct regulator *vdda_dac;
-
- if (venc->vdda_dac_reg != NULL)
+ case VENC_MODE_NTSC:
+ *vm = omap_dss_ntsc_vm;
return 0;
- vdda_dac = devm_regulator_get(&venc->pdev->dev, "vdda");
- if (IS_ERR(vdda_dac)) {
- if (PTR_ERR(vdda_dac) != -EPROBE_DEFER)
- DSSERR("can't get VDDA_DAC regulator\n");
- return PTR_ERR(vdda_dac);
+ default:
+ return -EINVAL;
}
-
- venc->vdda_dac_reg = vdda_dac;
-
- return 0;
}
static int venc_dump_regs(struct seq_file *s, void *p)
@@ -760,47 +692,28 @@ static int venc_get_clocks(struct venc_device *venc)
return 0;
}
-static int venc_connect(struct omap_dss_device *dssdev,
- struct omap_dss_device *dst)
+static int venc_connect(struct omap_dss_device *src,
+ struct omap_dss_device *dst)
{
- struct venc_device *venc = dssdev_to_venc(dssdev);
int r;
- r = venc_init_regulator(venc);
- if (r)
- return r;
-
- r = dss_mgr_connect(&venc->output, dssdev);
+ r = omapdss_device_connect(dst->dss, dst, dst->next);
if (r)
return r;
- r = omapdss_output_set_device(dssdev, dst);
- if (r) {
- DSSERR("failed to connect output to new device: %s\n",
- dst->name);
- dss_mgr_disconnect(&venc->output, dssdev);
- return r;
- }
-
+ dst->dispc_channel_connected = true;
return 0;
}
-static void venc_disconnect(struct omap_dss_device *dssdev,
- struct omap_dss_device *dst)
+static void venc_disconnect(struct omap_dss_device *src,
+ struct omap_dss_device *dst)
{
- struct venc_device *venc = dssdev_to_venc(dssdev);
-
- WARN_ON(dst != dssdev->dst);
-
- if (dst != dssdev->dst)
- return;
-
- omapdss_output_unset_device(dssdev);
+ dst->dispc_channel_connected = false;
- dss_mgr_disconnect(&venc->output, dssdev);
+ omapdss_device_disconnect(dst, dst->next);
}
-static const struct omapdss_atv_ops venc_ops = {
+static const struct omap_dss_device_ops venc_ops = {
.connect = venc_connect,
.disconnect = venc_disconnect,
@@ -808,31 +721,92 @@ static const struct omapdss_atv_ops venc_ops = {
.disable = venc_display_disable,
.check_timings = venc_check_timings,
- .set_timings = venc_set_timings,
.get_timings = venc_get_timings,
+ .set_timings = venc_set_timings,
+};
+
+/* -----------------------------------------------------------------------------
+ * Component Bind & Unbind
+ */
- .set_wss = venc_set_wss,
- .get_wss = venc_get_wss,
+static int venc_bind(struct device *dev, struct device *master, void *data)
+{
+ struct dss_device *dss = dss_get_device(master);
+ struct venc_device *venc = dev_get_drvdata(dev);
+ u8 rev_id;
+ int r;
+
+ venc->dss = dss;
+
+ r = venc_runtime_get(venc);
+ if (r)
+ return r;
+
+ rev_id = (u8)(venc_read_reg(venc, VENC_REV_ID) & 0xff);
+ dev_dbg(dev, "OMAP VENC rev %d\n", rev_id);
+
+ venc_runtime_put(venc);
+
+ venc->debugfs = dss_debugfs_create_file(dss, "venc", venc_dump_regs,
+ venc);
+
+ return 0;
+}
+
+static void venc_unbind(struct device *dev, struct device *master, void *data)
+{
+ struct venc_device *venc = dev_get_drvdata(dev);
+
+ dss_debugfs_remove_file(venc->debugfs);
+}
+
+static const struct component_ops venc_component_ops = {
+ .bind = venc_bind,
+ .unbind = venc_unbind,
};
-static void venc_init_output(struct venc_device *venc)
+/* -----------------------------------------------------------------------------
+ * Probe & Remove, Suspend & Resume
+ */
+
+static int venc_init_output(struct venc_device *venc)
{
struct omap_dss_device *out = &venc->output;
+ int r;
out->dev = &venc->pdev->dev;
out->id = OMAP_DSS_OUTPUT_VENC;
out->output_type = OMAP_DISPLAY_TYPE_VENC;
out->name = "venc.0";
out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
- out->ops.atv = &venc_ops;
+ out->ops = &venc_ops;
out->owner = THIS_MODULE;
+ out->of_ports = BIT(0);
+
+ 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);
+ }
- omapdss_register_output(out);
+ r = omapdss_output_validate(out);
+ if (r) {
+ omapdss_device_put(out->next);
+ out->next = NULL;
+ return r;
+ }
+
+ omapdss_device_register(out);
+
+ return 0;
}
static void venc_uninit_output(struct venc_device *venc)
{
- omapdss_unregister_output(&venc->output);
+ if (venc->output.next)
+ omapdss_device_put(venc->output.next);
+ omapdss_device_unregister(&venc->output);
}
static int venc_probe_of(struct venc_device *venc)
@@ -878,19 +852,15 @@ err:
return r;
}
-/* VENC HW IP initialisation */
static const struct soc_device_attribute venc_soc_devices[] = {
{ .machine = "OMAP3[45]*" },
{ .machine = "AM35*" },
{ /* sentinel */ }
};
-static int venc_bind(struct device *dev, struct device *master, void *data)
+static int venc_probe(struct platform_device *pdev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct dss_device *dss = dss_get_device(master);
struct venc_device *venc;
- u8 rev_id;
struct resource *venc_mem;
int r;
@@ -899,8 +869,8 @@ static int venc_bind(struct device *dev, struct device *master, void *data)
return -ENOMEM;
venc->pdev = pdev;
- venc->dss = dss;
- dev_set_drvdata(dev, venc);
+
+ platform_set_drvdata(pdev, venc);
/* The OMAP34xx, OMAP35xx and AM35xx VENC require the TV DAC clock. */
if (soc_device_match(venc_soc_devices))
@@ -909,6 +879,7 @@ static int venc_bind(struct device *dev, struct device *master, void *data)
mutex_init(&venc->venc_lock);
venc->wss_data = 0;
+ venc->vm = omap_dss_pal_vm;
venc_mem = platform_get_resource(venc->pdev, IORESOURCE_MEM, 0);
venc->base = devm_ioremap_resource(&pdev->dev, venc_mem);
@@ -917,68 +888,54 @@ static int venc_bind(struct device *dev, struct device *master, void *data)
goto err_free;
}
+ venc->vdda_dac_reg = devm_regulator_get(&pdev->dev, "vdda");
+ if (IS_ERR(venc->vdda_dac_reg)) {
+ r = PTR_ERR(venc->vdda_dac_reg);
+ if (r != -EPROBE_DEFER)
+ DSSERR("can't get VDDA_DAC regulator\n");
+ goto err_free;
+ }
+
r = venc_get_clocks(venc);
if (r)
goto err_free;
- pm_runtime_enable(&pdev->dev);
-
- r = venc_runtime_get(venc);
+ r = venc_probe_of(venc);
if (r)
- goto err_runtime_get;
-
- rev_id = (u8)(venc_read_reg(venc, VENC_REV_ID) & 0xff);
- dev_dbg(&pdev->dev, "OMAP VENC rev %d\n", rev_id);
-
- venc_runtime_put(venc);
+ goto err_free;
- r = venc_probe_of(venc);
- if (r) {
- DSSERR("Invalid DT data\n");
- goto err_probe_of;
- }
+ pm_runtime_enable(&pdev->dev);
- venc->debugfs = dss_debugfs_create_file(dss, "venc", venc_dump_regs,
- venc);
+ r = venc_init_output(venc);
+ if (r)
+ goto err_pm_disable;
- venc_init_output(venc);
+ r = component_add(&pdev->dev, &venc_component_ops);
+ if (r)
+ goto err_uninit_output;
return 0;
-err_probe_of:
-err_runtime_get:
+err_uninit_output:
+ venc_uninit_output(venc);
+err_pm_disable:
pm_runtime_disable(&pdev->dev);
err_free:
kfree(venc);
return r;
}
-static void venc_unbind(struct device *dev, struct device *master, void *data)
+static int venc_remove(struct platform_device *pdev)
{
- struct venc_device *venc = dev_get_drvdata(dev);
+ struct venc_device *venc = platform_get_drvdata(pdev);
- dss_debugfs_remove_file(venc->debugfs);
+ component_del(&pdev->dev, &venc_component_ops);
venc_uninit_output(venc);
- pm_runtime_disable(dev);
+ pm_runtime_disable(&pdev->dev);
kfree(venc);
-}
-
-static const struct component_ops venc_component_ops = {
- .bind = venc_bind,
- .unbind = venc_unbind,
-};
-
-static int venc_probe(struct platform_device *pdev)
-{
- return component_add(&pdev->dev, &venc_component_ops);
-}
-
-static int venc_remove(struct platform_device *pdev)
-{
- component_del(&pdev->dev, &venc_component_ops);
return 0;
}
OpenPOWER on IntegriCloud