drm/omap: Add OMAP5 support
authorAndy Gross <andy.gross@ti.com>
Wed, 19 Dec 2012 20:53:38 +0000 (14:53 -0600)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 17 Jan 2013 21:19:55 +0000 (13:19 -0800)
Add support for OMAP5 processor.  The main differences are that the OMAP5
has 2 containers, one for 1D and one for 2D.  Each container is 128MiB in
size.

Signed-off-by: Andy Gross <andy.gross@ti.com>
Signed-off-by: Rob Clark <rob@ti.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/omapdrm/omap_dmm_priv.h
drivers/staging/omapdrm/omap_dmm_tiler.c
drivers/staging/omapdrm/tcm.h

index 273ec12c028abd13f3257cbdc7bb24628b156bf1..58bcd6ae0255dace4ae845c366af35cf62be4f20 100644 (file)
@@ -118,6 +118,11 @@ struct pat {
 #define DESCR_SIZE 128
 #define REFILL_BUFFER_SIZE ((4 * 128 * 256) + (3 * DESCR_SIZE))
 
+/* For OMAP5, a fixed offset is added to all Y coordinates for 1D buffers.
+ * This is used in programming to address the upper portion of the LUT
+*/
+#define OMAP5_LUT_OFFSET       128
+
 struct dmm;
 
 struct dmm_txn {
index c42c5e500e02ba11a58a5e0abcab4877055f7d06..3910215371053037aff61580939cd8596298e9eb 100644 (file)
@@ -213,6 +213,11 @@ static void dmm_txn_append(struct dmm_txn *txn, struct pat_area *area,
                txn->last_pat->next_pa = (uint32_t)pat_pa;
 
        pat->area = *area;
+
+       /* adjust Y coordinates based off of container parameters */
+       pat->area.y0 += engine->tcm->y_offset;
+       pat->area.y1 += engine->tcm->y_offset;
+
        pat->ctrl = (struct pat_ctrl){
                        .start = 1,
                        .lut_id = engine->tcm->lut_id,
@@ -622,6 +627,11 @@ static int omap_dmm_probe(struct platform_device *dev)
        omap_dmm->lut_width = ((pat_geom >> 16) & 0xF) << 5;
        omap_dmm->lut_height = ((pat_geom >> 24) & 0xF) << 5;
 
+       /* increment LUT by one if on OMAP5 */
+       /* LUT has twice the height, and is split into a separate container */
+       if (omap_dmm->lut_height != omap_dmm->container_height)
+               omap_dmm->num_lut++;
+
        /* initialize DMM registers */
        writel(0x88888888, omap_dmm->base + DMM_PAT_VIEW__0);
        writel(0x88888888, omap_dmm->base + DMM_PAT_VIEW__1);
@@ -701,6 +711,9 @@ static int omap_dmm_probe(struct platform_device *dev)
        }
 
        /* init containers */
+       /* Each LUT is associated with a TCM (container manager).  We use the
+          lut_id to denote the lut_id used to identify the correct LUT for
+          programming during reill operations */
        for (i = 0; i < omap_dmm->num_lut; i++) {
                omap_dmm->tcm[i] = sita_init(omap_dmm->container_width,
                                                omap_dmm->container_height,
@@ -717,13 +730,23 @@ static int omap_dmm_probe(struct platform_device *dev)
 
        /* assign access mode containers to applicable tcm container */
        /* OMAP 4 has 1 container for all 4 views */
+       /* OMAP 5 has 2 containers, 1 for 2D and 1 for 1D */
        containers[TILFMT_8BIT] = omap_dmm->tcm[0];
        containers[TILFMT_16BIT] = omap_dmm->tcm[0];
        containers[TILFMT_32BIT] = omap_dmm->tcm[0];
-       containers[TILFMT_PAGE] = omap_dmm->tcm[0];
+
+       if (omap_dmm->container_height != omap_dmm->lut_height) {
+               /* second LUT is used for PAGE mode.  Programming must use
+                  y offset that is added to all y coordinates.  LUT id is still
+                  0, because it is the same LUT, just the upper 128 lines */
+               containers[TILFMT_PAGE] = omap_dmm->tcm[1];
+               omap_dmm->tcm[1]->y_offset = OMAP5_LUT_OFFSET;
+               omap_dmm->tcm[1]->lut_id = 0;
+       } else {
+               containers[TILFMT_PAGE] = omap_dmm->tcm[0];
+       }
 
        area = (struct tcm_area) {
-               .is2d = true,
                .tcm = NULL,
                .p1.x = omap_dmm->container_width - 1,
                .p1.y = omap_dmm->container_height - 1,
@@ -835,64 +858,81 @@ int tiler_map_show(struct seq_file *s, void *arg)
        int h_adj;
        int w_adj;
        unsigned long flags;
+       int lut_idx;
+
 
        if (!omap_dmm) {
                /* early return if dmm/tiler device is not initialized */
                return 0;
        }
 
-       h_adj = omap_dmm->lut_height / ydiv;
-       w_adj = omap_dmm->lut_width / xdiv;
+       h_adj = omap_dmm->container_height / ydiv;
+       w_adj = omap_dmm->container_width / xdiv;
 
-       map = kzalloc(h_adj * sizeof(*map), GFP_KERNEL);
-       global_map = kzalloc((w_adj + 1) * h_adj, GFP_KERNEL);
+       map = kmalloc(h_adj * sizeof(*map), GFP_KERNEL);
+       global_map = kmalloc((w_adj + 1) * h_adj, GFP_KERNEL);
 
        if (!map || !global_map)
                goto error;
 
-       memset(global_map, ' ', (w_adj + 1) * h_adj);
-       for (i = 0; i < omap_dmm->lut_height; i++) {
-               map[i] = global_map + i * (w_adj + 1);
-               map[i][w_adj] = 0;
-       }
-       spin_lock_irqsave(&list_lock, flags);
+       for (lut_idx = 0; lut_idx < omap_dmm->num_lut; lut_idx++) {
+               memset(map, 0, sizeof(h_adj * sizeof(*map)));
+               memset(global_map, ' ', (w_adj + 1) * h_adj);
 
-       list_for_each_entry(block, &omap_dmm->alloc_head, alloc_node) {
-               if (block->fmt != TILFMT_PAGE) {
-                       fill_map(map, xdiv, ydiv, &block->area, *m2dp, true);
-                       if (!*++a2dp)
-                               a2dp = a2d;
-                       if (!*++m2dp)
-                               m2dp = m2d;
-                       map_2d_info(map, xdiv, ydiv, nice, &block->area);
-               } else {
-                       bool start = read_map_pt(map, xdiv, ydiv,
-                                                       &block->area.p0)
-                                                                       == ' ';
-                       bool end = read_map_pt(map, xdiv, ydiv, &block->area.p1)
-                                                                       == ' ';
-                       tcm_for_each_slice(a, block->area, p)
-                               fill_map(map, xdiv, ydiv, &a, '=', true);
-                       fill_map_pt(map, xdiv, ydiv, &block->area.p0,
+               for (i = 0; i < omap_dmm->container_height; i++) {
+                       map[i] = global_map + i * (w_adj + 1);
+                       map[i][w_adj] = 0;
+               }
+
+               spin_lock_irqsave(&list_lock, flags);
+
+               list_for_each_entry(block, &omap_dmm->alloc_head, alloc_node) {
+                       if (block->area.tcm == omap_dmm->tcm[lut_idx]) {
+                               if (block->fmt != TILFMT_PAGE) {
+                                       fill_map(map, xdiv, ydiv, &block->area,
+                                               *m2dp, true);
+                                       if (!*++a2dp)
+                                               a2dp = a2d;
+                                       if (!*++m2dp)
+                                               m2dp = m2d;
+                                       map_2d_info(map, xdiv, ydiv, nice,
+                                                       &block->area);
+                               } else {
+                                       bool start = read_map_pt(map, xdiv,
+                                               ydiv, &block->area.p0) == ' ';
+                                       bool end = read_map_pt(map, xdiv, ydiv,
+                                                       &block->area.p1) == ' ';
+
+                                       tcm_for_each_slice(a, block->area, p)
+                                               fill_map(map, xdiv, ydiv, &a,
+                                                       '=', true);
+                                       fill_map_pt(map, xdiv, ydiv,
+                                                       &block->area.p0,
                                                        start ? '<' : 'X');
-                       fill_map_pt(map, xdiv, ydiv, &block->area.p1,
+                                       fill_map_pt(map, xdiv, ydiv,
+                                                       &block->area.p1,
                                                        end ? '>' : 'X');
-                       map_1d_info(map, xdiv, ydiv, nice, &block->area);
+                                       map_1d_info(map, xdiv, ydiv, nice,
+                                                       &block->area);
+                               }
+                       }
                }
-       }
 
-       spin_unlock_irqrestore(&list_lock, flags);
+               spin_unlock_irqrestore(&list_lock, flags);
 
-       if (s) {
-               seq_printf(s, "BEGIN DMM TILER MAP\n");
-               for (i = 0; i < 128; i++)
-                       seq_printf(s, "%03d:%s\n", i, map[i]);
-               seq_printf(s, "END TILER MAP\n");
-       } else {
-               dev_dbg(omap_dmm->dev, "BEGIN DMM TILER MAP\n");
-               for (i = 0; i < 128; i++)
-                       dev_dbg(omap_dmm->dev, "%03d:%s\n", i, map[i]);
-               dev_dbg(omap_dmm->dev, "END TILER MAP\n");
+               if (s) {
+                       seq_printf(s, "CONTAINER %d DUMP BEGIN\n", lut_idx);
+                       for (i = 0; i < 128; i++)
+                               seq_printf(s, "%03d:%s\n", i, map[i]);
+                       seq_printf(s, "CONTAINER %d DUMP END\n", lut_idx);
+               } else {
+                       dev_dbg(omap_dmm->dev, "CONTAINER %d DUMP BEGIN\n",
+                               lut_idx);
+                       for (i = 0; i < 128; i++)
+                               dev_dbg(omap_dmm->dev, "%03d:%s\n", i, map[i]);
+                       dev_dbg(omap_dmm->dev, "CONTAINER %d DUMP END\n",
+                               lut_idx);
+               }
        }
 
 error:
@@ -913,7 +953,6 @@ static int omap_dmm_resume(struct device *dev)
                return -ENODEV;
 
        area = (struct tcm_area) {
-               .is2d = true,
                .tcm = NULL,
                .p1.x = omap_dmm->container_width - 1,
                .p1.y = omap_dmm->container_height - 1,
index d273e3ee0b4c7d64737b1e52fbbcb068a0be089a..a8d5ce47686f791981b96b401d701ae83abab585 100644 (file)
@@ -59,6 +59,8 @@ struct tcm {
        u16 width, height;      /* container dimensions */
        int lut_id;             /* Lookup table identifier */
 
+       unsigned int y_offset;  /* offset to use for y coordinates */
+
        /* 'pvt' structure shall contain any tcm details (attr) along with
        linked list of allocated areas and mutex for mutually exclusive access
        to the list.  It may also contain copies of width and height to notice