First patch adds PM capabilities for omapdrm. Second patch adds OMAP5 support to DMM driver component.
Series was build tested and based on linux-next.
Andy Gross (2): drm/omap: Add PM capabilities drm/omap: Add OMAP5 support
drivers/staging/omapdrm/omap_dmm_priv.h | 5 + drivers/staging/omapdrm/omap_dmm_tiler.c | 159 ++++++++++++++++++++++-------- drivers/staging/omapdrm/omap_drv.c | 14 +++ drivers/staging/omapdrm/omap_drv.h | 4 + drivers/staging/omapdrm/omap_gem.c | 28 +++++ drivers/staging/omapdrm/tcm.h | 2 + 6 files changed, 169 insertions(+), 43 deletions(-)
Added resume hooks that will be called on resuming from DEVICE_OFF. The dmm portion of the patch reprograms the LUT to point to the dummy pages. The omapdrm portion of the patch repins the buffers into the DMM.
Signed-off-by: Andy Gross andy.gross@ti.com --- drivers/staging/omapdrm/omap_dmm_tiler.c | 34 ++++++++++++++++++++++++++++++ drivers/staging/omapdrm/omap_drv.c | 14 ++++++++++++ drivers/staging/omapdrm/omap_drv.h | 4 +++ drivers/staging/omapdrm/omap_gem.c | 28 ++++++++++++++++++++++++ 4 files changed, 80 insertions(+), 0 deletions(-)
diff --git a/drivers/staging/omapdrm/omap_dmm_tiler.c b/drivers/staging/omapdrm/omap_dmm_tiler.c index 59bf438..c42c5e5 100644 --- a/drivers/staging/omapdrm/omap_dmm_tiler.c +++ b/drivers/staging/omapdrm/omap_dmm_tiler.c @@ -903,12 +903,46 @@ error: } #endif
+#ifdef CONFIG_PM +static int omap_dmm_resume(struct device *dev) +{ + struct tcm_area area; + int i; + + if (!omap_dmm) + return -ENODEV; + + area = (struct tcm_area) { + .is2d = true, + .tcm = NULL, + .p1.x = omap_dmm->container_width - 1, + .p1.y = omap_dmm->container_height - 1, + }; + + /* initialize all LUTs to dummy page entries */ + for (i = 0; i < omap_dmm->num_lut; i++) { + area.tcm = omap_dmm->tcm[i]; + if (fill(&area, NULL, 0, 0, true)) + dev_err(dev, "refill failed"); + } + + return 0; +} + +static const struct dev_pm_ops omap_dmm_pm_ops = { + .resume = omap_dmm_resume, +}; +#endif + struct platform_driver omap_dmm_driver = { .probe = omap_dmm_probe, .remove = omap_dmm_remove, .driver = { .owner = THIS_MODULE, .name = DMM_DRIVER_NAME, +#ifdef CONFIG_PM + .pm = &omap_dmm_pm_ops, +#endif }, };
diff --git a/drivers/staging/omapdrm/omap_drv.c b/drivers/staging/omapdrm/omap_drv.c index ae5ecc2..d246f85 100644 --- a/drivers/staging/omapdrm/omap_drv.c +++ b/drivers/staging/omapdrm/omap_drv.c @@ -368,6 +368,9 @@ static int dev_load(struct drm_device *dev, unsigned long flags) /* well, limp along without an fbdev.. maybe X11 will work? */ }
+ /* store off drm_device for use in pm ops */ + dev_set_drvdata(dev->dev, dev); + drm_kms_helper_poll_init(dev);
return 0; @@ -393,6 +396,8 @@ static int dev_unload(struct drm_device *dev) kfree(dev->dev_private); dev->dev_private = NULL;
+ dev_set_drvdata(dev->dev, NULL); + return 0; }
@@ -558,10 +563,19 @@ static int pdev_remove(struct platform_device *device) return 0; }
+#ifdef CONFIG_PM +static const struct dev_pm_ops omapdrm_pm_ops = { + .resume = omap_gem_resume, +}; +#endif + struct platform_driver pdev = { .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, +#ifdef CONFIG_PM + .pm = &omapdrm_pm_ops, +#endif }, .probe = pdev_probe, .remove = pdev_remove, diff --git a/drivers/staging/omapdrm/omap_drv.h b/drivers/staging/omapdrm/omap_drv.h index cd1f22b..f921027 100644 --- a/drivers/staging/omapdrm/omap_drv.h +++ b/drivers/staging/omapdrm/omap_drv.h @@ -135,6 +135,10 @@ void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m); void omap_gem_describe_objects(struct list_head *list, struct seq_file *m); #endif
+#ifdef CONFIG_PM +int omap_gem_resume(struct device *dev); +#endif + int omap_irq_enable_vblank(struct drm_device *dev, int crtc); void omap_irq_disable_vblank(struct drm_device *dev, int crtc); irqreturn_t omap_irq_handler(DRM_IRQ_ARGS); diff --git a/drivers/staging/omapdrm/omap_gem.c b/drivers/staging/omapdrm/omap_gem.c index c38992b..08f1e292 100644 --- a/drivers/staging/omapdrm/omap_gem.c +++ b/drivers/staging/omapdrm/omap_gem.c @@ -964,6 +964,34 @@ void *omap_gem_vaddr(struct drm_gem_object *obj) return omap_obj->vaddr; }
+#ifdef CONFIG_PM +/* re-pin objects in DMM in resume path: */ +int omap_gem_resume(struct device *dev) +{ + struct drm_device *drm_dev = dev_get_drvdata(dev); + struct omap_drm_private *priv = drm_dev->dev_private; + struct omap_gem_object *omap_obj; + int ret = 0; + + list_for_each_entry(omap_obj, &priv->obj_list, mm_list) { + if (omap_obj->block) { + struct drm_gem_object *obj = &omap_obj->base; + uint32_t npages = obj->size >> PAGE_SHIFT; + WARN_ON(!omap_obj->pages); /* this can't happen */ + ret = tiler_pin(omap_obj->block, + omap_obj->pages, npages, + omap_obj->roll, true); + if (ret) { + dev_err(dev, "could not repin: %d\n", ret); + return ret; + } + } + } + + return 0; +} +#endif + #ifdef CONFIG_DEBUG_FS void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m) {
On Tue, Dec 18, 2012 at 12:02 AM, Andy Gross andy.gross@ti.com wrote:
Added resume hooks that will be called on resuming from DEVICE_OFF. The dmm portion of the patch reprograms the LUT to point to the dummy pages. The omapdrm portion of the patch repins the buffers into the DMM.
Signed-off-by: Andy Gross andy.gross@ti.com
I am sort of thinking it might be worth a comment somewhere explaining why this works (ie. resume order between the two platform devices), even if only in the commit msg. But with that:
Signed-off-by: Rob Clark rob@ti.com
drivers/staging/omapdrm/omap_dmm_tiler.c | 34 ++++++++++++++++++++++++++++++ drivers/staging/omapdrm/omap_drv.c | 14 ++++++++++++ drivers/staging/omapdrm/omap_drv.h | 4 +++ drivers/staging/omapdrm/omap_gem.c | 28 ++++++++++++++++++++++++ 4 files changed, 80 insertions(+), 0 deletions(-)
diff --git a/drivers/staging/omapdrm/omap_dmm_tiler.c b/drivers/staging/omapdrm/omap_dmm_tiler.c index 59bf438..c42c5e5 100644 --- a/drivers/staging/omapdrm/omap_dmm_tiler.c +++ b/drivers/staging/omapdrm/omap_dmm_tiler.c @@ -903,12 +903,46 @@ error: } #endif
+#ifdef CONFIG_PM +static int omap_dmm_resume(struct device *dev) +{
struct tcm_area area;
int i;
if (!omap_dmm)
return -ENODEV;
area = (struct tcm_area) {
.is2d = true,
.tcm = NULL,
.p1.x = omap_dmm->container_width - 1,
.p1.y = omap_dmm->container_height - 1,
};
/* initialize all LUTs to dummy page entries */
for (i = 0; i < omap_dmm->num_lut; i++) {
area.tcm = omap_dmm->tcm[i];
if (fill(&area, NULL, 0, 0, true))
dev_err(dev, "refill failed");
}
return 0;
+}
+static const struct dev_pm_ops omap_dmm_pm_ops = {
.resume = omap_dmm_resume,
+}; +#endif
struct platform_driver omap_dmm_driver = { .probe = omap_dmm_probe, .remove = omap_dmm_remove, .driver = { .owner = THIS_MODULE, .name = DMM_DRIVER_NAME, +#ifdef CONFIG_PM
.pm = &omap_dmm_pm_ops,
+#endif }, };
diff --git a/drivers/staging/omapdrm/omap_drv.c b/drivers/staging/omapdrm/omap_drv.c index ae5ecc2..d246f85 100644 --- a/drivers/staging/omapdrm/omap_drv.c +++ b/drivers/staging/omapdrm/omap_drv.c @@ -368,6 +368,9 @@ static int dev_load(struct drm_device *dev, unsigned long flags) /* well, limp along without an fbdev.. maybe X11 will work? */ }
/* store off drm_device for use in pm ops */
dev_set_drvdata(dev->dev, dev);
drm_kms_helper_poll_init(dev); return 0;
@@ -393,6 +396,8 @@ static int dev_unload(struct drm_device *dev) kfree(dev->dev_private); dev->dev_private = NULL;
dev_set_drvdata(dev->dev, NULL);
return 0;
}
@@ -558,10 +563,19 @@ static int pdev_remove(struct platform_device *device) return 0; }
+#ifdef CONFIG_PM +static const struct dev_pm_ops omapdrm_pm_ops = {
.resume = omap_gem_resume,
+}; +#endif
struct platform_driver pdev = { .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, +#ifdef CONFIG_PM
.pm = &omapdrm_pm_ops,
+#endif }, .probe = pdev_probe, .remove = pdev_remove, diff --git a/drivers/staging/omapdrm/omap_drv.h b/drivers/staging/omapdrm/omap_drv.h index cd1f22b..f921027 100644 --- a/drivers/staging/omapdrm/omap_drv.h +++ b/drivers/staging/omapdrm/omap_drv.h @@ -135,6 +135,10 @@ void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m); void omap_gem_describe_objects(struct list_head *list, struct seq_file *m); #endif
+#ifdef CONFIG_PM +int omap_gem_resume(struct device *dev); +#endif
int omap_irq_enable_vblank(struct drm_device *dev, int crtc); void omap_irq_disable_vblank(struct drm_device *dev, int crtc); irqreturn_t omap_irq_handler(DRM_IRQ_ARGS); diff --git a/drivers/staging/omapdrm/omap_gem.c b/drivers/staging/omapdrm/omap_gem.c index c38992b..08f1e292 100644 --- a/drivers/staging/omapdrm/omap_gem.c +++ b/drivers/staging/omapdrm/omap_gem.c @@ -964,6 +964,34 @@ void *omap_gem_vaddr(struct drm_gem_object *obj) return omap_obj->vaddr; }
+#ifdef CONFIG_PM +/* re-pin objects in DMM in resume path: */ +int omap_gem_resume(struct device *dev) +{
struct drm_device *drm_dev = dev_get_drvdata(dev);
struct omap_drm_private *priv = drm_dev->dev_private;
struct omap_gem_object *omap_obj;
int ret = 0;
list_for_each_entry(omap_obj, &priv->obj_list, mm_list) {
if (omap_obj->block) {
struct drm_gem_object *obj = &omap_obj->base;
uint32_t npages = obj->size >> PAGE_SHIFT;
WARN_ON(!omap_obj->pages); /* this can't happen */
ret = tiler_pin(omap_obj->block,
omap_obj->pages, npages,
omap_obj->roll, true);
if (ret) {
dev_err(dev, "could not repin: %d\n", ret);
return ret;
}
}
}
return 0;
+} +#endif
#ifdef CONFIG_DEBUG_FS void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m) { -- 1.7.5.4
dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
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 --- drivers/staging/omapdrm/omap_dmm_priv.h | 5 + drivers/staging/omapdrm/omap_dmm_tiler.c | 127 +++++++++++++++++++---------- drivers/staging/omapdrm/tcm.h | 2 + 3 files changed, 90 insertions(+), 44 deletions(-)
diff --git a/drivers/staging/omapdrm/omap_dmm_priv.h b/drivers/staging/omapdrm/omap_dmm_priv.h index 273ec12..58bcd6a 100644 --- a/drivers/staging/omapdrm/omap_dmm_priv.h +++ b/drivers/staging/omapdrm/omap_dmm_priv.h @@ -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 { diff --git a/drivers/staging/omapdrm/omap_dmm_tiler.c b/drivers/staging/omapdrm/omap_dmm_tiler.c index c42c5e5..3910215 100644 --- a/drivers/staging/omapdrm/omap_dmm_tiler.c +++ b/drivers/staging/omapdrm/omap_dmm_tiler.c @@ -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, diff --git a/drivers/staging/omapdrm/tcm.h b/drivers/staging/omapdrm/tcm.h index d273e3e..a8d5ce4 100644 --- a/drivers/staging/omapdrm/tcm.h +++ b/drivers/staging/omapdrm/tcm.h @@ -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
On Tue, Dec 18, 2012 at 12:02 AM, Andy Gross andy.gross@ti.com wrote:
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
drivers/staging/omapdrm/omap_dmm_priv.h | 5 + drivers/staging/omapdrm/omap_dmm_tiler.c | 127 +++++++++++++++++++---------- drivers/staging/omapdrm/tcm.h | 2 + 3 files changed, 90 insertions(+), 44 deletions(-)
diff --git a/drivers/staging/omapdrm/omap_dmm_priv.h b/drivers/staging/omapdrm/omap_dmm_priv.h index 273ec12..58bcd6a 100644 --- a/drivers/staging/omapdrm/omap_dmm_priv.h +++ b/drivers/staging/omapdrm/omap_dmm_priv.h @@ -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 { diff --git a/drivers/staging/omapdrm/omap_dmm_tiler.c b/drivers/staging/omapdrm/omap_dmm_tiler.c index c42c5e5..3910215 100644 --- a/drivers/staging/omapdrm/omap_dmm_tiler.c +++ b/drivers/staging/omapdrm/omap_dmm_tiler.c @@ -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,
diff --git a/drivers/staging/omapdrm/tcm.h b/drivers/staging/omapdrm/tcm.h index d273e3e..a8d5ce4 100644 --- a/drivers/staging/omapdrm/tcm.h +++ b/drivers/staging/omapdrm/tcm.h @@ -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
-- 1.7.5.4
dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
dri-devel@lists.freedesktop.org