]> Pileus Git - ~andy/linux/commitdiff
Merge branch 'work/old-omapfb-removal'
authorTomi Valkeinen <tomi.valkeinen@ti.com>
Thu, 23 Feb 2012 07:45:58 +0000 (09:45 +0200)
committerTomi Valkeinen <tomi.valkeinen@ti.com>
Thu, 23 Feb 2012 07:45:58 +0000 (09:45 +0200)
16 files changed:
drivers/video/omap2/displays/panel-generic-dpi.c
drivers/video/omap2/displays/panel-tpo-td043mtea1.c
drivers/video/omap2/dss/apply.c
drivers/video/omap2/dss/dispc.c
drivers/video/omap2/dss/display.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/rfbi.c
drivers/video/omap2/dss/ti_hdmi.h
drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h
drivers/video/omap2/dss/venc.c

index 28b9a6d61b0f96c05e52dd67923ea20d79583d24..30fe4dfeb22700a92f8347f4cad682252e68df36 100644 (file)
@@ -363,6 +363,29 @@ static struct panel_config generic_dpi_panels[] = {
 
                .name                   = "ortustech_com43h4m10xtc",
        },
+
+       /* Innolux AT080TN52 */
+       {
+               {
+                       .x_res = 800,
+                       .y_res = 600,
+
+                       .pixel_clock    = 41142,
+
+                       .hsw            = 20,
+                       .hfp            = 210,
+                       .hbp            = 46,
+
+                       .vsw            = 10,
+                       .vfp            = 12,
+                       .vbp            = 23,
+               },
+               .acb                    = 0x0,
+               .config                 = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
+                                         OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IEO,
+
+               .name                   = "innolux_at080tn52",
+       },
 };
 
 struct panel_drv_data {
index e6649aa8959135be0181744ea5e528ac4189e2c5..d63e5e5dbbfac2d505ca2be38b569594946baad2 100644 (file)
                        TPO_R03_EN_PRE_CHARGE | TPO_R03_SOFTWARE_CTL)
 
 static const u16 tpo_td043_def_gamma[12] = {
-       106, 200, 289, 375, 460, 543, 625, 705, 785, 864, 942, 1020
+       105, 315, 381, 431, 490, 537, 579, 686, 780, 837, 880, 1023
 };
 
 struct tpo_td043_device {
        struct spi_device *spi;
        struct regulator *vcc_reg;
+       int nreset_gpio;
        u16 gamma[12];
        u32 mode;
        u32 hmirror:1;
        u32 vmirror:1;
+       u32 powered_on:1;
+       u32 spi_suspended:1;
+       u32 power_on_resume:1;
 };
 
 static int tpo_td043_write(struct spi_device *spi, u8 addr, u8 data)
@@ -265,28 +269,16 @@ static const struct omap_video_timings tpo_td043_timings = {
        .vbp            = 34,
 };
 
-static int tpo_td043_power_on(struct omap_dss_device *dssdev)
+static int tpo_td043_power_on(struct tpo_td043_device *tpo_td043)
 {
-       struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
-       int nreset_gpio = dssdev->reset_gpio;
-       int r;
+       int nreset_gpio = tpo_td043->nreset_gpio;
 
-       if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
+       if (tpo_td043->powered_on)
                return 0;
 
-       r = omapdss_dpi_display_enable(dssdev);
-       if (r)
-               goto err0;
-
-       if (dssdev->platform_enable) {
-               r = dssdev->platform_enable(dssdev);
-               if (r)
-                       goto err1;
-       }
-
        regulator_enable(tpo_td043->vcc_reg);
 
-       /* wait for power up */
+       /* wait for regulator to stabilize */
        msleep(160);
 
        if (gpio_is_valid(nreset_gpio))
@@ -301,19 +293,15 @@ static int tpo_td043_power_on(struct omap_dss_device *dssdev)
                        tpo_td043->vmirror);
        tpo_td043_write_gamma(tpo_td043->spi, tpo_td043->gamma);
 
+       tpo_td043->powered_on = 1;
        return 0;
-err1:
-       omapdss_dpi_display_disable(dssdev);
-err0:
-       return r;
 }
 
-static void tpo_td043_power_off(struct omap_dss_device *dssdev)
+static void tpo_td043_power_off(struct tpo_td043_device *tpo_td043)
 {
-       struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
-       int nreset_gpio = dssdev->reset_gpio;
+       int nreset_gpio = tpo_td043->nreset_gpio;
 
-       if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+       if (!tpo_td043->powered_on)
                return;
 
        tpo_td043_write(tpo_td043->spi, 3,
@@ -329,54 +317,94 @@ static void tpo_td043_power_off(struct omap_dss_device *dssdev)
 
        regulator_disable(tpo_td043->vcc_reg);
 
+       tpo_td043->powered_on = 0;
+}
+
+static int tpo_td043_enable_dss(struct omap_dss_device *dssdev)
+{
+       struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
+       int r;
+
+       if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
+               return 0;
+
+       r = omapdss_dpi_display_enable(dssdev);
+       if (r)
+               goto err0;
+
+       if (dssdev->platform_enable) {
+               r = dssdev->platform_enable(dssdev);
+               if (r)
+                       goto err1;
+       }
+
+       /*
+        * If we are resuming from system suspend, SPI clocks might not be
+        * enabled yet, so we'll program the LCD from SPI PM resume callback.
+        */
+       if (!tpo_td043->spi_suspended) {
+               r = tpo_td043_power_on(tpo_td043);
+               if (r)
+                       goto err1;
+       }
+
+       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+       return 0;
+err1:
+       omapdss_dpi_display_disable(dssdev);
+err0:
+       return r;
+}
+
+static void tpo_td043_disable_dss(struct omap_dss_device *dssdev)
+{
+       struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
+
+       if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+               return;
+
        if (dssdev->platform_disable)
                dssdev->platform_disable(dssdev);
 
        omapdss_dpi_display_disable(dssdev);
+
+       if (!tpo_td043->spi_suspended)
+               tpo_td043_power_off(tpo_td043);
 }
 
 static int tpo_td043_enable(struct omap_dss_device *dssdev)
 {
-       int ret;
-
        dev_dbg(&dssdev->dev, "enable\n");
 
-       ret = tpo_td043_power_on(dssdev);
-       if (ret)
-               return ret;
-
-       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-       return 0;
+       return tpo_td043_enable_dss(dssdev);
 }
 
 static void tpo_td043_disable(struct omap_dss_device *dssdev)
 {
        dev_dbg(&dssdev->dev, "disable\n");
 
-       tpo_td043_power_off(dssdev);
+       tpo_td043_disable_dss(dssdev);
 
        dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
 }
 
 static int tpo_td043_suspend(struct omap_dss_device *dssdev)
 {
-       tpo_td043_power_off(dssdev);
+       dev_dbg(&dssdev->dev, "suspend\n");
+
+       tpo_td043_disable_dss(dssdev);
+
        dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
+
        return 0;
 }
 
 static int tpo_td043_resume(struct omap_dss_device *dssdev)
 {
-       int r = 0;
-
-       r = tpo_td043_power_on(dssdev);
-       if (r)
-               return r;
-
-       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+       dev_dbg(&dssdev->dev, "resume\n");
 
-       return 0;
+       return tpo_td043_enable_dss(dssdev);
 }
 
 static int tpo_td043_probe(struct omap_dss_device *dssdev)
@@ -491,6 +519,7 @@ static int tpo_td043_spi_probe(struct spi_device *spi)
                return -ENOMEM;
 
        tpo_td043->spi = spi;
+       tpo_td043->nreset_gpio = dssdev->reset_gpio;
        dev_set_drvdata(&spi->dev, tpo_td043);
        dev_set_drvdata(&dssdev->dev, tpo_td043);
 
@@ -509,10 +538,46 @@ static int __devexit tpo_td043_spi_remove(struct spi_device *spi)
        return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int tpo_td043_spi_suspend(struct device *dev)
+{
+       struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
+
+       dev_dbg(dev, "tpo_td043_spi_suspend, tpo %p\n", tpo_td043);
+
+       tpo_td043->power_on_resume = tpo_td043->powered_on;
+       tpo_td043_power_off(tpo_td043);
+       tpo_td043->spi_suspended = 1;
+
+       return 0;
+}
+
+static int tpo_td043_spi_resume(struct device *dev)
+{
+       struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
+       int ret;
+
+       dev_dbg(dev, "tpo_td043_spi_resume\n");
+
+       if (tpo_td043->power_on_resume) {
+               ret = tpo_td043_power_on(tpo_td043);
+               if (ret)
+                       return ret;
+       }
+       tpo_td043->spi_suspended = 0;
+
+       return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(tpo_td043_spi_pm,
+       tpo_td043_spi_suspend, tpo_td043_spi_resume);
+
 static struct spi_driver tpo_td043_spi_driver = {
        .driver = {
                .name   = "tpo_td043mtea1_panel_spi",
                .owner  = THIS_MODULE,
+               .pm     = &tpo_td043_spi_pm,
        },
        .probe  = tpo_td043_spi_probe,
        .remove = __devexit_p(tpo_td043_spi_remove),
index 052dc874cd3d9e6696c36f9e6e214081433d07e5..b0264a164652fe93af3cd3cc52503fd1b5467d9b 100644 (file)
@@ -105,6 +105,9 @@ static struct {
        struct ovl_priv_data ovl_priv_data_array[MAX_DSS_OVERLAYS];
        struct mgr_priv_data mgr_priv_data_array[MAX_DSS_MANAGERS];
 
+       bool fifo_merge_dirty;
+       bool fifo_merge;
+
        bool irq_enabled;
 } dss_data;
 
@@ -585,11 +588,40 @@ static void dss_mgr_write_regs(struct omap_overlay_manager *mgr)
        }
 }
 
+static void dss_write_regs_common(void)
+{
+       const int num_mgrs = omap_dss_get_num_overlay_managers();
+       int i;
+
+       if (!dss_data.fifo_merge_dirty)
+               return;
+
+       for (i = 0; i < num_mgrs; ++i) {
+               struct omap_overlay_manager *mgr;
+               struct mgr_priv_data *mp;
+
+               mgr = omap_dss_get_overlay_manager(i);
+               mp = get_mgr_priv(mgr);
+
+               if (mp->enabled) {
+                       if (dss_data.fifo_merge_dirty) {
+                               dispc_enable_fifomerge(dss_data.fifo_merge);
+                               dss_data.fifo_merge_dirty = false;
+                       }
+
+                       if (mp->updating)
+                               mp->shadow_info_dirty = true;
+               }
+       }
+}
+
 static void dss_write_regs(void)
 {
        const int num_mgrs = omap_dss_get_num_overlay_managers();
        int i;
 
+       dss_write_regs_common();
+
        for (i = 0; i < num_mgrs; ++i) {
                struct omap_overlay_manager *mgr;
                struct mgr_priv_data *mp;
@@ -659,6 +691,8 @@ void dss_mgr_start_update(struct omap_overlay_manager *mgr)
 
        dss_mgr_write_regs(mgr);
 
+       dss_write_regs_common();
+
        mp->updating = true;
 
        if (!dss_data.irq_enabled && need_isr())
@@ -859,11 +893,20 @@ static void dss_apply_ovl_fifo_thresholds(struct omap_overlay *ovl,
        op->extra_info_dirty = true;
 }
 
-static void dss_ovl_setup_fifo(struct omap_overlay *ovl)
+static void dss_apply_fifo_merge(bool use_fifo_merge)
+{
+       if (dss_data.fifo_merge == use_fifo_merge)
+               return;
+
+       dss_data.fifo_merge = use_fifo_merge;
+       dss_data.fifo_merge_dirty = true;
+}
+
+static void dss_ovl_setup_fifo(struct omap_overlay *ovl,
+               bool use_fifo_merge)
 {
        struct ovl_priv_data *op = get_ovl_priv(ovl);
        struct omap_dss_device *dssdev;
-       u32 size, burst_size;
        u32 fifo_low, fifo_high;
 
        if (!op->enabled && !op->enabling)
@@ -871,33 +914,14 @@ static void dss_ovl_setup_fifo(struct omap_overlay *ovl)
 
        dssdev = ovl->manager->device;
 
-       size = dispc_ovl_get_fifo_size(ovl->id);
-
-       burst_size = dispc_ovl_get_burst_size(ovl->id);
-
-       switch (dssdev->type) {
-       case OMAP_DISPLAY_TYPE_DPI:
-       case OMAP_DISPLAY_TYPE_DBI:
-       case OMAP_DISPLAY_TYPE_SDI:
-       case OMAP_DISPLAY_TYPE_VENC:
-       case OMAP_DISPLAY_TYPE_HDMI:
-               default_get_overlay_fifo_thresholds(ovl->id, size,
-                               burst_size, &fifo_low, &fifo_high);
-               break;
-#ifdef CONFIG_OMAP2_DSS_DSI
-       case OMAP_DISPLAY_TYPE_DSI:
-               dsi_get_overlay_fifo_thresholds(ovl->id, size,
-                               burst_size, &fifo_low, &fifo_high);
-               break;
-#endif
-       default:
-               BUG();
-       }
+       dispc_ovl_compute_fifo_thresholds(ovl->id, &fifo_low, &fifo_high,
+                       use_fifo_merge);
 
        dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high);
 }
 
-static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr)
+static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr,
+               bool use_fifo_merge)
 {
        struct omap_overlay *ovl;
        struct mgr_priv_data *mp;
@@ -908,19 +932,94 @@ static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr)
                return;
 
        list_for_each_entry(ovl, &mgr->overlays, list)
-               dss_ovl_setup_fifo(ovl);
+               dss_ovl_setup_fifo(ovl, use_fifo_merge);
+}
+
+static void dss_setup_fifos(bool use_fifo_merge)
+{
+       const int num_mgrs = omap_dss_get_num_overlay_managers();
+       struct omap_overlay_manager *mgr;
+       int i;
+
+       for (i = 0; i < num_mgrs; ++i) {
+               mgr = omap_dss_get_overlay_manager(i);
+               dss_mgr_setup_fifos(mgr, use_fifo_merge);
+       }
 }
 
-static void dss_setup_fifos(void)
+static int get_num_used_managers(void)
 {
        const int num_mgrs = omap_dss_get_num_overlay_managers();
        struct omap_overlay_manager *mgr;
+       struct mgr_priv_data *mp;
        int i;
+       int enabled_mgrs;
+
+       enabled_mgrs = 0;
 
        for (i = 0; i < num_mgrs; ++i) {
                mgr = omap_dss_get_overlay_manager(i);
-               dss_mgr_setup_fifos(mgr);
+               mp = get_mgr_priv(mgr);
+
+               if (!mp->enabled)
+                       continue;
+
+               enabled_mgrs++;
        }
+
+       return enabled_mgrs;
+}
+
+static int get_num_used_overlays(void)
+{
+       const int num_ovls = omap_dss_get_num_overlays();
+       struct omap_overlay *ovl;
+       struct ovl_priv_data *op;
+       struct mgr_priv_data *mp;
+       int i;
+       int enabled_ovls;
+
+       enabled_ovls = 0;
+
+       for (i = 0; i < num_ovls; ++i) {
+               ovl = omap_dss_get_overlay(i);
+               op = get_ovl_priv(ovl);
+
+               if (!op->enabled && !op->enabling)
+                       continue;
+
+               mp = get_mgr_priv(ovl->manager);
+
+               if (!mp->enabled)
+                       continue;
+
+               enabled_ovls++;
+       }
+
+       return enabled_ovls;
+}
+
+static bool get_use_fifo_merge(void)
+{
+       int enabled_mgrs = get_num_used_managers();
+       int enabled_ovls = get_num_used_overlays();
+
+       if (!dss_has_feature(FEAT_FIFO_MERGE))
+               return false;
+
+       /*
+        * In theory the only requirement for fifomerge is enabled_ovls <= 1.
+        * However, if we have two managers enabled and set/unset the fifomerge,
+        * we need to set the GO bits in particular sequence for the managers,
+        * and wait in between.
+        *
+        * This is rather difficult as new apply calls can happen at any time,
+        * so we simplify the problem by requiring also that enabled_mgrs <= 1.
+        * In practice this shouldn't matter, because when only one overlay is
+        * enabled, most likely only one output is enabled.
+        */
+
+       return enabled_mgrs <= 1 && enabled_ovls <= 1;
 }
 
 int dss_mgr_enable(struct omap_overlay_manager *mgr)
@@ -928,6 +1027,7 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr)
        struct mgr_priv_data *mp = get_mgr_priv(mgr);
        unsigned long flags;
        int r;
+       bool fifo_merge;
 
        mutex_lock(&apply_lock);
 
@@ -945,11 +1045,23 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr)
                goto err;
        }
 
-       dss_setup_fifos();
+       /* step 1: setup fifos/fifomerge before enabling the manager */
+
+       fifo_merge = get_use_fifo_merge();
+       dss_setup_fifos(fifo_merge);
+       dss_apply_fifo_merge(fifo_merge);
 
        dss_write_regs();
        dss_set_go_bits();
 
+       spin_unlock_irqrestore(&data_lock, flags);
+
+       /* wait until fifo config is in */
+       wait_pending_extra_info_updates();
+
+       /* step 2: enable the manager */
+       spin_lock_irqsave(&data_lock, flags);
+
        if (!mgr_manual_update(mgr))
                mp->updating = true;
 
@@ -974,6 +1086,7 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)
 {
        struct mgr_priv_data *mp = get_mgr_priv(mgr);
        unsigned long flags;
+       bool fifo_merge;
 
        mutex_lock(&apply_lock);
 
@@ -988,8 +1101,16 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)
        mp->updating = false;
        mp->enabled = false;
 
+       fifo_merge = get_use_fifo_merge();
+       dss_setup_fifos(fifo_merge);
+       dss_apply_fifo_merge(fifo_merge);
+
+       dss_write_regs();
+       dss_set_go_bits();
+
        spin_unlock_irqrestore(&data_lock, flags);
 
+       wait_pending_extra_info_updates();
 out:
        mutex_unlock(&apply_lock);
 }
@@ -1241,6 +1362,7 @@ int dss_ovl_enable(struct omap_overlay *ovl)
 {
        struct ovl_priv_data *op = get_ovl_priv(ovl);
        unsigned long flags;
+       bool fifo_merge;
        int r;
 
        mutex_lock(&apply_lock);
@@ -1266,7 +1388,22 @@ int dss_ovl_enable(struct omap_overlay *ovl)
                goto err2;
        }
 
-       dss_setup_fifos();
+       /* step 1: configure fifos/fifomerge for currently enabled ovls */
+
+       fifo_merge = get_use_fifo_merge();
+       dss_setup_fifos(fifo_merge);
+       dss_apply_fifo_merge(fifo_merge);
+
+       dss_write_regs();
+       dss_set_go_bits();
+
+       spin_unlock_irqrestore(&data_lock, flags);
+
+       /* wait for fifo configs to go in */
+       wait_pending_extra_info_updates();
+
+       /* step 2: enable the overlay */
+       spin_lock_irqsave(&data_lock, flags);
 
        op->enabling = false;
        dss_apply_ovl_enable(ovl, true);
@@ -1276,6 +1413,9 @@ int dss_ovl_enable(struct omap_overlay *ovl)
 
        spin_unlock_irqrestore(&data_lock, flags);
 
+       /* wait for overlay to be enabled */
+       wait_pending_extra_info_updates();
+
        mutex_unlock(&apply_lock);
 
        return 0;
@@ -1291,6 +1431,7 @@ int dss_ovl_disable(struct omap_overlay *ovl)
 {
        struct ovl_priv_data *op = get_ovl_priv(ovl);
        unsigned long flags;
+       bool fifo_merge;
        int r;
 
        mutex_lock(&apply_lock);
@@ -1305,14 +1446,34 @@ int dss_ovl_disable(struct omap_overlay *ovl)
                goto err;
        }
 
+       /* step 1: disable the overlay */
        spin_lock_irqsave(&data_lock, flags);
 
        dss_apply_ovl_enable(ovl, false);
+
        dss_write_regs();
        dss_set_go_bits();
 
        spin_unlock_irqrestore(&data_lock, flags);
 
+       /* wait for the overlay to be disabled */
+       wait_pending_extra_info_updates();
+
+       /* step 2: configure fifos/fifomerge */
+       spin_lock_irqsave(&data_lock, flags);
+
+       fifo_merge = get_use_fifo_merge();
+       dss_setup_fifos(fifo_merge);
+       dss_apply_fifo_merge(fifo_merge);
+
+       dss_write_regs();
+       dss_set_go_bits();
+
+       spin_unlock_irqrestore(&data_lock, flags);
+
+       /* wait for fifo config to go in */
+       wait_pending_extra_info_updates();
+
        mutex_unlock(&apply_lock);
 
        return 0;
index 0aecb680f8a7d743443e6e969f088dc033ebe869..700bb563cfcd59c6f39b85d9fd72965297e314e7 100644 (file)
@@ -908,7 +908,7 @@ static void dispc_configure_burst_sizes(void)
                dispc_ovl_set_burst_size(i, burst_size);
 }
 
-u32 dispc_ovl_get_burst_size(enum omap_plane plane)
+static u32 dispc_ovl_get_burst_size(enum omap_plane plane)
 {
        unsigned unit = dss_feat_get_burst_size_unit();
        /* burst multiplier is always x8 (see dispc_configure_burst_sizes()) */
@@ -1017,7 +1017,7 @@ static void dispc_read_plane_fifo_sizes(void)
        }
 }
 
-u32 dispc_ovl_get_fifo_size(enum omap_plane plane)
+static u32 dispc_ovl_get_fifo_size(enum omap_plane plane)
 {
        return dispc.fifo_size[plane];
 }
@@ -1038,13 +1038,13 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high)
        dss_feat_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end);
        dss_feat_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end);
 
-       DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n",
+       DSSDBG("fifo(%d) threshold (bytes), old %u/%u, new %u/%u\n",
                        plane,
                        REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane),
-                               lo_start, lo_end),
+                               lo_start, lo_end) * unit,
                        REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane),
-                               hi_start, hi_end),
-                       low, high);
+                               hi_start, hi_end) * unit,
+                       low * unit, high * unit);
 
        dispc_write_reg(DISPC_OVL_FIFO_THRESHOLD(plane),
                        FLD_VAL(high, hi_start, hi_end) |
@@ -1053,10 +1053,53 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high)
 
 void dispc_enable_fifomerge(bool enable)
 {
+       if (!dss_has_feature(FEAT_FIFO_MERGE)) {
+               WARN_ON(enable);
+               return;
+       }
+
        DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled");
        REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14);
 }
 
+void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
+               u32 *fifo_low, u32 *fifo_high, bool use_fifomerge)
+{
+       /*
+        * All sizes are in bytes. Both the buffer and burst are made of
+        * buffer_units, and the fifo thresholds must be buffer_unit aligned.
+        */
+
+       unsigned buf_unit = dss_feat_get_buffer_size_unit();
+       unsigned ovl_fifo_size, total_fifo_size, burst_size;
+       int i;
+
+       burst_size = dispc_ovl_get_burst_size(plane);
+       ovl_fifo_size = dispc_ovl_get_fifo_size(plane);
+
+       if (use_fifomerge) {
+               total_fifo_size = 0;
+               for (i = 0; i < omap_dss_get_num_overlays(); ++i)
+                       total_fifo_size += dispc_ovl_get_fifo_size(i);
+       } else {
+               total_fifo_size = ovl_fifo_size;
+       }
+
+       /*
+        * We use the same low threshold for both fifomerge and non-fifomerge
+        * cases, but for fifomerge we calculate the high threshold using the
+        * combined fifo size
+        */
+
+       if (dss_has_feature(FEAT_OMAP3_DSI_FIFO_BUG)) {
+               *fifo_low = ovl_fifo_size - burst_size * 2;
+               *fifo_high = total_fifo_size - burst_size;
+       } else {
+               *fifo_low = ovl_fifo_size - burst_size;
+               *fifo_high = total_fifo_size - buf_unit;
+       }
+}
+
 static void dispc_ovl_set_fir(enum omap_plane plane,
                                int hinc, int vinc,
                                enum omap_color_component color_comp)
@@ -1650,6 +1693,7 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width,
                u16 height, u16 out_width, u16 out_height)
 {
        unsigned int hf, vf;
+       unsigned long pclk = dispc_mgr_pclk_rate(channel);
 
        /*
         * FIXME how to determine the 'A' factor
@@ -1672,13 +1716,16 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width,
 
        if (cpu_is_omap24xx()) {
                if (vf > 1 && hf > 1)
-                       return dispc_mgr_pclk_rate(channel) * 4;
+                       return pclk * 4;
                else
-                       return dispc_mgr_pclk_rate(channel) * 2;
+                       return pclk * 2;
        } else if (cpu_is_omap34xx()) {
-               return dispc_mgr_pclk_rate(channel) * vf * hf;
+               return pclk * vf * hf;
        } else {
-               return dispc_mgr_pclk_rate(channel) * hf;
+               if (hf > 1)
+                       return DIV_ROUND_UP(pclk, out_width) * width;
+               else
+                       return pclk;
        }
 }
 
@@ -3297,15 +3344,6 @@ static int omap_dispchw_probe(struct platform_device *pdev)
 
        dispc.pdev = pdev;
 
-       clk = clk_get(&pdev->dev, "fck");
-       if (IS_ERR(clk)) {
-               DSSERR("can't get fck\n");
-               r = PTR_ERR(clk);
-               goto err_get_clk;
-       }
-
-       dispc.dss_clk = clk;
-
        spin_lock_init(&dispc.irq_lock);
 
 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
@@ -3318,29 +3356,38 @@ static int omap_dispchw_probe(struct platform_device *pdev)
        dispc_mem = platform_get_resource(dispc.pdev, IORESOURCE_MEM, 0);
        if (!dispc_mem) {
                DSSERR("can't get IORESOURCE_MEM DISPC\n");
-               r = -EINVAL;
-               goto err_ioremap;
+               return -EINVAL;
        }
-       dispc.base = ioremap(dispc_mem->start, resource_size(dispc_mem));
+
+       dispc.base = devm_ioremap(&pdev->dev, dispc_mem->start,
+                                 resource_size(dispc_mem));
        if (!dispc.base) {
                DSSERR("can't ioremap DISPC\n");
-               r = -ENOMEM;
-               goto err_ioremap;
+               return -ENOMEM;
        }
+
        dispc.irq = platform_get_irq(dispc.pdev, 0);
        if (dispc.irq < 0) {
                DSSERR("platform_get_irq failed\n");
-               r = -ENODEV;
-               goto err_irq;
+               return -ENODEV;
        }
 
-       r = request_irq(dispc.irq, omap_dispc_irq_handler, IRQF_SHARED,
-               "OMAP DISPC", dispc.pdev);
+       r = devm_request_irq(&pdev->dev, dispc.irq, omap_dispc_irq_handler,
+                            IRQF_SHARED, "OMAP DISPC", dispc.pdev);
        if (r < 0) {
                DSSERR("request_irq failed\n");
-               goto err_irq;
+               return r;
+       }
+
+       clk = clk_get(&pdev->dev, "fck");
+       if (IS_ERR(clk)) {
+               DSSERR("can't get fck\n");
+               r = PTR_ERR(clk);
+               return r;
        }
 
+       dispc.dss_clk = clk;
+
        pm_runtime_enable(&pdev->dev);
 
        r = dispc_runtime_get();
@@ -3361,12 +3408,7 @@ static int omap_dispchw_probe(struct platform_device *pdev)
 
 err_runtime_get:
        pm_runtime_disable(&pdev->dev);
-       free_irq(dispc.irq, dispc.pdev);
-err_irq:
-       iounmap(dispc.base);
-err_ioremap:
        clk_put(dispc.dss_clk);
-err_get_clk:
        return r;
 }
 
@@ -3376,8 +3418,6 @@ static int omap_dispchw_remove(struct platform_device *pdev)
 
        clk_put(dispc.dss_clk);
 
-       free_irq(dispc.irq, dispc.pdev);
-       iounmap(dispc.base);
        return 0;
 }
 
index be331dc5a61bc04404f607c202315a26c668e50f..4424c198dbcda6c3a34fa53189ecd28a5a446388 100644 (file)
@@ -279,16 +279,6 @@ void omapdss_default_get_resolution(struct omap_dss_device *dssdev,
 }
 EXPORT_SYMBOL(omapdss_default_get_resolution);
 
-void default_get_overlay_fifo_thresholds(enum omap_plane plane,
-               u32 fifo_size, u32 burst_size,
-               u32 *fifo_low, u32 *fifo_high)
-{
-       unsigned buf_unit = dss_feat_get_buffer_size_unit();
-
-       *fifo_high = fifo_size - buf_unit;
-       *fifo_low = fifo_size - burst_size;
-}
-
 int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev)
 {
        switch (dssdev->type) {
index 52f36ec1c8bb3889e9e23cb2c6b6eca2181a454a..662d14f8c2c382c4bdbe569c33863256314c122a 100644 (file)
@@ -4524,14 +4524,6 @@ int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable)
 }
 EXPORT_SYMBOL(omapdss_dsi_enable_te);
 
-void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
-               u32 fifo_size, u32 burst_size,
-               u32 *fifo_low, u32 *fifo_high)
-{
-       *fifo_high = fifo_size - burst_size;
-       *fifo_low = fifo_size - burst_size * 2;
-}
-
 int dsi_init_display(struct omap_dss_device *dssdev)
 {
        struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -4695,11 +4687,9 @@ static int omap_dsihw_probe(struct platform_device *dsidev)
        struct resource *dsi_mem;
        struct dsi_data *dsi;
 
-       dsi = kzalloc(sizeof(*dsi), GFP_KERNEL);
-       if (!dsi) {
-               r = -ENOMEM;
-               goto err_alloc;
-       }
+       dsi = devm_kzalloc(&dsidev->dev, sizeof(*dsi), GFP_KERNEL);
+       if (!dsi)
+               return -ENOMEM;
 
        dsi->pdev = dsidev;
        dsi_pdev_map[dsi_module] = dsidev;
@@ -4722,12 +4712,6 @@ static int omap_dsihw_probe(struct platform_device *dsidev)
        mutex_init(&dsi->lock);
        sema_init(&dsi->bus_lock, 1);
 
-       r = dsi_get_clocks(dsidev);
-       if (r)
-               goto err_get_clk;
-
-       pm_runtime_enable(&dsidev->dev);
-
        INIT_DELAYED_WORK_DEFERRABLE(&dsi->framedone_timeout_work,
                        dsi_framedone_timeout_work_callback);
 
@@ -4739,27 +4723,27 @@ static int omap_dsihw_probe(struct platform_device *dsidev)
        dsi_mem = platform_get_resource(dsi->pdev, IORESOURCE_MEM, 0);
        if (!dsi_mem) {
                DSSERR("can't get IORESOURCE_MEM DSI\n");
-               r = -EINVAL;
-               goto err_ioremap;
+               return -EINVAL;
        }
-       dsi->base = ioremap(dsi_mem->start, resource_size(dsi_mem));
+
+       dsi->base = devm_ioremap(&dsidev->dev, dsi_mem->start,
+                                resource_size(dsi_mem));
        if (!dsi->base) {
                DSSERR("can't ioremap DSI\n");
-               r = -ENOMEM;
-               goto err_ioremap;
+               return -ENOMEM;
        }
+
        dsi->irq = platform_get_irq(dsi->pdev, 0);
        if (dsi->irq < 0) {
                DSSERR("platform_get_irq failed\n");
-               r = -ENODEV;
-               goto err_get_irq;
+               return -ENODEV;
        }
 
-       r = request_irq(dsi->irq, omap_dsi_irq_handler, IRQF_SHARED,
-               dev_name(&dsidev->dev), dsi->pdev);
+       r = devm_request_irq(&dsidev->dev, dsi->irq, omap_dsi_irq_handler,
+                            IRQF_SHARED, dev_name(&dsidev->dev), dsi->pdev);
        if (r < 0) {
                DSSERR("request_irq failed\n");
-               goto err_get_irq;
+               return r;
        }
 
        /* DSI VCs initialization */
@@ -4771,9 +4755,15 @@ static int omap_dsihw_probe(struct platform_device *dsidev)
 
        dsi_calc_clock_param_ranges(dsidev);
 
+       r = dsi_get_clocks(dsidev);
+       if (r)
+               return r;
+
+       pm_runtime_enable(&dsidev->dev);
+
        r = dsi_runtime_get(dsidev);
        if (r)
-               goto err_get_dsi;
+               goto err_runtime_get;
 
        rev = dsi_read_reg(dsidev, DSI_REVISION);
        dev_dbg(&dsidev->dev, "OMAP DSI rev %d.%d\n",
@@ -4791,15 +4781,9 @@ static int omap_dsihw_probe(struct platform_device *dsidev)
 
        return 0;
 
-err_get_dsi:
-       free_irq(dsi->irq, dsi->pdev);
-err_get_irq:
-       iounmap(dsi->base);
-err_ioremap:
+err_runtime_get:
        pm_runtime_disable(&dsidev->dev);
-err_get_clk:
-       kfree(dsi);
-err_alloc:
+       dsi_put_clocks(dsidev);
        return r;
 }
 
@@ -4823,11 +4807,6 @@ static int omap_dsihw_remove(struct platform_device *dsidev)
                dsi->vdds_dsi_reg = NULL;
        }
 
-       free_irq(dsi->irq, dsi->pdev);
-       iounmap(dsi->base);
-
-       kfree(dsi);
-
        return 0;
 }
 
index 77c2b5a32b5d639687e84b8faa1e0385f55b86f9..4a6b5eeef6a798b2a4dbd060e603a6a8f235ecb9 100644 (file)
@@ -748,19 +748,19 @@ static int omap_dsshw_probe(struct platform_device *pdev)
        dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
        if (!dss_mem) {
                DSSERR("can't get IORESOURCE_MEM DSS\n");
-               r = -EINVAL;
-               goto err_ioremap;
+               return -EINVAL;
        }
-       dss.base = ioremap(dss_mem->start, resource_size(dss_mem));
+
+       dss.base = devm_ioremap(&pdev->dev, dss_mem->start,
+                               resource_size(dss_mem));
        if (!dss.base) {
                DSSERR("can't ioremap DSS\n");
-               r = -ENOMEM;
-               goto err_ioremap;
+               return -ENOMEM;
        }
 
        r = dss_get_clocks();
        if (r)
-               goto err_clocks;
+               return r;
 
        pm_runtime_enable(&pdev->dev);
 
@@ -808,9 +808,6 @@ err_dpi:
 err_runtime_get:
        pm_runtime_disable(&pdev->dev);
        dss_put_clocks();
-err_clocks:
-       iounmap(dss.base);
-err_ioremap:
        return r;
 }
 
@@ -819,8 +816,6 @@ static int omap_dsshw_remove(struct platform_device *pdev)
        dpi_exit();
        sdi_exit();
 
-       iounmap(dss.base);
-
        pm_runtime_disable(&pdev->dev);
 
        dss_put_clocks();
index 32ff69fb3333fbf352f03fcad01479020dc10efa..d4b3dff2ead338db918ce4801ac7380966f6b679 100644 (file)
@@ -202,9 +202,6 @@ void dss_uninit_device(struct platform_device *pdev,
                struct omap_dss_device *dssdev);
 bool dss_use_replication(struct omap_dss_device *dssdev,
                enum omap_color_mode mode);
-void default_get_overlay_fifo_thresholds(enum omap_plane plane,
-               u32 fifo_size, u32 burst_size,
-               u32 *fifo_low, u32 *fifo_high);
 
 /* manager */
 int dss_init_overlay_managers(struct platform_device *pdev);
@@ -313,9 +310,6 @@ int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev, bool is_tft,
 int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
                bool enable_hsdiv);
 void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes);
-void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
-               u32 fifo_size, u32 burst_size,
-               u32 *fifo_low, u32 *fifo_high);
 void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev);
 void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev);
 struct platform_device *dsi_get_dsidev_from_id(int module);
@@ -429,8 +423,8 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
 
 
 void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high);
-u32 dispc_ovl_get_fifo_size(enum omap_plane plane);
-u32 dispc_ovl_get_burst_size(enum omap_plane plane);
+void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
+               u32 *fifo_low, u32 *fifo_high, bool use_fifomerge);
 int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
                bool ilace, bool replication);
 int dispc_ovl_enable(enum omap_plane plane, bool enable);
index afcb59301c3727d20149d1b112fa8596cbf3127f..0a926432ccdc23a7e06b388ab73e151ce9c50c2e 100644 (file)
@@ -41,7 +41,8 @@ struct omap_dss_features {
        const struct dss_reg_field *reg_fields;
        const int num_reg_fields;
 
-       const u32 has_feature;
+       const enum dss_feat_id *features;
+       const int num_features;
 
        const int num_mgrs;
        const int num_ovls;
@@ -337,15 +338,110 @@ static const struct dss_param_range omap4_dss_param_range[] = {
        [FEAT_PARAM_LINEWIDTH]                  = { 1, 2048 },
 };
 
+static const enum dss_feat_id omap2_dss_feat_list[] = {
+       FEAT_LCDENABLEPOL,
+       FEAT_LCDENABLESIGNAL,
+       FEAT_PCKFREEENABLE,
+       FEAT_FUNCGATED,
+       FEAT_ROWREPEATENABLE,
+       FEAT_RESIZECONF,
+};
+
+static const enum dss_feat_id omap3430_dss_feat_list[] = {
+       FEAT_LCDENABLEPOL,
+       FEAT_LCDENABLESIGNAL,
+       FEAT_PCKFREEENABLE,
+       FEAT_FUNCGATED,
+       FEAT_LINEBUFFERSPLIT,
+       FEAT_ROWREPEATENABLE,
+       FEAT_RESIZECONF,
+       FEAT_DSI_PLL_FREQSEL,
+       FEAT_DSI_REVERSE_TXCLKESC,
+       FEAT_VENC_REQUIRES_TV_DAC_CLK,
+       FEAT_CPR,
+       FEAT_PRELOAD,
+       FEAT_FIR_COEF_V,
+       FEAT_ALPHA_FIXED_ZORDER,
+       FEAT_FIFO_MERGE,
+       FEAT_OMAP3_DSI_FIFO_BUG,
+};
+
+static const enum dss_feat_id omap3630_dss_feat_list[] = {
+       FEAT_LCDENABLEPOL,
+       FEAT_LCDENABLESIGNAL,
+       FEAT_PCKFREEENABLE,
+       FEAT_FUNCGATED,
+       FEAT_LINEBUFFERSPLIT,
+       FEAT_ROWREPEATENABLE,
+       FEAT_RESIZECONF,
+       FEAT_DSI_PLL_PWR_BUG,
+       FEAT_DSI_PLL_FREQSEL,
+       FEAT_CPR,
+       FEAT_PRELOAD,
+       FEAT_FIR_COEF_V,
+       FEAT_ALPHA_FIXED_ZORDER,
+       FEAT_FIFO_MERGE,
+       FEAT_OMAP3_DSI_FIFO_BUG,
+};
+
+static const enum dss_feat_id omap4430_es1_0_dss_feat_list[] = {
+       FEAT_MGR_LCD2,
+       FEAT_CORE_CLK_DIV,
+       FEAT_LCD_CLK_SRC,
+       FEAT_DSI_DCS_CMD_CONFIG_VC,
+       FEAT_DSI_VC_OCP_WIDTH,
+       FEAT_DSI_GNQ,
+       FEAT_HANDLE_UV_SEPARATE,
+       FEAT_ATTR2,
+       FEAT_CPR,
+       FEAT_PRELOAD,
+       FEAT_FIR_COEF_V,
+       FEAT_ALPHA_FREE_ZORDER,
+       FEAT_FIFO_MERGE,
+};
+
+static const enum dss_feat_id omap4430_es2_0_1_2_dss_feat_list[] = {
+       FEAT_MGR_LCD2,
+       FEAT_CORE_CLK_DIV,
+       FEAT_LCD_CLK_SRC,
+       FEAT_DSI_DCS_CMD_CONFIG_VC,
+       FEAT_DSI_VC_OCP_WIDTH,
+       FEAT_DSI_GNQ,
+       FEAT_HDMI_CTS_SWMODE,
+       FEAT_HANDLE_UV_SEPARATE,
+       FEAT_ATTR2,
+       FEAT_CPR,
+       FEAT_PRELOAD,
+       FEAT_FIR_COEF_V,
+       FEAT_ALPHA_FREE_ZORDER,
+       FEAT_FIFO_MERGE,
+};
+
+static const enum dss_feat_id omap4_dss_feat_list[] = {
+       FEAT_MGR_LCD2,
+       FEAT_CORE_CLK_DIV,
+       FEAT_LCD_CLK_SRC,
+       FEAT_DSI_DCS_CMD_CONFIG_VC,
+       FEAT_DSI_VC_OCP_WIDTH,
+       FEAT_DSI_GNQ,
+       FEAT_HDMI_CTS_SWMODE,
+       FEAT_HDMI_AUDIO_USE_MCLK,
+       FEAT_HANDLE_UV_SEPARATE,
+       FEAT_ATTR2,
+       FEAT_CPR,
+       FEAT_PRELOAD,
+       FEAT_FIR_COEF_V,
+       FEAT_ALPHA_FREE_ZORDER,
+       FEAT_FIFO_MERGE,
+};
+
 /* OMAP2 DSS Features */
 static const struct omap_dss_features omap2_dss_features = {
        .reg_fields = omap2_dss_reg_fields,
        .num_reg_fields = ARRAY_SIZE(omap2_dss_reg_fields),
 
-       .has_feature    =
-               FEAT_LCDENABLEPOL | FEAT_LCDENABLESIGNAL |
-               FEAT_PCKFREEENABLE | FEAT_FUNCGATED |
-               FEAT_ROWREPEATENABLE | FEAT_RESIZECONF,
+       .features = omap2_dss_feat_list,
+       .num_features = ARRAY_SIZE(omap2_dss_feat_list),
 
        .num_mgrs = 2,
        .num_ovls = 3,
@@ -363,14 +459,8 @@ static const struct omap_dss_features omap3430_dss_features = {
        .reg_fields = omap3_dss_reg_fields,
        .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
 
-       .has_feature    =
-               FEAT_LCDENABLEPOL |
-               FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE |
-               FEAT_FUNCGATED | FEAT_ROWREPEATENABLE |
-               FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF |
-               FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC |
-               FEAT_VENC_REQUIRES_TV_DAC_CLK | FEAT_CPR | FEAT_PRELOAD |
-               FEAT_FIR_COEF_V | FEAT_ALPHA_FIXED_ZORDER,
+       .features = omap3430_dss_feat_list,
+       .num_features = ARRAY_SIZE(omap3430_dss_feat_list),
 
        .num_mgrs = 2,
        .num_ovls = 3,
@@ -387,14 +477,8 @@ static const struct omap_dss_features omap3630_dss_features = {
        .reg_fields = omap3_dss_reg_fields,
        .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
 
-       .has_feature    =
-               FEAT_LCDENABLEPOL |
-               FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE |
-               FEAT_FUNCGATED |
-               FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT |
-               FEAT_RESIZECONF | FEAT_DSI_PLL_PWR_BUG |
-               FEAT_DSI_PLL_FREQSEL | FEAT_CPR | FEAT_PRELOAD |
-               FEAT_FIR_COEF_V | FEAT_ALPHA_FIXED_ZORDER,
+       .features = omap3630_dss_feat_list,
+       .num_features = ARRAY_SIZE(omap3630_dss_feat_list),
 
        .num_mgrs = 2,
        .num_ovls = 3,
@@ -413,13 +497,27 @@ static const struct omap_dss_features omap4430_es1_0_dss_features  = {
        .reg_fields = omap4_dss_reg_fields,
        .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields),
 
-       .has_feature    =
-               FEAT_MGR_LCD2 |
-               FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC |
-               FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH |
-               FEAT_DSI_GNQ | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 |
-               FEAT_CPR | FEAT_PRELOAD | FEAT_FIR_COEF_V |
-               FEAT_ALPHA_FREE_ZORDER,
+       .features = omap4430_es1_0_dss_feat_list,
+       .num_features = ARRAY_SIZE(omap4430_es1_0_dss_feat_list),
+
+       .num_mgrs = 3,
+       .num_ovls = 4,
+       .supported_displays = omap4_dss_supported_displays,
+       .supported_color_modes = omap4_dss_supported_color_modes,
+       .overlay_caps = omap4_dss_overlay_caps,
+       .clksrc_names = omap4_dss_clk_source_names,
+       .dss_params = omap4_dss_param_range,
+       .buffer_size_unit = 16,
+       .burst_size_unit = 16,
+};
+
+/* For OMAP4430 ES 2.0, 2.1 and 2.2 revisions */
+static const struct omap_dss_features omap4430_es2_0_1_2_dss_features = {
+       .reg_fields = omap4_dss_reg_fields,
+       .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields),
+
+       .features = omap4430_es2_0_1_2_dss_feat_list,
+       .num_features = ARRAY_SIZE(omap4430_es2_0_1_2_dss_feat_list),
 
        .num_mgrs = 3,
        .num_ovls = 4,
@@ -437,13 +535,8 @@ static const struct omap_dss_features omap4_dss_features = {
        .reg_fields = omap4_dss_reg_fields,
        .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields),
 
-       .has_feature    =
-               FEAT_MGR_LCD2 |
-               FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC |
-               FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH |
-               FEAT_DSI_GNQ | FEAT_HDMI_CTS_SWMODE |
-               FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 | FEAT_CPR |
-               FEAT_PRELOAD | FEAT_FIR_COEF_V | FEAT_ALPHA_FREE_ZORDER,
+       .features = omap4_dss_feat_list,
+       .num_features = ARRAY_SIZE(omap4_dss_feat_list),
 
        .num_mgrs = 3,
        .num_ovls = 4,
@@ -547,7 +640,16 @@ u32 dss_feat_get_burst_size_unit(void)
 /* DSS has_feature check */
 bool dss_has_feature(enum dss_feat_id id)
 {
-       return omap_current_dss_features->has_feature & id;
+       int i;
+       const enum dss_feat_id *features = omap_current_dss_features->features;
+       const int num_features = omap_current_dss_features->num_features;
+
+       for (i = 0; i < num_features; i++) {
+               if (features[i] == id)
+                       return true;
+       }
+
+       return false;
 }
 
 void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end)
@@ -569,6 +671,10 @@ void dss_features_init(void)
                omap_current_dss_features = &omap3430_dss_features;
        else if (omap_rev() == OMAP4430_REV_ES1_0)
                omap_current_dss_features = &omap4430_es1_0_dss_features;
+       else if (omap_rev() == OMAP4430_REV_ES2_0 ||
+               omap_rev() == OMAP4430_REV_ES2_1 ||
+               omap_rev() == OMAP4430_REV_ES2_2)
+               omap_current_dss_features = &omap4430_es2_0_1_2_dss_features;
        else if (cpu_is_omap44xx())
                omap_current_dss_features = &omap4_dss_features;
        else
index cd833bbaac3d60bf2e1b46395220a3a16d2bc907..c332e7ddfce14dfedfecad805f1eae2c5478d27e 100644 (file)
 
 /* DSS has feature id */
 enum dss_feat_id {
-       FEAT_LCDENABLEPOL               = 1 << 3,
-       FEAT_LCDENABLESIGNAL            = 1 << 4,
-       FEAT_PCKFREEENABLE              = 1 << 5,
-       FEAT_FUNCGATED                  = 1 << 6,
-       FEAT_MGR_LCD2                   = 1 << 7,
-       FEAT_LINEBUFFERSPLIT            = 1 << 8,
-       FEAT_ROWREPEATENABLE            = 1 << 9,
-       FEAT_RESIZECONF                 = 1 << 10,
+       FEAT_LCDENABLEPOL,
+       FEAT_LCDENABLESIGNAL,
+       FEAT_PCKFREEENABLE,
+       FEAT_FUNCGATED,
+       FEAT_MGR_LCD2,
+       FEAT_LINEBUFFERSPLIT,
+       FEAT_ROWREPEATENABLE,
+       FEAT_RESIZECONF,
        /* Independent core clk divider */
-       FEAT_CORE_CLK_DIV               = 1 << 11,
-       FEAT_LCD_CLK_SRC                = 1 << 12,
+       FEAT_CORE_CLK_DIV,
+       FEAT_LCD_CLK_SRC,
        /* DSI-PLL power command 0x3 is not working */
-       FEAT_DSI_PLL_PWR_BUG            = 1 << 13,
-       FEAT_DSI_PLL_FREQSEL            = 1 << 14,
-       FEAT_DSI_DCS_CMD_CONFIG_VC      = 1 << 15,
-       FEAT_DSI_VC_OCP_WIDTH           = 1 << 16,
-       FEAT_DSI_REVERSE_TXCLKESC       = 1 << 17,
-       FEAT_DSI_GNQ                    = 1 << 18,
-       FEAT_HDMI_CTS_SWMODE            = 1 << 19,
-       FEAT_HANDLE_UV_SEPARATE         = 1 << 20,
-       FEAT_ATTR2                      = 1 << 21,
-       FEAT_VENC_REQUIRES_TV_DAC_CLK   = 1 << 22,
-       FEAT_CPR                        = 1 << 23,
-       FEAT_PRELOAD                    = 1 << 24,
-       FEAT_FIR_COEF_V                 = 1 << 25,
-       FEAT_ALPHA_FIXED_ZORDER         = 1 << 26,
-       FEAT_ALPHA_FREE_ZORDER          = 1 << 27,
+       FEAT_DSI_PLL_PWR_BUG,
+       FEAT_DSI_PLL_FREQSEL,
+       FEAT_DSI_DCS_CMD_CONFIG_VC,
+       FEAT_DSI_VC_OCP_WIDTH,
+       FEAT_DSI_REVERSE_TXCLKESC,
+       FEAT_DSI_GNQ,
+       FEAT_HDMI_CTS_SWMODE,
+       FEAT_HDMI_AUDIO_USE_MCLK,
+       FEAT_HANDLE_UV_SEPARATE,
+       FEAT_ATTR2,
+       FEAT_VENC_REQUIRES_TV_DAC_CLK,
+       FEAT_CPR,
+       FEAT_PRELOAD,
+       FEAT_FIR_COEF_V,
+       FEAT_ALPHA_FIXED_ZORDER,
+       FEAT_ALPHA_FREE_ZORDER,
+       FEAT_FIFO_MERGE,
+       /* An unknown HW bug causing the normal FIFO thresholds not to work */
+       FEAT_OMAP3_DSI_FIFO_BUG,
 };
 
 /* DSS register field id */
index d7aa3b056529e9469a8e3c0346ebbe421a2df1be..012ee49c78ded4532101005653118e1a4e3c8723 100644 (file)
@@ -58,8 +58,6 @@
 #define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR     4
 #define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR     4
 
-#define OMAP_HDMI_TIMINGS_NB                   34
-
 #define HDMI_DEFAULT_REGN 16
 #define HDMI_DEFAULT_REGM2 1
 
@@ -68,8 +66,6 @@ static struct {
        struct omap_display_platform_data *pdata;
        struct platform_device *pdev;
        struct hdmi_ip_data ip_data;
-       int code;
-       int mode;
 
        struct clk *sys_clk;
 } hdmi;
@@ -88,77 +84,46 @@ static struct {
  * map it to corresponding CEA or VESA index.
  */
 
-static const struct hdmi_timings cea_vesa_timings[OMAP_HDMI_TIMINGS_NB] = {
-       { {640, 480, 25200, 96, 16, 48, 2, 10, 33} , 0 , 0},
-       { {1280, 720, 74250, 40, 440, 220, 5, 5, 20}, 1, 1},
-       { {1280, 720, 74250, 40, 110, 220, 5, 5, 20}, 1, 1},
-       { {720, 480, 27027, 62, 16, 60, 6, 9, 30}, 0, 0},
-       { {2880, 576, 108000, 256, 48, 272, 5, 5, 39}, 0, 0},
-       { {1440, 240, 27027, 124, 38, 114, 3, 4, 15}, 0, 0},
-       { {1440, 288, 27000, 126, 24, 138, 3, 2, 19}, 0, 0},
-       { {1920, 540, 74250, 44, 528, 148, 5, 2, 15}, 1, 1},
-       { {1920, 540, 74250, 44, 88, 148, 5, 2, 15}, 1, 1},
-       { {1920, 1080, 148500, 44, 88, 148, 5, 4, 36}, 1, 1},
-       { {720, 576, 27000, 64, 12, 68, 5, 5, 39}, 0, 0},
-       { {1440, 576, 54000, 128, 24, 136, 5, 5, 39}, 0, 0},
-       { {1920, 1080, 148500, 44, 528, 148, 5, 4, 36}, 1, 1},
-       { {2880, 480, 108108, 248, 64, 240, 6, 9, 30}, 0, 0},
-       { {1920, 1080, 74250, 44, 638, 148, 5, 4, 36}, 1, 1},
-       /* VESA From Here */
-       { {640, 480, 25175, 96, 16, 48, 2 , 11, 31}, 0, 0},
-       { {800, 600, 40000, 128, 40, 88, 4 , 1, 23}, 1, 1},
-       { {848, 480, 33750, 112, 16, 112, 8 , 6, 23}, 1, 1},
-       { {1280, 768, 79500, 128, 64, 192, 7 , 3, 20}, 1, 0},
-       { {1280, 800, 83500, 128, 72, 200, 6 , 3, 22}, 1, 0},
-       { {1360, 768, 85500, 112, 64, 256, 6 , 3, 18}, 1, 1},
-       { {1280, 960, 108000, 112, 96, 312, 3 , 1, 36}, 1, 1},
-       { {1280, 1024, 108000, 112, 48, 248, 3 , 1, 38}, 1, 1},
-       { {1024, 768, 65000, 136, 24, 160, 6, 3, 29}, 0, 0},
-       { {1400, 1050, 121750, 144, 88, 232, 4, 3, 32}, 1, 0},
-       { {1440, 900, 106500, 152, 80, 232, 6, 3, 25}, 1, 0},
-       { {1680, 1050, 146250, 176 , 104, 280, 6, 3, 30}, 1, 0},
-       { {1366, 768, 85500, 143, 70, 213, 3, 3, 24}, 1, 1},
-       { {1920, 1080, 148500, 44, 148, 80, 5, 4, 36}, 1, 1},
-       { {1280, 768, 68250, 32, 48, 80, 7, 3, 12}, 0, 1},
-       { {1400, 1050, 101000, 32, 48, 80, 4, 3, 23}, 0, 1},
-       { {1680, 1050, 119000, 32, 48, 80, 6, 3, 21}, 0, 1},
-       { {1280, 800, 79500, 32, 48, 80, 6, 3, 14}, 0, 1},
-       { {1280, 720, 74250, 40, 110, 220, 5, 5, 20}, 1, 1}
+static const struct hdmi_config cea_timings[] = {
+{ {640, 480, 25200, 96, 16, 48, 2, 10, 33, 0, 0, 0}, {1, HDMI_HDMI} },
+{ {720, 480, 27027, 62, 16, 60, 6, 9, 30, 0, 0, 0}, {2, HDMI_HDMI} },
+{ {1280, 720, 74250, 40, 110, 220, 5, 5, 20, 1, 1, 0}, {4, HDMI_HDMI} },
+{ {1920, 540, 74250, 44, 88, 148, 5, 2, 15, 1, 1, 1}, {5, HDMI_HDMI} },
+{ {1440, 240, 27027, 124, 38, 114, 3, 4, 15, 0, 0, 1}, {6, HDMI_HDMI} },
+{ {1920, 1080, 148500, 44, 88, 148, 5, 4, 36, 1, 1, 0}, {16, HDMI_HDMI} },
+{ {720, 576, 27000, 64, 12, 68, 5, 5, 39, 0, 0, 0}, {17, HDMI_HDMI} },
+{ {1280, 720, 74250, 40, 440, 220, 5, 5, 20, 1, 1, 0}, {19, HDMI_HDMI} },
+{ {1920, 540, 74250, 44, 528, 148, 5, 2, 15, 1, 1, 1}, {20, HDMI_HDMI} },
+{ {1440, 288, 27000, 126, 24, 138, 3, 2, 19, 0, 0, 1}, {21, HDMI_HDMI} },
+{ {1440, 576, 54000, 128, 24, 136, 5, 5, 39, 0, 0, 0}, {29, HDMI_HDMI} },
+{ {1920, 1080, 148500, 44, 528, 148, 5, 4, 36, 1, 1, 0}, {31, HDMI_HDMI} },
+{ {1920, 1080, 74250, 44, 638, 148, 5, 4, 36, 1, 1, 0}, {32, HDMI_HDMI} },
+{ {2880, 480, 108108, 248, 64, 240, 6, 9, 30, 0, 0, 0}, {35, HDMI_HDMI} },
+{ {2880, 576, 108000, 256, 48, 272, 5, 5, 39, 0, 0, 0}, {37, HDMI_HDMI} },
 };
-
-/*
- * This is a static mapping array which maps the timing values
- * with corresponding CEA / VESA code
- */
-static const int code_index[OMAP_HDMI_TIMINGS_NB] = {
-       1, 19, 4, 2, 37, 6, 21, 20, 5, 16, 17, 29, 31, 35, 32,
-       /* <--15 CEA 17--> vesa*/
-       4, 9, 0xE, 0x17, 0x1C, 0x27, 0x20, 0x23, 0x10, 0x2A,
-       0X2F, 0x3A, 0X51, 0X52, 0x16, 0x29, 0x39, 0x1B
+static const struct hdmi_config vesa_timings[] = {
+/* VESA From Here */
+{ {640, 480, 25175, 96, 16, 48, 2 , 11, 31, 0, 0, 0}, {4, HDMI_DVI} },
+{ {800, 600, 40000, 128, 40, 88, 4 , 1, 23, 1, 1, 0}, {9, HDMI_DVI} },
+{ {848, 480, 33750, 112, 16, 112, 8 , 6, 23, 1, 1, 0}, {0xE, HDMI_DVI} },
+{ {1280, 768, 79500, 128, 64, 192, 7 , 3, 20, 1, 0, 0}, {0x17, HDMI_DVI} },
+{ {1280, 800, 83500, 128, 72, 200, 6 , 3, 22, 1, 0, 0}, {0x1C, HDMI_DVI} },
+{ {1360, 768, 85500, 112, 64, 256, 6 , 3, 18, 1, 1, 0}, {0x27, HDMI_DVI} },
+{ {1280, 960, 108000, 112, 96, 312, 3 , 1, 36, 1, 1, 0}, {0x20, HDMI_DVI} },
+{ {1280, 1024, 108000, 112, 48, 248, 3 , 1, 38, 1, 1, 0}, {0x23, HDMI_DVI} },
+{ {1024, 768, 65000, 136, 24, 160, 6, 3, 29, 0, 0, 0}, {0x10, HDMI_DVI} },
+{ {1400, 1050, 121750, 144, 88, 232, 4, 3, 32, 1, 0, 0}, {0x2A, HDMI_DVI} },
+{ {1440, 900, 106500, 152, 80, 232, 6, 3, 25, 1, 0, 0}, {0x2F, HDMI_DVI} },
+{ {1680, 1050, 146250, 176 , 104, 280, 6, 3, 30, 1, 0, 0}, {0x3A, HDMI_DVI} },
+{ {1366, 768, 85500, 143, 70, 213, 3, 3, 24, 1, 1, 0}, {0x51, HDMI_DVI} },
+{ {1920, 1080, 148500, 44, 148, 80, 5, 4, 36, 1, 1, 0}, {0x52, HDMI_DVI} },
+{ {1280, 768, 68250, 32, 48, 80, 7, 3, 12, 0, 1, 0}, {0x16, HDMI_DVI} },
+{ {1400, 1050, 101000, 32, 48, 80, 4, 3, 23, 0, 1, 0}, {0x29, HDMI_DVI} },
+{ {1680, 1050, 119000, 32, 48, 80, 6, 3, 21, 0, 1, 0}, {0x39, HDMI_DVI} },
+{ {1280, 800, 79500, 32, 48, 80, 6, 3, 14, 0, 1, 0}, {0x1B, HDMI_DVI} },
+{ {1280, 720, 74250, 40, 110, 220, 5, 5, 20, 1, 1, 0}, {0x55, HDMI_DVI} }
 };
 
-/*
- * This is reverse static mapping which maps the CEA / VESA code
- * to the corresponding timing values
- */
-static const int code_cea[39] = {
-       -1,  0,  3,  3,  2,  8,  5,  5, -1, -1,
-       -1, -1, -1, -1, -1, -1,  9, 10, 10,  1,
-       7,   6,  6, -1, -1, -1, -1, -1, -1, 11,
-       11, 12, 14, -1, -1, 13, 13,  4,  4
-};
-
-static const int code_vesa[85] = {
-       -1, -1, -1, -1, 15, -1, -1, -1, -1, 16,
-       -1, -1, -1, -1, 17, -1, 23, -1, -1, -1,
-       -1, -1, 29, 18, -1, -1, -1, 32, 19, -1,
-       -1, -1, 21, -1, -1, 22, -1, -1, -1, 20,
-       -1, 30, 24, -1, -1, -1, -1, 25, -1, -1,
-       -1, -1, -1, -1, -1, -1, -1, 31, 26, -1,
-       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-       -1, 27, 28, -1, 33};
-
 static int hdmi_runtime_get(void)
 {
        int r;
@@ -188,88 +153,89 @@ int hdmi_init_display(struct omap_dss_device *dssdev)
        return 0;
 }
 
-static int get_timings_index(void)
+static const struct hdmi_config *hdmi_find_timing(
+                                       const struct hdmi_config *timings_arr,
+                                       int len)
 {
-       int code;
+       int i;
 
-       if (hdmi.mode == 0)
-               code = code_vesa[hdmi.code];
-       else
-               code = code_cea[hdmi.code];
+       for (i = 0; i < len; i++) {
+               if (timings_arr[i].cm.code == hdmi.ip_data.cfg.cm.code)
+                       return &timings_arr[i];
+       }
+       return NULL;
+}
 
-       if (code == -1) {
-               /* HDMI code 4 corresponds to 640 * 480 VGA */
-               hdmi.code = 4;
-               /* DVI mode 1 corresponds to HDMI 0 to DVI */
-               hdmi.mode = HDMI_DVI;
+static const struct hdmi_config *hdmi_get_timings(void)
+{
+       const struct hdmi_config *arr;
+       int len;
+
+       if (hdmi.ip_data.cfg.cm.mode == HDMI_DVI) {
+               arr = vesa_timings;
+               len = ARRAY_SIZE(vesa_timings);
+       } else {
+               arr = cea_timings;
+               len = ARRAY_SIZE(cea_timings);
+       }
+
+       return hdmi_find_timing(arr, len);
+}
+
+static bool hdmi_timings_compare(struct omap_video_timings *timing1,
+                               const struct hdmi_video_timings *timing2)
+{
+       int timing1_vsync, timing1_hsync, timing2_vsync, timing2_hsync;
 
-               code = code_vesa[hdmi.code];
+       if ((timing2->pixel_clock == timing1->pixel_clock) &&
+               (timing2->x_res == timing1->x_res) &&
+               (timing2->y_res == timing1->y_res)) {
+
+               timing2_hsync = timing2->hfp + timing2->hsw + timing2->hbp;
+               timing1_hsync = timing1->hfp + timing1->hsw + timing1->hbp;
+               timing2_vsync = timing2->vfp + timing2->vsw + timing2->vbp;
+               timing1_vsync = timing2->vfp + timing2->vsw + timing2->vbp;
+
+               DSSDBG("timing1_hsync = %d timing1_vsync = %d"\
+                       "timing2_hsync = %d timing2_vsync = %d\n",
+                       timing1_hsync, timing1_vsync,
+                       timing2_hsync, timing2_vsync);
+
+               if ((timing1_hsync == timing2_hsync) &&
+                       (timing1_vsync == timing2_vsync)) {
+                       return true;
+               }
        }
-       return code;
+       return false;
 }
 
 static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing)
 {
-       int i = 0, code = -1, temp_vsync = 0, temp_hsync = 0;
-       int timing_vsync = 0, timing_hsync = 0;
-       struct hdmi_video_timings temp;
+       int i;
        struct hdmi_cm cm = {-1};
        DSSDBG("hdmi_get_code\n");
 
-       for (i = 0; i < OMAP_HDMI_TIMINGS_NB; i++) {
-               temp = cea_vesa_timings[i].timings;
-               if ((temp.pixel_clock == timing->pixel_clock) &&
-                       (temp.x_res == timing->x_res) &&
-                       (temp.y_res == timing->y_res)) {
-
-                       temp_hsync = temp.hfp + temp.hsw + temp.hbp;
-                       timing_hsync = timing->hfp + timing->hsw + timing->hbp;
-                       temp_vsync = temp.vfp + temp.vsw + temp.vbp;
-                       timing_vsync = timing->vfp + timing->vsw + timing->vbp;
-
-                       DSSDBG("temp_hsync = %d , temp_vsync = %d"
-                               "timing_hsync = %d, timing_vsync = %d\n",
-                               temp_hsync, temp_hsync,
-                               timing_hsync, timing_vsync);
-
-                       if ((temp_hsync == timing_hsync) &&
-                                       (temp_vsync == timing_vsync)) {
-                               code = i;
-                               cm.code = code_index[i];
-                               if (code < 14)
-                                       cm.mode = HDMI_HDMI;
-                               else
-                                       cm.mode = HDMI_DVI;
-                               DSSDBG("Hdmi_code = %d mode = %d\n",
-                                        cm.code, cm.mode);
-                               break;
-                        }
+       for (i = 0; i < ARRAY_SIZE(cea_timings); i++) {
+               if (hdmi_timings_compare(timing, &cea_timings[i].timings)) {
+                       cm = cea_timings[i].cm;
+                       goto end;
+               }
+       }
+       for (i = 0; i < ARRAY_SIZE(vesa_timings); i++) {
+               if (hdmi_timings_compare(timing, &vesa_timings[i].timings)) {
+                       cm = vesa_timings[i].cm;
+                       goto end;
                }
        }
 
-       return cm;
-}
+end:   return cm;
 
-static void update_hdmi_timings(struct hdmi_config *cfg,
-               struct omap_video_timings *timings, int code)
-{
-       cfg->timings.timings.x_res = timings->x_res;
-       cfg->timings.timings.y_res = timings->y_res;
-       cfg->timings.timings.hbp = timings->hbp;
-       cfg->timings.timings.hfp = timings->hfp;
-       cfg->timings.timings.hsw = timings->hsw;
-       cfg->timings.timings.vbp = timings->vbp;
-       cfg->timings.timings.vfp = timings->vfp;
-       cfg->timings.timings.vsw = timings->vsw;
-       cfg->timings.timings.pixel_clock = timings->pixel_clock;
-       cfg->timings.vsync_pol = cea_vesa_timings[code].vsync_pol;
-       cfg->timings.hsync_pol = cea_vesa_timings[code].hsync_pol;
 }
 
 unsigned long hdmi_get_pixel_clock(void)
 {
        /* HDMI Pixel Clock in Mhz */
-       return hdmi.ip_data.cfg.timings.timings.pixel_clock * 1000;
+       return hdmi.ip_data.cfg.timings.pixel_clock * 1000;
 }
 
 static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
@@ -325,7 +291,8 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
 
 static int hdmi_power_on(struct omap_dss_device *dssdev)
 {
-       int r, code = 0;
+       int r;
+       const struct hdmi_config *timing;
        struct omap_video_timings *p;
        unsigned long phy;
 
@@ -341,9 +308,16 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
                dssdev->panel.timings.x_res,
                dssdev->panel.timings.y_res);
 
-       code = get_timings_index();
-       update_hdmi_timings(&hdmi.ip_data.cfg, p, code);
-
+       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);
@@ -363,8 +337,6 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
                goto err;
        }
 
-       hdmi.ip_data.cfg.cm.mode = hdmi.mode;
-       hdmi.ip_data.cfg.cm.code = hdmi.code;
        hdmi.ip_data.ops->video_configure(&hdmi.ip_data);
 
        /* Make selection of HDMI in DSS */
@@ -431,8 +403,8 @@ void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev)
        struct hdmi_cm cm;
 
        cm = hdmi_get_code(&dssdev->panel.timings);
-       hdmi.code = cm.code;
-       hdmi.mode = cm.mode;
+       hdmi.ip_data.cfg.cm.code = cm.code;
+       hdmi.ip_data.cfg.cm.mode = cm.mode;
 
        if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
                int r;
@@ -695,13 +667,15 @@ static int hdmi_audio_hw_params(struct snd_pcm_substream *substream,
        if (dss_has_feature(FEAT_HDMI_CTS_SWMODE)) {
                core_cfg.aud_par_busclk = 0;
                core_cfg.cts_mode = HDMI_AUDIO_CTS_MODE_SW;
-               core_cfg.use_mclk = false;
+               core_cfg.use_mclk = dss_has_feature(FEAT_HDMI_AUDIO_USE_MCLK);
        } else {
                core_cfg.aud_par_busclk = (((128 * 31) - 1) << 8);
                core_cfg.cts_mode = HDMI_AUDIO_CTS_MODE_HW;
                core_cfg.use_mclk = true;
-               core_cfg.mclk_mode = HDMI_AUDIO_MCLK_128FS;
        }
+
+       if (core_cfg.use_mclk)
+               core_cfg.mclk_mode = HDMI_AUDIO_MCLK_128FS;
        core_cfg.layout = HDMI_AUDIO_LAYOUT_2CH;
        core_cfg.en_spdif = false;
        /* Use sample frequency from channel status word */
@@ -734,7 +708,7 @@ static int hdmi_audio_hw_params(struct snd_pcm_substream *substream,
 static int hdmi_audio_startup(struct snd_pcm_substream *substream,
                                  struct snd_soc_dai *dai)
 {
-       if (!hdmi.mode) {
+       if (!hdmi.ip_data.cfg.cm.mode) {
                pr_err("Current video settings do not support audio.\n");
                return -EIO;
        }
index 55f398014f33b31863e0718a6600c25c368bac8e..788a0ef6323aef6e2784244b1825c5b72965abc5 100644 (file)
@@ -922,35 +922,34 @@ static int omap_rfbihw_probe(struct platform_device *pdev)
        rfbi_mem = platform_get_resource(rfbi.pdev, IORESOURCE_MEM, 0);
        if (!rfbi_mem) {
                DSSERR("can't get IORESOURCE_MEM RFBI\n");
-               r = -EINVAL;
-               goto err_ioremap;
+               return -EINVAL;
        }
-       rfbi.base = ioremap(rfbi_mem->start, resource_size(rfbi_mem));
+
+       rfbi.base = devm_ioremap(&pdev->dev, rfbi_mem->start,
+                                resource_size(rfbi_mem));
        if (!rfbi.base) {
                DSSERR("can't ioremap RFBI\n");
-               r = -ENOMEM;
-               goto err_ioremap;
+               return -ENOMEM;
        }
 
-       pm_runtime_enable(&pdev->dev);
-
-       r = rfbi_runtime_get();
-       if (r)
-               goto err_get_rfbi;
-
-       msleep(10);
-
        clk = clk_get(&pdev->dev, "ick");
        if (IS_ERR(clk)) {
                DSSERR("can't get ick\n");
-               r = PTR_ERR(clk);
-               goto err_get_ick;
+               return PTR_ERR(clk);
        }
 
        rfbi.l4_khz = clk_get_rate(clk) / 1000;
 
        clk_put(clk);
 
+       pm_runtime_enable(&pdev->dev);
+
+       r = rfbi_runtime_get();
+       if (r)
+               goto err_runtime_get;
+
+       msleep(10);
+
        rev = rfbi_read_reg(RFBI_REVISION);
        dev_dbg(&pdev->dev, "OMAP RFBI rev %d.%d\n",
               FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
@@ -959,19 +958,14 @@ static int omap_rfbihw_probe(struct platform_device *pdev)
 
        return 0;
 
-err_get_ick:
-       rfbi_runtime_put();
-err_get_rfbi:
+err_runtime_get:
        pm_runtime_disable(&pdev->dev);
-       iounmap(rfbi.base);
-err_ioremap:
        return r;
 }
 
 static int omap_rfbihw_remove(struct platform_device *pdev)
 {
        pm_runtime_disable(&pdev->dev);
-       iounmap(rfbi.base);
        return 0;
 }
 
index 50dadba5070a6fc862cb514979e30e7faf8f9f34..1f58b84d69015035c134bc5736b86a12bf7b46f8 100644 (file)
@@ -42,6 +42,7 @@ enum hdmi_clk_refsel {
        HDMI_REFSEL_SYSCLK = 3
 };
 
+/* HDMI timing structure */
 struct hdmi_video_timings {
        u16 x_res;
        u16 y_res;
@@ -53,13 +54,9 @@ struct hdmi_video_timings {
        u16 vsw;
        u16 vfp;
        u16 vbp;
-};
-
-/* HDMI timing structure */
-struct hdmi_timings {
-       struct hdmi_video_timings timings;
-       int vsync_pol;
-       int hsync_pol;
+       bool vsync_pol;
+       bool hsync_pol;
+       bool interlace;
 };
 
 struct hdmi_cm {
@@ -68,8 +65,7 @@ struct hdmi_cm {
 };
 
 struct hdmi_config {
-       struct hdmi_timings timings;
-       u16     interlace;
+       struct hdmi_video_timings timings;
        struct hdmi_cm cm;
 };
 
@@ -117,6 +113,47 @@ struct ti_hdmi_ip_ops {
 
 };
 
+/*
+ * Refer to section 8.2 in HDMI 1.3 specification for
+ * details about infoframe databytes
+ */
+struct hdmi_core_infoframe_avi {
+       /* Y0, Y1 rgb,yCbCr */
+       u8      db1_format;
+       /* A0  Active information Present */
+       u8      db1_active_info;
+       /* B0, B1 Bar info data valid */
+       u8      db1_bar_info_dv;
+       /* S0, S1 scan information */
+       u8      db1_scan_info;
+       /* C0, C1 colorimetry */
+       u8      db2_colorimetry;
+       /* M0, M1 Aspect ratio (4:3, 16:9) */
+       u8      db2_aspect_ratio;
+       /* R0...R3 Active format aspect ratio */
+       u8      db2_active_fmt_ar;
+       /* ITC IT content. */
+       u8      db3_itc;
+       /* EC0, EC1, EC2 Extended colorimetry */
+       u8      db3_ec;
+       /* Q1, Q0 Quantization range */
+       u8      db3_q_range;
+       /* SC1, SC0 Non-uniform picture scaling */
+       u8      db3_nup_scaling;
+       /* VIC0..6 Video format identification */
+       u8      db4_videocode;
+       /* PR0..PR3 Pixel repetition factor */
+       u8      db5_pixel_repeat;
+       /* Line number end of top bar */
+       u16     db6_7_line_eoftop;
+       /* Line number start of bottom bar */
+       u16     db8_9_line_sofbottom;
+       /* Pixel number end of left bar */
+       u16     db10_11_pixel_eofleft;
+       /* Pixel number start of right bar */
+       u16     db12_13_pixel_sofright;
+};
+
 struct hdmi_ip_data {
        void __iomem    *base_wp;       /* HDMI wrapper */
        unsigned long   core_sys_offset;
@@ -126,6 +163,7 @@ struct hdmi_ip_data {
        const struct ti_hdmi_ip_ops *ops;
        struct hdmi_config cfg;
        struct hdmi_pll_info pll_data;
+       struct hdmi_core_infoframe_avi avi_cfg;
 
        /* ti_hdmi_4xxx_ip private data. These should be in a separate struct */
        int hpd_gpio;
index 2d72334ca3da9a7d3bac43fba0c7e1ce6c26621e..bb784d2329b615cbc38fd1bfb48ac7f9ce3b90ec 100644 (file)
@@ -594,12 +594,12 @@ static void hdmi_core_video_config(struct hdmi_ip_data *ip_data,
                        HDMI_CORE_SYS_TMDS_CTRL, cfg->tclk_sel_clkmult, 6, 5);
 }
 
-static void hdmi_core_aux_infoframe_avi_config(struct hdmi_ip_data *ip_data,
-               struct hdmi_core_infoframe_avi info_avi)
+static void hdmi_core_aux_infoframe_avi_config(struct hdmi_ip_data *ip_data)
 {
        u32 val;
        char sum = 0, checksum = 0;
        void __iomem *av_base = hdmi_av_base(ip_data);
+       struct hdmi_core_infoframe_avi info_avi = ip_data->avi_cfg;
 
        sum += 0x82 + 0x002 + 0x00D;
        hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_TYPE, 0x082);
@@ -689,8 +689,7 @@ static void hdmi_core_av_packet_config(struct hdmi_ip_data *ip_data,
 }
 
 static void hdmi_wp_init(struct omap_video_timings *timings,
-                       struct hdmi_video_format *video_fmt,
-                       struct hdmi_video_interface *video_int)
+                       struct hdmi_video_format *video_fmt)
 {
        pr_debug("Enter hdmi_wp_init\n");
 
@@ -705,12 +704,6 @@ static void hdmi_wp_init(struct omap_video_timings *timings,
        video_fmt->y_res = 0;
        video_fmt->x_res = 0;
 
-       video_int->vsp = 0;
-       video_int->hsp = 0;
-
-       video_int->interlacing = 0;
-       video_int->tm = 0; /* HDMI_TIMING_SLAVE */
-
 }
 
 void ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data, bool start)
@@ -723,15 +716,15 @@ static void hdmi_wp_video_init_format(struct hdmi_video_format *video_fmt,
 {
        pr_debug("Enter hdmi_wp_video_init_format\n");
 
-       video_fmt->y_res = param->timings.timings.y_res;
-       video_fmt->x_res = param->timings.timings.x_res;
+       video_fmt->y_res = param->timings.y_res;
+       video_fmt->x_res = param->timings.x_res;
 
-       timings->hbp = param->timings.timings.hbp;
-       timings->hfp = param->timings.timings.hfp;
-       timings->hsw = param->timings.timings.hsw;
-       timings->vbp = param->timings.timings.vbp;
-       timings->vfp = param->timings.timings.vfp;
-       timings->vsw = param->timings.timings.vsw;
+       timings->hbp = param->timings.hbp;
+       timings->hfp = param->timings.hfp;
+       timings->hsw = param->timings.hsw;
+       timings->vbp = param->timings.vbp;
+       timings->vfp = param->timings.vfp;
+       timings->vsw = param->timings.vsw;
 }
 
 static void hdmi_wp_video_config_format(struct hdmi_ip_data *ip_data,
@@ -747,17 +740,16 @@ static void hdmi_wp_video_config_format(struct hdmi_ip_data *ip_data,
        hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_SIZE, l);
 }
 
-static void hdmi_wp_video_config_interface(struct hdmi_ip_data *ip_data,
-               struct hdmi_video_interface *video_int)
+static void hdmi_wp_video_config_interface(struct hdmi_ip_data *ip_data)
 {
        u32 r;
        pr_debug("Enter hdmi_wp_video_config_interface\n");
 
        r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG);
-       r = FLD_MOD(r, video_int->vsp, 7, 7);
-       r = FLD_MOD(r, video_int->hsp, 6, 6);
-       r = FLD_MOD(r, video_int->interlacing, 3, 3);
-       r = FLD_MOD(r, video_int->tm, 1, 0);
+       r = FLD_MOD(r, ip_data->cfg.timings.vsync_pol, 7, 7);
+       r = FLD_MOD(r, ip_data->cfg.timings.hsync_pol, 6, 6);
+       r = FLD_MOD(r, ip_data->cfg.timings.interlace, 3, 3);
+       r = FLD_MOD(r, 1, 1, 0); /* HDMI_TIMING_MASTER_24BIT */
        hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, r);
 }
 
@@ -785,15 +777,13 @@ void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data)
        /* HDMI */
        struct omap_video_timings video_timing;
        struct hdmi_video_format video_format;
-       struct hdmi_video_interface video_interface;
        /* HDMI core */
-       struct hdmi_core_infoframe_avi avi_cfg;
+       struct hdmi_core_infoframe_avi avi_cfg = ip_data->avi_cfg;
        struct hdmi_core_video_config v_core_cfg;
        struct hdmi_core_packet_enable_repeat repeat_cfg;
        struct hdmi_config *cfg = &ip_data->cfg;
 
-       hdmi_wp_init(&video_timing, &video_format,
-               &video_interface);
+       hdmi_wp_init(&video_timing, &video_format);
 
        hdmi_core_init(&v_core_cfg,
                &avi_cfg,
@@ -808,12 +798,7 @@ void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data)
 
        hdmi_wp_video_config_format(ip_data, &video_format);
 
-       video_interface.vsp = cfg->timings.vsync_pol;
-       video_interface.hsp = cfg->timings.hsync_pol;
-       video_interface.interlacing = cfg->interlace;
-       video_interface.tm = 1 ; /* HDMI_TIMING_MASTER_24BIT */
-
-       hdmi_wp_video_config_interface(ip_data, &video_interface);
+       hdmi_wp_video_config_interface(ip_data);
 
        /*
         * configure core video part
@@ -855,7 +840,7 @@ void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data)
        avi_cfg.db10_11_pixel_eofleft = 0;
        avi_cfg.db12_13_pixel_sofright = 0;
 
-       hdmi_core_aux_infoframe_avi_config(ip_data, avi_cfg);
+       hdmi_core_aux_infoframe_avi_config(ip_data);
 
        /* enable/repeat the infoframe */
        repeat_cfg.avi_infoframe = HDMI_PACKETENABLE;
@@ -1083,13 +1068,9 @@ void hdmi_core_audio_config(struct hdmi_ip_data *ip_data,
        u32 r;
        void __iomem *av_base = hdmi_av_base(ip_data);
 
-       /* audio clock recovery parameters */
-       r = hdmi_read_reg(av_base, HDMI_CORE_AV_ACR_CTRL);
-       r = FLD_MOD(r, cfg->use_mclk, 2, 2);
-       r = FLD_MOD(r, cfg->en_acr_pkt, 1, 1);
-       r = FLD_MOD(r, cfg->cts_mode, 0, 0);
-       hdmi_write_reg(av_base, HDMI_CORE_AV_ACR_CTRL, r);
-
+       /*
+        * Parameters for generation of Audio Clock Recovery packets
+        */
        REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL1, cfg->n, 7, 0);
        REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL2, cfg->n >> 8, 7, 0);
        REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL3, cfg->n >> 16, 7, 0);
@@ -1101,14 +1082,6 @@ void hdmi_core_audio_config(struct hdmi_ip_data *ip_data,
                REG_FLD_MOD(av_base,
                                HDMI_CORE_AV_CTS_SVAL3, cfg->cts >> 16, 7, 0);
        } else {
-               /*
-                * HDMI IP uses this configuration to divide the MCLK to
-                * update CTS value.
-                */
-               REG_FLD_MOD(av_base,
-                               HDMI_CORE_AV_FREQ_SVAL, cfg->mclk_mode, 2, 0);
-
-               /* Configure clock for audio packets */
                REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_1,
                                cfg->aud_par_busclk, 7, 0);
                REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_2,
@@ -1117,6 +1090,25 @@ void hdmi_core_audio_config(struct hdmi_ip_data *ip_data,
                                (cfg->aud_par_busclk >> 16), 7, 0);
        }
 
+       /* Set ACR clock divisor */
+       REG_FLD_MOD(av_base,
+                       HDMI_CORE_AV_FREQ_SVAL, cfg->mclk_mode, 2, 0);
+
+       r = hdmi_read_reg(av_base, HDMI_CORE_AV_ACR_CTRL);
+       /*
+        * Use TMDS clock for ACR packets. For devices that use
+        * the MCLK, this is the first part of the MCLK initialization.
+        */
+       r = FLD_MOD(r, 0, 2, 2);
+
+       r = FLD_MOD(r, cfg->en_acr_pkt, 1, 1);
+       r = FLD_MOD(r, cfg->cts_mode, 0, 0);
+       hdmi_write_reg(av_base, HDMI_CORE_AV_ACR_CTRL, r);
+
+       /* For devices using MCLK, this completes its initialization. */
+       if (cfg->use_mclk)
+               REG_FLD_MOD(av_base, HDMI_CORE_AV_ACR_CTRL, 1, 2, 2);
+
        /* Override of SPDIF sample frequency with value in I2S_CHST4 */
        REG_FLD_MOD(av_base, HDMI_CORE_AV_SPDIF_CTRL,
                                                cfg->fs_override, 1, 1);
@@ -1212,7 +1204,7 @@ int hdmi_config_audio_acr(struct hdmi_ip_data *ip_data,
 {
        u32 r;
        u32 deep_color = 0;
-       u32 pclk = ip_data->cfg.timings.timings.pixel_clock;
+       u32 pclk = ip_data->cfg.timings.pixel_clock;
 
        if (n == NULL || cts == NULL)
                return -EINVAL;
index a442998980f12231070592e9ade2d45cc5764716..a14d1a0e6e4146d00a70a88645d7292ea1793288 100644 (file)
@@ -446,46 +446,6 @@ struct hdmi_core_video_config {
        enum hdmi_core_tclkselclkmult   tclk_sel_clkmult;
 };
 
-/*
- * Refer to section 8.2 in HDMI 1.3 specification for
- * details about infoframe databytes
- */
-struct hdmi_core_infoframe_avi {
-       /* Y0, Y1 rgb,yCbCr */
-       u8      db1_format;
-       /* A0  Active information Present */
-       u8      db1_active_info;
-       /* B0, B1 Bar info data valid */
-       u8      db1_bar_info_dv;
-       /* S0, S1 scan information */
-       u8      db1_scan_info;
-       /* C0, C1 colorimetry */
-       u8      db2_colorimetry;
-       /* M0, M1 Aspect ratio (4:3, 16:9) */
-       u8      db2_aspect_ratio;
-       /* R0...R3 Active format aspect ratio */
-       u8      db2_active_fmt_ar;
-       /* ITC IT content. */
-       u8      db3_itc;
-       /* EC0, EC1, EC2 Extended colorimetry */
-       u8      db3_ec;
-       /* Q1, Q0 Quantization range */
-       u8      db3_q_range;
-       /* SC1, SC0 Non-uniform picture scaling */
-       u8      db3_nup_scaling;
-       /* VIC0..6 Video format identification */
-       u8      db4_videocode;
-       /* PR0..PR3 Pixel repetition factor */
-       u8      db5_pixel_repeat;
-       /* Line number end of top bar */
-       u16     db6_7_line_eoftop;
-       /* Line number start of bottom bar */
-       u16     db8_9_line_sofbottom;
-       /* Pixel number end of left bar */
-       u16     db10_11_pixel_eofleft;
-       /* Pixel number start of right bar */
-       u16     db12_13_pixel_sofright;
-};
 /*
  * Refer to section 8.2 in HDMI 1.3 specification for
  * details about infoframe databytes
@@ -517,13 +477,6 @@ struct hdmi_video_format {
        u32                     x_res;  /* pixel per line */
 };
 
-struct hdmi_video_interface {
-       int     vsp;    /* Vsync polarity */
-       int     hsp;    /* Hsync polarity */
-       int     interlacing;
-       int     tm;     /* Timing mode */
-};
-
 struct hdmi_audio_format {
        enum hdmi_stereo_channels               stereo_channels;
        u8                                      active_chnnls_msk;
index 5c3d0f9015105beb1d3a3946847097a181035ef1..9c3daf71750c769057d3a03f05019e950a3b5ed8 100644 (file)
@@ -699,6 +699,11 @@ 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;
 
@@ -790,39 +795,41 @@ static int omap_venchw_probe(struct platform_device *pdev)
        venc_mem = platform_get_resource(venc.pdev, IORESOURCE_MEM, 0);
        if (!venc_mem) {
                DSSERR("can't get IORESOURCE_MEM VENC\n");
-               r = -EINVAL;
-               goto err_ioremap;
+               return -EINVAL;
        }
-       venc.base = ioremap(venc_mem->start, resource_size(venc_mem));
+
+       venc.base = devm_ioremap(&pdev->dev, venc_mem->start,
+                                resource_size(venc_mem));
        if (!venc.base) {
                DSSERR("can't ioremap VENC\n");
-               r = -ENOMEM;
-               goto err_ioremap;
+               return -ENOMEM;
        }
 
        r = venc_get_clocks(pdev);
        if (r)
-               goto err_get_clk;
+               return r;
 
        pm_runtime_enable(&pdev->dev);
 
        r = venc_runtime_get();
        if (r)
-               goto err_get_venc;
+               goto err_runtime_get;
 
        rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff);
        dev_dbg(&pdev->dev, "OMAP VENC rev %d\n", rev_id);
 
        venc_runtime_put();
 
-       return omap_dss_register_driver(&venc_driver);
+       r = omap_dss_register_driver(&venc_driver);
+       if (r)
+               goto err_reg_panel_driver;
+
+       return 0;
 
-err_get_venc:
+err_reg_panel_driver:
+err_runtime_get:
        pm_runtime_disable(&pdev->dev);
        venc_put_clocks();
-err_get_clk:
-       iounmap(venc.base);
-err_ioremap:
        return r;
 }
 
@@ -837,7 +844,6 @@ static int omap_venchw_remove(struct platform_device *pdev)
        pm_runtime_disable(&pdev->dev);
        venc_put_clocks();
 
-       iounmap(venc.base);
        return 0;
 }