Merge tag 'v3.6-rc4'
authorTomi Valkeinen <tomi.valkeinen@ti.com>
Mon, 3 Sep 2012 06:26:33 +0000 (09:26 +0300)
committerTomi Valkeinen <tomi.valkeinen@ti.com>
Mon, 3 Sep 2012 06:26:33 +0000 (09:26 +0300)
Merge 3.6-rc4 to get latest OMAP and device tree fixes.

28 files changed:
arch/arm/mach-omap2/display.c
drivers/video/omap2/displays/panel-acx565akm.c
drivers/video/omap2/displays/panel-generic-dpi.c
drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
drivers/video/omap2/displays/panel-n8x0.c
drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
drivers/video/omap2/displays/panel-picodlp.c
drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
drivers/video/omap2/displays/panel-taal.c
drivers/video/omap2/displays/panel-tfp410.c
drivers/video/omap2/displays/panel-tpo-td043mtea1.c
drivers/video/omap2/dss/Makefile
drivers/video/omap2/dss/apply.c
drivers/video/omap2/dss/dispc.c
drivers/video/omap2/dss/dpi.c
drivers/video/omap2/dss/dsi.c
drivers/video/omap2/dss/dss.c
drivers/video/omap2/dss/dss.h
drivers/video/omap2/dss/dss_features.c
drivers/video/omap2/dss/dss_features.h
drivers/video/omap2/dss/hdmi.c
drivers/video/omap2/dss/hdmi_panel.c
drivers/video/omap2/dss/rfbi.c
drivers/video/omap2/dss/sdi.c
drivers/video/omap2/dss/venc.c
drivers/video/omap2/dss/venc_panel.c [new file with mode: 0644]
drivers/video/omap2/omapfb/omapfb-main.c
include/video/omapdss.h

index af1ed7d24a1fbb20fd7e1fffba8ebb1f12bbcca5..ee40739b55c01f49dca0e7d0d57d7e6da8dfb52e 100644 (file)
@@ -95,7 +95,6 @@ static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initdata = {
        { "dss_core", "omapdss_dss", -1 },
        { "dss_dispc", "omapdss_dispc", -1 },
        { "dss_rfbi", "omapdss_rfbi", -1 },
-       { "dss_venc", "omapdss_venc", -1 },
        { "dss_dsi1", "omapdss_dsi", 0 },
        { "dss_dsi2", "omapdss_dsi", 1 },
        { "dss_hdmi", "omapdss_hdmi", -1 },
index eaeed4340e04eaf49afd176ec3f95ed2b56d8734..c835aa70f96fb64829e7b7a8f8a328a64dd720e3 100644 (file)
@@ -600,6 +600,9 @@ static int acx_panel_power_on(struct omap_dss_device *dssdev)
 
        mutex_lock(&md->mutex);
 
+       omapdss_sdi_set_timings(dssdev, &dssdev->panel.timings);
+       omapdss_sdi_set_datapairs(dssdev, dssdev->phy.sdi.datapairs);
+
        r = omapdss_sdi_display_enable(dssdev);
        if (r) {
                pr_err("%s sdi enable failed\n", __func__);
@@ -731,18 +734,9 @@ static int acx_panel_resume(struct omap_dss_device *dssdev)
 static void acx_panel_set_timings(struct omap_dss_device *dssdev,
                struct omap_video_timings *timings)
 {
-       int r;
-
-       if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
-               omapdss_sdi_display_disable(dssdev);
+       omapdss_sdi_set_timings(dssdev, timings);
 
        dssdev->panel.timings = *timings;
-
-       if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
-               r = omapdss_sdi_display_enable(dssdev);
-               if (r)
-                       dev_err(&dssdev->dev, "%s enable failed\n", __func__);
-       }
 }
 
 static int acx_panel_check_timings(struct omap_dss_device *dssdev,
index bc5af2500eb923952a9c7a80aaedfb430ee50974..88295c526815e76a628e1e5641902e1ceac0b07d 100644 (file)
@@ -545,6 +545,8 @@ struct panel_drv_data {
        struct omap_dss_device *dssdev;
 
        struct panel_config *panel_config;
+
+       struct mutex lock;
 };
 
 static inline struct panel_generic_dpi_data
@@ -563,6 +565,9 @@ static int generic_dpi_panel_power_on(struct omap_dss_device *dssdev)
        if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
                return 0;
 
+       omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
+       omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
+
        r = omapdss_dpi_display_enable(dssdev);
        if (r)
                goto err0;
@@ -634,6 +639,8 @@ static int generic_dpi_panel_probe(struct omap_dss_device *dssdev)
        drv_data->dssdev = dssdev;
        drv_data->panel_config = panel_config;
 
+       mutex_init(&drv_data->lock);
+
        dev_set_drvdata(&dssdev->dev, drv_data);
 
        return 0;
@@ -652,56 +659,108 @@ static void __exit generic_dpi_panel_remove(struct omap_dss_device *dssdev)
 
 static int generic_dpi_panel_enable(struct omap_dss_device *dssdev)
 {
-       int r = 0;
+       struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
+       int r;
+
+       mutex_lock(&drv_data->lock);
 
        r = generic_dpi_panel_power_on(dssdev);
        if (r)
-               return r;
+               goto err;
 
        dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+err:
+       mutex_unlock(&drv_data->lock);
 
-       return 0;
+       return r;
 }
 
 static void generic_dpi_panel_disable(struct omap_dss_device *dssdev)
 {
+       struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
+
+       mutex_lock(&drv_data->lock);
+
        generic_dpi_panel_power_off(dssdev);
 
        dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+
+       mutex_unlock(&drv_data->lock);
 }
 
 static int generic_dpi_panel_suspend(struct omap_dss_device *dssdev)
 {
+       struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
+
+       mutex_lock(&drv_data->lock);
+
        generic_dpi_panel_power_off(dssdev);
 
        dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
 
+       mutex_unlock(&drv_data->lock);
+
        return 0;
 }
 
 static int generic_dpi_panel_resume(struct omap_dss_device *dssdev)
 {
-       int r = 0;
+       struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
+       int r;
+
+       mutex_lock(&drv_data->lock);
 
        r = generic_dpi_panel_power_on(dssdev);
        if (r)
-               return r;
+               goto err;
 
        dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
 
-       return 0;
+err:
+       mutex_unlock(&drv_data->lock);
+
+       return r;
 }
 
 static void generic_dpi_panel_set_timings(struct omap_dss_device *dssdev,
                struct omap_video_timings *timings)
 {
-       dpi_set_timings(dssdev, timings);
+       struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
+
+       mutex_lock(&drv_data->lock);
+
+       omapdss_dpi_set_timings(dssdev, timings);
+
+       dssdev->panel.timings = *timings;
+
+       mutex_unlock(&drv_data->lock);
+}
+
+static void generic_dpi_panel_get_timings(struct omap_dss_device *dssdev,
+               struct omap_video_timings *timings)
+{
+       struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
+
+       mutex_lock(&drv_data->lock);
+
+       *timings = dssdev->panel.timings;
+
+       mutex_unlock(&drv_data->lock);
 }
 
 static int generic_dpi_panel_check_timings(struct omap_dss_device *dssdev,
                struct omap_video_timings *timings)
 {
-       return dpi_check_timings(dssdev, timings);
+       struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
+       int r;
+
+       mutex_lock(&drv_data->lock);
+
+       r = dpi_check_timings(dssdev, timings);
+
+       mutex_unlock(&drv_data->lock);
+
+       return r;
 }
 
 static struct omap_dss_driver dpi_driver = {
@@ -714,6 +773,7 @@ static struct omap_dss_driver dpi_driver = {
        .resume         = generic_dpi_panel_resume,
 
        .set_timings    = generic_dpi_panel_set_timings,
+       .get_timings    = generic_dpi_panel_get_timings,
        .check_timings  = generic_dpi_panel_check_timings,
 
        .driver         = {
index 802807798846a3ff976019784b51158f16df4b66..90c1cabf244e183ea7572b083a3a2b9a9fa3cc69 100644 (file)
@@ -55,6 +55,9 @@ static int lb035q02_panel_power_on(struct omap_dss_device *dssdev)
        if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
                return 0;
 
+       omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
+       omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
+
        r = omapdss_dpi_display_enable(dssdev);
        if (r)
                goto err0;
index e6c115373c0088cce331cb9bcf74aae22ec10830..17ae85e0033f4f02f92dc95d6ae8224e6c87f9cb 100644 (file)
@@ -150,11 +150,17 @@ static void blizzard_ctrl_setup_update(struct omap_dss_device *dssdev,
                        BLIZZARD_SRC_WRITE_LCD :
                        BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE;
 
-       omap_rfbi_configure(dssdev, 16, 8);
+       omapdss_rfbi_set_pixel_size(dssdev, 16);
+       omapdss_rfbi_set_data_lines(dssdev, 8);
+
+       omap_rfbi_configure(dssdev);
 
        blizzard_write(BLIZZARD_INPUT_WIN_X_START_0, tmp, 18);
 
-       omap_rfbi_configure(dssdev, 16, 16);
+       omapdss_rfbi_set_pixel_size(dssdev, 16);
+       omapdss_rfbi_set_data_lines(dssdev, 16);
+
+       omap_rfbi_configure(dssdev);
 }
 
 static void mipid_transfer(struct spi_device *spi, int cmd, const u8 *wbuf,
@@ -297,6 +303,12 @@ static int n8x0_panel_power_on(struct omap_dss_device *dssdev)
                        goto err_plat_en;
        }
 
+       omapdss_rfbi_set_size(dssdev, dssdev->panel.timings.x_res,
+               dssdev->panel.timings.y_res);
+       omapdss_rfbi_set_pixel_size(dssdev, dssdev->ctrl.pixel_size);
+       omapdss_rfbi_set_data_lines(dssdev, dssdev->phy.rfbi.data_lines);
+       omapdss_rfbi_set_interface_timings(dssdev, &dssdev->ctrl.rfbi_timings);
+
        r = omapdss_rfbi_display_enable(dssdev);
        if (r)
                goto err_rfbi_en;
@@ -625,17 +637,25 @@ static int n8x0_panel_update(struct omap_dss_device *dssdev,
                u16 x, u16 y, u16 w, u16 h)
 {
        struct panel_drv_data *ddata = get_drv_data(dssdev);
+       u16 dw, dh;
 
        dev_dbg(&dssdev->dev, "update\n");
 
+       dw = dssdev->panel.timings.x_res;
+       dh = dssdev->panel.timings.y_res;
+
+       if (x != 0 || y != 0 || w != dw || h != dh) {
+               dev_err(&dssdev->dev, "invaid update region %d, %d, %d, %d\n",
+                       x, y, w, h);
+               return -EINVAL;
+       }
+
        mutex_lock(&ddata->lock);
        rfbi_bus_lock();
 
-       omap_rfbi_prepare_update(dssdev, &x, &y, &w, &h);
-
        blizzard_ctrl_setup_update(dssdev, x, y, w, h);
 
-       omap_rfbi_update(dssdev, x, y, w, h, update_done, NULL);
+       omap_rfbi_update(dssdev, update_done, NULL);
 
        mutex_unlock(&ddata->lock);
 
index b122b0f31c43b34602a0f8215ca8106819ea3512..908fd268f3dc90fd98b3eb4827166a5f5e94214f 100644 (file)
@@ -175,6 +175,9 @@ static int nec_8048_panel_power_on(struct omap_dss_device *dssdev)
        if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
                return 0;
 
+       omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
+       omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
+
        r = omapdss_dpi_display_enable(dssdev);
        if (r)
                goto err0;
index 2d35bd388860001c08ddbaf5cc1a551764a2f5a5..9df87640ddd2b0ed574d93e30c69492756167628 100644 (file)
@@ -377,6 +377,10 @@ static int picodlp_panel_power_on(struct omap_dss_device *dssdev)
         * then only i2c commands can be successfully sent to dpp2600
         */
        msleep(1000);
+
+       omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
+       omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
+
        r = omapdss_dpi_display_enable(dssdev);
        if (r) {
                dev_err(&dssdev->dev, "failed to enable DPI\n");
index bd86ba9ccf7600bed53c29c257e164c7dda763ec..1ec3b277ff155edca2861be48f3d013b01334aa1 100644 (file)
@@ -142,6 +142,9 @@ static int sharp_ls_power_on(struct omap_dss_device *dssdev)
        if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
                return 0;
 
+       omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
+       omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
+
        r = omapdss_dpi_display_enable(dssdev);
        if (r)
                goto err0;
index 3f5acc7771da34f6f08549c7c8db27b40d102af9..77aed0e51f9befa931239ec99e1e4fddd16da7eb 100644 (file)
@@ -1060,6 +1060,11 @@ static int taal_power_on(struct omap_dss_device *dssdev)
                goto err0;
        };
 
+       omapdss_dsi_set_size(dssdev, dssdev->panel.timings.x_res,
+               dssdev->panel.timings.y_res);
+       omapdss_dsi_set_pixel_format(dssdev, OMAP_DSS_DSI_FMT_RGB888);
+       omapdss_dsi_set_operation_mode(dssdev, OMAP_DSS_DSI_CMD_MODE);
+
        r = omapdss_dsi_display_enable(dssdev);
        if (r) {
                dev_err(&dssdev->dev, "failed to enable DSI\n");
@@ -1487,6 +1492,7 @@ static int taal_get_te(struct omap_dss_device *dssdev)
 static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
 {
        struct taal_data *td = dev_get_drvdata(&dssdev->dev);
+       u16 dw, dh;
        int r;
 
        dev_dbg(&dssdev->dev, "rotate %d\n", rotate);
@@ -1508,6 +1514,16 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
                        goto err;
        }
 
+       if (rotate == 0 || rotate == 2) {
+               dw = dssdev->panel.timings.x_res;
+               dh = dssdev->panel.timings.y_res;
+       } else {
+               dw = dssdev->panel.timings.y_res;
+               dh = dssdev->panel.timings.x_res;
+       }
+
+       omapdss_dsi_set_size(dssdev, dw, dh);
+
        td->rotate = rotate;
 
        dsi_bus_unlock(dssdev);
index 40cc0cfa5d179c77ce8c4bcf0282391162140766..4be9a59664d58cd20274c865b6583138217dd446 100644 (file)
@@ -65,6 +65,9 @@ static int tfp410_power_on(struct omap_dss_device *dssdev)
        if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
                return 0;
 
+       omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
+       omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
+
        r = omapdss_dpi_display_enable(dssdev);
        if (r)
                goto err0;
@@ -231,7 +234,8 @@ static void tfp410_set_timings(struct omap_dss_device *dssdev,
        struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
 
        mutex_lock(&ddata->lock);
-       dpi_set_timings(dssdev, timings);
+       omapdss_dpi_set_timings(dssdev, timings);
+       dssdev->panel.timings = *timings;
        mutex_unlock(&ddata->lock);
 }
 
index fa7baa650ae06bcc18a911a3e3fed34cb4e6f0b2..b5e6dbc59f0a654c79d9d3b6b40eaba955680c2a 100644 (file)
@@ -337,6 +337,9 @@ static int tpo_td043_enable_dss(struct omap_dss_device *dssdev)
        if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
                return 0;
 
+       omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
+       omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
+
        r = omapdss_dpi_display_enable(dssdev);
        if (r)
                goto err0;
@@ -480,7 +483,9 @@ static void tpo_td043_remove(struct omap_dss_device *dssdev)
 static void tpo_td043_set_timings(struct omap_dss_device *dssdev,
                struct omap_video_timings *timings)
 {
-       dpi_set_timings(dssdev, timings);
+       omapdss_dpi_set_timings(dssdev, timings);
+
+       dssdev->panel.timings = *timings;
 }
 
 static int tpo_td043_check_timings(struct omap_dss_device *dssdev,
index 5c450b0f94d0bb03a5bfef064ac613424e527247..30a48fba75b0b9354a8d35d0450481c99ac3597c 100644 (file)
@@ -3,7 +3,7 @@ omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \
        manager.o overlay.o apply.o
 omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o
 omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
-omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
+omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o venc_panel.o
 omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
 omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
 omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \
index 0fefc68372b93ca326b9c194f4529fd201b6161c..52a5940a3773c2f73e5585abda2c09cf01be7875 100644 (file)
@@ -1302,7 +1302,7 @@ err:
 }
 
 static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr,
-               struct omap_video_timings *timings)
+               const struct omap_video_timings *timings)
 {
        struct mgr_priv_data *mp = get_mgr_priv(mgr);
 
@@ -1311,7 +1311,7 @@ static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr,
 }
 
 void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
-               struct omap_video_timings *timings)
+               const struct omap_video_timings *timings)
 {
        unsigned long flags;
 
index 5b289c5f695bdd7f9cb888a70dbdf7da909b1df2..0de9a7efcbc49d350ec1d415ecd631edaece5e23 100644 (file)
@@ -81,6 +81,23 @@ struct dispc_irq_stats {
        unsigned irqs[32];
 };
 
+struct dispc_features {
+       u8 sw_start;
+       u8 fp_start;
+       u8 bp_start;
+       u16 sw_max;
+       u16 vp_max;
+       u16 hp_max;
+       int (*calc_scaling) (enum omap_channel channel,
+               const struct omap_video_timings *mgr_timings,
+               u16 width, u16 height, u16 out_width, u16 out_height,
+               enum omap_color_mode color_mode, bool *five_taps,
+               int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
+               u16 pos_x, unsigned long *core_clk);
+       unsigned long (*calc_core_clk) (enum omap_channel channel,
+               u16 width, u16 height, u16 out_width, u16 out_height);
+};
+
 static struct {
        struct platform_device *pdev;
        void __iomem    *base;
@@ -101,6 +118,8 @@ static struct {
        bool            ctx_valid;
        u32             ctx[DISPC_SZ_REGS / sizeof(u32)];
 
+       const struct dispc_features *feat;
+
 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
        spinlock_t irq_stats_lock;
        struct dispc_irq_stats irq_stats;
@@ -1939,7 +1958,18 @@ static unsigned long calc_core_clk_five_taps(enum omap_channel channel,
        return core_clk;
 }
 
-static unsigned long calc_core_clk(enum omap_channel channel, u16 width,
+static unsigned long calc_core_clk_24xx(enum omap_channel channel, u16 width,
+               u16 height, u16 out_width, u16 out_height)
+{
+       unsigned long pclk = dispc_mgr_pclk_rate(channel);
+
+       if (height > out_height && width > out_width)
+               return pclk * 4;
+       else
+               return pclk * 2;
+}
+
+static unsigned long calc_core_clk_34xx(enum omap_channel channel, u16 width,
                u16 height, u16 out_width, u16 out_height)
 {
        unsigned int hf, vf;
@@ -1958,25 +1988,163 @@ static unsigned long calc_core_clk(enum omap_channel channel, u16 width,
                hf = 2;
        else
                hf = 1;
-
        if (height > out_height)
                vf = 2;
        else
                vf = 1;
 
-       if (cpu_is_omap24xx()) {
-               if (vf > 1 && hf > 1)
-                       return pclk * 4;
-               else
-                       return pclk * 2;
-       } else if (cpu_is_omap34xx()) {
-               return pclk * vf * hf;
-       } else {
-               if (hf > 1)
-                       return DIV_ROUND_UP(pclk, out_width) * width;
-               else
-                       return pclk;
+       return pclk * vf * hf;
+}
+
+static unsigned long calc_core_clk_44xx(enum omap_channel channel, u16 width,
+               u16 height, u16 out_width, u16 out_height)
+{
+       unsigned long pclk = dispc_mgr_pclk_rate(channel);
+
+       if (width > out_width)
+               return DIV_ROUND_UP(pclk, out_width) * width;
+       else
+               return pclk;
+}
+
+static int dispc_ovl_calc_scaling_24xx(enum omap_channel channel,
+               const struct omap_video_timings *mgr_timings,
+               u16 width, u16 height, u16 out_width, u16 out_height,
+               enum omap_color_mode color_mode, bool *five_taps,
+               int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
+               u16 pos_x, unsigned long *core_clk)
+{
+       int error;
+       u16 in_width, in_height;
+       int min_factor = min(*decim_x, *decim_y);
+       const int maxsinglelinewidth =
+                       dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
+       *five_taps = false;
+
+       do {
+               in_height = DIV_ROUND_UP(height, *decim_y);
+               in_width = DIV_ROUND_UP(width, *decim_x);
+               *core_clk = dispc.feat->calc_core_clk(channel, in_width,
+                               in_height, out_width, out_height);
+               error = (in_width > maxsinglelinewidth || !*core_clk ||
+                       *core_clk > dispc_core_clk_rate());
+               if (error) {
+                       if (*decim_x == *decim_y) {
+                               *decim_x = min_factor;
+                               ++*decim_y;
+                       } else {
+                               swap(*decim_x, *decim_y);
+                               if (*decim_x < *decim_y)
+                                       ++*decim_x;
+                       }
+               }
+       } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error);
+
+       if (in_width > maxsinglelinewidth) {
+               DSSERR("Cannot scale max input width exceeded");
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int dispc_ovl_calc_scaling_34xx(enum omap_channel channel,
+               const struct omap_video_timings *mgr_timings,
+               u16 width, u16 height, u16 out_width, u16 out_height,
+               enum omap_color_mode color_mode, bool *five_taps,
+               int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
+               u16 pos_x, unsigned long *core_clk)
+{
+       int error;
+       u16 in_width, in_height;
+       int min_factor = min(*decim_x, *decim_y);
+       const int maxsinglelinewidth =
+                       dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
+
+       do {
+               in_height = DIV_ROUND_UP(height, *decim_y);
+               in_width = DIV_ROUND_UP(width, *decim_x);
+               *core_clk = calc_core_clk_five_taps(channel, mgr_timings,
+                       in_width, in_height, out_width, out_height, color_mode);
+
+               error = check_horiz_timing_omap3(channel, mgr_timings, pos_x,
+                       in_width, in_height, out_width, out_height);
+
+               if (in_width > maxsinglelinewidth)
+                       if (in_height > out_height &&
+                                               in_height < out_height * 2)
+                               *five_taps = false;
+               if (!*five_taps)
+                       *core_clk = dispc.feat->calc_core_clk(channel, in_width,
+                                       in_height, out_width, out_height);
+
+               error = (error || in_width > maxsinglelinewidth * 2 ||
+                       (in_width > maxsinglelinewidth && *five_taps) ||
+                       !*core_clk || *core_clk > dispc_core_clk_rate());
+               if (error) {
+                       if (*decim_x == *decim_y) {
+                               *decim_x = min_factor;
+                               ++*decim_y;
+                       } else {
+                               swap(*decim_x, *decim_y);
+                               if (*decim_x < *decim_y)
+                                       ++*decim_x;
+                       }
+               }
+       } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error);
+
+       if (check_horiz_timing_omap3(channel, mgr_timings, pos_x, width, height,
+               out_width, out_height)){
+                       DSSERR("horizontal timing too tight\n");
+                       return -EINVAL;
+       }
+
+       if (in_width > (maxsinglelinewidth * 2)) {
+               DSSERR("Cannot setup scaling");
+               DSSERR("width exceeds maximum width possible");
+               return -EINVAL;
+       }
+
+       if (in_width > maxsinglelinewidth && *five_taps) {
+               DSSERR("cannot setup scaling with five taps");
+               return -EINVAL;
        }
+       return 0;
+}
+
+static int dispc_ovl_calc_scaling_44xx(enum omap_channel channel,
+               const struct omap_video_timings *mgr_timings,
+               u16 width, u16 height, u16 out_width, u16 out_height,
+               enum omap_color_mode color_mode, bool *five_taps,
+               int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
+               u16 pos_x, unsigned long *core_clk)
+{
+       u16 in_width, in_width_max;
+       int decim_x_min = *decim_x;
+       u16 in_height = DIV_ROUND_UP(height, *decim_y);
+       const int maxsinglelinewidth =
+                               dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
+
+       in_width_max = dispc_core_clk_rate() /
+                       DIV_ROUND_UP(dispc_mgr_pclk_rate(channel), out_width);
+       *decim_x = DIV_ROUND_UP(width, in_width_max);
+
+       *decim_x = *decim_x > decim_x_min ? *decim_x : decim_x_min;
+       if (*decim_x > *x_predecim)
+               return -EINVAL;
+
+       do {
+               in_width = DIV_ROUND_UP(width, *decim_x);
+       } while (*decim_x <= *x_predecim &&
+                       in_width > maxsinglelinewidth && ++*decim_x);
+
+       if (in_width > maxsinglelinewidth) {
+               DSSERR("Cannot scale width exceeds max line width");
+               return -EINVAL;
+       }
+
+       *core_clk = dispc.feat->calc_core_clk(channel, in_width, in_height,
+                               out_width, out_height);
+       return 0;
 }
 
 static int dispc_ovl_calc_scaling(enum omap_plane plane,
@@ -1988,12 +2156,9 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
 {
        struct omap_overlay *ovl = omap_dss_get_overlay(plane);
        const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
-       const int maxsinglelinewidth =
-                               dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
        const int max_decim_limit = 16;
        unsigned long core_clk = 0;
-       int decim_x, decim_y, error, min_factor;
-       u16 in_width, in_height, in_width_max = 0;
+       int decim_x, decim_y, ret;
 
        if (width == out_width && height == out_height)
                return 0;
@@ -2017,118 +2182,17 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
        decim_x = DIV_ROUND_UP(DIV_ROUND_UP(width, out_width), maxdownscale);
        decim_y = DIV_ROUND_UP(DIV_ROUND_UP(height, out_height), maxdownscale);
 
-       min_factor = min(decim_x, decim_y);
-
        if (decim_x > *x_predecim || out_width > width * 8)
                return -EINVAL;
 
        if (decim_y > *y_predecim || out_height > height * 8)
                return -EINVAL;
 
-       if (cpu_is_omap24xx()) {
-               *five_taps = false;
-
-               do {
-                       in_height = DIV_ROUND_UP(height, decim_y);
-                       in_width = DIV_ROUND_UP(width, decim_x);
-                       core_clk = calc_core_clk(channel, in_width, in_height,
-                                       out_width, out_height);
-                       error = (in_width > maxsinglelinewidth || !core_clk ||
-                               core_clk > dispc_core_clk_rate());
-                       if (error) {
-                               if (decim_x == decim_y) {
-                                       decim_x = min_factor;
-                                       decim_y++;
-                               } else {
-                                       swap(decim_x, decim_y);
-                                       if (decim_x < decim_y)
-                                               decim_x++;
-                               }
-                       }
-               } while (decim_x <= *x_predecim && decim_y <= *y_predecim &&
-                               error);
-
-               if (in_width > maxsinglelinewidth) {
-                       DSSERR("Cannot scale max input width exceeded");
-                       return -EINVAL;
-               }
-       } else if (cpu_is_omap34xx()) {
-
-               do {
-                       in_height = DIV_ROUND_UP(height, decim_y);
-                       in_width = DIV_ROUND_UP(width, decim_x);
-                       core_clk = calc_core_clk_five_taps(channel, mgr_timings,
-                               in_width, in_height, out_width, out_height,
-                               color_mode);
-
-                       error = check_horiz_timing_omap3(channel, mgr_timings,
-                               pos_x, in_width, in_height, out_width,
-                               out_height);
-
-                       if (in_width > maxsinglelinewidth)
-                               if (in_height > out_height &&
-                                       in_height < out_height * 2)
-                                       *five_taps = false;
-                       if (!*five_taps)
-                               core_clk = calc_core_clk(channel, in_width,
-                                       in_height, out_width, out_height);
-                       error = (error || in_width > maxsinglelinewidth * 2 ||
-                               (in_width > maxsinglelinewidth && *five_taps) ||
-                               !core_clk || core_clk > dispc_core_clk_rate());
-                       if (error) {
-                               if (decim_x == decim_y) {
-                                       decim_x = min_factor;
-                                       decim_y++;
-                               } else {
-                                       swap(decim_x, decim_y);
-                                       if (decim_x < decim_y)
-                                               decim_x++;
-                               }
-                       }
-               } while (decim_x <= *x_predecim && decim_y <= *y_predecim
-                       && error);
-
-               if (check_horiz_timing_omap3(channel, mgr_timings, pos_x, width,
-                       height, out_width, out_height)){
-                               DSSERR("horizontal timing too tight\n");
-                               return -EINVAL;
-               }
-
-               if (in_width > (maxsinglelinewidth * 2)) {
-                       DSSERR("Cannot setup scaling");
-                       DSSERR("width exceeds maximum width possible");
-                       return -EINVAL;
-               }
-
-               if (in_width > maxsinglelinewidth && *five_taps) {
-                       DSSERR("cannot setup scaling with five taps");
-                       return -EINVAL;
-               }
-       } else {
-               int decim_x_min = decim_x;
-               in_height = DIV_ROUND_UP(height, decim_y);
-               in_width_max = dispc_core_clk_rate() /
-                               DIV_ROUND_UP(dispc_mgr_pclk_rate(channel),
-                                               out_width);
-               decim_x = DIV_ROUND_UP(width, in_width_max);
-
-               decim_x = decim_x > decim_x_min ? decim_x : decim_x_min;
-               if (decim_x > *x_predecim)
-                       return -EINVAL;
-
-               do {
-                       in_width = DIV_ROUND_UP(width, decim_x);
-               } while (decim_x <= *x_predecim &&
-                               in_width > maxsinglelinewidth && decim_x++);
-
-               if (in_width > maxsinglelinewidth) {
-                       DSSERR("Cannot scale width exceeds max line width");
-                       return -EINVAL;
-               }
-
-               core_clk = calc_core_clk(channel, in_width, in_height,
-                               out_width, out_height);
-       }
+       ret = dispc.feat->calc_scaling(channel, mgr_timings, width, height,
+               out_width, out_height, color_mode, five_taps, x_predecim,
+               y_predecim, &decim_x, &decim_y, pos_x, &core_clk);
+       if (ret)
+               return ret;
 
        DSSDBG("required core clk rate = %lu Hz\n", core_clk);
        DSSDBG("current core clk rate = %lu Hz\n", dispc_core_clk_rate());
@@ -2604,24 +2668,13 @@ static bool _dispc_mgr_size_ok(u16 width, u16 height)
 static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
                int vsw, int vfp, int vbp)
 {
-       if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) {
-               if (hsw < 1 || hsw > 64 ||
-                               hfp < 1 || hfp > 256 ||
-                               hbp < 1 || hbp > 256 ||
-                               vsw < 1 || vsw > 64 ||
-                               vfp < 0 || vfp > 255 ||
-                               vbp < 0 || vbp > 255)
-                       return false;
-       } else {
-               if (hsw < 1 || hsw > 256 ||
-                               hfp < 1 || hfp > 4096 ||
-                               hbp < 1 || hbp > 4096 ||
-                               vsw < 1 || vsw > 256 ||
-                               vfp < 0 || vfp > 4095 ||
-                               vbp < 0 || vbp > 4095)
-                       return false;
-       }
-
+       if (hsw < 1 || hsw > dispc.feat->sw_max ||
+                       hfp < 1 || hfp > dispc.feat->hp_max ||
+                       hbp < 1 || hbp > dispc.feat->hp_max ||
+                       vsw < 1 || vsw > dispc.feat->sw_max ||
+                       vfp < 0 || vfp > dispc.feat->vp_max ||
+                       vbp < 0 || vbp > dispc.feat->vp_max)
+               return false;
        return true;
 }
 
@@ -2653,19 +2706,12 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw,
        u32 timing_h, timing_v, l;
        bool onoff, rf, ipc;
 
-       if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) {
-               timing_h = FLD_VAL(hsw-1, 5, 0) | FLD_VAL(hfp-1, 15, 8) |
-                       FLD_VAL(hbp-1, 27, 20);
-
-               timing_v = FLD_VAL(vsw-1, 5, 0) | FLD_VAL(vfp, 15, 8) |
-                       FLD_VAL(vbp, 27, 20);
-       } else {
-               timing_h = FLD_VAL(hsw-1, 7, 0) | FLD_VAL(hfp-1, 19, 8) |
-                       FLD_VAL(hbp-1, 31, 20);
-
-               timing_v = FLD_VAL(vsw-1, 7, 0) | FLD_VAL(vfp, 19, 8) |
-                       FLD_VAL(vbp, 31, 20);
-       }
+       timing_h = FLD_VAL(hsw-1, dispc.feat->sw_start, 0) |
+                       FLD_VAL(hfp-1, dispc.feat->fp_start, 8) |
+                       FLD_VAL(hbp-1, dispc.feat->bp_start, 20);
+       timing_v = FLD_VAL(vsw-1, dispc.feat->sw_start, 0) |
+                       FLD_VAL(vfp, dispc.feat->fp_start, 8) |
+                       FLD_VAL(vbp, dispc.feat->bp_start, 20);
 
        dispc_write_reg(DISPC_TIMING_H(channel), timing_h);
        dispc_write_reg(DISPC_TIMING_V(channel), timing_v);
@@ -3491,7 +3537,7 @@ static void dispc_error_worker(struct work_struct *work)
                                        ovl->name);
                        dispc_ovl_enable(ovl->id, false);
                        dispc_mgr_go(ovl->manager->id);
-                       mdelay(50);
+                       msleep(50);
                }
        }
 
@@ -3523,7 +3569,7 @@ static void dispc_error_worker(struct work_struct *work)
                        }
 
                        dispc_mgr_go(mgr->id);
-                       mdelay(50);
+                       msleep(50);
 
                        if (enable)
                                dssdev->driver->enable(dssdev);
@@ -3671,6 +3717,80 @@ static void _omap_dispc_initial_config(void)
        dispc_ovl_enable_zorder_planes();
 }
 
+static const struct dispc_features omap24xx_dispc_feats __initconst = {
+       .sw_start               =       5,
+       .fp_start               =       15,
+       .bp_start               =       27,
+       .sw_max                 =       64,
+       .vp_max                 =       255,
+       .hp_max                 =       256,
+       .calc_scaling           =       dispc_ovl_calc_scaling_24xx,
+       .calc_core_clk          =       calc_core_clk_24xx,
+};
+
+static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = {
+       .sw_start               =       5,
+       .fp_start               =       15,
+       .bp_start               =       27,
+       .sw_max                 =       64,
+       .vp_max                 =       255,
+       .hp_max                 =       256,
+       .calc_scaling           =       dispc_ovl_calc_scaling_34xx,
+       .calc_core_clk          =       calc_core_clk_34xx,
+};
+
+static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = {
+       .sw_start               =       7,
+       .fp_start               =       19,
+       .bp_start               =       31,
+       .sw_max                 =       256,
+       .vp_max                 =       4095,
+       .hp_max                 =       4096,
+       .calc_scaling           =       dispc_ovl_calc_scaling_34xx,
+       .calc_core_clk          =       calc_core_clk_34xx,
+};
+
+static const struct dispc_features omap44xx_dispc_feats __initconst = {
+       .sw_start               =       7,
+       .fp_start               =       19,
+       .bp_start               =       31,
+       .sw_max                 =       256,
+       .vp_max                 =       4095,
+       .hp_max                 =       4096,
+       .calc_scaling           =       dispc_ovl_calc_scaling_44xx,
+       .calc_core_clk          =       calc_core_clk_44xx,
+};
+
+static int __init dispc_init_features(struct device *dev)
+{
+       const struct dispc_features *src;
+       struct dispc_features *dst;
+
+       dst = devm_kzalloc(dev, sizeof(*dst), GFP_KERNEL);
+       if (!dst) {
+               dev_err(dev, "Failed to allocate DISPC Features\n");
+               return -ENOMEM;
+       }
+
+       if (cpu_is_omap24xx()) {
+               src = &omap24xx_dispc_feats;
+       } else if (cpu_is_omap34xx()) {
+               if (omap_rev() < OMAP3430_REV_ES3_0)
+                       src = &omap34xx_rev1_0_dispc_feats;
+               else
+                       src = &omap34xx_rev3_0_dispc_feats;
+       } else if (cpu_is_omap44xx()) {
+               src = &omap44xx_dispc_feats;
+       } else {
+               return -ENODEV;
+       }
+
+       memcpy(dst, src, sizeof(*dst));
+       dispc.feat = dst;
+
+       return 0;
+}
+
 /* DISPC HW IP initialisation */
 static int __init omap_dispchw_probe(struct platform_device *pdev)
 {
@@ -3681,6 +3801,10 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
 
        dispc.pdev = pdev;
 
+       r = dispc_init_features(&dispc.pdev->dev);
+       if (r)
+               return r;
+
        spin_lock_init(&dispc.irq_lock);
 
 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
index 3266be23fc0dbd529e4e1b457c37462a3faef442..25fb8953b80aa202f56fd0c8d1f71d2ffb3dca6b 100644 (file)
 #include <plat/cpu.h>
 
 #include "dss.h"
+#include "dss_features.h"
 
 static struct {
        struct regulator *vdds_dsi_reg;
        struct platform_device *dsidev;
 
+       struct mutex lock;
+
+       struct omap_video_timings timings;
        struct dss_lcd_mgr_config mgr_config;
+       int data_lines;
 } dpi;
 
 static struct platform_device *dpi_get_dsidev(enum omap_dss_clk_source clk)
@@ -121,7 +126,7 @@ static int dpi_set_dispc_clk(struct omap_dss_device *dssdev,
 
 static int dpi_set_mode(struct omap_dss_device *dssdev)
 {
-       struct omap_video_timings *t = &dssdev->panel.timings;
+       struct omap_video_timings *t = &dpi.timings;
        int lck_div = 0, pck_div = 0;
        unsigned long fck = 0;
        unsigned long pck;
@@ -158,7 +163,7 @@ static void dpi_config_lcd_manager(struct omap_dss_device *dssdev)
        dpi.mgr_config.stallmode = false;
        dpi.mgr_config.fifohandcheck = false;
 
-       dpi.mgr_config.video_port_width = dssdev->phy.dpi.data_lines;
+       dpi.mgr_config.video_port_width = dpi.data_lines;
 
        dpi.mgr_config.lcden_sig_polarity = 0;
 
@@ -169,14 +174,18 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
 {
        int r;
 
-       if (cpu_is_omap34xx() && !dpi.vdds_dsi_reg) {
+       mutex_lock(&dpi.lock);
+
+       if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) && !dpi.vdds_dsi_reg) {
                DSSERR("no VDSS_DSI regulator\n");
-               return -ENODEV;
+               r = -ENODEV;
+               goto err_no_reg;
        }
 
        if (dssdev->manager == NULL) {
                DSSERR("failed to enable display: no manager\n");
-               return -ENODEV;
+               r = -ENODEV;
+               goto err_no_mgr;
        }
 
        r = omap_dss_start_device(dssdev);
@@ -185,7 +194,7 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
                goto err_start_dev;
        }
 
-       if (cpu_is_omap34xx()) {
+       if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI)) {
                r = regulator_enable(dpi.vdds_dsi_reg);
                if (r)
                        goto err_reg_enable;
@@ -217,6 +226,8 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
        if (r)
                goto err_mgr_enable;
 
+       mutex_unlock(&dpi.lock);
+
        return 0;
 
 err_mgr_enable:
@@ -229,17 +240,22 @@ err_dsi_pll_init:
 err_get_dsi:
        dispc_runtime_put();
 err_get_dispc:
-       if (cpu_is_omap34xx())
+       if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
                regulator_disable(dpi.vdds_dsi_reg);
 err_reg_enable:
        omap_dss_stop_device(dssdev);
 err_start_dev:
+err_no_mgr:
+err_no_reg:
+       mutex_unlock(&dpi.lock);
        return r;
 }
 EXPORT_SYMBOL(omapdss_dpi_display_enable);
 
 void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
 {
+       mutex_lock(&dpi.lock);
+
        dss_mgr_disable(dssdev->manager);
 
        if (dpi_use_dsi_pll(dssdev)) {
@@ -250,20 +266,26 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
 
        dispc_runtime_put();
 
-       if (cpu_is_omap34xx())
+       if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
                regulator_disable(dpi.vdds_dsi_reg);
 
        omap_dss_stop_device(dssdev);
+
+       mutex_unlock(&dpi.lock);
 }
 EXPORT_SYMBOL(omapdss_dpi_display_disable);
 
-void dpi_set_timings(struct omap_dss_device *dssdev,
-                       struct omap_video_timings *timings)
+void omapdss_dpi_set_timings(struct omap_dss_device *dssdev,
+               struct omap_video_timings *timings)
 {
        int r;
 
        DSSDBG("dpi_set_timings\n");
-       dssdev->panel.timings = *timings;
+
+       mutex_lock(&dpi.lock);
+
+       dpi.timings = *timings;
+
        if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
                r = dispc_runtime_get();
                if (r)
@@ -275,8 +297,10 @@ void dpi_set_timings(struct omap_dss_device *dssdev,
        } else {
                dss_mgr_set_timings(dssdev->manager, timings);
        }
+
+       mutex_unlock(&dpi.lock);
 }
-EXPORT_SYMBOL(dpi_set_timings);
+EXPORT_SYMBOL(omapdss_dpi_set_timings);
 
 int dpi_check_timings(struct omap_dss_device *dssdev,
                        struct omap_video_timings *timings)
@@ -325,11 +349,22 @@ int dpi_check_timings(struct omap_dss_device *dssdev,
 }
 EXPORT_SYMBOL(dpi_check_timings);
 
+void omapdss_dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
+{
+       mutex_lock(&dpi.lock);
+
+       dpi.data_lines = data_lines;
+
+       mutex_unlock(&dpi.lock);
+}
+EXPORT_SYMBOL(omapdss_dpi_set_data_lines);
+
 static int __init dpi_init_display(struct omap_dss_device *dssdev)
 {
        DSSDBG("init_display\n");
 
-       if (cpu_is_omap34xx() && dpi.vdds_dsi_reg == NULL) {
+       if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) &&
+                                       dpi.vdds_dsi_reg == NULL) {
                struct regulator *vdds_dsi;
 
                vdds_dsi = dss_get_vdds_dsi();
@@ -377,6 +412,8 @@ static void __init dpi_probe_pdata(struct platform_device *pdev)
 
 static int __init omap_dpi_probe(struct platform_device *pdev)
 {
+       mutex_init(&dpi.lock);
+
        dpi_probe_pdata(pdev);
 
        return 0;
index b07e8864f82fd4f034f5b59cf2009850bb3ec6d1..96d0024ada4078507d456e2b3ba384b60d2b3ccf 100644 (file)
@@ -333,6 +333,10 @@ struct dsi_data {
        unsigned scp_clk_refcount;
 
        struct dss_lcd_mgr_config mgr_config;
+       struct omap_video_timings timings;
+       enum omap_dss_dsi_pixel_format pix_fmt;
+       enum omap_dss_dsi_mode mode;
+       struct omap_dss_dsi_videomode_timings vm_timings;
 };
 
 struct dsi_packet_sent_handler_data {
@@ -2360,10 +2364,10 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
 
        dsi_cio_timings(dsidev);
 
-       if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
+       if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
                /* DDR_CLK_ALWAYS_ON */
                REG_FLD_MOD(dsidev, DSI_CLK_CTRL,
-                       dssdev->panel.dsi_vm_data.ddr_clk_always_on, 13, 13);
+                       dsi->vm_timings.ddr_clk_always_on, 13, 13);
        }
 
        dsi->ulps_enabled = false;
@@ -2685,6 +2689,7 @@ void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
                bool enable)
 {
        struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 
        DSSDBG("dsi_vc_enable_hs(%d, %d)\n", channel, enable);
 
@@ -2701,7 +2706,7 @@ void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
        dsi_force_tx_stop_mode_io(dsidev);
 
        /* start the DDR clock by sending a NULL packet */
-       if (dssdev->panel.dsi_vm_data.ddr_clk_always_on && enable)
+       if (dsi->vm_timings.ddr_clk_always_on && enable)
                dsi_vc_send_null(dssdev, channel);
 }
 EXPORT_SYMBOL(omapdss_dsi_vc_enable_hs);
@@ -3607,12 +3612,14 @@ static void dsi_set_hs_tx_timeout(struct platform_device *dsidev,
 static void dsi_config_vp_num_line_buffers(struct omap_dss_device *dssdev)
 {
        struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
        int num_line_buffers;
 
-       if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
-               int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
+       if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
+               struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+               int bpp = dsi_get_pixel_size(dsi->pix_fmt);
                unsigned line_buf_size = dsi_get_line_buf_size(dsidev);
-               struct omap_video_timings *timings = &dssdev->panel.timings;
+               struct omap_video_timings *timings = &dsi->timings;
                /*
                 * Don't use line buffers if width is greater than the video
                 * port's line buffer size
@@ -3633,8 +3640,9 @@ static void dsi_config_vp_num_line_buffers(struct omap_dss_device *dssdev)
 static void dsi_config_vp_sync_events(struct omap_dss_device *dssdev)
 {
        struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-       bool vsync_end = dssdev->panel.dsi_vm_data.vp_vsync_end;
-       bool hsync_end = dssdev->panel.dsi_vm_data.vp_hsync_end;
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+       bool vsync_end = dsi->vm_timings.vp_vsync_end;
+       bool hsync_end = dsi->vm_timings.vp_hsync_end;
        u32 r;
 
        r = dsi_read_reg(dsidev, DSI_CTRL);
@@ -3651,10 +3659,11 @@ static void dsi_config_vp_sync_events(struct omap_dss_device *dssdev)
 static void dsi_config_blanking_modes(struct omap_dss_device *dssdev)
 {
        struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-       int blanking_mode = dssdev->panel.dsi_vm_data.blanking_mode;
-       int hfp_blanking_mode = dssdev->panel.dsi_vm_data.hfp_blanking_mode;
-       int hbp_blanking_mode = dssdev->panel.dsi_vm_data.hbp_blanking_mode;
-       int hsa_blanking_mode = dssdev->panel.dsi_vm_data.hsa_blanking_mode;
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+       int blanking_mode = dsi->vm_timings.blanking_mode;
+       int hfp_blanking_mode = dsi->vm_timings.hfp_blanking_mode;
+       int hbp_blanking_mode = dsi->vm_timings.hbp_blanking_mode;
+       int hsa_blanking_mode = dsi->vm_timings.hsa_blanking_mode;
        u32 r;
 
        /*
@@ -3741,8 +3750,8 @@ static void dsi_config_cmd_mode_interleaving(struct omap_dss_device *dssdev)
        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 omap_video_timings *timings = &dssdev->panel.timings;
-       int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
+       struct omap_video_timings *timings = &dsi->timings;
+       int bpp = dsi_get_pixel_size(dsi->pix_fmt);
        int ndl = dsi->num_lanes_used - 1;
        int dsi_fclk_hsdiv = dssdev->clocks.dsi.regm_dsi + 1;
        int hsa_interleave_hs = 0, hsa_interleave_lp = 0;
@@ -3852,6 +3861,7 @@ static void dsi_config_cmd_mode_interleaving(struct omap_dss_device *dssdev)
 static int dsi_proto_config(struct omap_dss_device *dssdev)
 {
        struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
        u32 r;
        int buswidth = 0;
 
@@ -3871,7 +3881,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
        dsi_set_lp_rx_timeout(dsidev, 0x1fff, true, true);
        dsi_set_hs_tx_timeout(dsidev, 0x1fff, true, true);
 
-       switch (dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt)) {
+       switch (dsi_get_pixel_size(dsi->pix_fmt)) {
        case 16:
                buswidth = 0;
                break;
@@ -3905,7 +3915,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
 
        dsi_config_vp_num_line_buffers(dssdev);
 
-       if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
+       if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
                dsi_config_vp_sync_events(dssdev);
                dsi_config_blanking_modes(dssdev);
                dsi_config_cmd_mode_interleaving(dssdev);
@@ -3984,18 +3994,18 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)
        DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n",
                        enter_hs_mode_lat, exit_hs_mode_lat);
 
-        if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
+        if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
                /* TODO: Implement a video mode check_timings function */
-               int hsa = dssdev->panel.dsi_vm_data.hsa;
-               int hfp = dssdev->panel.dsi_vm_data.hfp;
-               int hbp = dssdev->panel.dsi_vm_data.hbp;
-               int vsa = dssdev->panel.dsi_vm_data.vsa;
-               int vfp = dssdev->panel.dsi_vm_data.vfp;
-               int vbp = dssdev->panel.dsi_vm_data.vbp;
-               int window_sync = dssdev->panel.dsi_vm_data.window_sync;
-               bool hsync_end = dssdev->panel.dsi_vm_data.vp_hsync_end;
-               struct omap_video_timings *timings = &dssdev->panel.timings;
-               int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
+               int hsa = dsi->vm_timings.hsa;
+               int hfp = dsi->vm_timings.hfp;
+               int hbp = dsi->vm_timings.hbp;
+               int vsa = dsi->vm_timings.vsa;
+               int vfp = dsi->vm_timings.vfp;
+               int vbp = dsi->vm_timings.vbp;
+               int window_sync = dsi->vm_timings.window_sync;
+               bool hsync_end = dsi->vm_timings.vp_hsync_end;
+               struct omap_video_timings *timings = &dsi->timings;
+               int bpp = dsi_get_pixel_size(dsi->pix_fmt);
                int tl, t_he, width_bytes;
 
                t_he = hsync_end ?
@@ -4103,13 +4113,14 @@ EXPORT_SYMBOL(omapdss_dsi_configure_pins);
 int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
 {
        struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-       int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+       int bpp = dsi_get_pixel_size(dsi->pix_fmt);
        u8 data_type;
        u16 word_count;
        int r;
 
-       if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
-               switch (dssdev->panel.dsi_pix_fmt) {
+       if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
+               switch (dsi->pix_fmt) {
                case OMAP_DSS_DSI_FMT_RGB888:
                        data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24;
                        break;
@@ -4133,7 +4144,7 @@ int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
                /* MODE, 1 = video mode */
                REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 4, 4);
 
-               word_count = DIV_ROUND_UP(dssdev->panel.timings.x_res * bpp, 8);
+               word_count = DIV_ROUND_UP(dsi->timings.x_res * bpp, 8);
 
                dsi_vc_write_long_header(dsidev, channel, data_type,
                                word_count, 0);
@@ -4144,7 +4155,7 @@ int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
 
        r = dss_mgr_enable(dssdev->manager);
        if (r) {
-               if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
+               if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
                        dsi_if_enable(dsidev, false);
                        dsi_vc_enable(dsidev, channel, false);
                }
@@ -4159,8 +4170,9 @@ EXPORT_SYMBOL(dsi_enable_video_output);
 void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel)
 {
        struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 
-       if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
+       if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
                dsi_if_enable(dsidev, false);
                dsi_vc_enable(dsidev, channel, false);
 
@@ -4175,8 +4187,7 @@ void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel)
 }
 EXPORT_SYMBOL(dsi_disable_video_output);
 
-static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
-               u16 w, u16 h)
+static void dsi_update_screen_dispc(struct omap_dss_device *dssdev)
 {
        struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
@@ -4190,12 +4201,14 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
        int r;
        const unsigned channel = dsi->update_channel;
        const unsigned line_buf_size = dsi_get_line_buf_size(dsidev);
+       u16 w = dsi->timings.x_res;
+       u16 h = dsi->timings.y_res;
 
        DSSDBG("dsi_update_screen_dispc(%dx%d)\n", w, h);
 
        dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_VP);
 
-       bytespp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8;
+       bytespp = dsi_get_pixel_size(dsi->pix_fmt) / 8;
        bytespl = w * bytespp;
        bytespf = bytespl * h;
 
@@ -4239,6 +4252,8 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
                msecs_to_jiffies(250));
        BUG_ON(r == 0);
 
+       dss_mgr_set_timings(dssdev->manager, &dsi->timings);
+
        dss_mgr_start_update(dssdev->manager);
 
        if (dsi->te_enabled) {
@@ -4325,13 +4340,14 @@ int omap_dsi_update(struct omap_dss_device *dssdev, int channel,
        dsi->framedone_callback = callback;
        dsi->framedone_data = data;
 
-       dssdev->driver->get_resolution(dssdev, &dw, &dh);
+       dw = dsi->timings.x_res;
+       dh = dsi->timings.y_res;
 
 #ifdef DEBUG
        dsi->update_bytes = dw * dh *
-               dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8;
+               dsi_get_pixel_size(dsi->pix_fmt) / 8;
 #endif
-       dsi_update_screen_dispc(dssdev, dw, dh);
+       dsi_update_screen_dispc(dssdev);
 
        return 0;
 }
@@ -4367,23 +4383,16 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
 {
        struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-       struct omap_video_timings timings;
        int r;
        u32 irq = 0;
 
-       if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) {
-               u16 dw, dh;
-
-               dssdev->driver->get_resolution(dssdev, &dw, &dh);
-
-               timings.x_res = dw;
-               timings.y_res = dh;
-               timings.hsw = 1;
-               timings.hfp = 1;
-               timings.hbp = 1;
-               timings.vsw = 1;
-               timings.vfp = 0;
-               timings.vbp = 0;
+       if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {
+               dsi->timings.hsw = 1;
+               dsi->timings.hfp = 1;
+               dsi->timings.hbp = 1;
+               dsi->timings.vsw = 1;
+               dsi->timings.vfp = 0;
+               dsi->timings.vbp = 0;
 
                irq = dispc_mgr_get_framedone_irq(dssdev->manager->id);
 
@@ -4397,8 +4406,6 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
                dsi->mgr_config.stallmode = true;
                dsi->mgr_config.fifohandcheck = true;
        } else {
-               timings = dssdev->panel.timings;
-
                dsi->mgr_config.stallmode = false;
                dsi->mgr_config.fifohandcheck = false;
        }
@@ -4407,14 +4414,14 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
         * override interlace, logic level and edge related parameters in
         * omap_video_timings with default values
         */
-       timings.interlace = false;
-       timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
-       timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
-       timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
-       timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH;
-       timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
+       dsi->timings.interlace = false;
+       dsi->timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
+       dsi->timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
+       dsi->timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
+       dsi->timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH;
+       dsi->timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
 
-       dss_mgr_set_timings(dssdev->manager, &timings);
+       dss_mgr_set_timings(dssdev->manager, &dsi->timings);
 
        r = dsi_configure_dispc_clocks(dssdev);
        if (r)
@@ -4422,14 +4429,14 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
 
        dsi->mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
        dsi->mgr_config.video_port_width =
-                       dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
+                       dsi_get_pixel_size(dsi->pix_fmt);
        dsi->mgr_config.lcden_sig_polarity = 0;
 
        dss_mgr_set_lcd_config(dssdev->manager, &dsi->mgr_config);
 
        return 0;
 err1:
-       if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE)
+       if (dsi->mode == OMAP_DSS_DSI_CMD_MODE)
                omap_dispc_unregister_isr(dsi_framedone_irq_callback,
                        (void *) dssdev, irq);
 err:
@@ -4438,7 +4445,10 @@ err:
 
 static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev)
 {
-       if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) {
+       struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+       if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {
                u32 irq;
 
                irq = dispc_mgr_get_framedone_irq(dssdev->manager->id);
@@ -4653,6 +4663,76 @@ int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable)
 }
 EXPORT_SYMBOL(omapdss_dsi_enable_te);
 
+void omapdss_dsi_set_timings(struct omap_dss_device *dssdev,
+               struct omap_video_timings *timings)
+{
+       struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+       mutex_lock(&dsi->lock);
+
+       dsi->timings = *timings;
+
+       mutex_unlock(&dsi->lock);
+}
+EXPORT_SYMBOL(omapdss_dsi_set_timings);
+
+void omapdss_dsi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h)
+{
+       struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+       mutex_lock(&dsi->lock);
+
+       dsi->timings.x_res = w;
+       dsi->timings.y_res = h;
+
+       mutex_unlock(&dsi->lock);
+}
+EXPORT_SYMBOL(omapdss_dsi_set_size);
+
+void omapdss_dsi_set_pixel_format(struct omap_dss_device *dssdev,
+               enum omap_dss_dsi_pixel_format fmt)
+{
+       struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+       mutex_lock(&dsi->lock);
+
+       dsi->pix_fmt = fmt;
+
+       mutex_unlock(&dsi->lock);
+}
+EXPORT_SYMBOL(omapdss_dsi_set_pixel_format);
+
+void omapdss_dsi_set_operation_mode(struct omap_dss_device *dssdev,
+               enum omap_dss_dsi_mode mode)
+{
+       struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+       mutex_lock(&dsi->lock);
+
+       dsi->mode = mode;
+
+       mutex_unlock(&dsi->lock);
+}
+EXPORT_SYMBOL(omapdss_dsi_set_operation_mode);
+
+void omapdss_dsi_set_videomode_timings(struct omap_dss_device *dssdev,
+               struct omap_dss_dsi_videomode_timings *timings)
+{
+       struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+       mutex_lock(&dsi->lock);
+
+       dsi->vm_timings = *timings;
+
+       mutex_unlock(&dsi->lock);
+}
+EXPORT_SYMBOL(omapdss_dsi_set_videomode_timings);
+
 static int __init dsi_init_display(struct omap_dss_device *dssdev)
 {
        struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -4660,7 +4740,7 @@ static int __init dsi_init_display(struct omap_dss_device *dssdev)
 
        DSSDBG("DSI init\n");
 
-       if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) {
+       if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {
                dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
                        OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
        }
index 04b4586113e34928e1784e22c844da287d5750ed..31a553a6ee6f2dd08ab579e451ed6e880e242bb4 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/clk.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
+#include <linux/gfp.h>
 
 #include <video/omapdss.h>
 
@@ -65,6 +66,12 @@ struct dss_reg {
 static int dss_runtime_get(void);
 static void dss_runtime_put(void);
 
+struct dss_features {
+       u8 fck_div_max;
+       u8 dss_fck_multiplier;
+       const char *clk_name;
+};
+
 static struct {
        struct platform_device *pdev;
        void __iomem    *base;
@@ -83,6 +90,8 @@ static struct {
 
        bool            ctx_valid;
        u32             ctx[DSS_SZ_REGS / sizeof(u32)];
+
+       const struct dss_features *feat;
 } dss;
 
 static const char * const dss_generic_clk_source_names[] = {
@@ -91,6 +100,30 @@ static const char * const dss_generic_clk_source_names[] = {
        [OMAP_DSS_CLK_SRC_FCK]                  = "DSS_FCK",
 };
 
+static const struct dss_features omap24xx_dss_feats __initconst = {
+       .fck_div_max            =       16,
+       .dss_fck_multiplier     =       2,
+       .clk_name               =       NULL,
+};
+
+static const struct dss_features omap34xx_dss_feats __initconst = {
+       .fck_div_max            =       16,
+       .dss_fck_multiplier     =       2,
+       .clk_name               =       "dpll4_m4_ck",
+};
+
+static const struct dss_features omap3630_dss_feats __initconst = {
+       .fck_div_max            =       32,
+       .dss_fck_multiplier     =       1,
+       .clk_name               =       "dpll4_m4_ck",
+};
+
+static const struct dss_features omap44xx_dss_feats __initconst = {
+       .fck_div_max            =       32,
+       .dss_fck_multiplier     =       1,
+       .clk_name               =       "dpll_per_m5x2_ck",
+};
+
 static inline void dss_write_reg(const struct dss_reg idx, u32 val)
 {
        __raw_writel(val, dss.base + idx.idx);
@@ -144,7 +177,7 @@ static void dss_restore_context(void)
 #undef SR
 #undef RR
 
-void dss_sdi_init(u8 datapairs)
+void dss_sdi_init(int datapairs)
 {
        u32 l;
 
@@ -236,7 +269,6 @@ const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src)
        return dss_generic_clk_source_names[clk_src];
 }
 
-
 void dss_dump_clocks(struct seq_file *s)
 {
        unsigned long dpll4_ck_rate;
@@ -259,18 +291,10 @@ void dss_dump_clocks(struct seq_file *s)
 
                seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate);
 
-               if (cpu_is_omap3630() || cpu_is_omap44xx())
-                       seq_printf(s, "%s (%s) = %lu / %lu  = %lu\n",
-                                       fclk_name, fclk_real_name,
-                                       dpll4_ck_rate,
-                                       dpll4_ck_rate / dpll4_m4_ck_rate,
-                                       fclk_rate);
-               else
-                       seq_printf(s, "%s (%s) = %lu / %lu * 2 = %lu\n",
-                                       fclk_name, fclk_real_name,
-                                       dpll4_ck_rate,
-                                       dpll4_ck_rate / dpll4_m4_ck_rate,
-                                       fclk_rate);
+               seq_printf(s, "%s (%s) = %lu / %lu * %d  = %lu\n",
+                               fclk_name, fclk_real_name, dpll4_ck_rate,
+                               dpll4_ck_rate / dpll4_m4_ck_rate,
+                               dss.feat->dss_fck_multiplier, fclk_rate);
        } else {
                seq_printf(s, "%s (%s) = %lu\n",
                                fclk_name, fclk_real_name,
@@ -431,31 +455,6 @@ enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
        }
 }
 
-/* calculate clock rates using dividers in cinfo */
-int dss_calc_clock_rates(struct dss_clock_info *cinfo)
-{
-       if (dss.dpll4_m4_ck) {
-               unsigned long prate;
-               u16 fck_div_max = 16;
-
-               if (cpu_is_omap3630() || cpu_is_omap44xx())
-                       fck_div_max = 32;
-
-               if (cinfo->fck_div > fck_div_max || cinfo->fck_div == 0)
-                       return -EINVAL;
-
-               prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
-
-               cinfo->fck = prate / cinfo->fck_div;
-       } else {
-               if (cinfo->fck_div != 0)
-                       return -EINVAL;
-               cinfo->fck = clk_get_rate(dss.dss_clk);
-       }
-
-       return 0;
-}
-
 int dss_set_clock_div(struct dss_clock_info *cinfo)
 {
        if (dss.dpll4_m4_ck) {
@@ -478,26 +477,6 @@ int dss_set_clock_div(struct dss_clock_info *cinfo)
        return 0;
 }
 
-int dss_get_clock_div(struct dss_clock_info *cinfo)
-{
-       cinfo->fck = clk_get_rate(dss.dss_clk);
-
-       if (dss.dpll4_m4_ck) {
-               unsigned long prate;
-
-               prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
-
-               if (cpu_is_omap3630() || cpu_is_omap44xx())
-                       cinfo->fck_div = prate / (cinfo->fck);
-               else
-                       cinfo->fck_div = prate / (cinfo->fck / 2);
-       } else {
-               cinfo->fck_div = 0;
-       }
-
-       return 0;
-}
-
 unsigned long dss_get_dpll4_rate(void)
 {
        if (dss.dpll4_m4_ck)
@@ -515,7 +494,7 @@ int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
 
        unsigned long fck, max_dss_fck;
 
-       u16 fck_div, fck_div_max = 16;
+       u16 fck_div;
 
        int match = 0;
        int min_fck_per_pck;
@@ -525,9 +504,8 @@ int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
        max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
 
        fck = clk_get_rate(dss.dss_clk);
-       if (req_pck == dss.cache_req_pck &&
-                       ((cpu_is_omap34xx() && prate == dss.cache_prate) ||
-                        dss.cache_dss_cinfo.fck == fck)) {
+       if (req_pck == dss.cache_req_pck && prate == dss.cache_prate &&
+               dss.cache_dss_cinfo.fck == fck) {
                DSSDBG("dispc clock info found from cache.\n");
                *dss_cinfo = dss.cache_dss_cinfo;
                *dispc_cinfo = dss.cache_dispc_cinfo;
@@ -564,16 +542,10 @@ retry:
 
                goto found;
        } else {
-               if (cpu_is_omap3630() || cpu_is_omap44xx())
-                       fck_div_max = 32;
-
-               for (fck_div = fck_div_max; fck_div > 0; --fck_div) {
+               for (fck_div = dss.feat->fck_div_max; fck_div > 0; --fck_div) {
                        struct dispc_clock_info cur_dispc;
 
-                       if (fck_div_max == 32)
-                               fck = prate / fck_div;
-                       else
-                               fck = prate / fck_div * 2;
+                       fck = prate / fck_div * dss.feat->dss_fck_multiplier;
 
                        if (fck > max_dss_fck)
                                continue;
@@ -648,9 +620,18 @@ void dss_set_dac_pwrdn_bgz(bool enable)
        REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */
 }
 
-void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi)
+void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select src)
 {
-       REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15); /* VENC_HDMI_SWITCH */
+       enum omap_display_type dp;
+       dp = dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_DIGIT);
+
+       /* Complain about invalid selections */
+       WARN_ON((src == DSS_VENC_TV_CLK) && !(dp & OMAP_DISPLAY_TYPE_VENC));
+       WARN_ON((src == DSS_HDMI_M_PCLK) && !(dp & OMAP_DISPLAY_TYPE_HDMI));
+
+       /* Select only if we have options */
+       if ((dp & OMAP_DISPLAY_TYPE_VENC) && (dp & OMAP_DISPLAY_TYPE_HDMI))
+               REG_FLD_MOD(DSS_CONTROL, src, 15, 15);  /* VENC_HDMI_SWITCH */
 }
 
 enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void)
@@ -661,6 +642,9 @@ enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void)
        if ((displays & OMAP_DISPLAY_TYPE_HDMI) == 0)
                return DSS_VENC_TV_CLK;
 
+       if ((displays & OMAP_DISPLAY_TYPE_VENC) == 0)
+               return DSS_HDMI_M_PCLK;
+
        return REG_GET(DSS_CONTROL, 15, 15);
 }
 
@@ -678,22 +662,11 @@ static int dss_get_clocks(void)
 
        dss.dss_clk = clk;
 
-       if (cpu_is_omap34xx()) {
-               clk = clk_get(NULL, "dpll4_m4_ck");
-               if (IS_ERR(clk)) {
-                       DSSERR("Failed to get dpll4_m4_ck\n");
-                       r = PTR_ERR(clk);
-                       goto err;
-               }
-       } else if (cpu_is_omap44xx()) {
-               clk = clk_get(NULL, "dpll_per_m5x2_ck");
-               if (IS_ERR(clk)) {
-                       DSSERR("Failed to get dpll_per_m5x2_ck\n");
-                       r = PTR_ERR(clk);
-                       goto err;
-               }
-       } else { /* omap24xx */
-               clk = NULL;
+       clk = clk_get(NULL, dss.feat->clk_name);
+       if (IS_ERR(clk)) {
+               DSSERR("Failed to get %s\n", dss.feat->clk_name);
+               r = PTR_ERR(clk);
+               goto err;
        }
 
        dss.dpll4_m4_ck = clk;
@@ -749,6 +722,34 @@ void dss_debug_dump_clocks(struct seq_file *s)
 }
 #endif
 
+static int __init dss_init_features(struct device *dev)
+{
+       const struct dss_features *src;
+       struct dss_features *dst;
+
+       dst = devm_kzalloc(dev, sizeof(*dst), GFP_KERNEL);
+       if (!dst) {
+               dev_err(dev, "Failed to allocate local DSS Features\n");
+               return -ENOMEM;
+       }
+
+       if (cpu_is_omap24xx())
+               src = &omap24xx_dss_feats;
+       else if (cpu_is_omap34xx())
+               src = &omap34xx_dss_feats;
+       else if (cpu_is_omap3630())
+               src = &omap3630_dss_feats;
+       else if (cpu_is_omap44xx())
+               src = &omap44xx_dss_feats;
+       else
+               return -ENODEV;
+
+       memcpy(dst, src, sizeof(*dst));
+       dss.feat = dst;
+
+       return 0;
+}
+
 /* DSS HW IP initialisation */
 static int __init omap_dsshw_probe(struct platform_device *pdev)
 {
@@ -758,6 +759,10 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
 
        dss.pdev = pdev;
 
+       r = dss_init_features(&dss.pdev->dev);
+       if (r)
+               return r;
+
        dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
        if (!dss_mem) {
                DSSERR("can't get IORESOURCE_MEM DSS\n");
index f67afe76f217f01c1aea097b49e26fefd0af0ce2..d6cca820723cf846e135cd7badbb53c51cd670ca 100644 (file)
@@ -206,7 +206,7 @@ int dss_mgr_set_device(struct omap_overlay_manager *mgr,
                struct omap_dss_device *dssdev);
 int dss_mgr_unset_device(struct omap_overlay_manager *mgr);
 void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
-               struct omap_video_timings *timings);
+               const struct omap_video_timings *timings);
 void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
                const struct dss_lcd_mgr_config *config);
 const struct omap_video_timings *dss_mgr_get_timings(struct omap_overlay_manager *mgr);
@@ -279,7 +279,7 @@ void dss_dump_clocks(struct seq_file *s);
 void dss_debug_dump_clocks(struct seq_file *s);
 #endif
 
-void dss_sdi_init(u8 datapairs);
+void dss_sdi_init(int datapairs);
 int dss_sdi_enable(void);
 void dss_sdi_disable(void);
 
@@ -296,9 +296,7 @@ void dss_set_venc_output(enum omap_dss_venc_type type);
 void dss_set_dac_pwrdn_bgz(bool enable);
 
 unsigned long dss_get_dpll4_rate(void);
-int dss_calc_clock_rates(struct dss_clock_info *cinfo);
 int dss_set_clock_div(struct dss_clock_info *cinfo);
-int dss_get_clock_div(struct dss_clock_info *cinfo);
 int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
                struct dispc_clock_info *dispc_cinfo);
 
@@ -469,6 +467,20 @@ static inline unsigned long venc_get_pixel_clock(void)
        return 0;
 }
 #endif
+int omapdss_venc_display_enable(struct omap_dss_device *dssdev);
+void omapdss_venc_display_disable(struct omap_dss_device *dssdev);
+void omapdss_venc_set_timings(struct omap_dss_device *dssdev,
+               struct omap_video_timings *timings);
+int omapdss_venc_check_timings(struct omap_dss_device *dssdev,
+               struct omap_video_timings *timings);
+u32 omapdss_venc_get_wss(struct omap_dss_device *dssdev);
+int omapdss_venc_set_wss(struct omap_dss_device *dssdev, u32 wss);
+void omapdss_venc_set_type(struct omap_dss_device *dssdev,
+               enum omap_dss_venc_type type);
+void omapdss_venc_invert_vid_out_polarity(struct omap_dss_device *dssdev,
+               bool invert_polarity);
+int venc_panel_init(void);
+void venc_panel_exit(void);
 
 /* HDMI */
 #ifdef CONFIG_OMAP4_DSS_HDMI
@@ -484,7 +496,8 @@ static inline unsigned long hdmi_get_pixel_clock(void)
 #endif
 int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev);
 void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev);
-void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev);
+void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev,
+               struct omap_video_timings *timings);
 int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
                                        struct omap_video_timings *timings);
 int omapdss_hdmi_read_edid(u8 *buf, int len);
index 938709724f0cda2f6201c52b9548410e449eab49..2fe39d65502fec775cc66322bfef59f8d273b272 100644 (file)
@@ -373,6 +373,7 @@ static const enum dss_feat_id omap3430_dss_feat_list[] = {
        FEAT_ALPHA_FIXED_ZORDER,
        FEAT_FIFO_MERGE,
        FEAT_OMAP3_DSI_FIFO_BUG,
+       FEAT_DPI_USES_VDDS_DSI,
 };
 
 static const enum dss_feat_id omap3630_dss_feat_list[] = {
index 996ffcbfed58f4991b98ce7c34971dd0a400dba2..26d43a4b9812d4e096a311d3a0c64b2e79aaa485 100644 (file)
@@ -50,6 +50,7 @@ enum dss_feat_id {
        FEAT_DSI_VC_OCP_WIDTH,
        FEAT_DSI_REVERSE_TXCLKESC,
        FEAT_DSI_GNQ,
+       FEAT_DPI_USES_VDDS_DSI,
        FEAT_HDMI_CTS_SWMODE,
        FEAT_HDMI_AUDIO_USE_MCLK,
        FEAT_HANDLE_UV_SEPARATE,
index 060216fdc5783da6675ebddb32f5ef3aa7cdfa70..0cdf24673d48d74050ac56a72b08556bd1777151 100644 (file)
@@ -459,7 +459,6 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
 static int hdmi_power_on(struct omap_dss_device *dssdev)
 {
        int r;
-       const struct hdmi_config *timing;
        struct omap_video_timings *p;
        unsigned long phy;
 
@@ -469,22 +468,10 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
 
        dss_mgr_disable(dssdev->manager);
 
-       p = &dssdev->panel.timings;
+       p = &hdmi.ip_data.cfg.timings;
 
-       DSSDBG("hdmi_power_on x_res= %d y_res = %d\n",
-               dssdev->panel.timings.x_res,
-               dssdev->panel.timings.y_res);
+       DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res);
 
-       timing = hdmi_get_timings();
-       if (timing == NULL) {
-               /* HDMI code 4 corresponds to 640 * 480 VGA */
-               hdmi.ip_data.cfg.cm.code = 4;
-               /* DVI mode 1 corresponds to HDMI 0 to DVI */
-               hdmi.ip_data.cfg.cm.mode = HDMI_DVI;
-               hdmi.ip_data.cfg = vesa_timings[0];
-       } else {
-               hdmi.ip_data.cfg = *timing;
-       }
        phy = p->pixel_clock;
 
        hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data);
@@ -501,7 +488,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
        r = hdmi.ip_data.ops->phy_enable(&hdmi.ip_data);
        if (r) {
                DSSDBG("Failed to start PHY\n");
-               goto err;
+               goto err_phy_enable;
        }
 
        hdmi.ip_data.ops->video_configure(&hdmi.ip_data);
@@ -521,7 +508,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
        dispc_enable_gamma_table(0);
 
        /* tv size */
-       dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings);
+       dss_mgr_set_timings(dssdev->manager, p);
 
        r = hdmi.ip_data.ops->video_enable(&hdmi.ip_data);
        if (r)
@@ -537,6 +524,7 @@ err_mgr_enable:
        hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
 err_vid_enable:
        hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
+err_phy_enable:
        hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
 err:
        hdmi_runtime_put();
@@ -567,13 +555,20 @@ int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
 
 }
 
-void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev)
+void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev,
+               struct omap_video_timings *timings)
 {
        struct hdmi_cm cm;
+       const struct hdmi_config *t;
+
+       mutex_lock(&hdmi.lock);
 
-       cm = hdmi_get_code(&dssdev->panel.timings);
-       hdmi.ip_data.cfg.cm.code = cm.code;
-       hdmi.ip_data.cfg.cm.mode = cm.mode;
+       cm = hdmi_get_code(timings);
+       hdmi.ip_data.cfg.cm = cm;
+
+       t = hdmi_get_timings();
+       if (t != NULL)
+               hdmi.ip_data.cfg = *t;
 
        if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
                int r;
@@ -584,8 +579,10 @@ void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev)
                if (r)
                        DSSERR("failed to power on device\n");
        } else {
-               dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings);
+               dss_mgr_set_timings(dssdev->manager, &t->timings);
        }
+
+       mutex_unlock(&hdmi.lock);
 }
 
 static void hdmi_dump_regs(struct seq_file *s)
@@ -929,6 +926,7 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
        hdmi.ip_data.core_av_offset = HDMI_CORE_AV;
        hdmi.ip_data.pll_offset = HDMI_PLLCTRL;
        hdmi.ip_data.phy_offset = HDMI_PHY;
+
        mutex_init(&hdmi.ip_data.lock);
 
        hdmi_panel_init();
index e10844faadf91434df1c096aaf0e3dd5cc5e88d0..69fb115bab32928d7ce58574cb0120020b5720fe 100644 (file)
@@ -41,17 +41,34 @@ static struct {
 
 static int hdmi_panel_probe(struct omap_dss_device *dssdev)
 {
+       /* Initialize default timings to VGA in DVI mode */
+       const struct omap_video_timings default_timings = {
+               .x_res          = 640,
+               .y_res          = 480,
+               .pixel_clock    = 25175,
+               .hsw            = 96,
+               .hfp            = 16,
+               .hbp            = 48,
+               .vsw            = 2,
+               .vfp            = 11,
+               .vbp            = 31,
+
+               .vsync_level    = OMAPDSS_SIG_ACTIVE_LOW,
+               .hsync_level    = OMAPDSS_SIG_ACTIVE_LOW,
+
+               .interlace      = false,
+       };
+
        DSSDBG("ENTER hdmi_panel_probe\n");
 
-       dssdev->panel.timings = (struct omap_video_timings)
-                       { 640, 480, 25175, 96, 16, 48, 2, 11, 31,
-                               OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
-                               false,
-                       };
+       dssdev->panel.timings = default_timings;
 
        DSSDBG("hdmi_panel_probe x_res= %d y_res = %d\n",
                dssdev->panel.timings.x_res,
                dssdev->panel.timings.y_res);
+
+       omapdss_hdmi_display_set_timing(dssdev, &dssdev->panel.timings);
+
        return 0;
 }
 
@@ -228,6 +245,8 @@ static int hdmi_panel_enable(struct omap_dss_device *dssdev)
                goto err;
        }
 
+       omapdss_hdmi_display_set_timing(dssdev, &dssdev->panel.timings);
+
        r = omapdss_hdmi_display_enable(dssdev);
        if (r) {
                DSSERR("failed to power on\n");
@@ -336,8 +355,8 @@ static void hdmi_set_timings(struct omap_dss_device *dssdev,
         */
        hdmi_panel_audio_disable(dssdev);
 
+       omapdss_hdmi_display_set_timing(dssdev, timings);
        dssdev->panel.timings = *timings;
-       omapdss_hdmi_display_set_timing(dssdev);
 
        mutex_unlock(&hdmi.lock);
 }
index 7c087424b63428d33cd2bbb1560cb476dfefab38..5a9c0e9d8710fb6f615e77f8505f191440d4afe8 100644 (file)
@@ -111,6 +111,11 @@ static struct {
        struct omap_dss_device *dssdev[2];
 
        struct semaphore bus_lock;
+
+       struct omap_video_timings timings;
+       int pixel_size;
+       int data_lines;
+       struct rfbi_timings intf_timings;
 } rfbi;
 
 static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val)
@@ -300,28 +305,20 @@ void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width,
 }
 EXPORT_SYMBOL(omap_rfbi_write_pixels);
 
-static int rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width,
-               u16 height, void (*callback)(void *data), void *data)
+static int rfbi_transfer_area(struct omap_dss_device *dssdev,
+               void (*callback)(void *data), void *data)
 {
        u32 l;
        int r;
-       struct omap_video_timings timings = {
-               .hsw            = 1,
-               .hfp            = 1,
-               .hbp            = 1,
-               .vsw            = 1,
-               .vfp            = 0,
-               .vbp            = 0,
-               .x_res          = width,
-               .y_res          = height,
-       };
+       u16 width = rfbi.timings.x_res;
+       u16 height = rfbi.timings.y_res;
 
        /*BUG_ON(callback == 0);*/
        BUG_ON(rfbi.framedone_callback != NULL);
 
        DSSDBG("rfbi_transfer_area %dx%d\n", width, height);
 
-       dss_mgr_set_timings(dssdev->manager, &timings);
+       dss_mgr_set_timings(dssdev->manager, &rfbi.timings);
 
        r = dss_mgr_enable(dssdev->manager);
        if (r)
@@ -770,62 +767,45 @@ static int rfbi_configure(int rfbi_module, int bpp, int lines)
        return 0;
 }
 
-int omap_rfbi_configure(struct omap_dss_device *dssdev, int pixel_size,
-               int data_lines)
+int omap_rfbi_configure(struct omap_dss_device *dssdev)
 {
-       return rfbi_configure(dssdev->phy.rfbi.channel, pixel_size, data_lines);
+       return rfbi_configure(dssdev->phy.rfbi.channel, rfbi.pixel_size,
+                       rfbi.data_lines);
 }
 EXPORT_SYMBOL(omap_rfbi_configure);
 
-int omap_rfbi_prepare_update(struct omap_dss_device *dssdev,
-               u16 *x, u16 *y, u16 *w, u16 *h)
+int omap_rfbi_update(struct omap_dss_device *dssdev, void (*callback)(void *),
+               void *data)
 {
-       u16 dw, dh;
-       struct omap_video_timings timings = {
-               .hsw            = 1,
-               .hfp            = 1,
-               .hbp            = 1,
-               .vsw            = 1,
-               .vfp            = 0,
-               .vbp            = 0,
-               .x_res          = *w,
-               .y_res          = *h,
-       };
-
-       dssdev->driver->get_resolution(dssdev, &dw, &dh);
-
-       if  (*x > dw || *y > dh)
-               return -EINVAL;
-
-       if (*x + *w > dw)
-               return -EINVAL;
-
-       if (*y + *h > dh)
-               return -EINVAL;
-
-       if (*w == 1)
-               return -EINVAL;
-
-       if (*w == 0 || *h == 0)
-               return -EINVAL;
-
-       dss_mgr_set_timings(dssdev->manager, &timings);
+       return rfbi_transfer_area(dssdev, callback, data);
+}
+EXPORT_SYMBOL(omap_rfbi_update);
 
-       return 0;
+void omapdss_rfbi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h)
+{
+       rfbi.timings.x_res = w;
+       rfbi.timings.y_res = h;
 }
-EXPORT_SYMBOL(omap_rfbi_prepare_update);
+EXPORT_SYMBOL(omapdss_rfbi_set_size);
 
-int omap_rfbi_update(struct omap_dss_device *dssdev,
-               u16 x, u16 y, u16 w, u16 h,
-               void (*callback)(void *), void *data)
+void omapdss_rfbi_set_pixel_size(struct omap_dss_device *dssdev, int pixel_size)
 {
-       int r;
+       rfbi.pixel_size = pixel_size;
+}
+EXPORT_SYMBOL(omapdss_rfbi_set_pixel_size);
 
-       r = rfbi_transfer_area(dssdev, w, h, callback, data);
+void omapdss_rfbi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
+{
+       rfbi.data_lines = data_lines;
+}
+EXPORT_SYMBOL(omapdss_rfbi_set_data_lines);
 
-       return r;
+void omapdss_rfbi_set_interface_timings(struct omap_dss_device *dssdev,
+               struct rfbi_timings *timings)
+{
+       rfbi.intf_timings = *timings;
 }
-EXPORT_SYMBOL(omap_rfbi_update);
+EXPORT_SYMBOL(omapdss_rfbi_set_interface_timings);
 
 static void rfbi_dump_regs(struct seq_file *s)
 {
@@ -877,10 +857,31 @@ static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev)
        /* Do we need fifohandcheck for RFBI? */
        mgr_config.fifohandcheck = false;
 
-       mgr_config.video_port_width = dssdev->ctrl.pixel_size;
+       mgr_config.video_port_width = rfbi.pixel_size;
        mgr_config.lcden_sig_polarity = 0;
 
        dss_mgr_set_lcd_config(dssdev->manager, &mgr_config);
+
+       /*
+        * Set rfbi.timings with default values, the x_res and y_res fields
+        * are expected to be already configured by the panel driver via
+        * omapdss_rfbi_set_size()
+        */
+       rfbi.timings.hsw = 1;
+       rfbi.timings.hfp = 1;
+       rfbi.timings.hbp = 1;
+       rfbi.timings.vsw = 1;
+       rfbi.timings.vfp = 0;
+       rfbi.timings.vbp = 0;
+
+       rfbi.timings.interlace = false;
+       rfbi.timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
+       rfbi.timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
+       rfbi.timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
+       rfbi.timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH;
+       rfbi.timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
+
+       dss_mgr_set_timings(dssdev->manager, &rfbi.timings);
 }
 
 int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
@@ -911,13 +912,10 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
 
        rfbi_config_lcd_manager(dssdev);
 
-       rfbi_configure(dssdev->phy.rfbi.channel,
-                              dssdev->ctrl.pixel_size,
-                              dssdev->phy.rfbi.data_lines);
-
-       rfbi_set_timings(dssdev->phy.rfbi.channel,
-                        &dssdev->ctrl.rfbi_timings);
+       rfbi_configure(dssdev->phy.rfbi.channel, rfbi.pixel_size,
+                       rfbi.data_lines);
 
+       rfbi_set_timings(dssdev->phy.rfbi.channel, &rfbi.intf_timings);
 
        return 0;
 err1:
index 5d31699fbd3caf4c885840b77c76fd4512d52ed9..3bf1bfe2958536e2072c9a86ec8242a3ff0c56fe 100644 (file)
@@ -34,6 +34,8 @@ static struct {
        struct regulator *vdds_sdi_reg;
 
        struct dss_lcd_mgr_config mgr_config;
+       struct omap_video_timings timings;
+       int datapairs;
 } sdi;
 
 static void sdi_config_lcd_manager(struct omap_dss_device *dssdev)
@@ -51,7 +53,7 @@ static void sdi_config_lcd_manager(struct omap_dss_device *dssdev)
 
 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;
        unsigned long pck;
@@ -77,8 +79,8 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
                goto err_get_dispc;
 
        /* 15.5.9.1.2 */
-       dssdev->panel.timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
-       dssdev->panel.timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
+       t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
+       t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
 
        r = dss_calc_clock_div(t->pixel_clock * 1000, &dss_cinfo, &dispc_cinfo);
        if (r)
@@ -105,7 +107,8 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
 
        sdi_config_lcd_manager(dssdev);
 
-       dss_sdi_init(dssdev->phy.sdi.datapairs);
+       dss_sdi_init(sdi.datapairs);
+
        r = dss_sdi_enable();
        if (r)
                goto err_sdi_enable;
@@ -146,6 +149,29 @@ void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
 }
 EXPORT_SYMBOL(omapdss_sdi_display_disable);
 
+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);
+
+void omapdss_sdi_set_datapairs(struct omap_dss_device *dssdev, int datapairs)
+{
+       sdi.datapairs = datapairs;
+}
+EXPORT_SYMBOL(omapdss_sdi_set_datapairs);
+
 static int __init sdi_init_display(struct omap_dss_device *dssdev)
 {
        DSSDBG("SDI init\n");
index 3a220877461ac9adbf3ab62369e9d10a7476a952..4a6caf9c6da3822eb5c373c0923bb91336ea37ba 100644 (file)
@@ -300,6 +300,10 @@ static struct {
        struct regulator *vdda_dac_reg;
 
        struct clk      *tv_dac_clk;
+
+       struct omap_video_timings timings;
+       enum omap_dss_venc_type type;
+       bool invert_polarity;
 } venc;
 
 static inline void venc_write_reg(int idx, u32 val)
@@ -427,48 +431,48 @@ static int venc_power_on(struct omap_dss_device *dssdev)
        u32 l;
        int r;
 
+       r = venc_runtime_get();
+       if (r)
+               goto err0;
+
        venc_reset();
-       venc_write_config(venc_timings_to_config(&dssdev->panel.timings));
+       venc_write_config(venc_timings_to_config(&venc.timings));
 
-       dss_set_venc_output(dssdev->phy.venc.type);
+       dss_set_venc_output(venc.type);
        dss_set_dac_pwrdn_bgz(1);
 
        l = 0;
 
-       if (dssdev->phy.venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE)
+       if (venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE)
                l |= 1 << 1;
        else /* S-Video */
                l |= (1 << 0) | (1 << 2);
 
-       if (dssdev->phy.venc.invert_polarity == false)
+       if (venc.invert_polarity == false)
                l |= 1 << 3;
 
        venc_write_reg(VENC_OUTPUT_CONTROL, l);
 
-       dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings);
+       dss_mgr_set_timings(dssdev->manager, &venc.timings);
 
        r = regulator_enable(venc.vdda_dac_reg);
        if (r)
-               goto err;
-
-       if (dssdev->platform_enable)
-               dssdev->platform_enable(dssdev);
+               goto err1;
 
        r = dss_mgr_enable(dssdev->manager);
        if (r)
-               goto err;
+               goto err2;
 
        return 0;
 
-err:
+err2:
+       regulator_disable(venc.vdda_dac_reg);
+err1:
        venc_write_reg(VENC_OUTPUT_CONTROL, 0);
        dss_set_dac_pwrdn_bgz(0);
 
-       if (dssdev->platform_disable)
-               dssdev->platform_disable(dssdev);
-
-       regulator_disable(venc.vdda_dac_reg);
-
+       venc_runtime_put();
+err0:
        return r;
 }
 
@@ -479,10 +483,9 @@ static void venc_power_off(struct omap_dss_device *dssdev)
 
        dss_mgr_disable(dssdev->manager);
 
-       if (dssdev->platform_disable)
-               dssdev->platform_disable(dssdev);
-
        regulator_disable(venc.vdda_dac_reg);
+
+       venc_runtime_put();
 }
 
 unsigned long venc_get_pixel_clock(void)
@@ -491,171 +494,95 @@ unsigned long venc_get_pixel_clock(void)
        return 13500000;
 }
 
-static ssize_t display_output_type_show(struct device *dev,
-               struct device_attribute *attr, char *buf)
+int omapdss_venc_display_enable(struct omap_dss_device *dssdev)
 {
-       struct omap_dss_device *dssdev = to_dss_device(dev);
-       const char *ret;
-
-       switch (dssdev->phy.venc.type) {
-       case OMAP_DSS_VENC_TYPE_COMPOSITE:
-               ret = "composite";
-               break;
-       case OMAP_DSS_VENC_TYPE_SVIDEO:
-               ret = "svideo";
-               break;
-       default:
-               return -EINVAL;
-       }
+       int r;
 
-       return snprintf(buf, PAGE_SIZE, "%s\n", ret);
-}
-
-static ssize_t display_output_type_store(struct device *dev,
-               struct device_attribute *attr, const char *buf, size_t size)
-{
-       struct omap_dss_device *dssdev = to_dss_device(dev);
-       enum omap_dss_venc_type new_type;
-
-       if (sysfs_streq("composite", buf))
-               new_type = OMAP_DSS_VENC_TYPE_COMPOSITE;
-       else if (sysfs_streq("svideo", buf))
-               new_type = OMAP_DSS_VENC_TYPE_SVIDEO;
-       else
-               return -EINVAL;
+       DSSDBG("venc_display_enable\n");
 
        mutex_lock(&venc.venc_lock);
 
-       if (dssdev->phy.venc.type != new_type) {
-               dssdev->phy.venc.type = new_type;
-               if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
-                       venc_power_off(dssdev);
-                       venc_power_on(dssdev);
-               }
+       if (dssdev->manager == NULL) {
+               DSSERR("Failed to enable display: no manager\n");
+               r = -ENODEV;
+               goto err0;
        }
 
-       mutex_unlock(&venc.venc_lock);
-
-       return size;
-}
-
-static DEVICE_ATTR(output_type, S_IRUGO | S_IWUSR,
-               display_output_type_show, display_output_type_store);
-
-/* driver */
-static int venc_panel_probe(struct omap_dss_device *dssdev)
-{
-       dssdev->panel.timings = omap_dss_pal_timings;
-
-       return device_create_file(&dssdev->dev, &dev_attr_output_type);
-}
-
-static void venc_panel_remove(struct omap_dss_device *dssdev)
-{
-       device_remove_file(&dssdev->dev, &dev_attr_output_type);
-}
-
-static int venc_panel_enable(struct omap_dss_device *dssdev)
-{
-       int r = 0;
-
-       DSSDBG("venc_enable_display\n");
-
-       mutex_lock(&venc.venc_lock);
-
        r = omap_dss_start_device(dssdev);
        if (r) {
                DSSERR("failed to start device\n");
                goto err0;
        }
 
-       if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
-               r = -EINVAL;
-               goto err1;
-       }
+       if (dssdev->platform_enable)
+               dssdev->platform_enable(dssdev);
 
-       r = venc_runtime_get();
-       if (r)
-               goto err1;
 
        r = venc_power_on(dssdev);
        if (r)
-               goto err2;
+               goto err1;
 
        venc.wss_data = 0;
 
-       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
        mutex_unlock(&venc.venc_lock);
+
        return 0;
-err2:
-       venc_runtime_put();
 err1:
+       if (dssdev->platform_disable)
+               dssdev->platform_disable(dssdev);
        omap_dss_stop_device(dssdev);
 err0:
        mutex_unlock(&venc.venc_lock);
-
        return r;
 }
 
-static void venc_panel_disable(struct omap_dss_device *dssdev)
+void omapdss_venc_display_disable(struct omap_dss_device *dssdev)
 {
-       DSSDBG("venc_disable_display\n");
+       DSSDBG("venc_display_disable\n");
 
        mutex_lock(&venc.venc_lock);
 
-       if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
-               goto end;
-
-       if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) {
-               /* suspended is the same as disabled with venc */
-               dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-               goto end;
-       }
-
        venc_power_off(dssdev);
 
-       venc_runtime_put();
-
-       dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-
        omap_dss_stop_device(dssdev);
-end:
-       mutex_unlock(&venc.venc_lock);
-}
 
-static int venc_panel_suspend(struct omap_dss_device *dssdev)
-{
-       venc_panel_disable(dssdev);
-       return 0;
-}
+       if (dssdev->platform_disable)
+               dssdev->platform_disable(dssdev);
 
-static int venc_panel_resume(struct omap_dss_device *dssdev)
-{
-       return venc_panel_enable(dssdev);
+       mutex_unlock(&venc.venc_lock);
 }
 
-static void venc_set_timings(struct omap_dss_device *dssdev,
-                       struct omap_video_timings *timings)
+void omapdss_venc_set_timings(struct omap_dss_device *dssdev,
+               struct omap_video_timings *timings)
 {
        DSSDBG("venc_set_timings\n");
 
+       mutex_lock(&venc.venc_lock);
+
        /* Reset WSS data when the TV standard changes. */
-       if (memcmp(&dssdev->panel.timings, timings, sizeof(*timings)))
+       if (memcmp(&venc.timings, timings, sizeof(*timings)))
                venc.wss_data = 0;
 
-       dssdev->panel.timings = *timings;
+       venc.timings = *timings;
+
        if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
+               int r;
+
                /* turn the venc off and on to get new timings to use */
-               venc_panel_disable(dssdev);
-               venc_panel_enable(dssdev);
+               venc_power_off(dssdev);
+
+               r = venc_power_on(dssdev);
+               if (r)
+                       DSSERR("failed to power on VENC\n");
        } else {
                dss_mgr_set_timings(dssdev->manager, timings);
        }
+
+       mutex_unlock(&venc.venc_lock);
 }
 
-static int venc_check_timings(struct omap_dss_device *dssdev,
-                       struct omap_video_timings *timings)
+int omapdss_venc_check_timings(struct omap_dss_device *dssdev,
+               struct omap_video_timings *timings)
 {
        DSSDBG("venc_check_timings\n");
 
@@ -668,13 +595,13 @@ static int venc_check_timings(struct omap_dss_device *dssdev,
        return -EINVAL;
 }
 
-static u32 venc_get_wss(struct omap_dss_device *dssdev)
+u32 omapdss_venc_get_wss(struct omap_dss_device *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)
+int omapdss_venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
 {
        const struct venc_config *config;
        int r;
@@ -683,7 +610,7 @@ static int venc_set_wss(struct omap_dss_device *dssdev,     u32 wss)
 
        mutex_lock(&venc.venc_lock);
 
-       config = venc_timings_to_config(&dssdev->panel.timings);
+       config = venc_timings_to_config(&venc.timings);
 
        /* Invert due to VENC_L21_WC_CTL:INV=1 */
        venc.wss_data = (wss ^ 0xfffff) << 8;
@@ -703,30 +630,25 @@ err:
        return r;
 }
 
-static struct omap_dss_driver venc_driver = {
-       .probe          = venc_panel_probe,
-       .remove         = venc_panel_remove,
+void omapdss_venc_set_type(struct omap_dss_device *dssdev,
+               enum omap_dss_venc_type type)
+{
+       mutex_lock(&venc.venc_lock);
 
-       .enable         = venc_panel_enable,
-       .disable        = venc_panel_disable,
-       .suspend        = venc_panel_suspend,
-       .resume         = venc_panel_resume,
+       venc.type = type;
 
-       .get_resolution = omapdss_default_get_resolution,
-       .get_recommended_bpp = omapdss_default_get_recommended_bpp,
+       mutex_unlock(&venc.venc_lock);
+}
 
-       .set_timings    = venc_set_timings,
-       .check_timings  = venc_check_timings,
+void omapdss_venc_invert_vid_out_polarity(struct omap_dss_device *dssdev,
+               bool invert_polarity)
+{
+       mutex_lock(&venc.venc_lock);
 
-       .get_wss        = venc_get_wss,
-       .set_wss        = venc_set_wss,
+       venc.invert_polarity = invert_polarity;
 
-       .driver         = {
-               .name   = "venc",
-               .owner  = THIS_MODULE,
-       },
-};
-/* driver end */
+       mutex_unlock(&venc.venc_lock);
+}
 
 static int __init venc_init_display(struct omap_dss_device *dssdev)
 {
@@ -752,11 +674,6 @@ static void venc_dump_regs(struct seq_file *s)
 {
 #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r))
 
-       if (cpu_is_omap44xx()) {
-               seq_printf(s, "VENC currently disabled on OMAP44xx\n");
-               return;
-       }
-
        if (venc_runtime_get())
                return;
 
@@ -897,9 +814,9 @@ static int __init omap_venchw_probe(struct platform_device *pdev)
 
        venc_runtime_put();
 
-       r = omap_dss_register_driver(&venc_driver);
+       r = venc_panel_init();
        if (r)
-               goto err_reg_panel_driver;
+               goto err_panel_init;
 
        dss_debugfs_create_file("venc", venc_dump_regs);
 
@@ -907,7 +824,7 @@ static int __init omap_venchw_probe(struct platform_device *pdev)
 
        return 0;
 
-err_reg_panel_driver:
+err_panel_init:
 err_runtime_get:
        pm_runtime_disable(&pdev->dev);
        venc_put_clocks();
@@ -923,7 +840,7 @@ static int __exit omap_venchw_remove(struct platform_device *pdev)
                venc.vdda_dac_reg = NULL;
        }
 
-       omap_dss_unregister_driver(&venc_driver);
+       venc_panel_exit();
 
        pm_runtime_disable(&pdev->dev);
        venc_put_clocks();
@@ -971,16 +888,10 @@ static struct platform_driver omap_venchw_driver = {
 
 int __init venc_init_platform_driver(void)
 {
-       if (cpu_is_omap44xx())
-               return 0;
-
        return platform_driver_probe(&omap_venchw_driver, omap_venchw_probe);
 }
 
 void __exit venc_uninit_platform_driver(void)
 {
-       if (cpu_is_omap44xx())
-               return;
-
        platform_driver_unregister(&omap_venchw_driver);
 }
diff --git a/drivers/video/omap2/dss/venc_panel.c b/drivers/video/omap2/dss/venc_panel.c
new file mode 100644 (file)
index 0000000..d55b878
--- /dev/null
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * VENC panel driver
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/mutex.h>
+#include <linux/module.h>
+
+#include <video/omapdss.h>
+
+#include "dss.h"
+
+static struct {
+       struct mutex lock;
+} venc_panel;
+
+static ssize_t display_output_type_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct omap_dss_device *dssdev = to_dss_device(dev);
+       const char *ret;
+
+       switch (dssdev->phy.venc.type) {
+       case OMAP_DSS_VENC_TYPE_COMPOSITE:
+               ret = "composite";
+               break;
+       case OMAP_DSS_VENC_TYPE_SVIDEO:
+               ret = "svideo";
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return snprintf(buf, PAGE_SIZE, "%s\n", ret);
+}
+
+static ssize_t display_output_type_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t size)
+{
+       struct omap_dss_device *dssdev = to_dss_device(dev);
+       enum omap_dss_venc_type new_type;
+
+       if (sysfs_streq("composite", buf))
+               new_type = OMAP_DSS_VENC_TYPE_COMPOSITE;
+       else if (sysfs_streq("svideo", buf))
+               new_type = OMAP_DSS_VENC_TYPE_SVIDEO;
+       else
+               return -EINVAL;
+
+       mutex_lock(&venc_panel.lock);
+
+       if (dssdev->phy.venc.type != new_type) {
+               dssdev->phy.venc.type = new_type;
+               omapdss_venc_set_type(dssdev, new_type);
+               if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
+                       omapdss_venc_display_disable(dssdev);
+                       omapdss_venc_display_enable(dssdev);
+               }
+       }
+
+       mutex_unlock(&venc_panel.lock);
+
+       return size;
+}
+
+static DEVICE_ATTR(output_type, S_IRUGO | S_IWUSR,
+               display_output_type_show, display_output_type_store);
+
+static int venc_panel_probe(struct omap_dss_device *dssdev)
+{
+       /* set default timings to PAL */
+       const struct omap_video_timings default_timings = {
+               .x_res          = 720,
+               .y_res          = 574,
+               .pixel_clock    = 13500,
+               .hsw            = 64,
+               .hfp            = 12,
+               .hbp            = 68,
+               .vsw            = 5,
+               .vfp            = 5,
+               .vbp            = 41,
+
+               .vsync_level    = OMAPDSS_SIG_ACTIVE_HIGH,
+               .hsync_level    = OMAPDSS_SIG_ACTIVE_HIGH,
+
+               .interlace      = true,
+       };
+
+       mutex_init(&venc_panel.lock);
+
+       dssdev->panel.timings = default_timings;
+
+       return device_create_file(&dssdev->dev, &dev_attr_output_type);
+}
+
+static void venc_panel_remove(struct omap_dss_device *dssdev)
+{
+       device_remove_file(&dssdev->dev, &dev_attr_output_type);
+}
+
+static int venc_panel_enable(struct omap_dss_device *dssdev)
+{
+       int r;
+
+       dev_dbg(&dssdev->dev, "venc_panel_enable\n");
+
+       mutex_lock(&venc_panel.lock);
+
+       if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
+               r = -EINVAL;
+               goto err;
+       }
+
+       omapdss_venc_set_timings(dssdev, &dssdev->panel.timings);
+       omapdss_venc_set_type(dssdev, dssdev->phy.venc.type);
+       omapdss_venc_invert_vid_out_polarity(dssdev,
+               dssdev->phy.venc.invert_polarity);
+
+       r = omapdss_venc_display_enable(dssdev);
+       if (r)
+               goto err;
+
+       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+       mutex_unlock(&venc_panel.lock);
+
+       return 0;
+err:
+       mutex_unlock(&venc_panel.lock);
+
+       return r;
+}
+
+static void venc_panel_disable(struct omap_dss_device *dssdev)
+{
+       dev_dbg(&dssdev->dev, "venc_panel_disable\n");
+
+       mutex_lock(&venc_panel.lock);
+
+       if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
+               goto end;
+
+       if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) {
+               /* suspended is the same as disabled with venc */
+               dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+               goto end;
+       }
+
+       omapdss_venc_display_disable(dssdev);
+
+       dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+end:
+       mutex_unlock(&venc_panel.lock);
+}
+
+static int venc_panel_suspend(struct omap_dss_device *dssdev)
+{
+       venc_panel_disable(dssdev);
+       return 0;
+}
+
+static int venc_panel_resume(struct omap_dss_device *dssdev)
+{
+       return venc_panel_enable(dssdev);
+}
+
+static void venc_panel_set_timings(struct omap_dss_device *dssdev,
+               struct omap_video_timings *timings)
+{
+       dev_dbg(&dssdev->dev, "venc_panel_set_timings\n");
+
+       mutex_lock(&venc_panel.lock);
+
+       omapdss_venc_set_timings(dssdev, timings);
+       dssdev->panel.timings = *timings;
+
+       mutex_unlock(&venc_panel.lock);
+}
+
+static int venc_panel_check_timings(struct omap_dss_device *dssdev,
+               struct omap_video_timings *timings)
+{
+       dev_dbg(&dssdev->dev, "venc_panel_check_timings\n");
+
+       return omapdss_venc_check_timings(dssdev, timings);
+}
+
+static u32 venc_panel_get_wss(struct omap_dss_device *dssdev)
+{
+       dev_dbg(&dssdev->dev, "venc_panel_get_wss\n");
+
+       return omapdss_venc_get_wss(dssdev);
+}
+
+static int venc_panel_set_wss(struct omap_dss_device *dssdev, u32 wss)
+{
+       dev_dbg(&dssdev->dev, "venc_panel_set_wss\n");
+
+       return omapdss_venc_set_wss(dssdev, wss);
+}
+
+static struct omap_dss_driver venc_driver = {
+       .probe          = venc_panel_probe,
+       .remove         = venc_panel_remove,
+
+       .enable         = venc_panel_enable,
+       .disable        = venc_panel_disable,
+       .suspend        = venc_panel_suspend,
+       .resume         = venc_panel_resume,
+
+       .get_resolution = omapdss_default_get_resolution,
+       .get_recommended_bpp = omapdss_default_get_recommended_bpp,
+
+       .set_timings    = venc_panel_set_timings,
+       .check_timings  = venc_panel_check_timings,
+
+       .get_wss        = venc_panel_get_wss,
+       .set_wss        = venc_panel_set_wss,
+
+       .driver         = {
+               .name   = "venc",
+               .owner  = THIS_MODULE,
+       },
+};
+
+int venc_panel_init(void)
+{
+       return omap_dss_register_driver(&venc_driver);
+}
+
+void venc_panel_exit(void)
+{
+       omap_dss_unregister_driver(&venc_driver);
+}
index 08ec1a7103f2b728420f9e534a2002b20f457d45..fc671d3d8004899ba36064954fc1343ddefb85e2 100644 (file)
@@ -1192,7 +1192,7 @@ static int _setcolreg(struct fb_info *fbi, u_int regno, u_int red, u_int green,
                        break;
 
                if (regno < 16) {
-                       u16 pal;
+                       u32 pal;
                        pal = ((red >> (16 - var->red.length)) <<
                                        var->red.offset) |
                                ((green >> (16 - var->green.length)) <<
index a6267a2d292bfa07a815003410060348656392ce..9c7cca3746e1462a2fef019c3be95281808a9b75 100644 (file)
 #define DISPC_IRQ_FRAMEDONEWB          (1 << 23)
 #define DISPC_IRQ_FRAMEDONETV          (1 << 24)
 #define DISPC_IRQ_WBBUFFEROVERFLOW     (1 << 25)
-#define DISPC_IRQ_FRAMEDONE3           (1 << 26)
-#define DISPC_IRQ_VSYNC3               (1 << 27)
-#define DISPC_IRQ_ACBIAS_COUNT_STAT3   (1 << 28)
-#define DISPC_IRQ_SYNC_LOST3           (1 << 29)
+#define DISPC_IRQ_SYNC_LOST3           (1 << 27)
+#define DISPC_IRQ_VSYNC3               (1 << 28)
+#define DISPC_IRQ_ACBIAS_COUNT_STAT3   (1 << 29)
+#define DISPC_IRQ_FRAMEDONE3           (1 << 30)
 
 struct omap_dss_device;
 struct omap_overlay_manager;
@@ -243,7 +243,7 @@ void rfbi_bus_unlock(void);
 
 /* DSI */
 
-struct omap_dss_dsi_videomode_data {
+struct omap_dss_dsi_videomode_timings {
        /* DSI video mode blanking data */
        /* Unit: byte clock cycles */
        u16 hsa;
@@ -564,7 +564,7 @@ struct omap_dss_device {
 
                enum omap_dss_dsi_pixel_format dsi_pix_fmt;
                enum omap_dss_dsi_mode dsi_mode;
-               struct omap_dss_dsi_videomode_data dsi_vm_data;
+               struct omap_dss_dsi_videomode_timings dsi_vm_timings;
        } panel;
 
        struct {
@@ -719,6 +719,15 @@ int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
 void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
                bool enable);
 int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable);
+void omapdss_dsi_set_timings(struct omap_dss_device *dssdev,
+               struct omap_video_timings *timings);
+void omapdss_dsi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h);
+void omapdss_dsi_set_pixel_format(struct omap_dss_device *dssdev,
+               enum omap_dss_dsi_pixel_format fmt);
+void omapdss_dsi_set_operation_mode(struct omap_dss_device *dssdev,
+               enum omap_dss_dsi_mode mode);
+void omapdss_dsi_set_videomode_timings(struct omap_dss_device *dssdev,
+               struct omap_dss_dsi_videomode_timings *timings);
 
 int omap_dsi_update(struct omap_dss_device *dssdev, int channel,
                void (*callback)(int, void *), void *data);
@@ -734,22 +743,29 @@ void omapdss_dsi_display_disable(struct omap_dss_device *dssdev,
 
 int omapdss_dpi_display_enable(struct omap_dss_device *dssdev);
 void omapdss_dpi_display_disable(struct omap_dss_device *dssdev);
-void dpi_set_timings(struct omap_dss_device *dssdev,
-                       struct omap_video_timings *timings);
+void omapdss_dpi_set_timings(struct omap_dss_device *dssdev,
+               struct omap_video_timings *timings);
 int dpi_check_timings(struct omap_dss_device *dssdev,
                        struct omap_video_timings *timings);
+void omapdss_dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines);
 
 int omapdss_sdi_display_enable(struct omap_dss_device *dssdev);
 void omapdss_sdi_display_disable(struct omap_dss_device *dssdev);
+void omapdss_sdi_set_timings(struct omap_dss_device *dssdev,
+               struct omap_video_timings *timings);
+void omapdss_sdi_set_datapairs(struct omap_dss_device *dssdev, int datapairs);
 
 int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev);
 void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev);
-int omap_rfbi_prepare_update(struct omap_dss_device *dssdev,
-               u16 *x, u16 *y, u16 *w, u16 *h);
-int omap_rfbi_update(struct omap_dss_device *dssdev,
-               u16 x, u16 y, u16 w, u16 h,
-               void (*callback)(void *), void *data);
-int omap_rfbi_configure(struct omap_dss_device *dssdev, int pixel_size,
+int omap_rfbi_update(struct omap_dss_device *dssdev, void (*callback)(void *),
+               void *data);
+int omap_rfbi_configure(struct omap_dss_device *dssdev);
+void omapdss_rfbi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h);
+void omapdss_rfbi_set_pixel_size(struct omap_dss_device *dssdev,
+               int pixel_size);
+void omapdss_rfbi_set_data_lines(struct omap_dss_device *dssdev,
                int data_lines);
+void omapdss_rfbi_set_interface_timings(struct omap_dss_device *dssdev,
+               struct rfbi_timings *timings);
 
 #endif