summaryrefslogtreecommitdiffstats
path: root/drivers/video/omap2/dss/dsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/omap2/dss/dsi.c')
-rw-r--r--drivers/video/omap2/dss/dsi.c232
1 files changed, 146 insertions, 86 deletions
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index a73dedc3310..99a043b08f0 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -363,7 +363,7 @@ struct dsi_data {
enum omap_dss_dsi_mode mode;
struct omap_dss_dsi_videomode_timings vm_timings;
- struct omap_dss_output output;
+ struct omap_dss_device output;
};
struct dsi_packet_sent_handler_data {
@@ -383,12 +383,21 @@ static inline struct dsi_data *dsi_get_dsidrv_data(struct platform_device *dside
static inline struct platform_device *dsi_get_dsidev_from_dssdev(struct omap_dss_device *dssdev)
{
- return dssdev->output->pdev;
+ /* HACK: dssdev can be either the panel device, when using old API, or
+ * the dsi device itself, when using the new API. So we solve this for
+ * now by checking the dssdev->id. This will be removed when the old API
+ * is removed.
+ */
+ if (dssdev->id == OMAP_DSS_OUTPUT_DSI1 ||
+ dssdev->id == OMAP_DSS_OUTPUT_DSI2)
+ return to_platform_device(dssdev->dev);
+
+ return to_platform_device(dssdev->output->dev);
}
struct platform_device *dsi_get_dsidev_from_id(int module)
{
- struct omap_dss_output *out;
+ struct omap_dss_device *out;
enum omap_dss_output_id id;
switch (module) {
@@ -404,7 +413,7 @@ struct platform_device *dsi_get_dsidev_from_id(int module)
out = omap_dss_get_output(id);
- return out ? out->pdev : NULL;
+ return out ? to_platform_device(out->dev) : NULL;
}
static inline void dsi_write_reg(struct platform_device *dsidev,
@@ -1114,6 +1123,30 @@ void dsi_runtime_put(struct platform_device *dsidev)
WARN_ON(r < 0 && r != -ENOSYS);
}
+static int dsi_regulator_init(struct platform_device *dsidev)
+{
+ struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+ struct regulator *vdds_dsi;
+
+ if (dsi->vdds_dsi_reg != NULL)
+ return 0;
+
+ vdds_dsi = devm_regulator_get(&dsi->pdev->dev, "vdds_dsi");
+
+ /* DT HACK: try VCXIO to make omapdss work for o4 sdp/panda */
+ if (IS_ERR(vdds_dsi))
+ vdds_dsi = devm_regulator_get(&dsi->pdev->dev, "VCXIO");
+
+ if (IS_ERR(vdds_dsi)) {
+ DSSERR("can't get VDDS_DSI regulator\n");
+ return PTR_ERR(vdds_dsi);
+ }
+
+ dsi->vdds_dsi_reg = vdds_dsi;
+
+ return 0;
+}
+
/* source clock for DSI PLL. this could also be PCLKFREE */
static inline void dsi_enable_pll_clock(struct platform_device *dsidev,
bool enable)
@@ -1592,22 +1625,9 @@ int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
*/
enable_hsclk = enable_hsdiv = true;
- if (dsi->vdds_dsi_reg == NULL) {
- struct regulator *vdds_dsi;
-
- vdds_dsi = regulator_get(&dsi->pdev->dev, "vdds_dsi");
-
- /* DT HACK: try VCXIO to make omapdss work for o4 sdp/panda */
- if (IS_ERR(vdds_dsi))
- vdds_dsi = regulator_get(&dsi->pdev->dev, "VCXIO");
-
- if (IS_ERR(vdds_dsi)) {
- DSSERR("can't get VDDS_DSI regulator\n");
- return PTR_ERR(vdds_dsi);
- }
-
- dsi->vdds_dsi_reg = vdds_dsi;
- }
+ r = dsi_regulator_init(dsidev);
+ if (r)
+ return r;
dsi_enable_pll_clock(dsidev, 1);
/*
@@ -4122,7 +4142,7 @@ int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
struct omap_overlay_manager *mgr = dsi->output.manager;
int bpp = dsi_get_pixel_size(dsi->pix_fmt);
- struct omap_dss_output *out = &dsi->output;
+ struct omap_dss_device *out = &dsi->output;
u8 data_type;
u16 word_count;
int r;
@@ -4581,12 +4601,6 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
mutex_lock(&dsi->lock);
- r = omap_dss_start_device(dssdev);
- if (r) {
- DSSERR("failed to start device\n");
- goto err_start_dev;
- }
-
r = dsi_runtime_get(dsidev);
if (r)
goto err_get_dsi;
@@ -4607,8 +4621,6 @@ err_init_dsi:
dsi_enable_pll_clock(dsidev, 0);
dsi_runtime_put(dsidev);
err_get_dsi:
- omap_dss_stop_device(dssdev);
-err_start_dev:
mutex_unlock(&dsi->lock);
DSSDBG("dsi_display_enable FAILED\n");
return r;
@@ -4637,8 +4649,6 @@ void omapdss_dsi_display_disable(struct omap_dss_device *dssdev,
dsi_runtime_put(dsidev);
dsi_enable_pll_clock(dsidev, 0);
- omap_dss_stop_device(dssdev);
-
mutex_unlock(&dsi->lock);
}
EXPORT_SYMBOL(omapdss_dsi_display_disable);
@@ -5225,34 +5235,6 @@ static enum omap_channel dsi_get_channel(int module_id)
}
}
-static int dsi_init_display(struct omap_dss_device *dssdev)
-{
- struct platform_device *dsidev =
- dsi_get_dsidev_from_id(dssdev->phy.dsi.module);
- struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
- DSSDBG("DSI init\n");
-
- if (dsi->vdds_dsi_reg == NULL) {
- struct regulator *vdds_dsi;
-
- vdds_dsi = regulator_get(&dsi->pdev->dev, "vdds_dsi");
-
- /* DT HACK: try VCXIO to make omapdss work for o4 sdp/panda */
- if (IS_ERR(vdds_dsi))
- vdds_dsi = regulator_get(&dsi->pdev->dev, "VCXIO");
-
- if (IS_ERR(vdds_dsi)) {
- DSSERR("can't get VDDS_DSI regulator\n");
- return PTR_ERR(vdds_dsi);
- }
-
- dsi->vdds_dsi_reg = vdds_dsi;
- }
-
- return 0;
-}
-
int omap_dsi_request_vc(struct omap_dss_device *dssdev, int *channel)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -5410,19 +5392,16 @@ static int dsi_probe_pdata(struct platform_device *dsidev)
if (!plat_dssdev)
return 0;
+ r = dsi_regulator_init(dsidev);
+ if (r)
+ return r;
+
dssdev = dss_alloc_and_init_device(&dsidev->dev);
if (!dssdev)
return -ENOMEM;
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;
- }
-
r = omapdss_output_set_device(&dsi->output, dssdev);
if (r) {
DSSERR("failed to connect output to new device: %s\n",
@@ -5442,28 +5421,113 @@ static int dsi_probe_pdata(struct platform_device *dsidev)
return 0;
}
+static int dsi_connect(struct omap_dss_device *dssdev,
+ struct omap_dss_device *dst)
+{
+ struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+ struct omap_overlay_manager *mgr;
+ int r;
+
+ r = dsi_regulator_init(dsidev);
+ if (r)
+ return r;
+
+ mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel);
+ if (!mgr)
+ return -ENODEV;
+
+ r = dss_mgr_connect(mgr, dssdev);
+ 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(mgr, dssdev);
+ return r;
+ }
+
+ return 0;
+}
+
+static void dsi_disconnect(struct omap_dss_device *dssdev,
+ struct omap_dss_device *dst)
+{
+ WARN_ON(dst != dssdev->device);
+
+ if (dst != dssdev->device)
+ return;
+
+ omapdss_output_unset_device(dssdev);
+
+ if (dssdev->manager)
+ dss_mgr_disconnect(dssdev->manager, dssdev);
+}
+
+static const struct omapdss_dsi_ops dsi_ops = {
+ .connect = dsi_connect,
+ .disconnect = dsi_disconnect,
+
+ .bus_lock = dsi_bus_lock,
+ .bus_unlock = dsi_bus_unlock,
+
+ .enable = omapdss_dsi_display_enable,
+ .disable = omapdss_dsi_display_disable,
+
+ .enable_hs = omapdss_dsi_vc_enable_hs,
+
+ .configure_pins = omapdss_dsi_configure_pins,
+ .set_config = omapdss_dsi_set_config,
+
+ .enable_video_output = dsi_enable_video_output,
+ .disable_video_output = dsi_disable_video_output,
+
+ .update = omap_dsi_update,
+
+ .enable_te = omapdss_dsi_enable_te,
+
+ .request_vc = omap_dsi_request_vc,
+ .set_vc_id = omap_dsi_set_vc_id,
+ .release_vc = omap_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 platform_device *dsidev)
{
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
- struct omap_dss_output *out = &dsi->output;
+ struct omap_dss_device *out = &dsi->output;
- out->pdev = dsidev;
+ out->dev = &dsidev->dev;
out->id = dsi->module_id == 0 ?
OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2;
- out->type = OMAP_DISPLAY_TYPE_DSI;
+ out->output_type = OMAP_DISPLAY_TYPE_DSI;
out->name = dsi->module_id == 0 ? "dsi.0" : "dsi.1";
out->dispc_channel = dsi_get_channel(dsi->module_id);
+ out->ops.dsi = &dsi_ops;
+ out->owner = THIS_MODULE;
- dss_register_output(out);
+ omapdss_register_output(out);
}
static void dsi_uninit_output(struct platform_device *dsidev)
{
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
- struct omap_dss_output *out = &dsi->output;
+ struct omap_dss_device *out = &dsi->output;
- dss_unregister_output(out);
+ omapdss_unregister_output(out);
}
/* DSI1 HW IP initialisation */
@@ -5563,12 +5627,10 @@ static int omap_dsihw_probe(struct platform_device *dsidev)
dsi_init_output(dsidev);
- r = dsi_probe_pdata(dsidev);
- if (r) {
- dsi_runtime_put(dsidev);
- dsi_uninit_output(dsidev);
- pm_runtime_disable(&dsidev->dev);
- return r;
+ if (dsidev->dev.platform_data) {
+ r = dsi_probe_pdata(dsidev);
+ if (r)
+ goto err_probe;
}
dsi_runtime_put(dsidev);
@@ -5586,6 +5648,9 @@ static int omap_dsihw_probe(struct platform_device *dsidev)
#endif
return 0;
+err_probe:
+ dsi_runtime_put(dsidev);
+ dsi_uninit_output(dsidev);
err_runtime_get:
pm_runtime_disable(&dsidev->dev);
return r;
@@ -5603,14 +5668,9 @@ static int __exit omap_dsihw_remove(struct platform_device *dsidev)
pm_runtime_disable(&dsidev->dev);
- if (dsi->vdds_dsi_reg != NULL) {
- if (dsi->vdds_dsi_enabled) {
- regulator_disable(dsi->vdds_dsi_reg);
- dsi->vdds_dsi_enabled = false;
- }
-
- regulator_put(dsi->vdds_dsi_reg);
- dsi->vdds_dsi_reg = NULL;
+ if (dsi->vdds_dsi_reg != NULL && dsi->vdds_dsi_enabled) {
+ regulator_disable(dsi->vdds_dsi_reg);
+ dsi->vdds_dsi_enabled = false;
}
return 0;