Commit c0ca7c38 authored by Tomi Valkeinen's avatar Tomi Valkeinen

Merge omapdss single-dssdev series

This series contains patches that change how omapdss's panel devices
(omap_dss_device) are initialized and registered. There are two patches that
change behaviour, the rest are just cleanups:

The patch "omap_dss_register_device() doesn't take display index" affects the
number for the "displayX" sysfs files. This hopefully doesn't affect the
userspace, as the number has never been a clear indication of what the
particular display is.

The patch "register only one display device per output" affects how panel
devices are created. Currently we support multiple panels per output, i.e. you
could have DVI and an LCD displays using the same DPI output, as long as the
DVI and LCD are not used at the same time.

This patch changes the omapdss driver to only register one display device per
output. If there are multiple displays for the output, either the first one is
picked or, if def_display has been defined in kernel parameters and the
def_display is one of the displays for this output, the def_display is picked.
See the patch for more information.

  OMAPDSS: alloc dssdevs dynamically
  OMAPDSS: cleanup dss_recheck_connections further
  OMAPDSS: cleanup dss_recheck_connections
  OMAPDSS: handle errors in dss_init_device
  OMAPDSS: explicitely initialize dssdev->channel for new displays
  OMAPDSS: register only one display device per output
  OMAPDSS: Add dss_get_default_display_name()
  OMAPDSS: omap_dss_register_device() doesn't take display index
parents 524d9f48 5274484b
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <linux/device.h> #include <linux/device.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/suspend.h> #include <linux/suspend.h>
#include <linux/slab.h>
#include <video/omapdss.h> #include <video/omapdss.h>
...@@ -57,6 +58,11 @@ bool dss_debug; ...@@ -57,6 +58,11 @@ bool dss_debug;
module_param_named(debug, dss_debug, bool, 0644); module_param_named(debug, dss_debug, bool, 0644);
#endif #endif
const char *dss_get_default_display_name(void)
{
return core.default_display_name;
}
/* REGULATORS */ /* REGULATORS */
struct regulator *dss_get_vdds_dsi(void) struct regulator *dss_get_vdds_dsi(void)
...@@ -347,17 +353,14 @@ static int dss_driver_probe(struct device *dev) ...@@ -347,17 +353,14 @@ static int dss_driver_probe(struct device *dev)
int r; int r;
struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver); struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver);
struct omap_dss_device *dssdev = to_dss_device(dev); struct omap_dss_device *dssdev = to_dss_device(dev);
bool force;
DSSDBG("driver_probe: dev %s/%s, drv %s\n", DSSDBG("driver_probe: dev %s/%s, drv %s\n",
dev_name(dev), dssdev->driver_name, dev_name(dev), dssdev->driver_name,
dssdrv->driver.name); dssdrv->driver.name);
dss_init_device(core.pdev, dssdev); r = dss_init_device(core.pdev, dssdev);
if (r)
force = core.default_display_name && return r;
strcmp(core.default_display_name, dssdev->name) == 0;
dss_recheck_connections(dssdev, force);
r = dssdrv->probe(dssdev); r = dssdrv->probe(dssdev);
...@@ -416,54 +419,44 @@ void omap_dss_unregister_driver(struct omap_dss_driver *dssdriver) ...@@ -416,54 +419,44 @@ void omap_dss_unregister_driver(struct omap_dss_driver *dssdriver)
EXPORT_SYMBOL(omap_dss_unregister_driver); EXPORT_SYMBOL(omap_dss_unregister_driver);
/* DEVICE */ /* DEVICE */
static void reset_device(struct device *dev, int check)
{
u8 *dev_p = (u8 *)dev;
u8 *dev_end = dev_p + sizeof(*dev);
void *saved_pdata;
saved_pdata = dev->platform_data;
if (check) {
/*
* Check if there is any other setting than platform_data
* in struct device; warn that these will be reset by our
* init.
*/
dev->platform_data = NULL;
while (dev_p < dev_end) {
if (*dev_p) {
WARN("%s: struct device fields will be "
"discarded\n",
__func__);
break;
}
dev_p++;
}
}
memset(dev, 0, sizeof(*dev));
dev->platform_data = saved_pdata;
}
static void omap_dss_dev_release(struct device *dev) static void omap_dss_dev_release(struct device *dev)
{ {
reset_device(dev, 0); struct omap_dss_device *dssdev = to_dss_device(dev);
kfree(dssdev);
} }
int omap_dss_register_device(struct omap_dss_device *dssdev, static int disp_num_counter;
struct device *parent, int disp_num)
struct omap_dss_device *dss_alloc_and_init_device(struct device *parent)
{ {
WARN_ON(!dssdev->driver_name); struct omap_dss_device *dssdev;
dssdev = kzalloc(sizeof(*dssdev), GFP_KERNEL);
if (!dssdev)
return NULL;
reset_device(&dssdev->dev, 1);
dssdev->dev.bus = &dss_bus_type; dssdev->dev.bus = &dss_bus_type;
dssdev->dev.parent = parent; dssdev->dev.parent = parent;
dssdev->dev.release = omap_dss_dev_release; dssdev->dev.release = omap_dss_dev_release;
dev_set_name(&dssdev->dev, "display%d", disp_num); dev_set_name(&dssdev->dev, "display%d", disp_num_counter++);
return device_register(&dssdev->dev);
device_initialize(&dssdev->dev);
return dssdev;
}
int dss_add_device(struct omap_dss_device *dssdev)
{
return device_add(&dssdev->dev);
}
void dss_put_device(struct omap_dss_device *dssdev)
{
put_device(&dssdev->dev);
} }
void omap_dss_unregister_device(struct omap_dss_device *dssdev) void dss_unregister_device(struct omap_dss_device *dssdev)
{ {
device_unregister(&dssdev->dev); device_unregister(&dssdev->dev);
} }
...@@ -471,15 +464,25 @@ void omap_dss_unregister_device(struct omap_dss_device *dssdev) ...@@ -471,15 +464,25 @@ void omap_dss_unregister_device(struct omap_dss_device *dssdev)
static int dss_unregister_dss_dev(struct device *dev, void *data) static int dss_unregister_dss_dev(struct device *dev, void *data)
{ {
struct omap_dss_device *dssdev = to_dss_device(dev); struct omap_dss_device *dssdev = to_dss_device(dev);
omap_dss_unregister_device(dssdev); dss_unregister_device(dssdev);
return 0; return 0;
} }
void omap_dss_unregister_child_devices(struct device *parent) void dss_unregister_child_devices(struct device *parent)
{ {
device_for_each_child(parent, NULL, dss_unregister_dss_dev); device_for_each_child(parent, NULL, dss_unregister_dss_dev);
} }
void dss_copy_device_pdata(struct omap_dss_device *dst,
const struct omap_dss_device *src)
{
u8 *d = (u8 *)dst;
u8 *s = (u8 *)src;
size_t dsize = sizeof(struct device);
memcpy(d + dsize, s + dsize, sizeof(struct omap_dss_device) - dsize);
}
/* BUS */ /* BUS */
static int __init omap_dss_bus_register(void) static int __init omap_dss_bus_register(void)
{ {
......
...@@ -320,26 +320,98 @@ void omapdss_default_get_timings(struct omap_dss_device *dssdev, ...@@ -320,26 +320,98 @@ void omapdss_default_get_timings(struct omap_dss_device *dssdev,
} }
EXPORT_SYMBOL(omapdss_default_get_timings); EXPORT_SYMBOL(omapdss_default_get_timings);
void dss_init_device(struct platform_device *pdev, /*
* Connect dssdev to a manager if the manager is free or if force is specified.
* Connect all overlays to that manager if they are free or if force is
* specified.
*/
static int dss_init_connections(struct omap_dss_device *dssdev, bool force)
{
struct omap_overlay_manager *mgr;
int i, r;
WARN_ON(dssdev->manager);
mgr = omap_dss_get_overlay_manager(dssdev->channel);
if (mgr->device && !force)
return 0;
if (mgr->device)
mgr->unset_device(mgr);
r = mgr->set_device(mgr, dssdev);
if (r) {
DSSERR("failed to set initial manager\n");
return r;
}
for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
struct omap_overlay *ovl = omap_dss_get_overlay(i);
if (!ovl->manager || force) {
if (ovl->manager)
ovl->unset_manager(ovl);
r = ovl->set_manager(ovl, mgr);
if (r) {
DSSERR("failed to set initial overlay\n");
return r;
}
}
}
return 0;
}
static void dss_uninit_connections(struct omap_dss_device *dssdev)
{
if (dssdev->manager)
dssdev->manager->unset_device(dssdev->manager);
}
int dss_init_device(struct platform_device *pdev,
struct omap_dss_device *dssdev) struct omap_dss_device *dssdev)
{ {
struct device_attribute *attr; struct device_attribute *attr;
int i; int i, r;
int r; const char *def_disp_name = dss_get_default_display_name();
bool force;
force = def_disp_name && strcmp(def_disp_name, dssdev->name) == 0;
dss_init_connections(dssdev, force);
/* create device sysfs files */ /* create device sysfs files */
i = 0; i = 0;
while ((attr = display_sysfs_attrs[i++]) != NULL) { while ((attr = display_sysfs_attrs[i++]) != NULL) {
r = device_create_file(&dssdev->dev, attr); r = device_create_file(&dssdev->dev, attr);
if (r) if (r) {
for (i = i - 2; i >= 0; i--) {
attr = display_sysfs_attrs[i];
device_remove_file(&dssdev->dev, attr);
}
dss_uninit_connections(dssdev);
DSSERR("failed to create sysfs file\n"); DSSERR("failed to create sysfs file\n");
return r;
}
} }
/* create display? sysfs links */ /* create display? sysfs links */
r = sysfs_create_link(&pdev->dev.kobj, &dssdev->dev.kobj, r = sysfs_create_link(&pdev->dev.kobj, &dssdev->dev.kobj,
dev_name(&dssdev->dev)); dev_name(&dssdev->dev));
if (r) if (r) {
while ((attr = display_sysfs_attrs[i++]) != NULL)
device_remove_file(&dssdev->dev, attr);
dss_uninit_connections(dssdev);
DSSERR("failed to create sysfs display link\n"); DSSERR("failed to create sysfs display link\n");
return r;
}
return 0;
} }
void dss_uninit_device(struct platform_device *pdev, void dss_uninit_device(struct platform_device *pdev,
...@@ -353,8 +425,7 @@ void dss_uninit_device(struct platform_device *pdev, ...@@ -353,8 +425,7 @@ void dss_uninit_device(struct platform_device *pdev,
while ((attr = display_sysfs_attrs[i++]) != NULL) while ((attr = display_sysfs_attrs[i++]) != NULL)
device_remove_file(&dssdev->dev, attr); device_remove_file(&dssdev->dev, attr);
if (dssdev->manager) dss_uninit_connections(dssdev);
dssdev->manager->unset_device(dssdev->manager);
} }
static int dss_suspend_device(struct device *dev, void *data) static int dss_suspend_device(struct device *dev, void *data)
......
...@@ -371,10 +371,14 @@ static int __init dpi_init_display(struct omap_dss_device *dssdev) ...@@ -371,10 +371,14 @@ static int __init dpi_init_display(struct omap_dss_device *dssdev)
return 0; return 0;
} }
static void __init dpi_probe_pdata(struct platform_device *pdev) static struct omap_dss_device * __init dpi_find_dssdev(struct platform_device *pdev)
{ {
struct omap_dss_board_info *pdata = pdev->dev.platform_data; struct omap_dss_board_info *pdata = pdev->dev.platform_data;
int i, r; const char *def_disp_name = dss_get_default_display_name();
struct omap_dss_device *def_dssdev;
int i;
def_dssdev = NULL;
for (i = 0; i < pdata->num_devices; ++i) { for (i = 0; i < pdata->num_devices; ++i) {
struct omap_dss_device *dssdev = pdata->devices[i]; struct omap_dss_device *dssdev = pdata->devices[i];
...@@ -382,16 +386,48 @@ static void __init dpi_probe_pdata(struct platform_device *pdev) ...@@ -382,16 +386,48 @@ static void __init dpi_probe_pdata(struct platform_device *pdev)
if (dssdev->type != OMAP_DISPLAY_TYPE_DPI) if (dssdev->type != OMAP_DISPLAY_TYPE_DPI)
continue; continue;
r = dpi_init_display(dssdev); if (def_dssdev == NULL)
if (r) { def_dssdev = dssdev;
DSSERR("device %s init failed: %d\n", dssdev->name, r);
continue; if (def_disp_name != NULL &&
strcmp(dssdev->name, def_disp_name) == 0) {
def_dssdev = dssdev;
break;
} }
}
r = omap_dss_register_device(dssdev, &pdev->dev, i); return def_dssdev;
if (r) }
DSSERR("device %s register failed: %d\n",
dssdev->name, r); static void __init dpi_probe_pdata(struct platform_device *dpidev)
{
struct omap_dss_device *plat_dssdev;
struct omap_dss_device *dssdev;
int r;
plat_dssdev = dpi_find_dssdev(dpidev);
if (!plat_dssdev)
return;
dssdev = dss_alloc_and_init_device(&dpidev->dev);
if (!dssdev)
return;
dss_copy_device_pdata(dssdev, plat_dssdev);
r = dpi_init_display(dssdev);
if (r) {
DSSERR("device %s init failed: %d\n", dssdev->name, r);
dss_put_device(dssdev);
return;
}
r = dss_add_device(dssdev);
if (r) {
DSSERR("device %s register failed: %d\n", dssdev->name, r);
dss_put_device(dssdev);
return;
} }
} }
...@@ -406,7 +442,7 @@ static int __init omap_dpi_probe(struct platform_device *pdev) ...@@ -406,7 +442,7 @@ static int __init omap_dpi_probe(struct platform_device *pdev)
static int __exit omap_dpi_remove(struct platform_device *pdev) static int __exit omap_dpi_remove(struct platform_device *pdev)
{ {
omap_dss_unregister_child_devices(&pdev->dev); dss_unregister_child_devices(&pdev->dev);
return 0; return 0;
} }
......
...@@ -5006,11 +5006,15 @@ static void dsi_put_clocks(struct platform_device *dsidev) ...@@ -5006,11 +5006,15 @@ static void dsi_put_clocks(struct platform_device *dsidev)
clk_put(dsi->sys_clk); clk_put(dsi->sys_clk);
} }
static void __init dsi_probe_pdata(struct platform_device *dsidev) static struct omap_dss_device * __init dsi_find_dssdev(struct platform_device *pdev)
{ {
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); struct omap_dss_board_info *pdata = pdev->dev.platform_data;
struct omap_dss_board_info *pdata = dsidev->dev.platform_data; struct dsi_data *dsi = dsi_get_dsidrv_data(pdev);
int i, r; const char *def_disp_name = dss_get_default_display_name();
struct omap_dss_device *def_dssdev;
int i;
def_dssdev = NULL;
for (i = 0; i < pdata->num_devices; ++i) { for (i = 0; i < pdata->num_devices; ++i) {
struct omap_dss_device *dssdev = pdata->devices[i]; struct omap_dss_device *dssdev = pdata->devices[i];
...@@ -5021,16 +5025,48 @@ static void __init dsi_probe_pdata(struct platform_device *dsidev) ...@@ -5021,16 +5025,48 @@ static void __init dsi_probe_pdata(struct platform_device *dsidev)
if (dssdev->phy.dsi.module != dsi->module_id) if (dssdev->phy.dsi.module != dsi->module_id)
continue; continue;
r = dsi_init_display(dssdev); if (def_dssdev == NULL)
if (r) { def_dssdev = dssdev;
DSSERR("device %s init failed: %d\n", dssdev->name, r);
continue; if (def_disp_name != NULL &&
strcmp(dssdev->name, def_disp_name) == 0) {
def_dssdev = dssdev;
break;
} }
}
r = omap_dss_register_device(dssdev, &dsidev->dev, i); return def_dssdev;
if (r) }
DSSERR("device %s register failed: %d\n",
dssdev->name, r); static void __init dsi_probe_pdata(struct platform_device *dsidev)
{
struct omap_dss_device *plat_dssdev;
struct omap_dss_device *dssdev;
int r;
plat_dssdev = dsi_find_dssdev(dsidev);
if (!plat_dssdev)
return;
dssdev = dss_alloc_and_init_device(&dsidev->dev);
if (!dssdev)
return;
dss_copy_device_pdata(dssdev, plat_dssdev);
r = dsi_init_display(dssdev);
if (r) {
DSSERR("device %s init failed: %d\n", dssdev->name, r);
dss_put_device(dssdev);
return;
}
r = dss_add_device(dssdev);
if (r) {
DSSERR("device %s register failed: %d\n", dssdev->name, r);
dss_put_device(dssdev);
return;
} }
} }
...@@ -5157,7 +5193,7 @@ static int __exit omap_dsihw_remove(struct platform_device *dsidev) ...@@ -5157,7 +5193,7 @@ static int __exit omap_dsihw_remove(struct platform_device *dsidev)
WARN_ON(dsi->scp_clk_refcount > 0); WARN_ON(dsi->scp_clk_refcount > 0);
omap_dss_unregister_child_devices(&dsidev->dev); dss_unregister_child_devices(&dsidev->dev);
pm_runtime_disable(&dsidev->dev); pm_runtime_disable(&dsidev->dev);
......
...@@ -175,6 +175,7 @@ struct seq_file; ...@@ -175,6 +175,7 @@ struct seq_file;
struct platform_device; struct platform_device;
/* core */ /* core */
const char *dss_get_default_display_name(void);
struct bus_type *dss_get_bus(void); struct bus_type *dss_get_bus(void);
struct regulator *dss_get_vdds_dsi(void); struct regulator *dss_get_vdds_dsi(void);
struct regulator *dss_get_vdds_sdi(void); struct regulator *dss_get_vdds_sdi(void);
...@@ -184,10 +185,13 @@ void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask); ...@@ -184,10 +185,13 @@ void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask);
int dss_set_min_bus_tput(struct device *dev, unsigned long tput); int dss_set_min_bus_tput(struct device *dev, unsigned long tput);
int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *)); int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *));
int omap_dss_register_device(struct omap_dss_device *dssdev, struct omap_dss_device *dss_alloc_and_init_device(struct device *parent);
struct device *parent, int disp_num); int dss_add_device(struct omap_dss_device *dssdev);
void omap_dss_unregister_device(struct omap_dss_device *dssdev); void dss_unregister_device(struct omap_dss_device *dssdev);
void omap_dss_unregister_child_devices(struct device *parent); void dss_unregister_child_devices(struct device *parent);
void dss_put_device(struct omap_dss_device *dssdev);
void dss_copy_device_pdata(struct omap_dss_device *dst,
const struct omap_dss_device *src);
/* apply */ /* apply */
void dss_apply_init(void); void dss_apply_init(void);
...@@ -227,7 +231,7 @@ int dss_suspend_all_devices(void); ...@@ -227,7 +231,7 @@ int dss_suspend_all_devices(void);
int dss_resume_all_devices(void); int dss_resume_all_devices(void);
void dss_disable_all_devices(void); void dss_disable_all_devices(void);
void dss_init_device(struct platform_device *pdev, int dss_init_device(struct platform_device *pdev,
struct omap_dss_device *dssdev); struct omap_dss_device *dssdev);
void dss_uninit_device(struct platform_device *pdev, void dss_uninit_device(struct platform_device *pdev,
struct omap_dss_device *dssdev); struct omap_dss_device *dssdev);
...@@ -262,7 +266,6 @@ void dss_manager_kobj_uninit(struct omap_overlay_manager *mgr); ...@@ -262,7 +266,6 @@ void dss_manager_kobj_uninit(struct omap_overlay_manager *mgr);
void dss_init_overlays(struct platform_device *pdev); void dss_init_overlays(struct platform_device *pdev);
void dss_uninit_overlays(struct platform_device *pdev); void dss_uninit_overlays(struct platform_device *pdev);
void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr); void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr);
void dss_recheck_connections(struct omap_dss_device *dssdev, bool force);
int dss_ovl_simple_check(struct omap_overlay *ovl, int dss_ovl_simple_check(struct omap_overlay *ovl,
const struct omap_overlay_info *info); const struct omap_overlay_info *info);
int dss_ovl_check(struct omap_overlay *ovl, struct omap_overlay_info *info, int dss_ovl_check(struct omap_overlay *ovl, struct omap_overlay_info *info,
......
...@@ -901,32 +901,72 @@ int hdmi_audio_config(struct omap_dss_audio *audio) ...@@ -901,32 +901,72 @@ int hdmi_audio_config(struct omap_dss_audio *audio)
#endif #endif
static void __init hdmi_probe_pdata(struct platform_device *pdev) static struct omap_dss_device * __init hdmi_find_dssdev(struct platform_device *pdev)
{ {
struct omap_dss_board_info *pdata = pdev->dev.platform_data; struct omap_dss_board_info *pdata = pdev->dev.platform_data;
int r, i; const char *def_disp_name = dss_get_default_display_name();
struct omap_dss_device *def_dssdev;
int i;
def_dssdev = NULL;
for (i = 0; i < pdata->num_devices; ++i) { for (i = 0; i < pdata->num_devices; ++i) {
struct omap_dss_device *dssdev = pdata->devices[i]; struct omap_dss_device *dssdev = pdata->devices[i];
struct omap_dss_hdmi_data *priv = dssdev->data;
if (dssdev->type != OMAP_DISPLAY_TYPE_HDMI) if (dssdev->type != OMAP_DISPLAY_TYPE_HDMI)
continue; continue;
hdmi.ct_cp_hpd_gpio = priv->ct_cp_hpd_gpio; if (def_dssdev == NULL)
hdmi.ls_oe_gpio = priv->ls_oe_gpio; def_dssdev = dssdev;
hdmi.hpd_gpio = priv->hpd_gpio;
r = hdmi_init_display(dssdev); if (def_disp_name != NULL &&
if (r) { strcmp(dssdev->name, def_disp_name) == 0) {
DSSERR("device %s init failed: %d\n", dssdev->name, r); def_dssdev = dssdev;
continue; break;
} }
}
return def_dssdev;
}
r = omap_dss_register_device(dssdev, &pdev->dev, i); static void __init hdmi_probe_pdata(struct platform_device *pdev)
if (r) {
DSSERR("device %s register failed: %d\n", struct omap_dss_device *plat_dssdev;
dssdev->name, r); struct omap_dss_device *dssdev;
struct omap_dss_hdmi_data *priv;
int r;
plat_dssdev = hdmi_find_dssdev(pdev);
if (!plat_dssdev)
return;
dssdev = dss_alloc_and_init_device(&pdev->dev);
if (!dssdev)
return;
dss_copy_device_pdata(dssdev, plat_dssdev);
priv = dssdev->data;
hdmi.ct_cp_hpd_gpio = priv->ct_cp_hpd_gpio;
hdmi.ls_oe_gpio = priv->ls_oe_gpio;
hdmi.hpd_gpio = priv->hpd_gpio;
dssdev->channel = OMAP_DSS_CHANNEL_DIGIT;
r = hdmi_init_display(dssdev);
if (r) {
DSSERR("device %s init failed: %d\n", dssdev->name, r);
dss_put_device(dssdev);
return;
}
r = dss_add_device(dssdev);
if (r) {
DSSERR("device %s register failed: %d\n", dssdev->name, r);
dss_put_device(dssdev);
return;
} }
} }
...@@ -989,7 +1029,7 @@ static int __exit omapdss_hdmihw_remove(struct platform_device *pdev) ...@@ -989,7 +1029,7 @@ static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
{ {
device_for_each_child(&pdev->dev, NULL, hdmi_remove_child); device_for_each_child(&pdev->dev, NULL, hdmi_remove_child);
omap_dss_unregister_child_devices(&pdev->dev); dss_unregister_child_devices(&pdev->dev);
hdmi_panel_exit(); hdmi_panel_exit();
......
...@@ -105,75 +105,6 @@ void dss_init_overlays(struct platform_device *pdev) ...@@ -105,75 +105,6 @@ void dss_init_overlays(struct platform_device *pdev)
} }
} }
/* connect overlays to the new device, if not already connected. if force
* selected, connect always. */
void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
{
int i;
struct omap_overlay_manager *lcd_mgr;
struct omap_overlay_manager *tv_mgr;
struct omap_overlay_manager *lcd2_mgr = NULL;
struct omap_overlay_manager *lcd3_mgr = NULL;
struct omap_overlay_manager *mgr = NULL;
lcd_mgr = omap_dss_get_overlay_manager(OMAP_DSS_CHANNEL_LCD);
tv_mgr = omap_dss_get_overlay_manager(OMAP_DSS_CHANNEL_DIGIT);
if (dss_has_feature(FEAT_MGR_LCD3))
lcd3_mgr = omap_dss_get_overlay_manager(OMAP_DSS_CHANNEL_LCD3);
if (dss_has_feature(FEAT_MGR_LCD2))
lcd2_mgr = omap_dss_get_overlay_manager(OMAP_DSS_CHANNEL_LCD2);
if (dssdev->channel == OMAP_DSS_CHANNEL_LCD3) {
if (!lcd3_mgr->device || force) {
if (lcd3_mgr->device)
lcd3_mgr->unset_device(lcd3_mgr);
lcd3_mgr->set_device(lcd3_mgr, dssdev);
mgr = lcd3_mgr;
}
} else if (dssdev->channel == OMAP_DSS_CHANNEL_LCD2) {
if (!lcd2_mgr->device || force) {
if (lcd2_mgr->device)
lcd2_mgr->unset_device(lcd2_mgr);
lcd2_mgr->set_device(lcd2_mgr, dssdev);
mgr = lcd2_mgr;
}
} else if (dssdev->type != OMAP_DISPLAY_TYPE_VENC
&& dssdev->type != OMAP_DISPLAY_TYPE_HDMI) {
if (!lcd_mgr->device || force) {
if (lcd_mgr->device)
lcd_mgr->unset_device(lcd_mgr);
lcd_mgr->set_device(lcd_mgr, dssdev);
mgr = lcd_mgr;
}
}
if (dssdev->type == OMAP_DISPLAY_TYPE_VENC
|| dssdev->type == OMAP_DISPLAY_TYPE_HDMI) {
if (!tv_mgr->device || force) {
if (tv_mgr->device)
tv_mgr->unset_device(tv_mgr);
tv_mgr->set_device(tv_mgr, dssdev);
mgr = tv_mgr;
}
}
if (mgr) {
dispc_runtime_get();
for (i = 0; i < dss_feat_get_num_ovls(); i++) {
struct omap_overlay *ovl;
ovl = omap_dss_get_overlay(i);
if (!ovl->manager || force) {
if (ovl->manager)
ovl->unset_manager(ovl);
ovl->set_manager(ovl, mgr);
}
}
dispc_runtime_put();
}
}
void dss_uninit_overlays(struct platform_device *pdev) void dss_uninit_overlays(struct platform_device *pdev)
{ {
int i; int i;
......
...@@ -942,10 +942,14 @@ static int __init rfbi_init_display(struct omap_dss_device *dssdev) ...@@ -942,10 +942,14 @@ static int __init rfbi_init_display(struct omap_dss_device *dssdev)
return 0; return 0;
} }
static void __init rfbi_probe_pdata(struct platform_device *pdev) static struct omap_dss_device * __init rfbi_find_dssdev(struct platform_device *pdev)
{ {
struct omap_dss_board_info *pdata = pdev->dev.platform_data; struct omap_dss_board_info *pdata = pdev->dev.platform_data;
int i, r; const char *def_disp_name = dss_get_default_display_name();
struct omap_dss_device *def_dssdev;
int i;
def_dssdev = NULL;
for (i = 0; i < pdata->num_devices; ++i) { for (i = 0; i < pdata->num_devices; ++i) {
struct omap_dss_device *dssdev = pdata->devices[i]; struct omap_dss_device *dssdev = pdata->devices[i];
...@@ -953,16 +957,48 @@ static void __init rfbi_probe_pdata(struct platform_device *pdev) ...@@ -953,16 +957,48 @@ static void __init rfbi_probe_pdata(struct platform_device *pdev)
if (dssdev->type != OMAP_DISPLAY_TYPE_DBI) if (dssdev->type != OMAP_DISPLAY_TYPE_DBI)
continue; continue;
r = rfbi_init_display(dssdev); if (def_dssdev == NULL)
if (r) { def_dssdev = dssdev;
DSSERR("device %s init failed: %d\n", dssdev->name, r);
continue; if (def_disp_name != NULL &&
strcmp(dssdev->name, def_disp_name) == 0) {
def_dssdev = dssdev;
break;
} }
}
return def_dssdev;
}
static void __init rfbi_probe_pdata(struct platform_device *rfbidev)
{
struct omap_dss_device *plat_dssdev;
struct omap_dss_device *dssdev;
int r;
plat_dssdev = rfbi_find_dssdev(rfbidev);
r = omap_dss_register_device(dssdev, &pdev->dev, i); if (!plat_dssdev)
if (r) return;
DSSERR("device %s register failed: %d\n",
dssdev->name, r); dssdev = dss_alloc_and_init_device(&rfbidev->dev);
if (!dssdev)
return;
dss_copy_device_pdata(dssdev, plat_dssdev);
r = rfbi_init_display(dssdev);
if (r) {
DSSERR("device %s init failed: %d\n", dssdev->name, r);
dss_put_device(dssdev);
return;
}
r = dss_add_device(dssdev);
if (r) {
DSSERR("device %s register failed: %d\n", dssdev->name, r);
dss_put_device(dssdev);
return;
} }
} }
...@@ -1028,7 +1064,7 @@ static int __init omap_rfbihw_probe(struct platform_device *pdev) ...@@ -1028,7 +1064,7 @@ static int __init omap_rfbihw_probe(struct platform_device *pdev)
static int __exit omap_rfbihw_remove(struct platform_device *pdev) static int __exit omap_rfbihw_remove(struct platform_device *pdev)
{ {
omap_dss_unregister_child_devices(&pdev->dev); dss_unregister_child_devices(&pdev->dev);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
return 0; return 0;
} }
......
...@@ -195,10 +195,14 @@ static int __init sdi_init_display(struct omap_dss_device *dssdev) ...@@ -195,10 +195,14 @@ static int __init sdi_init_display(struct omap_dss_device *dssdev)
return 0; return 0;
} }
static void __init sdi_probe_pdata(struct platform_device *pdev) static struct omap_dss_device * __init sdi_find_dssdev(struct platform_device *pdev)
{ {
struct omap_dss_board_info *pdata = pdev->dev.platform_data; struct omap_dss_board_info *pdata = pdev->dev.platform_data;
int i, r; const char *def_disp_name = dss_get_default_display_name();
struct omap_dss_device *def_dssdev;
int i;
def_dssdev = NULL;
for (i = 0; i < pdata->num_devices; ++i) { for (i = 0; i < pdata->num_devices; ++i) {
struct omap_dss_device *dssdev = pdata->devices[i]; struct omap_dss_device *dssdev = pdata->devices[i];
...@@ -206,16 +210,48 @@ static void __init sdi_probe_pdata(struct platform_device *pdev) ...@@ -206,16 +210,48 @@ static void __init sdi_probe_pdata(struct platform_device *pdev)
if (dssdev->type != OMAP_DISPLAY_TYPE_SDI) if (dssdev->type != OMAP_DISPLAY_TYPE_SDI)
continue; continue;
r = sdi_init_display(dssdev); if (def_dssdev == NULL)
if (r) { def_dssdev = dssdev;
DSSERR("device %s init failed: %d\n", dssdev->name, r);
continue; if (def_disp_name != NULL &&
strcmp(dssdev->name, def_disp_name) == 0) {
def_dssdev = dssdev;
break;
} }
}
return def_dssdev;
}
static void __init sdi_probe_pdata(struct platform_device *sdidev)
{
struct omap_dss_device *plat_dssdev;
struct omap_dss_device *dssdev;
int r;
r = omap_dss_register_device(dssdev, &pdev->dev, i); plat_dssdev = sdi_find_dssdev(sdidev);
if (r)
DSSERR("device %s register failed: %d\n", if (!plat_dssdev)
dssdev->name, r); return;
dssdev = dss_alloc_and_init_device(&sdidev->dev);
if (!dssdev)
return;
dss_copy_device_pdata(dssdev, plat_dssdev);
r = sdi_init_display(dssdev);
if (r) {
DSSERR("device %s init failed: %d\n", dssdev->name, r);
dss_put_device(dssdev);
return;
}
r = dss_add_device(dssdev);
if (r) {
DSSERR("device %s register failed: %d\n", dssdev->name, r);
dss_put_device(dssdev);
return;
} }
} }
...@@ -228,7 +264,7 @@ static int __init omap_sdi_probe(struct platform_device *pdev) ...@@ -228,7 +264,7 @@ static int __init omap_sdi_probe(struct platform_device *pdev)
static int __exit omap_sdi_remove(struct platform_device *pdev) static int __exit omap_sdi_remove(struct platform_device *pdev)
{ {
omap_dss_unregister_child_devices(&pdev->dev); dss_unregister_child_devices(&pdev->dev);
return 0; return 0;
} }
......
...@@ -735,10 +735,14 @@ static void venc_put_clocks(void) ...@@ -735,10 +735,14 @@ static void venc_put_clocks(void)
clk_put(venc.tv_dac_clk); clk_put(venc.tv_dac_clk);
} }
static void __init venc_probe_pdata(struct platform_device *pdev) static struct omap_dss_device * __init venc_find_dssdev(struct platform_device *pdev)
{ {
struct omap_dss_board_info *pdata = pdev->dev.platform_data; struct omap_dss_board_info *pdata = pdev->dev.platform_data;
int r, i; const char *def_disp_name = dss_get_default_display_name();
struct omap_dss_device *def_dssdev;
int i;
def_dssdev = NULL;
for (i = 0; i < pdata->num_devices; ++i) { for (i = 0; i < pdata->num_devices; ++i) {
struct omap_dss_device *dssdev = pdata->devices[i]; struct omap_dss_device *dssdev = pdata->devices[i];
...@@ -746,16 +750,50 @@ static void __init venc_probe_pdata(struct platform_device *pdev) ...@@ -746,16 +750,50 @@ static void __init venc_probe_pdata(struct platform_device *pdev)
if (dssdev->type != OMAP_DISPLAY_TYPE_VENC) if (dssdev->type != OMAP_DISPLAY_TYPE_VENC)
continue; continue;
r = venc_init_display(dssdev); if (def_dssdev == NULL)
if (r) { def_dssdev = dssdev;
DSSERR("device %s init failed: %d\n", dssdev->name, r);
continue; if (def_disp_name != NULL &&
strcmp(dssdev->name, def_disp_name) == 0) {
def_dssdev = dssdev;
break;
} }
}
return def_dssdev;
}
static void __init venc_probe_pdata(struct platform_device *vencdev)
{
struct omap_dss_device *plat_dssdev;
struct omap_dss_device *dssdev;
int r;
plat_dssdev = venc_find_dssdev(vencdev);
if (!plat_dssdev)
return;
dssdev = dss_alloc_and_init_device(&vencdev->dev);
if (!dssdev)
return;
r = omap_dss_register_device(dssdev, &pdev->dev, i); dss_copy_device_pdata(dssdev, plat_dssdev);
if (r)
DSSERR("device %s register failed: %d\n", dssdev->channel = OMAP_DSS_CHANNEL_DIGIT;
dssdev->name, r);
r = venc_init_display(dssdev);
if (r) {
DSSERR("device %s init failed: %d\n", dssdev->name, r);
dss_put_device(dssdev);
return;
}
r = dss_add_device(dssdev);
if (r) {
DSSERR("device %s register failed: %d\n", dssdev->name, r);
dss_put_device(dssdev);
return;
} }
} }
...@@ -819,7 +857,7 @@ static int __init omap_venchw_probe(struct platform_device *pdev) ...@@ -819,7 +857,7 @@ static int __init omap_venchw_probe(struct platform_device *pdev)
static int __exit omap_venchw_remove(struct platform_device *pdev) static int __exit omap_venchw_remove(struct platform_device *pdev)
{ {
omap_dss_unregister_child_devices(&pdev->dev); dss_unregister_child_devices(&pdev->dev);
if (venc.vdda_dac_reg != NULL) { if (venc.vdda_dac_reg != NULL) {
regulator_put(venc.vdda_dac_reg); regulator_put(venc.vdda_dac_reg);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment