#include <linux/device.h>
#include <linux/regulator/consumer.h>
#include <linux/suspend.h>
+#include <linux/slab.h>
#include <video/omapdss.h>
EXPORT_SYMBOL(omap_dss_unregister_driver);
/* 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)
{
- reset_device(dev, 0);
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ kfree(dssdev);
}
static int disp_num_counter;
-int omap_dss_register_device(struct omap_dss_device *dssdev,
- struct device *parent)
+struct omap_dss_device *dss_alloc_and_init_device(struct device *parent)
{
- reset_device(&dssdev->dev, 1);
+ struct omap_dss_device *dssdev;
+
+ dssdev = kzalloc(sizeof(*dssdev), GFP_KERNEL);
+ if (!dssdev)
+ return NULL;
dssdev->dev.bus = &dss_bus_type;
dssdev->dev.parent = parent;
dssdev->dev.release = omap_dss_dev_release;
dev_set_name(&dssdev->dev, "display%d", disp_num_counter++);
- return device_register(&dssdev->dev);
+
+ device_initialize(&dssdev->dev);
+
+ return dssdev;
}
-void omap_dss_unregister_device(struct omap_dss_device *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 dss_unregister_device(struct omap_dss_device *dssdev)
{
device_unregister(&dssdev->dev);
}
static int dss_unregister_dss_dev(struct device *dev, void *data)
{
struct omap_dss_device *dssdev = to_dss_device(dev);
- omap_dss_unregister_device(dssdev);
+ dss_unregister_device(dssdev);
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);
}
+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 */
static int __init omap_dss_bus_register(void)
{
return def_dssdev;
}
-static void __init dpi_probe_pdata(struct platform_device *pdev)
+static void __init dpi_probe_pdata(struct platform_device *dpidev)
{
+ struct omap_dss_device *plat_dssdev;
struct omap_dss_device *dssdev;
int r;
- dssdev = dpi_find_dssdev(pdev);
+ 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 = omap_dss_register_device(dssdev, &pdev->dev);
+ r = dss_add_device(dssdev);
if (r) {
DSSERR("device %s register failed: %d\n", dssdev->name, r);
+ dss_put_device(dssdev);
return;
}
}
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;
}
static void __init dsi_probe_pdata(struct platform_device *dsidev)
{
+ struct omap_dss_device *plat_dssdev;
struct omap_dss_device *dssdev;
int r;
- dssdev = dsi_find_dssdev(dsidev);
+ 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 = omap_dss_register_device(dssdev, &dsidev->dev);
+ r = dss_add_device(dssdev);
if (r) {
DSSERR("device %s register failed: %d\n", dssdev->name, r);
+ dss_put_device(dssdev);
return;
}
}
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);
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 omap_dss_register_device(struct omap_dss_device *dssdev,
- struct device *parent);
-void omap_dss_unregister_device(struct omap_dss_device *dssdev);
-void omap_dss_unregister_child_devices(struct device *parent);
+struct omap_dss_device *dss_alloc_and_init_device(struct device *parent);
+int dss_add_device(struct omap_dss_device *dssdev);
+void dss_unregister_device(struct omap_dss_device *dssdev);
+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 */
void dss_apply_init(void);
static void __init hdmi_probe_pdata(struct platform_device *pdev)
{
+ struct omap_dss_device *plat_dssdev;
struct omap_dss_device *dssdev;
struct omap_dss_hdmi_data *priv;
int r;
- dssdev = hdmi_find_dssdev(pdev);
+ 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;
r = hdmi_init_display(dssdev);
if (r) {
DSSERR("device %s init failed: %d\n", dssdev->name, r);
+ dss_put_device(dssdev);
return;
}
- r = omap_dss_register_device(dssdev, &pdev->dev);
+ r = dss_add_device(dssdev);
if (r) {
DSSERR("device %s register failed: %d\n", dssdev->name, r);
+ dss_put_device(dssdev);
return;
}
}
{
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();
return def_dssdev;
}
-static void __init rfbi_probe_pdata(struct platform_device *pdev)
+static void __init rfbi_probe_pdata(struct platform_device *rfbidev)
{
+ struct omap_dss_device *plat_dssdev;
struct omap_dss_device *dssdev;
int r;
- dssdev = rfbi_find_dssdev(pdev);
+ plat_dssdev = rfbi_find_dssdev(rfbidev);
+ if (!plat_dssdev)
+ return;
+
+ 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 = omap_dss_register_device(dssdev, &pdev->dev);
+ r = dss_add_device(dssdev);
if (r) {
DSSERR("device %s register failed: %d\n", dssdev->name, r);
+ dss_put_device(dssdev);
return;
}
}
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);
return 0;
}
return def_dssdev;
}
-static void __init sdi_probe_pdata(struct platform_device *pdev)
+static void __init sdi_probe_pdata(struct platform_device *sdidev)
{
+ struct omap_dss_device *plat_dssdev;
struct omap_dss_device *dssdev;
int r;
- dssdev = sdi_find_dssdev(pdev);
+ plat_dssdev = sdi_find_dssdev(sdidev);
+ if (!plat_dssdev)
+ 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 = omap_dss_register_device(dssdev, &pdev->dev);
+ r = dss_add_device(dssdev);
if (r) {
DSSERR("device %s register failed: %d\n", dssdev->name, r);
+ dss_put_device(dssdev);
return;
}
}
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 def_dssdev;
}
-static void __init venc_probe_pdata(struct platform_device *pdev)
+static void __init venc_probe_pdata(struct platform_device *vencdev)
{
+ struct omap_dss_device *plat_dssdev;
struct omap_dss_device *dssdev;
int r;
- dssdev = venc_find_dssdev(pdev);
+ plat_dssdev = venc_find_dssdev(vencdev);
+ if (!plat_dssdev)
+ return;
+
+ dssdev = dss_alloc_and_init_device(&vencdev->dev);
if (!dssdev)
return;
+ dss_copy_device_pdata(dssdev, plat_dssdev);
+
dssdev->channel = OMAP_DSS_CHANNEL_DIGIT;
r = venc_init_display(dssdev);
if (r) {
DSSERR("device %s init failed: %d\n", dssdev->name, r);
+ dss_put_device(dssdev);
return;
}
- r = omap_dss_register_device(dssdev, &pdev->dev);
+ r = dss_add_device(dssdev);
if (r) {
DSSERR("device %s register failed: %d\n", dssdev->name, r);
+ dss_put_device(dssdev);
return;
}
}
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) {
regulator_put(venc.vdda_dac_reg);