OMAPDSS: SDI: Maintain our own timings field in driver data
[firefly-linux-kernel-4.4.55.git] / drivers / video / omap2 / dss / sdi.c
index 8266ca0d666bc2de7547a12c38eca9dc98aba11a..6ec6614009ed93fdc31c418c4b21b1733f71a04d 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/err.h>
 #include <linux/regulator/consumer.h>
 #include <linux/export.h>
+#include <linux/platform_device.h>
 
 #include <video/omapdss.h>
 #include "dss.h"
 static struct {
        bool update_enabled;
        struct regulator *vdds_sdi_reg;
-} sdi;
 
-static void sdi_basic_init(struct omap_dss_device *dssdev)
+       struct dss_lcd_mgr_config mgr_config;
+       struct omap_video_timings timings;
+} sdi;
 
+static void sdi_config_lcd_manager(struct omap_dss_device *dssdev)
 {
-       dispc_mgr_set_io_pad_mode(DSS_IO_PAD_MODE_BYPASS);
-       dispc_mgr_enable_stallmode(dssdev->manager->id, false);
+       sdi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
+
+       sdi.mgr_config.stallmode = false;
+       sdi.mgr_config.fifohandcheck = false;
 
-       dispc_mgr_set_lcd_display_type(dssdev->manager->id,
-                       OMAP_DSS_LCD_DISPLAY_TFT);
+       sdi.mgr_config.video_port_width = 24;
+       sdi.mgr_config.lcden_sig_polarity = 1;
 
-       dispc_mgr_set_tft_data_lines(dssdev->manager->id, 24);
-       dispc_lcd_enable_signal_polarity(1);
+       dss_mgr_set_lcd_config(dssdev->manager, &sdi.mgr_config);
 }
 
 int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
 {
-       struct omap_video_timings *t = &dssdev->panel.timings;
+       struct omap_video_timings *t = &sdi.timings;
        struct dss_clock_info dss_cinfo;
        struct dispc_clock_info dispc_cinfo;
-       u16 lck_div, pck_div;
-       unsigned long fck;
        unsigned long pck;
        int r;
 
@@ -71,32 +73,21 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
        if (r)
                goto err_reg_enable;
 
-       r = dss_runtime_get();
-       if (r)
-               goto err_get_dss;
-
        r = dispc_runtime_get();
        if (r)
                goto err_get_dispc;
 
-       sdi_basic_init(dssdev);
-
        /* 15.5.9.1.2 */
-       dssdev->panel.config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF;
-
-       dispc_mgr_set_pol_freq(dssdev->manager->id, dssdev->panel.config,
-                       dssdev->panel.acbi, dssdev->panel.acb);
+       t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
+       t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
 
-       r = dss_calc_clock_div(1, t->pixel_clock * 1000,
-                       &dss_cinfo, &dispc_cinfo);
+       r = dss_calc_clock_div(t->pixel_clock * 1000, &dss_cinfo, &dispc_cinfo);
        if (r)
                goto err_calc_clock_div;
 
-       fck = dss_cinfo.fck;
-       lck_div = dispc_cinfo.lck_div;
-       pck_div = dispc_cinfo.pck_div;
+       sdi.mgr_config.clock_info = dispc_cinfo;
 
-       pck = fck / lck_div / pck_div / 1000;
+       pck = dss_cinfo.fck / dispc_cinfo.lck_div / dispc_cinfo.pck_div / 1000;
 
        if (pck != t->pixel_clock) {
                DSSWARN("Could not find exact pixel clock. Requested %d kHz, "
@@ -107,15 +98,13 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
        }
 
 
-       dispc_mgr_set_lcd_timings(dssdev->manager->id, t);
+       dss_mgr_set_timings(dssdev->manager, t);
 
        r = dss_set_clock_div(&dss_cinfo);
        if (r)
                goto err_set_dss_clock_div;
 
-       r = dispc_mgr_set_clock_div(dssdev->manager->id, &dispc_cinfo);
-       if (r)
-               goto err_set_dispc_clock_div;
+       sdi_config_lcd_manager(dssdev);
 
        dss_sdi_init(dssdev->phy.sdi.datapairs);
        r = dss_sdi_enable();
@@ -132,13 +121,10 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
 err_mgr_enable:
        dss_sdi_disable();
 err_sdi_enable:
-err_set_dispc_clock_div:
 err_set_dss_clock_div:
 err_calc_clock_div:
        dispc_runtime_put();
 err_get_dispc:
-       dss_runtime_put();
-err_get_dss:
        regulator_disable(sdi.vdds_sdi_reg);
 err_reg_enable:
        omap_dss_stop_device(dssdev);
@@ -154,7 +140,6 @@ void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
        dss_sdi_disable();
 
        dispc_runtime_put();
-       dss_runtime_put();
 
        regulator_disable(sdi.vdds_sdi_reg);
 
@@ -162,7 +147,24 @@ void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
 }
 EXPORT_SYMBOL(omapdss_sdi_display_disable);
 
-int sdi_init_display(struct omap_dss_device *dssdev)
+void omapdss_sdi_set_timings(struct omap_dss_device *dssdev,
+               struct omap_video_timings *timings)
+{
+       int r;
+
+       sdi.timings = *timings;
+
+       if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
+               omapdss_sdi_display_disable(dssdev);
+
+               r = omapdss_sdi_display_enable(dssdev);
+               if (r)
+                       DSSERR("failed to set new timings\n");
+       }
+}
+EXPORT_SYMBOL(omapdss_sdi_set_timings);
+
+static int __init sdi_init_display(struct omap_dss_device *dssdev)
 {
        DSSDBG("SDI init\n");
 
@@ -182,11 +184,58 @@ int sdi_init_display(struct omap_dss_device *dssdev)
        return 0;
 }
 
-int sdi_init(void)
+static void __init sdi_probe_pdata(struct platform_device *pdev)
 {
+       struct omap_dss_board_info *pdata = pdev->dev.platform_data;
+       int i, r;
+
+       for (i = 0; i < pdata->num_devices; ++i) {
+               struct omap_dss_device *dssdev = pdata->devices[i];
+
+               if (dssdev->type != OMAP_DISPLAY_TYPE_SDI)
+                       continue;
+
+               r = sdi_init_display(dssdev);
+               if (r) {
+                       DSSERR("device %s init failed: %d\n", dssdev->name, r);
+                       continue;
+               }
+
+               r = omap_dss_register_device(dssdev, &pdev->dev, i);
+               if (r)
+                       DSSERR("device %s register failed: %d\n",
+                                       dssdev->name, r);
+       }
+}
+
+static int __init omap_sdi_probe(struct platform_device *pdev)
+{
+       sdi_probe_pdata(pdev);
+
        return 0;
 }
 
-void sdi_exit(void)
+static int __exit omap_sdi_remove(struct platform_device *pdev)
+{
+       omap_dss_unregister_child_devices(&pdev->dev);
+
+       return 0;
+}
+
+static struct platform_driver omap_sdi_driver = {
+       .remove         = __exit_p(omap_sdi_remove),
+       .driver         = {
+               .name   = "omapdss_sdi",
+               .owner  = THIS_MODULE,
+       },
+};
+
+int __init sdi_init_platform_driver(void)
+{
+       return platform_driver_probe(&omap_sdi_driver, omap_sdi_probe);
+}
+
+void __exit sdi_uninit_platform_driver(void)
 {
+       platform_driver_unregister(&omap_sdi_driver);
 }