]> Pileus Git - ~andy/linux/blobdiff - drivers/video/omap2/dss/dispc.c
Merge branch 'work/old-omapfb-removal'
[~andy/linux] / drivers / video / omap2 / dss / dispc.c
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;
 }