linux-omap.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC 0/8] TI TILER-DMM driver
@ 2010-07-23 23:22 David Sin
  2010-07-23 23:22 ` [RFC 1/8] TILER-DMM: DMM-PAT driver for TI TILER David Sin
                   ` (2 more replies)
  0 siblings, 3 replies; 46+ messages in thread
From: David Sin @ 2010-07-23 23:22 UTC (permalink / raw)
  To: linux-arm-kernel, linux-omap, Tony Lindgren, Russell King
  Cc: Hari Kanigeri, Ohad Ben-Cohen, Vaibhav Hiremath,
	Santosh Shilimkar, David Sin

TILER is a hardware block made by Texas Instruments.  Its purpose is to 
organize video/image memory in a 2-dimensional fashion to limit memory 
bandwidth and facilitate 0 effort rotation and mirroring.  The TILER 
driver facilitates allocating, freeing, as well as mapping 2D blocks (areas) 
in the TILER container(s).  It also facilitates rotating and mirroring 
the allocated blocks or its rectangular subsections.

List of pending items in proposed order:

* Add area packing support (multiple blocks can reside in the same band/area)
  to optimize area use
* Add group-ID support (to specify which blocks can reside together in the
  same area)
* Add multiple search directions to TCM-SiTA
* Add 1D block support (including adding 1D search algo to TCM-SiTA)
* Optimize mutex handling (don.t hold mutex during memory
  allocation/mapping/cache flushing)
* Add block reference counting, support for sharing blocks
* Move all kernel-API-s to tiler-iface.c
* Support orphaned block support (in preparation for process cleanup support)
* Change block identification from physical address to key-ID pair
  (in preparation for user space support, and process security)
* Add support for process security (blocks from separate processes never
  reside in the same band)
* Support file interface (ioctl and mmap)
* Support for buffers (ordered list of blocks that are mapped to userspace
  together, such as YUV420sp)
* Support 1D user buffer mapping into TILER container
* Support for block pre-reservation (to further optimize area use)

David Sin (1):
  TILER-DMM: DMM-PAT driver for TI TILER

Lajos Molnar (6):
  TILER-DMM: Container manager interface and utility definitons
  TILER-DMM: TILER Memory Manager interface and implementation
  TILER-DMM: TILER interface file and documentation
  TILER-DMM: Geometry and view manipulation functions.
  TILER-DMM: Main TILER driver implementation.
  TILER-DMM: Linking TILER driver into the Linux kernel build

Ravi Ramachandra (1):
  TILER-DMM: Sample TCM implementation: Simple TILER Allocator

 Documentation/arm/TILER                   |  144 +++++++++
 arch/arm/mach-omap2/include/mach/dmm.h    |  128 ++++++++
 arch/arm/mach-omap2/include/mach/tiler.h  |  201 +++++++++++++
 drivers/media/Kconfig                     |    6 +
 drivers/media/Makefile                    |    2 +
 drivers/media/video/tiler/Kconfig         |   65 ++++
 drivers/media/video/tiler/Makefile        |    7 +
 drivers/media/video/tiler/_tiler.h        |   51 ++++
 drivers/media/video/tiler/dmm.c           |  200 +++++++++++++
 drivers/media/video/tiler/tcm.h           |  209 +++++++++++++
 drivers/media/video/tiler/tcm/Makefile    |    1 +
 drivers/media/video/tiler/tcm/_tcm-sita.h |   64 ++++
 drivers/media/video/tiler/tcm/tcm-sita.c  |  459 +++++++++++++++++++++++++++++
 drivers/media/video/tiler/tcm/tcm-sita.h  |   37 +++
 drivers/media/video/tiler/tcm/tcm-utils.h |   54 ++++
 drivers/media/video/tiler/tiler-geom.c    |  360 ++++++++++++++++++++++
 drivers/media/video/tiler/tiler-iface.c   |  106 +++++++
 drivers/media/video/tiler/tiler-main.c    |  426 ++++++++++++++++++++++++++
 drivers/media/video/tiler/tmm-pat.c       |  274 +++++++++++++++++
 drivers/media/video/tiler/tmm.h           |  109 +++++++
 20 files changed, 2903 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/arm/TILER
 create mode 100644 arch/arm/mach-omap2/include/mach/dmm.h
 create mode 100644 arch/arm/mach-omap2/include/mach/tiler.h
 create mode 100644 drivers/media/video/tiler/Kconfig
 create mode 100644 drivers/media/video/tiler/Makefile
 create mode 100644 drivers/media/video/tiler/_tiler.h
 create mode 100644 drivers/media/video/tiler/dmm.c
 create mode 100644 drivers/media/video/tiler/tcm.h
 create mode 100644 drivers/media/video/tiler/tcm/Makefile
 create mode 100644 drivers/media/video/tiler/tcm/_tcm-sita.h
 create mode 100644 drivers/media/video/tiler/tcm/tcm-sita.c
 create mode 100644 drivers/media/video/tiler/tcm/tcm-sita.h
 create mode 100644 drivers/media/video/tiler/tcm/tcm-utils.h
 create mode 100644 drivers/media/video/tiler/tiler-geom.c
 create mode 100644 drivers/media/video/tiler/tiler-iface.c
 create mode 100644 drivers/media/video/tiler/tiler-main.c
 create mode 100644 drivers/media/video/tiler/tmm-pat.c
 create mode 100644 drivers/media/video/tiler/tmm.h


^ permalink raw reply	[flat|nested] 46+ messages in thread

* [RFC 1/8] TILER-DMM: DMM-PAT driver for TI TILER
  2010-07-23 23:22 [RFC 0/8] TI TILER-DMM driver David Sin
@ 2010-07-23 23:22 ` David Sin
  2010-07-23 23:22   ` [RFC 2/8] TILER-DMM: Container manager interface and utility definitons David Sin
                     ` (3 more replies)
  2010-07-24  7:44 ` [RFC 0/8] TI TILER-DMM driver Shilimkar, Santosh
  2010-07-24 11:12 ` Hans Verkuil
  2 siblings, 4 replies; 46+ messages in thread
From: David Sin @ 2010-07-23 23:22 UTC (permalink / raw)
  To: linux-arm-kernel, linux-omap, Tony Lindgren, Russell King
  Cc: Hari Kanigeri, Ohad Ben-Cohen, Vaibhav Hiremath,
	Santosh Shilimkar, David Sin, Lajos Molnar

This patch adds support for DMM-PAT initialization and programming.

Signed-off-by: David Sin <davidsin@ti.com>
Signed-off-by: Lajos Molnar <molnar@ti.com>
---
 arch/arm/mach-omap2/include/mach/dmm.h |  128 ++++++++++++++++++++
 drivers/media/video/tiler/dmm.c        |  200 ++++++++++++++++++++++++++++++++
 2 files changed, 328 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-omap2/include/mach/dmm.h
 create mode 100644 drivers/media/video/tiler/dmm.c

diff --git a/arch/arm/mach-omap2/include/mach/dmm.h b/arch/arm/mach-omap2/include/mach/dmm.h
new file mode 100644
index 0000000..68b798a
--- /dev/null
+++ b/arch/arm/mach-omap2/include/mach/dmm.h
@@ -0,0 +1,128 @@
+/*
+ * dmm.h
+ *
+ * DMM driver support functions for TI DMM-TILER hardware block.
+ *
+ * Author: David Sin <davidsin@ti.com>
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef DMM_H
+#define DMM_H
+
+#define DMM_BASE 0x4E000000
+#define DMM_SIZE 0x800
+
+#define DMM_REVISION          0x000
+#define DMM_HWINFO            0x004
+#define DMM_LISA_HWINFO       0x008
+#define DMM_DMM_SYSCONFIG     0x010
+#define DMM_LISA_LOCK         0x01C
+#define DMM_LISA_MAP__0       0x040
+#define DMM_LISA_MAP__1       0x044
+#define DMM_TILER_HWINFO      0x208
+#define DMM_TILER_OR__0       0x220
+#define DMM_TILER_OR__1       0x224
+#define DMM_PAT_HWINFO        0x408
+#define DMM_PAT_GEOMETRY      0x40C
+#define DMM_PAT_CONFIG        0x410
+#define DMM_PAT_VIEW__0       0x420
+#define DMM_PAT_VIEW__1       0x424
+#define DMM_PAT_VIEW_MAP__0   0x440
+#define DMM_PAT_VIEW_MAP_BASE 0x460
+#define DMM_PAT_IRQ_EOI       0x478
+#define DMM_PAT_IRQSTATUS_RAW 0x480
+#define DMM_PAT_IRQSTATUS     0x490
+#define DMM_PAT_IRQENABLE_SET 0x4A0
+#define DMM_PAT_IRQENABLE_CLR 0x4B0
+#define DMM_PAT_STATUS__0     0x4C0
+#define DMM_PAT_STATUS__1     0x4C4
+#define DMM_PAT_STATUS__2     0x4C8
+#define DMM_PAT_STATUS__3     0x4CC
+#define DMM_PAT_DESCR__0      0x500
+#define DMM_PAT_AREA__0       0x504
+#define DMM_PAT_CTRL__0       0x508
+#define DMM_PAT_DATA__0       0x50C
+#define DMM_PEG_HWINFO        0x608
+#define DMM_PEG_PRIO          0x620
+#define DMM_PEG_PRIO_PAT      0x640
+
+/**
+ * PAT refill programming mode.
+ */
+enum pat_mode {
+	MANUAL,
+	AUTO
+};
+
+/**
+ * Area definition for DMM physical address translator.
+ */
+struct pat_area {
+	s32 x0:8;
+	s32 y0:8;
+	s32 x1:8;
+	s32 y1:8;
+};
+
+/**
+ * DMM physical address translator control.
+ */
+struct pat_ctrl {
+	s32 start:4;
+	s32 dir:4;
+	s32 lut_id:8;
+	s32 sync:12;
+	s32 ini:4;
+};
+
+/**
+ * PAT descriptor.
+ */
+struct pat {
+	struct pat *next;
+	struct pat_area area;
+	struct pat_ctrl ctrl;
+	u32 data;
+};
+
+/**
+ * DMM device data
+ */
+struct dmm {
+	void __iomem *base;
+};
+
+/**
+ * Create and initialize the physical address translator.
+ * @param id    PAT id
+ * @return pointer to device data
+ */
+struct dmm *dmm_pat_init(u32 id);
+
+/**
+ * Program the physical address translator.
+ * @param dmm   Device data
+ * @param desc  PAT descriptor
+ * @param mode  programming mode
+ * @return an error status.
+ */
+s32 dmm_pat_refill(struct dmm *dmm, struct pat *desc, enum pat_mode mode);
+
+/**
+ * Clean up the physical address translator.
+ * @param dmm    Device data
+ * @return an error status.
+ */
+void dmm_pat_release(struct dmm *dmm);
+
+#endif
diff --git a/drivers/media/video/tiler/dmm.c b/drivers/media/video/tiler/dmm.c
new file mode 100644
index 0000000..e715936
--- /dev/null
+++ b/drivers/media/video/tiler/dmm.c
@@ -0,0 +1,200 @@
+/*
+ * dmm.c
+ *
+ * DMM driver support functions for TI OMAP processors.
+ *
+ * Authors: David Sin <davidsin@ti.com>
+ *          Lajos Molnar <molnar@ti.com>
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h> /* platform_device() */
+#include <linux/io.h>              /* ioremap() */
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+#include <mach/dmm.h>
+
+#define MASK(msb, lsb) (((1 << ((msb) + 1 - (lsb))) - 1) << (lsb))
+#define SET_FLD(reg, msb, lsb, val) \
+(((reg) & ~MASK((msb), (lsb))) | (((val) << (lsb)) & MASK((msb), (lsb))))
+
+static struct platform_driver dmm_driver_ldm = {
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "dmm",
+	},
+	.probe = NULL,
+	.shutdown = NULL,
+	.remove = NULL,
+};
+
+s32 dmm_pat_refill(struct dmm *dmm, struct pat *pd, enum pat_mode mode)
+{
+	void __iomem *r;
+	u32 v;
+
+	/* Only manual refill supported */
+	if (mode != MANUAL)
+		return -EFAULT;
+
+	/* Check that the DMM_PAT_STATUS register has not reported an error */
+	r = dmm->base + DMM_PAT_STATUS__0;
+	v = __raw_readl(r);
+	if (WARN(v & 0xFC00, KERN_ERR "dmm_pat_refill() error.\n"))
+		return -EIO;
+
+	/* Set "next" register to NULL */
+	r = dmm->base + DMM_PAT_DESCR__0;
+	v = __raw_readl(r);
+	v = SET_FLD(v, 31, 4, (u32) NULL);
+	__raw_writel(v, r);
+
+	/* Set area to be refilled */
+	r = dmm->base + DMM_PAT_AREA__0;
+	v = __raw_readl(r);
+	v = SET_FLD(v, 30, 24, pd->area.y1);
+	v = SET_FLD(v, 23, 16, pd->area.x1);
+	v = SET_FLD(v, 14, 8, pd->area.y0);
+	v = SET_FLD(v, 7, 0, pd->area.x0);
+	__raw_writel(v, r);
+	wmb();
+
+	/* First, clear the DMM_PAT_IRQSTATUS register */
+	r = dmm->base + DMM_PAT_IRQSTATUS;
+	__raw_writel(0xFFFFFFFF, r);
+	wmb();
+
+	r = dmm->base + DMM_PAT_IRQSTATUS_RAW;
+	while (__raw_readl(r) != 0)
+		;
+
+	/* Fill data register */
+	r = dmm->base + DMM_PAT_DATA__0;
+	v = __raw_readl(r);
+
+	v = SET_FLD(v, 31, 4, pd->data >> 4);
+	__raw_writel(v, r);
+	wmb();
+
+	/* Read back PAT_DATA__0 to see if write was successful */
+	while (__raw_readl(r) != pd->data)
+		;
+
+	r = dmm->base + DMM_PAT_CTRL__0;
+	v = __raw_readl(r);
+	v = SET_FLD(v, 31, 28, pd->ctrl.ini);
+	v = SET_FLD(v, 16, 16, pd->ctrl.sync);
+	v = SET_FLD(v, 9, 8, pd->ctrl.lut_id);
+	v = SET_FLD(v, 6, 4, pd->ctrl.dir);
+	v = SET_FLD(v, 0, 0, pd->ctrl.start);
+	__raw_writel(v, r);
+	wmb();
+
+	/* Check if PAT_IRQSTATUS_RAW is set after the PAT has been refilled */
+	r = dmm->base + DMM_PAT_IRQSTATUS_RAW;
+	while ((__raw_readl(r) & 0x3) != 0x3)
+		;
+
+	/* Again, clear the DMM_PAT_IRQSTATUS register */
+	r = dmm->base + DMM_PAT_IRQSTATUS;
+	__raw_writel(0xFFFFFFFF, r);
+	wmb();
+
+	r = dmm->base + DMM_PAT_IRQSTATUS_RAW;
+	while (__raw_readl(r) != 0)
+		;
+
+	/* Again, set "next" register to NULL to clear any PAT STATUS errors */
+	r = dmm->base + DMM_PAT_DESCR__0;
+	v = __raw_readl(r);
+	v = SET_FLD(v, 31, 4, (u32) NULL);
+	__raw_writel(v, r);
+
+	/*
+	 * Now, check that the DMM_PAT_STATUS register
+	 * has not reported an error before exiting.
+	*/
+	r = dmm->base + DMM_PAT_STATUS__0;
+	v = __raw_readl(r);
+	if (WARN(v & 0xFC00, KERN_ERR "dmm_pat_refill() error.\n"))
+		return -EIO;
+
+	return 0;
+}
+EXPORT_SYMBOL(dmm_pat_refill);
+
+struct dmm *dmm_pat_init(u32 id)
+{
+	u32 base;
+	struct dmm *dmm;
+	switch (id) {
+	case 0:
+		/* only support id 0 for now */
+		base = DMM_BASE;
+		break;
+	default:
+		return NULL;
+	}
+
+	dmm = kzalloc(sizeof(*dmm), GFP_KERNEL);
+	if (!dmm)
+		return NULL;
+
+	dmm->base = ioremap(base, DMM_SIZE);
+	if (!dmm->base) {
+		kfree(dmm);
+		return NULL;
+	}
+
+	__raw_writel(0x88888888, dmm->base + DMM_PAT_VIEW__0);
+	__raw_writel(0x88888888, dmm->base + DMM_PAT_VIEW__1);
+	__raw_writel(0x80808080, dmm->base + DMM_PAT_VIEW_MAP__0);
+	__raw_writel(0x80000000, dmm->base + DMM_PAT_VIEW_MAP_BASE);
+	__raw_writel(0x88888888, dmm->base + DMM_TILER_OR__0);
+	__raw_writel(0x88888888, dmm->base + DMM_TILER_OR__1);
+
+	return dmm;
+}
+EXPORT_SYMBOL(dmm_pat_init);
+
+/**
+ * Clean up the physical address translator.
+ * @param dmm    Device data
+ * @return an error status.
+ */
+void dmm_pat_release(struct dmm *dmm)
+{
+	if (dmm) {
+		iounmap(dmm->base);
+		kfree(dmm);
+	}
+}
+EXPORT_SYMBOL(dmm_pat_release);
+
+static s32 __init dmm_init(void)
+{
+	return platform_driver_register(&dmm_driver_ldm);
+}
+
+static void __exit dmm_exit(void)
+{
+	platform_driver_unregister(&dmm_driver_ldm);
+}
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("davidsin@ti.com");
+MODULE_AUTHOR("molnar@ti.com");
+module_init(dmm_init);
+module_exit(dmm_exit);
-- 
1.6.3.3


^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [RFC 2/8] TILER-DMM: Container manager interface and utility definitons
  2010-07-23 23:22 ` [RFC 1/8] TILER-DMM: DMM-PAT driver for TI TILER David Sin
@ 2010-07-23 23:22   ` David Sin
  2010-07-23 23:22     ` [RFC 3/8] TILER-DMM: Sample TCM implementation: Simple TILER Allocator David Sin
                       ` (2 more replies)
  2010-07-24  6:51   ` [RFC 1/8] TILER-DMM: DMM-PAT driver for TI TILER Shilimkar, Santosh
                     ` (2 subsequent siblings)
  3 siblings, 3 replies; 46+ messages in thread
From: David Sin @ 2010-07-23 23:22 UTC (permalink / raw)
  To: linux-arm-kernel, linux-omap, Tony Lindgren, Russell King
  Cc: Hari Kanigeri, Ohad Ben-Cohen, Vaibhav Hiremath,
	Santosh Shilimkar, Lajos Molnar, David Sin, Ravi Ramachandra

From: Lajos Molnar <molnar@ti.com>

This patch defined the TILER Container Manager (TCM) interface and
provides utility methods for implementing a TCM.

Signed-off-by: Lajos Molnar <molnar@ti.com>
Signed-off-by: David Sin <davidsin@ti.com>
Signed-off-by: Ravi Ramachandra <r.ramachandra@ti.com>
---
 drivers/media/video/tiler/tcm.h           |  209 +++++++++++++++++++++++++++++
 drivers/media/video/tiler/tcm/tcm-utils.h |   54 ++++++++
 2 files changed, 263 insertions(+), 0 deletions(-)
 create mode 100644 drivers/media/video/tiler/tcm.h
 create mode 100644 drivers/media/video/tiler/tcm/tcm-utils.h

diff --git a/drivers/media/video/tiler/tcm.h b/drivers/media/video/tiler/tcm.h
new file mode 100644
index 0000000..52a022a
--- /dev/null
+++ b/drivers/media/video/tiler/tcm.h
@@ -0,0 +1,209 @@
+/*
+ * tcm.h
+ *
+ * TILER container manager specification and support functions for TI
+ * TILER driver.
+ *
+ * Author: Lajos Molnar <molnar@ti.com>
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef TCM_H
+#define TCM_H
+
+struct tcm;
+
+/* point */
+struct tcm_pt {
+	u16 x;
+	u16 y;
+};
+
+/* 2d area */
+struct tcm_area {
+	struct tcm    *tcm;	/* parent */
+	struct tcm_pt  p0;
+	struct tcm_pt  p1;
+};
+
+struct tcm {
+	u16 width, height;	/* container dimensions */
+
+	/* '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
+	any changes to the publicly available width and height fields. */
+	void *pvt;
+
+	/* function table */
+	s32 (*reserve_2d)(struct tcm *tcm, u16 height, u16 width, u8 align,
+			  struct tcm_area *area);
+	s32 (*free)      (struct tcm *tcm, struct tcm_area *area);
+	void (*deinit)   (struct tcm *tcm);
+};
+
+/*=============================================================================
+    BASIC TILER CONTAINER MANAGER INTERFACE
+=============================================================================*/
+
+/*
+ * NOTE:
+ *
+ * Since some basic parameter checking is done outside the TCM algorithms,
+ * TCM implementation do NOT have to check the following:
+ *
+ *   area pointer is NULL
+ *   width and height fits within container
+ *   number of pages is more than the size of the container
+ *
+ */
+
+/**
+ * Template for <ALGO_NAME>_tcm_init method.  Define as:
+ * TCM_INIT(<ALGO_NAME>_tcm_init)
+ *
+ * Allocates and initializes a tiler container manager.
+ *
+ * @param width		Width of container
+ * @param height	Height of container
+ * @param attr		Container manager specific configuration
+ *			arguments.  Please describe these in
+ *			your header file.
+ *
+ * @return Pointer to the allocated and initialized container
+ *	   manager.  NULL on failure.  DO NOT leak any memory on
+ *	   failure!
+ */
+#define TCM_INIT(name, attr_t) \
+struct tcm *name(u16 width, u16 height, typeof(attr_t) *attr);
+
+/**
+ * Deinitialize tiler container manager.
+ *
+ * @param tcm	Pointer to container manager.
+ *
+ * @return 0 on success, non-0 error value on error.  The call
+ *	   should free as much memory as possible and meaningful
+ *	   even on failure.  Some error codes: -ENODEV: invalid
+ *	   manager.
+ */
+static inline void tcm_deinit(struct tcm *tcm)
+{
+	if (tcm)
+		tcm->deinit(tcm);
+}
+
+/**
+ * Reserves a 2D area in the container.
+ *
+ * @param tcm		Pointer to container manager.
+ * @param height	Height(in pages) of area to be reserved.
+ * @param width		Width(in pages) of area to be reserved.
+ * @param align		Alignment requirement for top-left corner of area. Not
+ *			all values may be supported by the container manager,
+ *			but it must support 0 (1), 32 and 64.
+ *			0 value is equivalent to 1.
+ * @param area		Pointer to where the reserved area should be stored.
+ *
+ * @return 0 on success.  Non-0 error code on failure.  Also,
+ *	   the tcm field of the area will be set to NULL on
+ *	   failure.  Some error codes: -ENODEV: invalid manager,
+ *	   -EINVAL: invalid area, -ENOMEM: not enough space for
+ *	    allocation.
+ */
+static inline s32 tcm_reserve_2d(struct tcm *tcm, u16 width, u16 height,
+				 u16 align, struct tcm_area *area)
+{
+	/* perform rudimentary error checking */
+	s32 res = (tcm  == NULL ? -ENODEV :
+		(area == NULL || width == 0 || height == 0 ||
+		 /* align must be a 2 power */
+		 align & (align - 1)) ? -EINVAL :
+		(height > tcm->height || width > tcm->width) ? -ENOMEM :
+		tcm->reserve_2d(tcm, height, width, align, area));
+
+	if (area)
+		area->tcm = res ? NULL : tcm;
+
+	return res;
+}
+
+/**
+ * Free a previously reserved area from the container.
+ *
+ * @param area	Pointer to area reserved by a prior call to tcm_reserve_2d call,
+ *		whether it was successful or not. (Note: all fields of
+ *		the structure must match.)
+ *
+ * @return 0 on success.  Non-0 error code on failure.  Also, the tcm
+ *	   field of the area is set to NULL on success to avoid subsequent
+ *	   freeing.  This call will succeed even if supplying
+ *	   the area from a failed reserved call.
+ */
+static inline s32 tcm_free(struct tcm_area *area)
+{
+	s32 res = 0; /* free succeeds by default */
+
+	if (area && area->tcm) {
+		res = area->tcm->free(area->tcm, area);
+		if (res == 0)
+			area->tcm = NULL;
+	}
+
+	return res;
+}
+
+/*=============================================================================
+    HELPER FUNCTION FOR ANY TILER CONTAINER MANAGER
+=============================================================================*/
+
+/* Verify if a tcm area is logically valid */
+static inline bool tcm_area_is_valid(struct tcm_area *area)
+{
+	return area && area->tcm &&
+		/* coordinate bounds */
+		area->p1.x < area->tcm->width &&
+		area->p1.y < area->tcm->height &&
+		area->p0.y <= area->p1.y &&
+		area->p0.x <= area->p1.x;
+}
+
+/* see if a coordinate is within an area */
+static inline bool __tcm_is_in(struct tcm_pt *p, struct tcm_area *a)
+{
+	return p->x >= a->p0.x && p->x <= a->p1.x &&
+		p->y >= a->p0.y && p->y <= a->p1.y;
+}
+
+/* calculate area width */
+static inline u16 __tcm_area_width(struct tcm_area *area)
+{
+	return area->p1.x - area->p0.x + 1;
+}
+
+/* calculate area height */
+static inline u16 __tcm_area_height(struct tcm_area *area)
+{
+	return area->p1.y - area->p0.y + 1;
+}
+
+/* calculate number of slots in an area */
+static inline u16 __tcm_sizeof(struct tcm_area *area)
+{
+	return __tcm_area_width(area) * __tcm_area_height(area);
+}
+#define tcm_sizeof(area) __tcm_sizeof(&(area))
+#define tcm_awidth(area) __tcm_area_width(&(area))
+#define tcm_aheight(area) __tcm_area_height(&(area))
+#define tcm_is_in(pt, area) __tcm_is_in(&(pt), &(area))
+
+#endif
diff --git a/drivers/media/video/tiler/tcm/tcm-utils.h b/drivers/media/video/tiler/tcm/tcm-utils.h
new file mode 100644
index 0000000..0d1260a
--- /dev/null
+++ b/drivers/media/video/tiler/tcm/tcm-utils.h
@@ -0,0 +1,54 @@
+/*
+ * tcm_utils.h
+ *
+ * Utility functions for implementing TILER container managers.
+ *
+ * Author: Lajos Molnar <molnar@ti.com>
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef TCM_UTILS_H
+#define TCM_UTILS_H
+
+#include "../tcm.h"
+
+/* TCM_ALG_NAME must be defined to use the debug methods */
+
+#ifdef DEBUG
+#define IFDEBUG(x) x
+#else
+/* compile-check debug statements even if not DEBUG */
+#define IFDEBUG(x) do { if (0) x; } while (0)
+#endif
+
+#define P(level, fmt, ...) \
+	IFDEBUG(printk(level TCM_ALG_NAME ":%d:%s()" fmt "\n", \
+			__LINE__, __func__, ##__VA_ARGS__))
+
+#define P1(fmt, ...) P(KERN_NOTICE, fmt, ##__VA_ARGS__)
+#define P2(fmt, ...) P(KERN_INFO, fmt, ##__VA_ARGS__)
+#define P3(fmt, ...) P(KERN_DEBUG, fmt, ##__VA_ARGS__)
+
+#define PA(level, msg, p_area) P##level(msg " (%03d %03d)-(%03d %03d)\n", \
+	(p_area)->p0.x, (p_area)->p0.y, (p_area)->p1.x, (p_area)->p1.y)
+
+/* assign coordinates to area */
+static inline
+void assign(struct tcm_area *a, u16 x0, u16 y0, u16 x1, u16 y1)
+{
+	a->p0.x = x0;
+	a->p0.y = y0;
+	a->p1.x = x1;
+	a->p1.y = y1;
+}
+
+#endif
-- 
1.6.3.3


^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [RFC 3/8] TILER-DMM: Sample TCM implementation: Simple TILER Allocator
  2010-07-23 23:22   ` [RFC 2/8] TILER-DMM: Container manager interface and utility definitons David Sin
@ 2010-07-23 23:22     ` David Sin
  2010-07-23 23:22       ` [RFC 4/8] TILER-DMM: TILER Memory Manager interface and implementation David Sin
                         ` (2 more replies)
  2010-07-24  6:56     ` [RFC 2/8] TILER-DMM: Container manager interface and utility definitons Shilimkar, Santosh
  2010-07-27 20:21     ` Hiremath, Vaibhav
  2 siblings, 3 replies; 46+ messages in thread
From: David Sin @ 2010-07-23 23:22 UTC (permalink / raw)
  To: linux-arm-kernel, linux-omap, Tony Lindgren, Russell King
  Cc: Hari Kanigeri, Ohad Ben-Cohen, Vaibhav Hiremath,
	Santosh Shilimkar, Ravi Ramachandra, Lajos Molnar, David Sin

From: Ravi Ramachandra <r.ramachandra@ti.com>

This patch implements a simple TILER Container Manager.

Signed-off-by: Ravi Ramachandra <r.ramachandra@ti.com>
Signed-off-by: Lajos Molnar <molnar@ti.com>
Signed-off-by: David Sin <davidsin@ti.com>
---
 drivers/media/video/tiler/tcm/Makefile    |    1 +
 drivers/media/video/tiler/tcm/_tcm-sita.h |   64 ++++
 drivers/media/video/tiler/tcm/tcm-sita.c  |  459 +++++++++++++++++++++++++++++
 drivers/media/video/tiler/tcm/tcm-sita.h  |   37 +++
 4 files changed, 561 insertions(+), 0 deletions(-)
 create mode 100644 drivers/media/video/tiler/tcm/Makefile
 create mode 100644 drivers/media/video/tiler/tcm/_tcm-sita.h
 create mode 100644 drivers/media/video/tiler/tcm/tcm-sita.c
 create mode 100644 drivers/media/video/tiler/tcm/tcm-sita.h

diff --git a/drivers/media/video/tiler/tcm/Makefile b/drivers/media/video/tiler/tcm/Makefile
new file mode 100644
index 0000000..8434607
--- /dev/null
+++ b/drivers/media/video/tiler/tcm/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_TI_TILER) += tcm-sita.o
diff --git a/drivers/media/video/tiler/tcm/_tcm-sita.h b/drivers/media/video/tiler/tcm/_tcm-sita.h
new file mode 100644
index 0000000..4ede1ab
--- /dev/null
+++ b/drivers/media/video/tiler/tcm/_tcm-sita.h
@@ -0,0 +1,64 @@
+/*
+ * _tcm_sita.h
+ *
+ * SImple Tiler Allocator (SiTA) private structures.
+ *
+ * Author: Ravi Ramachandra <r.ramachandra@ti.com>
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef _TCM_SITA_H
+#define _TCM_SITA_H
+
+#include "../tcm.h"
+
+/* length between two coordinates */
+#define LEN(a, b) ((a) > (b) ? (a) - (b) + 1 : (b) - (a) + 1)
+
+enum criteria {
+	CR_MAX_NEIGHS		= 0x01,
+	CR_FIRST_FOUND		= 0x10,
+	CR_BIAS_HORIZONTAL	= 0x20,
+	CR_BIAS_VERTICAL	= 0x40,
+	CR_DIAGONAL_BALANCE	= 0x80
+};
+
+/* nearness to the beginning of the search field from 0 to 1000 */
+struct nearness_factor {
+	s32 x;
+	s32 y;
+};
+
+/*
+ * Statistics on immediately neighboring slots.  Edge is the number of
+ * border segments that are also border segments of the scan field.  Busy
+ * refers to the number of neighbors that are occupied.
+ */
+struct neighbor_stats {
+	u16 edge;
+	u16 busy;
+};
+
+/* structure to keep the score of a potential allocation */
+struct score {
+	struct nearness_factor	f;
+	struct neighbor_stats	n;
+	struct tcm_area		a;
+	u16    neighs;		/* number of busy neighbors */
+};
+
+struct sita_pvt {
+	struct mutex mtx;
+	struct tcm_area ***map;	/* pointers to the parent area for each slot */
+};
+
+#endif
diff --git a/drivers/media/video/tiler/tcm/tcm-sita.c b/drivers/media/video/tiler/tcm/tcm-sita.c
new file mode 100644
index 0000000..93be3e6
--- /dev/null
+++ b/drivers/media/video/tiler/tcm/tcm-sita.c
@@ -0,0 +1,459 @@
+/*
+ * tcm-sita.c
+ *
+ * SImple Tiler Allocator (SiTA): 2D and 1D allocation(reservation) algorithm
+ *
+ * Authors: Ravi Ramachandra <r.ramachandra@ti.com>,
+ *          Lajos Molnar <molnar@ti.com>
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+#include <linux/slab.h>
+
+#include "_tcm-sita.h"
+#include "tcm-sita.h"
+
+#define TCM_ALG_NAME "tcm_sita"
+#include "tcm-utils.h"
+
+#define ALIGN_DOWN(value, align) ((value) & ~((align) - 1))
+
+/* Individual selection criteria for different scan areas */
+static s32 CR_L2R_T2B = CR_BIAS_HORIZONTAL;
+
+/*********************************************
+ *	TCM API - Sita Implementation
+ *********************************************/
+static s32 sita_reserve_2d(struct tcm *tcm, u16 h, u16 w, u8 align,
+			   struct tcm_area *area);
+static s32 sita_free(struct tcm *tcm, struct tcm_area *area);
+static void sita_deinit(struct tcm *tcm);
+
+/*********************************************
+ *	Main Scanner functions
+ *********************************************/
+static s32 scan_areas_and_find_fit(struct tcm *tcm, u16 w, u16 h, u16 align,
+				   struct tcm_area *area);
+
+static s32 scan_l2r_t2b(struct tcm *tcm, u16 w, u16 h, u16 align,
+			struct tcm_area *field, struct tcm_area *area);
+
+/*********************************************
+ *	Support Infrastructure Methods
+ *********************************************/
+static s32 is_area_free(struct tcm_area ***map, u16 x0, u16 y0, u16 w, u16 h);
+
+static s32 update_candidate(struct tcm *tcm, u16 x0, u16 y0, u16 w, u16 h,
+			    struct tcm_area *field, s32 criteria,
+			    struct score *best);
+
+static void get_nearness_factor(struct tcm_area *field,
+				struct tcm_area *candidate,
+				struct nearness_factor *nf);
+
+static void get_neighbor_stats(struct tcm *tcm, struct tcm_area *area,
+			       struct neighbor_stats *stat);
+
+static void fill_area(struct tcm *tcm,
+				struct tcm_area *area, struct tcm_area *parent);
+
+/*********************************************/
+
+/*********************************************
+ *	Utility Methods
+ *********************************************/
+struct tcm *sita_init(u16 width, u16 height, void *attr)
+{
+	struct tcm *tcm;
+	struct sita_pvt *pvt;
+	struct tcm_area area = {0};
+	s32 i;
+
+	if (width == 0 || height == 0)
+		return NULL;
+
+	tcm = kzalloc(sizeof(*tcm), GFP_KERNEL);
+	pvt = kzalloc(sizeof(*pvt), GFP_KERNEL);
+	if (!tcm || !pvt)
+		goto error;
+
+	/* Updating the pointers to SiTA implementation APIs */
+	tcm->height = height;
+	tcm->width = width;
+	tcm->reserve_2d = sita_reserve_2d;
+	tcm->free = sita_free;
+	tcm->deinit = sita_deinit;
+	tcm->pvt = (void *)pvt;
+
+	mutex_init(&(pvt->mtx));
+
+	/* Creating tam map */
+	pvt->map = kzalloc(sizeof(*pvt->map) * tcm->width, GFP_KERNEL);
+	if (!pvt->map)
+		goto error;
+
+	for (i = 0; i < tcm->width; i++) {
+		pvt->map[i] =
+			kzalloc(sizeof(**pvt->map) * tcm->height,
+								GFP_KERNEL);
+		if (pvt->map[i] == NULL) {
+			while (i--)
+				kfree(pvt->map[i]);
+			kfree(pvt->map);
+			goto error;
+		}
+	}
+
+	mutex_lock(&(pvt->mtx));
+	assign(&area, 0, 0, width - 1, height - 1);
+	fill_area(tcm, &area, NULL);
+	mutex_unlock(&(pvt->mtx));
+	return tcm;
+
+error:
+	kfree(tcm);
+	kfree(pvt);
+	return NULL;
+}
+
+static void sita_deinit(struct tcm *tcm)
+{
+	struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
+	struct tcm_area area = {0};
+	s32 i;
+
+	area.p1.x = tcm->width - 1;
+	area.p1.y = tcm->height - 1;
+
+	mutex_lock(&(pvt->mtx));
+	fill_area(tcm, &area, NULL);
+	mutex_unlock(&(pvt->mtx));
+
+	mutex_destroy(&(pvt->mtx));
+
+	for (i = 0; i < tcm->height; i++)
+		kfree(pvt->map[i]);
+	kfree(pvt->map);
+	kfree(pvt);
+}
+
+/**
+ * Reserve a 2D area in the container
+ *
+ * @param w	width
+ * @param h	height
+ * @param area	pointer to the area that will be populated with the reesrved
+ *		area
+ *
+ * @return 0 on success, non-0 error value on failure.
+ */
+static s32 sita_reserve_2d(struct tcm *tcm, u16 h, u16 w, u8 align,
+			   struct tcm_area *area)
+{
+	s32 ret;
+	struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
+
+	/* not supporting more than 64 as alignment */
+	if (align > 64)
+		return -EINVAL;
+
+	/* we prefer 1, 32 and 64 as alignment */
+	align = align <= 1 ? 1 : align <= 32 ? 32 : 64;
+
+	mutex_lock(&(pvt->mtx));
+	ret = scan_areas_and_find_fit(tcm, w, h, align, area);
+	if (!ret)
+		/* update map */
+		fill_area(tcm, area, area);
+
+	mutex_unlock(&(pvt->mtx));
+	return ret;
+}
+
+/**
+ * Unreserve a previously allocated 2D or 1D area
+ * @param area	area to be freed
+ * @return 0 - success
+ */
+static s32 sita_free(struct tcm *tcm, struct tcm_area *area)
+{
+	struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
+
+	mutex_lock(&(pvt->mtx));
+
+	/* Clear the contents of the associated tiles in the map */
+	fill_area(tcm, area, NULL);
+
+	mutex_unlock(&(pvt->mtx));
+
+	return 0;
+}
+
+/**
+ * Note: In general the cordinates in the scan field area relevant to the can
+ * sweep directions. The scan origin (e.g. top-left corner) will always be
+ * the p0 member of the field.  Therfore, for a scan from top-left p0.x <= p1.x
+ * and p0.y <= p1.y; whereas, for a scan from bottom-right p1.x <= p0.x and p1.y
+ * <= p0.y
+ */
+
+/**
+ * Raster scan horizontally left to right from top to bottom to find a place for
+ * a 2D area of given size inside a scan field.
+ *
+ * @param w	width of desired area
+ * @param h	height of desired area
+ * @param align	desired area alignment
+ * @param area	pointer to the area that will be set to the best position
+ * @param field	area to scan (inclusive)
+ *
+ * @return 0 on success, non-0 error value on failure.
+ */
+static s32 scan_l2r_t2b(struct tcm *tcm, u16 w, u16 h, u16 align,
+			struct tcm_area *field, struct tcm_area *area)
+{
+	s32 x, y;
+	s16 start_x, end_x, start_y, end_y;
+	struct tcm_area ***map = ((struct sita_pvt *)tcm->pvt)->map;
+	struct score best = {{0}, {0}, {0}, 0};
+
+	PA(2, "scan_l2r_t2b:", field);
+
+	start_x = field->p0.x;
+	end_x = field->p1.x;
+	start_y = field->p0.y;
+	end_y = field->p1.y;
+
+	/* check scan area co-ordinates */
+	if (field->p1.x < field->p0.x ||
+	    field->p1.y < field->p0.y)
+		return -EINVAL;
+
+	/* check if allocation would fit in scan area */
+	if (w > LEN(end_x, start_x) || h > LEN(end_y, start_y))
+		return -ENOSPC;
+
+	start_x = ALIGN(start_x, align);
+
+	/* check if allocation would still fit in scan area */
+	if (w > LEN(end_x, start_x))
+		return -ENOSPC;
+
+	/* adjust end_x and end_y, as allocation would not fit beyond */
+	end_x = end_x - w + 1; /* + 1 to be inclusive */
+	end_y = end_y - h + 1;
+
+	P2("ali=%d x=%d..%d y=%d..%d", align, start_x, end_x, start_y, end_y);
+
+	/* scan field top-to-bottom, left-to-right */
+	for (y = start_y; y <= end_y; y++) {
+		for (x = start_x; x <= end_x; x += align) {
+			if (is_area_free(map, x, y, w, h)) {
+				P3("found shoulder: %d,%d", x, y);
+
+				/* update best candidate */
+				if (update_candidate(tcm, x, y, w, h, field,
+							CR_L2R_T2B, &best))
+					goto done;
+				break;
+			} else if (map[x][y]) {
+				/* step over 2D areas */
+				x = ALIGN_DOWN(map[x][y]->p1.x, align);
+				P3("moving to: %d,%d", x, y);
+			}
+		}
+	}
+
+	if (!best.a.tcm)
+		return -ENOSPC;
+done:
+	assign(area, best.a.p0.x, best.a.p0.y, best.a.p1.x, best.a.p1.y);
+	return 0;
+}
+
+/**
+ * Find a place for a 2D area of given size inside a scan field based on its
+ * alignment needs.
+ *
+ * @param w	width of desired area
+ * @param h	height of desired area
+ * @param align	desired area alignment
+ * @param area	pointer to the area that will be set to the best position
+ *
+ * @return 0 on success, non-0 error value on failure.
+ */
+static s32 scan_areas_and_find_fit(struct tcm *tcm, u16 w, u16 h, u16 align,
+				   struct tcm_area *area)
+{
+	struct tcm_area field = {0};
+
+	/* scan whole container left to right, top to bottom */
+	assign(&field, 0, 0, tcm->width - 1, tcm->height - 1);
+	return scan_l2r_t2b(tcm, w, h, align, &field, area);
+}
+
+/* check if an entire area is free */
+static s32 is_area_free(struct tcm_area ***map, u16 x0, u16 y0, u16 w, u16 h)
+{
+	u16 x = 0, y = 0;
+	for (y = y0; y < y0 + h; y++) {
+		for (x = x0; x < x0 + w; x++) {
+			if (map[x][y])
+				return false;
+		}
+	}
+	return true;
+}
+
+/* fills an area with a parent tcm_area */
+static void fill_area(struct tcm *tcm, struct tcm_area *area,
+			struct tcm_area *parent)
+{
+	s32 x, y;
+	struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
+
+	PA(2, "fill 2d area", area);
+	for (x = area->p0.x; x <= area->p1.x; ++x)
+		for (y = area->p0.y; y <= area->p1.y; ++y)
+			pvt->map[x][y] = parent;
+}
+
+/**
+ * Compares a candidate area to the current best area, and if it is a better
+ * fit, it updates the best to this one.
+ *
+ * @param x0, y0, w, h		top, left, width, height of candidate area
+ * @param field			scan field
+ * @param criteria		scan criteria
+ * @param best			best candidate and its scores
+ *
+ * @return 1 (true) if the candidate area is known to be the final best, so no
+ * more searching should be performed
+ */
+static s32 update_candidate(struct tcm *tcm, u16 x0, u16 y0, u16 w, u16 h,
+			    struct tcm_area *field, s32 criteria,
+			    struct score *best)
+{
+	struct score me;	/* score for area */
+
+	/*
+	 * If first found is enabled then we stop looking
+	 * NOTE: For horizontal bias we always give the first found, because our
+	 * scan is horizontal-raster-based and the first candidate will always
+	 * have the horizontal bias.
+	 */
+	bool first = criteria & (CR_FIRST_FOUND | CR_BIAS_HORIZONTAL);
+
+	assign(&me.a, x0, y0, x0 + w - 1, y0 + h - 1);
+
+	/* calculate score for current candidate */
+	if (!first) {
+		get_neighbor_stats(tcm, &me.a, &me.n);
+		me.neighs = me.n.edge + me.n.busy;
+		get_nearness_factor(field, &me.a, &me.f);
+	}
+
+	/* the 1st candidate is always the best */
+	if (!best->a.tcm)
+		goto better;
+
+	/* see if this are is better than the best so far */
+
+	/* neighbor check */
+	if ((criteria & CR_MAX_NEIGHS) &&
+		me.neighs > best->neighs)
+		goto better;
+
+	/* vertical bias check */
+	if ((criteria & CR_BIAS_VERTICAL) &&
+	/*
+	 * NOTE: not checking if lengths are same, because that does not
+	 * find new shoulders on the same row after a fit
+	 */
+		LEN(me.a.p0.y, field->p0.y) >
+		LEN(best->a.p0.y, field->p0.y))
+		goto better;
+
+	/* diagonal balance check */
+	if ((criteria & CR_DIAGONAL_BALANCE) &&
+		best->neighs <= me.neighs &&
+		(best->neighs < me.neighs ||
+		 /* this implies that neighs and occupied match */
+		 best->n.busy < me.n.busy ||
+		 (best->n.busy == me.n.busy &&
+		  /* check the nearness factor */
+		  best->f.x + best->f.y > me.f.x + me.f.y)))
+		goto better;
+
+	/* not better, keep going */
+	return 0;
+
+better:
+	/* save current area as best */
+	memcpy(best, &me, sizeof(me));
+	best->a.tcm = tcm;
+	return first;
+}
+
+/**
+ * Calculate the nearness factor of an area in a search field.  The nearness
+ * factor is smaller if the area is closer to the search origin.
+ */
+static void get_nearness_factor(struct tcm_area *field, struct tcm_area *area,
+				struct nearness_factor *nf)
+{
+	/**
+	 * Using signed math as field coordinates may be reversed if
+	 * search direction is right-to-left or bottom-to-top.
+	 */
+	nf->x = (s32)(area->p0.x - field->p0.x) * 1000 /
+		(field->p1.x - field->p0.x);
+	nf->y = (s32)(area->p0.y - field->p0.y) * 1000 /
+		(field->p1.y - field->p0.y);
+}
+
+/* get neighbor statistics */
+static void get_neighbor_stats(struct tcm *tcm, struct tcm_area *area,
+			 struct neighbor_stats *stat)
+{
+	s16 x = 0, y = 0;
+	struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
+
+	/* Clearing any exisiting values */
+	memset(stat, 0, sizeof(*stat));
+
+	/* process top & bottom edges */
+	for (x = area->p0.x; x <= area->p1.x; x++) {
+		if (area->p0.y == 0)
+			stat->edge++;
+		else if (pvt->map[x][area->p0.y - 1])
+			stat->busy++;
+
+		if (area->p1.y == tcm->height - 1)
+			stat->edge++;
+		else if (pvt->map[x][area->p1.y + 1])
+			stat->busy++;
+	}
+
+	/* process left & right edges */
+	for (y = area->p0.y; y <= area->p1.y; ++y) {
+		if (area->p0.x == 0)
+			stat->edge++;
+		else if (pvt->map[area->p0.x - 1][y])
+			stat->busy++;
+
+		if (area->p1.x == tcm->width - 1)
+			stat->edge++;
+		else if (pvt->map[area->p1.x + 1][y])
+			stat->busy++;
+	}
+}
diff --git a/drivers/media/video/tiler/tcm/tcm-sita.h b/drivers/media/video/tiler/tcm/tcm-sita.h
new file mode 100644
index 0000000..ab2d05b
--- /dev/null
+++ b/drivers/media/video/tiler/tcm/tcm-sita.h
@@ -0,0 +1,37 @@
+/*
+ * tcm_sita.h
+ *
+ * SImple Tiler Allocator (SiTA) interface.
+ *
+ * Author: Ravi Ramachandra <r.ramachandra@ti.com>
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef TCM_SITA_H
+#define TCM_SITA_H
+
+#include "../tcm.h"
+
+/**
+ * Create a SiTA tiler container manager.
+ *
+ * @param width  Container width
+ * @param height Container height
+ * @param attr   unused
+ *
+ * @return TCM instance
+ */
+struct tcm *sita_init(u16 width, u16 height, void *attr);
+
+TCM_INIT(sita_init, void);
+
+#endif /* TCM_SITA_H_ */
-- 
1.6.3.3


^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [RFC 4/8] TILER-DMM: TILER Memory Manager interface and implementation
  2010-07-23 23:22     ` [RFC 3/8] TILER-DMM: Sample TCM implementation: Simple TILER Allocator David Sin
@ 2010-07-23 23:22       ` David Sin
  2010-07-23 23:22         ` [RFC 5/8] TILER-DMM: TILER interface file and documentation David Sin
                           ` (2 more replies)
  2010-07-24  7:13       ` [RFC 3/8] TILER-DMM: Sample TCM implementation: Simple TILER Allocator Shilimkar, Santosh
  2010-07-27 20:41       ` Hiremath, Vaibhav
  2 siblings, 3 replies; 46+ messages in thread
From: David Sin @ 2010-07-23 23:22 UTC (permalink / raw)
  To: linux-arm-kernel, linux-omap, Tony Lindgren, Russell King
  Cc: Hari Kanigeri, Ohad Ben-Cohen, Vaibhav Hiremath,
	Santosh Shilimkar, Lajos Molnar, David Sin

From: Lajos Molnar <molnar@ti.com>

This patch defines the TILER Memory Manager (TMM) interface and
provides implementation for a PAT-supporting TMM.

Signed-off-by: Lajos Molnar <molnar@ti.com>
Signed-off-by: David Sin <davidsin@ti.com>
---
 drivers/media/video/tiler/tmm-pat.c |  274 +++++++++++++++++++++++++++++++++++
 drivers/media/video/tiler/tmm.h     |  109 ++++++++++++++
 2 files changed, 383 insertions(+), 0 deletions(-)
 create mode 100644 drivers/media/video/tiler/tmm-pat.c
 create mode 100644 drivers/media/video/tiler/tmm.h

diff --git a/drivers/media/video/tiler/tmm-pat.c b/drivers/media/video/tiler/tmm-pat.c
new file mode 100644
index 0000000..ccd32b4
--- /dev/null
+++ b/drivers/media/video/tiler/tmm-pat.c
@@ -0,0 +1,274 @@
+/*
+ * tmm-pat.c
+ *
+ * DMM driver support functions for TI TILER hardware block.
+ *
+ * Authors: Lajos Molnar <molnar@ti.com>
+ *          David Sin <davidsin@ti.com>
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/mmzone.h>
+#include <asm/cacheflush.h>
+#include <linux/mutex.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+
+#include "tmm.h"
+
+/* Page size granularity can be 4k, 16k, or 64k */
+#define DMM_PAGE 0x1000
+
+/* Memory limit to cache free pages. TILER will eventually use this much */
+static u32 cache_limit = CONFIG_TILER_CACHE_LIMIT << 20;
+module_param_named(cache, cache_limit, uint, 0644);
+MODULE_PARM_DESC(cache, "Cache free pages if total memory is under this limit");
+
+/* global state - statically initialized */
+static LIST_HEAD(free_list);	/* page cache: list of free pages */
+static u32 total_mem;		/* total memory allocated (free & used) */
+static u32 refs;		/* number of tmm_pat instances */
+static DEFINE_MUTEX(mtx);	/* global mutex */
+
+/* The page struct pointer and physical address of each page.*/
+struct mem {
+	struct list_head list;
+	struct page *pg;	/* page struct */
+	u32 pa;			/* physical address */
+};
+
+/* Used to keep track of mem per tmm_pat_get_pages call */
+struct fast {
+	struct list_head list;
+	struct mem **mem;	/* array of page info */
+	u32 *pa;		/* array of physical addresses */
+	u32 num;		/* number of pages */
+};
+
+/* TMM PAT private structure */
+struct dmm_mem {
+	struct list_head fast_list;
+	struct dmm *dmm;
+};
+
+/**
+ *  Frees pages in a fast structure.  Moves pages to the free list if there
+ *  are	less pages used	than max_to_keep.  Otherwise, it frees the pages
+ */
+static void free_fast(struct fast *f)
+{
+	s32 i = 0;
+
+	/* mutex is locked */
+	for (i = 0; i < f->num; i++) {
+		if (total_mem < cache_limit) {
+			/* cache free page if under the limit */
+			list_add(&f->mem[i]->list, &free_list);
+		} else {
+			/* otherwise, free */
+			total_mem -= PAGE_SIZE;
+			__free_page(f->mem[i]->pg);
+		}
+	}
+	kfree(f->pa);
+	kfree(f->mem);
+	/* remove only if element was added */
+	if (f->list.next)
+		list_del(&f->list);
+	kfree(f);
+}
+
+/* allocate and flush a page */
+static struct mem *alloc_mem(void)
+{
+	struct mem *m = kzalloc(sizeof(*m), GFP_KERNEL);
+	if (!m)
+		return NULL;
+
+	m->pg = alloc_page(GFP_KERNEL | GFP_DMA);
+	if (!m->pg) {
+		kfree(m);
+		return NULL;
+	}
+
+	m->pa = page_to_phys(m->pg);
+
+	/* flush the cache entry for each page we allocate. */
+	dmac_flush_range(page_address(m->pg),
+				page_address(m->pg) + PAGE_SIZE);
+	outer_flush_range(m->pa, m->pa + PAGE_SIZE);
+
+	return m;
+}
+
+static void free_page_cache(void)
+{
+	struct mem *m, *m_;
+
+	/* mutex is locked */
+	list_for_each_entry_safe(m, m_, &free_list, list) {
+		__free_page(m->pg);
+		total_mem -= PAGE_SIZE;
+		list_del(&m->list);
+		kfree(m);
+	}
+}
+
+static void tmm_pat_deinit(struct tmm *tmm)
+{
+	struct fast *f, *f_;
+	struct dmm_mem *pvt = (struct dmm_mem *) tmm->pvt;
+
+	mutex_lock(&mtx);
+
+	/* free all outstanding used memory */
+	list_for_each_entry_safe(f, f_, &pvt->fast_list, list)
+		free_fast(f);
+
+	/* if this is the last tmm_pat, free all memory */
+	if (--refs == 0)
+		free_page_cache();
+
+	mutex_unlock(&mtx);
+}
+
+static u32 *tmm_pat_get_pages(struct tmm *tmm, u32 n)
+{
+	struct mem *m;
+	struct fast *f;
+	struct dmm_mem *pvt = (struct dmm_mem *) tmm->pvt;
+
+	f = kzalloc(sizeof(*f), GFP_KERNEL);
+	if (!f)
+		return NULL;
+
+	/* array of mem struct pointers */
+	f->mem = kzalloc(n * sizeof(*f->mem), GFP_KERNEL);
+
+	/* array of physical addresses */
+	f->pa = kzalloc(n * sizeof(*f->pa), GFP_KERNEL);
+
+	/* no pages have been allocated yet (needed for cleanup) */
+	f->num = 0;
+
+	if (!f->mem || !f->pa)
+		goto cleanup;
+
+	/* fill out fast struct mem array with free pages */
+	mutex_lock(&mtx);
+	while (f->num < n) {
+		/* if there is a free cached page use it */
+		if (!list_empty(&free_list)) {
+			/* unbind first element from list */
+			m = list_first_entry(&free_list, typeof(*m), list);
+			list_del(&m->list);
+		} else {
+			mutex_unlock(&mtx);
+
+			/**
+			 * Unlock mutex during allocation and cache flushing.
+			 */
+			m = alloc_mem();
+			if (!m)
+				goto cleanup;
+
+			mutex_lock(&mtx);
+			total_mem += PAGE_SIZE;
+		}
+
+		f->mem[f->num] = m;
+		f->pa[f->num++] = m->pa;
+	}
+
+	list_add(&f->list, &pvt->fast_list);
+	mutex_unlock(&mtx);
+	return f->pa;
+
+cleanup:
+	free_fast(f);
+	return NULL;
+}
+
+static void tmm_pat_free_pages(struct tmm *tmm, u32 *page_list)
+{
+	struct dmm_mem *pvt = (struct dmm_mem *) tmm->pvt;
+	struct fast *f, *f_;
+
+	mutex_lock(&mtx);
+	/* find fast struct based on 1st page */
+	list_for_each_entry_safe(f, f_, &pvt->fast_list, list) {
+		if (f->pa[0] == page_list[0]) {
+			free_fast(f);
+			break;
+		}
+	}
+	mutex_unlock(&mtx);
+}
+
+static s32 tmm_pat_map(struct tmm *tmm, struct pat_area area, u32 page_pa)
+{
+	struct dmm_mem *pvt = (struct dmm_mem *) tmm->pvt;
+	struct pat pat_desc = {0};
+
+	/* send pat descriptor to dmm driver */
+	pat_desc.ctrl.dir = 0;
+	pat_desc.ctrl.ini = 0;
+	pat_desc.ctrl.lut_id = 0;
+	pat_desc.ctrl.start = 1;
+	pat_desc.ctrl.sync = 0;
+	pat_desc.area = area;
+	pat_desc.next = NULL;
+
+	/* must be a 16-byte aligned physical address */
+	pat_desc.data = page_pa;
+	return dmm_pat_refill(pvt->dmm, &pat_desc, MANUAL);
+}
+
+struct tmm *tmm_pat_init(u32 pat_id)
+{
+	struct tmm *tmm = NULL;
+	struct dmm_mem *pvt = NULL;
+
+	struct dmm *dmm = dmm_pat_init(pat_id);
+	if (dmm)
+		tmm = kzalloc(sizeof(*tmm), GFP_KERNEL);
+	if (tmm)
+		pvt = kzalloc(sizeof(*pvt), GFP_KERNEL);
+	if (pvt) {
+		/* private data */
+		pvt->dmm = dmm;
+		INIT_LIST_HEAD(&pvt->fast_list);
+
+		/* increate tmm_pat references */
+		mutex_lock(&mtx);
+		refs++;
+		mutex_unlock(&mtx);
+
+		/* public data */
+		tmm->pvt = pvt;
+		tmm->deinit = tmm_pat_deinit;
+		tmm->get = tmm_pat_get_pages;
+		tmm->free = tmm_pat_free_pages;
+		tmm->map = tmm_pat_map;
+		tmm->clear = NULL;   /* not yet supported */
+
+		return tmm;
+	}
+
+	kfree(pvt);
+	kfree(tmm);
+	dmm_pat_release(dmm);
+	return NULL;
+}
+EXPORT_SYMBOL(tmm_pat_init);
diff --git a/drivers/media/video/tiler/tmm.h b/drivers/media/video/tiler/tmm.h
new file mode 100644
index 0000000..fbdc1e2
--- /dev/null
+++ b/drivers/media/video/tiler/tmm.h
@@ -0,0 +1,109 @@
+/*
+ * tmm.h
+ *
+ * TMM interface definition for TI TILER driver.
+ *
+ * Author: Lajos Molnar <molnar@ti.com>
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#ifndef TMM_H
+#define TMM_H
+
+#include <mach/dmm.h>
+/**
+ * TMM interface
+ */
+struct tmm {
+	void *pvt;
+
+	/* function table */
+	u32 *(*get)	(struct tmm *tmm, u32 num_pages);
+	void (*free)	(struct tmm *tmm, u32 *pages);
+	s32  (*map)	(struct tmm *tmm, struct pat_area area, u32 page_pa);
+	void (*clear)	(struct tmm *tmm, struct pat_area area);
+	void (*deinit)	(struct tmm *tmm);
+};
+
+/**
+ * Request a set of pages from the DMM free page stack.
+ * @return a pointer to a list of physical page addresses.
+ */
+static inline
+u32 *tmm_get(struct tmm *tmm, u32 num_pages)
+{
+	if (tmm && tmm->pvt)
+		return tmm->get(tmm, num_pages);
+	return NULL;
+}
+
+/**
+ * Return a set of used pages to the DMM free page stack.
+ * @param list a pointer to a list of physical page addresses.
+ */
+static inline
+void tmm_free(struct tmm *tmm, u32 *pages)
+{
+	if (tmm && tmm->pvt)
+		tmm->free(tmm, pages);
+}
+
+/**
+ * Program the physical address translator.
+ * @param area PAT area
+ * @param list of pages
+ */
+static inline
+s32 tmm_map(struct tmm *tmm, struct pat_area area, u32 page_pa)
+{
+	if (tmm && tmm->map && tmm->pvt)
+		return tmm->map(tmm, area, page_pa);
+	return -ENODEV;
+}
+
+/**
+ * Clears the physical address translator.
+ * @param area PAT area
+ */
+static inline
+void tmm_clear(struct tmm *tmm, struct pat_area area)
+{
+	if (tmm && tmm->clear && tmm->pvt)
+		tmm->clear(tmm, area);
+}
+
+/**
+ * Checks whether tiler memory manager supports mapping
+ */
+static inline
+bool tmm_can_map(struct tmm *tmm)
+{
+	return tmm && tmm->map;
+}
+
+/**
+ * Deinitialize tiler memory manager
+ */
+static inline
+void tmm_deinit(struct tmm *tmm)
+{
+	if (tmm && tmm->pvt)
+		tmm->deinit(tmm);
+}
+
+/**
+ * TMM implementation for PAT support.
+ *
+ * Initialize TMM for PAT with given id.
+ */
+struct tmm *tmm_pat_init(u32 pat_id);
+
+#endif
-- 
1.6.3.3


^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [RFC 5/8] TILER-DMM: TILER interface file and documentation
  2010-07-23 23:22       ` [RFC 4/8] TILER-DMM: TILER Memory Manager interface and implementation David Sin
@ 2010-07-23 23:22         ` David Sin
  2010-07-23 23:22           ` [RFC 6/8] TILER-DMM: Geometry and view manipulation functions David Sin
  2010-07-24  7:21           ` [RFC 5/8] TILER-DMM: TILER interface file and documentation Shilimkar, Santosh
  2010-07-24  8:01         ` [RFC 4/8] TILER-DMM: TILER Memory Manager interface and implementation Russell King - ARM Linux
  2010-07-28  5:53         ` Hiremath, Vaibhav
  2 siblings, 2 replies; 46+ messages in thread
From: David Sin @ 2010-07-23 23:22 UTC (permalink / raw)
  To: linux-arm-kernel, linux-omap, Tony Lindgren, Russell King
  Cc: Hari Kanigeri, Ohad Ben-Cohen, Vaibhav Hiremath,
	Santosh Shilimkar, Lajos Molnar, David Sin

From: Lajos Molnar <molnar@ti.com>

This patch contains the TILER interface file and the documentation.

Signed-off-by: Lajos Molnar <molnar@ti.com>
Signed-off-by: David Sin <davidsin@ti.com>
---
 Documentation/arm/TILER                  |  144 +++++++++++++++++++++
 arch/arm/mach-omap2/include/mach/tiler.h |  201 ++++++++++++++++++++++++++++++
 2 files changed, 345 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/arm/TILER
 create mode 100644 arch/arm/mach-omap2/include/mach/tiler.h

diff --git a/Documentation/arm/TILER b/Documentation/arm/TILER
new file mode 100644
index 0000000..9c54037
--- /dev/null
+++ b/Documentation/arm/TILER
@@ -0,0 +1,144 @@
+TILER driver
+
+TILER is a hardware block made by Texas Instruments.  Its purpose is to
+organize video/image memory in a 2-dimensional fashion to limit memory
+bandwidth and facilitate 0 effort rotation and mirroring.  The TILER driver
+facilitates allocating, freeing, as well as mapping 2D blocks (areas) in the
+TILER container(s).  It also facilitates rotating and mirroring the allocated
+blocks or its rectangular subsections.
+
+TERMINOLOGY
+
+"slot"
+
+The basic TILER driver operates on blocks of slots.  A slot is the granularity
+of the TILER hardware device.  For all current uses it is 4K, but could also be
+16 or 64K.  The DMM-TILER TRM refers to this as "page" but we want to separate
+this concept from the MMU pages.
+
+"page"
+
+The granularity of the MMU, used by the kernel.  This is 4K.
+
+"block"
+
+The TILER hardware block supports 1D and 2D blocks.  A 2D block is a rectangular
+arrangement of slots with arbitrary width and height in a 2D container.  A
+1D block is a linear arrangement of slots with arbitrary length in a 1D
+container.  This TILER driver only supports 2D blocks.
+
+"container"
+
+The TILER driver supports an arbitrary TILER container size.  However, for
+all current implementations it is 256 by 128 slots.  The container currently can
+only be used as a 2D container.
+
+"reserved area"
+
+Each block resides within a reserved area in the container.  This area may
+be larger than the actual set of slots that a block occupies.  The reason for
+this is to protect access from one block into another.  Since TILER container is
+mmap-ped into user space as individual pages, all slots that are spanned by
+that page become visible to the user.  The tiler driver allows restricting the
+granularity of the reserved area (default alignment) as well as the mapped
+area (granularity).
+
+KERNEL API to the TILER driver.
+
+1. Allocating and freeing a 1080p YUV422 block
+
+        struct tiler_block_t blk = {0};
+        int res;
+
+        blk.width = 1920;
+        blk.height = 1080;
+        res = tiler_alloc(&blk, TILFMT_16BIT, 0, 0);
+
+        tiler_free(&blk);
+
+2. Allocating and freeing a 1080p YUV420p block
+
+        struct tiler_block_t blk_Y = {0}, blk_UV = {0};
+        int res;
+
+        blk_Y.width = 1920;
+        blk_Y.height = 1080;
+        blk_UV.widht = 960;
+        blk_UV.height = 540;
+        res = tiler_alloc(&blk_Y, TILFMT_8BIT, 0, 0) ? :
+                tiler_alloc(&blk_UV, TILFMT_16BIT, PAGE_SIZE,
+                                blk_y->phys & ~PAGE_MASK);
+
+        tiler_free(&blk_Y);
+        tiler_free(&blk_UV);
+
+Note how we allocated the UV block at the same in-page offset as the Y buffer.
+This facilitates mmap-ping both Y and UV blocks into userspace as one
+contiguous buffer.
+
+3. Mmap-ing YUV420p block into user space
+
+        static int my_mmap(struct file *file, struct vm_area_struct *vma)
+        {
+                unsigned long size = (vma->vm_end - vma->vm_start);
+                unsigned long start = vma->vm_start;
+
+                if (size != tiler_size(&blk_Y) + tiler_size(&blk_UV))
+                        return -EINVAL;
+
+                return tiler_mmap_blk(&blk_Y, 0, tiler_size(&blk_Y), vma, 0) ?
+                        : tiler_mmap_blk(&blk_UV, 0, tiler_size(&blk_UV), vma,
+                                tiler_size(&blk_Y));
+        }
+
+4. Ioremap-ing YUV422 block into kernel space
+
+        void *my_ioremap(tiler_block_t *blk) {
+                struct vm_struct *area;
+                int res;
+
+                area = get_vm_area(tiler_size(&blk), VM_IOREMAP);
+                if (!area)
+                        return NULL;
+
+                int res = tiler_ioremap_blk(&blk, 0, tiler_size(&block),
+                                        (u32) area->addr, MT_DEVICE_WC);
+                if (res) {
+                        vunmap(area->addr);
+                        return NULL;
+                }
+                return area->addr;
+        }
+
+CONFIGURATIONS
+
+The TILER driver allows specifying a container manager (tcm) for each
+pixel format.  The same container manager can be specified for more than
+one pixel formats.
+
+Each container manager also operates on a PAT instance.  One can also
+specify a "virtual" PAT (with a linear preassigned memory space no actual
+PAT programming), but it is not implemented.
+
+PARAMETERS
+
+The TILER driver allows specifying:
+
+    granularity (tiler.grain, CONFIG_TILER_GRANULARITY):
+
+        Each block is mapped in width-chunks of granularity.
+
+    default alignment (tiler.align, CONFIG_TILER_ALIGNMENT):
+
+        Default alignment if aligment is not specified (0). Otherwise,
+        blocks are allocated at an address aligned to the value given plus an
+        offset within the alignment.
+
+    cache limit (tiler.cache, CONFIG_TILER_CACHE_LIMIT):
+
+        TILER driver keeps a cache of allocated pages to speed up allocation of
+        TILER blocks.  You can set a limit of how much memory the TILER driver
+        should keep if there are no actual TILER allocations.  This also means
+        that if there is less memory used than this limit, the pages of freed
+        tiler blocks will not actually be freed, but instead are put into this
+        cache.
diff --git a/arch/arm/mach-omap2/include/mach/tiler.h b/arch/arm/mach-omap2/include/mach/tiler.h
new file mode 100644
index 0000000..8509678
--- /dev/null
+++ b/arch/arm/mach-omap2/include/mach/tiler.h
@@ -0,0 +1,201 @@
+/*
+ * tiler.h
+ *
+ * TILER driver support functions for TI TILER hardware block.
+ *
+ * Authors: Lajos Molnar <molnar@ti.com>
+ *          David Sin <davidsin@ti.com>
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef TILER_H
+#define TILER_H
+
+#include <linux/mm.h>
+
+/*
+ * ----------------------------- API Definitions -----------------------------
+ */
+
+/* return true if physical address is in the tiler container */
+bool is_tiler_addr(u32 phys);
+
+enum tiler_fmt {
+	TILFMT_MIN     = -2,
+	TILFMT_INVALID = -2,
+	TILFMT_NONE    = -1,
+	TILFMT_8BIT    = 0,
+	TILFMT_16BIT   = 1,
+	TILFMT_32BIT   = 2,
+	TILFMT_MAX     = 2,
+	TILFMT_PAGE    = 3,	/* for completeness */
+};
+
+/* tiler block info */
+struct tiler_block_t {
+	u32 phys;		/* system space (L3) tiler addr */
+	u32 width;		/* width */
+	u32 height;		/* height */
+};
+
+/* tiler (image/video frame) view */
+struct tiler_view_t {
+	u32 tsptr;		/* tiler space addr */
+	u32 width;		/* width */
+	u32 height;		/* height */
+	u32 bpp;		/* bytes per pixel */
+	s32 h_inc;		/* horizontal increment */
+	s32 v_inc;		/* vertical increment */
+};
+
+/* get tiler format for a physical address */
+enum tiler_fmt tiler_fmt(u32 phys);
+
+/* get tiler block bytes-per-pixel */
+u32 tiler_bpp(const struct tiler_block_t *b);
+
+/* get tiler block physical stride */
+u32 tiler_pstride(const struct tiler_block_t *b);
+
+/* get tiler block virtual stride */
+static inline u32 tiler_vstride(const struct tiler_block_t *b)
+{
+	return PAGE_ALIGN((b->phys & ~PAGE_MASK) + tiler_bpp(b) * b->width);
+}
+
+/* returns the virtual size of the block (for mmap) */
+static inline u32 tiler_size(const struct tiler_block_t *b)
+{
+	return b->height * tiler_vstride(b);
+}
+
+/**
+ * Reserves a 2D TILER block area and memory.
+ *
+ * @param blk	pointer to tiler block data.  This must be set up ('phys' member
+ *		must be 0) with the tiler block information.
+ * @param fmt	TILER block format
+ * @param align	block alignment (default: normally PAGE_SIZE)
+ * @param offs	block offset
+ *
+ * @return error status
+ */
+s32 tiler_alloc(struct tiler_block_t *blk, enum tiler_fmt fmt, u32 align,
+		u32 offs);
+
+/**
+ * Mmaps a portion of a tiler block to a virtual address.  Use this method in
+ * your driver's mmap function to potentially combine multiple tiler blocks as
+ * one virtual buffer.
+ *
+ * @param blk		pointer to tiler block data
+ * @param offs		offset from where to map (must be page aligned)
+ * @param size		size of area to map (must be page aligned)
+ * @param vma		VMM memory area to map to
+ * @param voffs		offset (from vm_start) in the VMM memory area to start
+ *			mapping at
+ *
+ * @return error status
+ */
+s32 tiler_mmap_blk(struct tiler_block_t *blk, u32 offs, u32 size,
+				struct vm_area_struct *vma, u32 voffs);
+
+/**
+ * Ioremaps a portion of a tiler block.  Use this method in your driver instead
+ * of ioremap to potentially combine multiple tiler blocks as one virtual
+ * buffer.
+ *
+ * @param blk		pointer to tiler block data
+ * @param offs		offset from where to map (must be page aligned)
+ * @param size		size of area to map (must be page aligned)
+ * @param addr		virtual address
+ * @param mtype		ioremap memory type (e.g. MT_DEVICE)
+ *
+ * @return error status
+ */
+s32 tiler_ioremap_blk(struct tiler_block_t *blk, u32 offs, u32 size, u32 addr,
+							u32 mtype);
+
+/**
+ * Frees TILER memory.  Since there may be multiple references for the same area
+ * if duplicated by tiler_dup, the area is only actually freed if all references
+ * have been freed.
+ *
+ * @param blk	pointer to a tiler block data as filled by tiler_alloc,
+ *		tiler_map or tiler_dup.  'phys' member will be set to 0 on
+ *		success.
+ */
+void tiler_free(struct tiler_block_t *blk);
+
+/**
+ * Create a view based on a tiler address and width and height
+ *
+ * This method should only be used as a last resort, e.g. if tilview object
+ * cannot be passed because of incoherence with other view 2D objects that must
+ * be supported.
+ *
+ * @param view		Pointer to a view where the information will be stored
+ * @param ssptr		MUST BE a tiler address
+ * @param width		view width
+ * @param height	view height
+ */
+void tilview_create(struct tiler_view_t *view, u32 phys, u32 width, u32 height);
+
+/**
+ * Obtains the view information for a tiler block
+ *
+ * @param view		Pointer to a view where the information will be stored
+ * @param blk		Pointer to an existing allocated tiler block
+ */
+void tilview_get(struct tiler_view_t *view, struct tiler_block_t *blk);
+
+/**
+ * Crops a tiler view to a rectangular portion. Crop area must be fully within
+ * the orginal tiler view: 0 <= left <= left + width <= view->width, also:
+ * 0 <= top <= top + height <= view->height.
+ *
+ * @param view		Pointer to tiler view to be cropped
+ * @param left		x of top-left corner
+ * @param top		y of top-left corner
+ * @param width		crop width
+ * @param height	crop height
+ *
+ * @return error status.  The view will be reduced to the crop region if the
+ *	   crop region is correct.  Otherwise, no modifications are made.
+ */
+s32 tilview_crop(struct tiler_view_t *view, u32 left, u32 top, u32 width,
+								u32 height);
+
+/**
+ * Rotates a tiler view clockwise by a specified degree.
+ *
+ * @param view		Pointer to tiler view to be cropped
+ * @param rotate	Degree of rotation (clockwise).  Must be a multiple of
+ *			90.
+ * @return error status.  View is not modified on error; otherwise, it is
+ *	   updated in place.
+ */
+s32 tilview_rotate(struct tiler_view_t *view, s32 rotation);
+
+/**
+ * Mirrors a tiler view horizontally and/or vertically.
+ *
+ * @param view		Pointer to tiler view to be cropped
+ * @param flip_x	Mirror horizontally (left-to-right)
+ * @param flip_y	Mirror vertically (top-to-bottom)
+ *
+ * @return error status.  View is not modified on error; otherwise, it is
+ *	   updated in place.
+ */
+s32 tilview_flip(struct tiler_view_t *view, bool flip_x, bool flip_y);
+
+#endif
-- 
1.6.3.3


^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [RFC 6/8] TILER-DMM: Geometry and view manipulation functions.
  2010-07-23 23:22         ` [RFC 5/8] TILER-DMM: TILER interface file and documentation David Sin
@ 2010-07-23 23:22           ` David Sin
  2010-07-23 23:22             ` [RFC 7/8] TILER-DMM: Main TILER driver implementation David Sin
  2010-07-24  7:21           ` [RFC 5/8] TILER-DMM: TILER interface file and documentation Shilimkar, Santosh
  1 sibling, 1 reply; 46+ messages in thread
From: David Sin @ 2010-07-23 23:22 UTC (permalink / raw)
  To: linux-arm-kernel, linux-omap, Tony Lindgren, Russell King
  Cc: Hari Kanigeri, Ohad Ben-Cohen, Vaibhav Hiremath,
	Santosh Shilimkar, Lajos Molnar, David Sin

From: Lajos Molnar <molnar@ti.com>

This patch contains information on TILER geometry, as well as
tiler_view_t object manipulation functions.

It also contains an internal TILER header file to share geometric
information with other TILER files.

Signed-off-by: Lajos Molnar <molnar@ti.com>
Signed-off-by: David Sin <davidsin@ti.com>
---
 drivers/media/video/tiler/_tiler.h     |   51 +++++
 drivers/media/video/tiler/tiler-geom.c |  360 ++++++++++++++++++++++++++++++++
 2 files changed, 411 insertions(+), 0 deletions(-)
 create mode 100644 drivers/media/video/tiler/_tiler.h
 create mode 100644 drivers/media/video/tiler/tiler-geom.c

diff --git a/drivers/media/video/tiler/_tiler.h b/drivers/media/video/tiler/_tiler.h
new file mode 100644
index 0000000..38fff3b
--- /dev/null
+++ b/drivers/media/video/tiler/_tiler.h
@@ -0,0 +1,51 @@
+/*
+ * _tiler.h
+ *
+ * TI TILER driver internal shared definitions.
+ *
+ * Author: Lajos Molnar <molnar@ti.com>
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef _TILER_H
+#define _TILER_H
+
+#include <linux/kernel.h>
+#include <mach/tiler.h>
+#include "tcm.h"
+
+#define TILER_FORMATS		(TILFMT_MAX - TILFMT_MIN + 1)
+
+/* tiler geometry information */
+struct tiler_geom {
+	u32 x_shft;	/* unused X-bits (as part of bpp) */
+	u32 y_shft;	/* unused Y-bits (as part of bpp) */
+	u32 bpp;	/* bytes per pixel */
+	u32 slot_w;	/* width of each slot (in pixels) */
+	u32 slot_h;	/* height of each slot (in pixels) */
+};
+
+/* methods and variables shared between source files */
+struct tiler_ops {
+	/* geometry operations */
+	void (*xy) (u32 ssptr, u32 *x, u32 *y);
+	u32 (*addr) (enum tiler_fmt fmt, u32 x, u32 y);
+	const struct tiler_geom * (*geom) (enum tiler_fmt fmt);
+
+	u32 page;		/* page size */
+	u32 width;		/* container width */
+	u32 height;		/* container height */
+};
+
+void tiler_geom_init(struct tiler_ops *tiler);
+
+#endif
diff --git a/drivers/media/video/tiler/tiler-geom.c b/drivers/media/video/tiler/tiler-geom.c
new file mode 100644
index 0000000..619413f
--- /dev/null
+++ b/drivers/media/video/tiler/tiler-geom.c
@@ -0,0 +1,360 @@
+/*
+ * tiler-geom.c
+ *
+ * TILER geometry functions for TI TILER hardware block.
+ *
+ * Author: Lajos Molnar <molnar@ti.com>
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <linux/module.h>
+#include "_tiler.h"
+
+/* bits representing the same slot in DMM-TILER hw-block */
+#define SLOT_WIDTH_BITS		6
+#define SLOT_HEIGHT_BITS	6
+
+/* bits reserved to describe coordinates in DMM-TILER hw-block */
+#define CONT_WIDTH_BITS		14
+#define CONT_HEIGHT_BITS	13
+
+static struct tiler_geom geom[TILER_FORMATS] = {
+	{
+		.x_shft = 0,
+		.y_shft = 0,
+	},
+	{
+		.x_shft = 0,
+		.y_shft = 1,
+	},
+	{
+		.x_shft = 1,
+		.y_shft = 1,
+	},
+};
+
+/* tiler space addressing bitfields */
+#define MASK_XY_FLIP		(1 << 31)
+#define MASK_Y_INVERT		(1 << 30)
+#define MASK_X_INVERT		(1 << 29)
+#define SHIFT_ACC_MODE		27
+#define MASK_ACC_MODE		3
+
+/* calculated constants */
+#define TILER_PAGE		(1 << (SLOT_WIDTH_BITS + SLOT_HEIGHT_BITS))
+#define TILER_WIDTH		(1 << (CONT_WIDTH_BITS - SLOT_WIDTH_BITS))
+#define TILER_HEIGHT		(1 << (CONT_HEIGHT_BITS - SLOT_HEIGHT_BITS))
+
+#define VIEW_SIZE		(1u << (CONT_WIDTH_BITS + CONT_HEIGHT_BITS))
+#define VIEW_MASK		(VIEW_SIZE - 1u)
+
+#define MASK(bits) ((1 << (bits)) - 1)
+
+#define TILER_FMT(x)	((enum tiler_fmt) \
+		((x >> SHIFT_ACC_MODE) & MASK_ACC_MODE))
+
+#define MASK_VIEW		(MASK_X_INVERT | MASK_Y_INVERT | MASK_XY_FLIP)
+
+/* location of the various tiler views in physical address space */
+#define TILVIEW_8BIT	0x60000000u
+#define TILVIEW_16BIT	(TILVIEW_8BIT  + VIEW_SIZE)
+#define TILVIEW_32BIT	(TILVIEW_16BIT + VIEW_SIZE)
+#define TILVIEW_PAGE	(TILVIEW_32BIT + VIEW_SIZE)
+#define TILVIEW_END	(TILVIEW_PAGE  + VIEW_SIZE)
+
+/* create tsptr by adding view orientation and access mode */
+#define TIL_ADDR(x, orient, a)\
+	((u32) (x) | (orient) | ((a) << SHIFT_ACC_MODE))
+
+bool is_tiler_addr(u32 phys)
+{
+	return phys >= TILVIEW_8BIT && phys < TILVIEW_END;
+}
+EXPORT_SYMBOL(is_tiler_addr);
+
+u32 tiler_bpp(const struct tiler_block_t *b)
+{
+	enum tiler_fmt fmt = tiler_fmt(b->phys);
+	BUG_ON(fmt == TILFMT_INVALID || fmt == TILFMT_PAGE);
+
+	return geom[fmt].bpp;
+}
+EXPORT_SYMBOL(tiler_bpp);
+
+/* return the stride of a tiler-block in tiler space */
+static inline s32 tiler_stride(u32 tsptr)
+{
+	enum tiler_fmt fmt = TILER_FMT(tsptr);
+
+	if (fmt == TILFMT_PAGE)
+		return 0;
+	else if (tsptr & MASK_XY_FLIP)
+		return 1 << (CONT_HEIGHT_BITS + geom[fmt].x_shft);
+	else
+		return 1 << (CONT_WIDTH_BITS + geom[fmt].y_shft);
+}
+
+u32 tiler_pstride(const struct tiler_block_t *b)
+{
+	enum tiler_fmt fmt = tiler_fmt(b->phys);
+	BUG_ON(fmt == TILFMT_INVALID);
+
+	/* return the virtual stride for page mode */
+	if (fmt == TILFMT_PAGE)
+		return tiler_vstride(b);
+
+	return tiler_stride(b->phys & ~MASK_VIEW);
+}
+EXPORT_SYMBOL(tiler_pstride);
+
+enum tiler_fmt tiler_fmt(u32 phys)
+{
+	if (!is_tiler_addr(phys))
+		return TILFMT_INVALID;
+
+	return TILER_FMT(phys);
+}
+EXPORT_SYMBOL(tiler_fmt);
+
+/* returns the tiler geometry information for a format */
+static const struct tiler_geom *get_geom(enum tiler_fmt fmt)
+{
+	if (fmt >= TILFMT_MIN && fmt <= TILFMT_MAX)
+		return geom + fmt;
+	return NULL;
+}
+
+/**
+ * Returns the natural x and y coordinates for a pixel in tiler space address.
+ * That is, the coordinates for the same pixel in the natural (non-rotated,
+ * non-mirrored) view. This allows to uniquely identify a tiler pixel in any
+ * view orientation.
+ */
+static void tiler_get_natural_xy(u32 tsptr, u32 *x, u32 *y)
+{
+	u32 x_bits, y_bits, offset;
+	enum tiler_fmt fmt;
+
+	fmt = TILER_FMT(tsptr);
+
+	x_bits = CONT_WIDTH_BITS - geom[fmt].x_shft;
+	y_bits = CONT_HEIGHT_BITS - geom[fmt].y_shft;
+	offset = (tsptr & VIEW_MASK) >> (geom[fmt].x_shft + geom[fmt].y_shft);
+
+	/* separate coordinate bitfields based on view orientation */
+	if (tsptr & MASK_XY_FLIP) {
+		*x = offset >> y_bits;
+		*y = offset & MASK(y_bits);
+	} else {
+		*x = offset & MASK(x_bits);
+		*y = offset >> x_bits;
+	}
+
+	/* account for mirroring */
+	if (tsptr & MASK_X_INVERT)
+		*x ^= MASK(x_bits);
+	if (tsptr & MASK_Y_INVERT)
+		*y ^= MASK(y_bits);
+}
+
+/* calculate the tiler space address of a pixel in a view orientation */
+static u32 tiler_get_address(u32 orient, enum tiler_fmt fmt, u32 x, u32 y)
+{
+	u32 x_bits, y_bits, tmp, x_mask, y_mask, alignment;
+
+	x_bits = CONT_WIDTH_BITS - geom[fmt].x_shft;
+	y_bits = CONT_HEIGHT_BITS - geom[fmt].y_shft;
+	alignment = geom[fmt].x_shft + geom[fmt].y_shft;
+
+	/* validate coordinate */
+	x_mask = MASK(x_bits);
+	y_mask = MASK(y_bits);
+	if (x < 0 || x > x_mask || y < 0 || y > y_mask)
+		return 0;
+
+	/* account for mirroring */
+	if (orient & MASK_X_INVERT)
+		x ^= x_mask;
+	if (orient & MASK_Y_INVERT)
+		y ^= y_mask;
+
+	/* get coordinate address */
+	if (orient & MASK_XY_FLIP)
+		tmp = ((x << y_bits) + y);
+	else
+		tmp = ((y << x_bits) + x);
+
+	return TIL_ADDR((tmp << alignment), orient, fmt);
+}
+
+void tilview_create(struct tiler_view_t *view, u32 phys, u32 width, u32 height)
+{
+	BUG_ON(!is_tiler_addr(phys));
+
+	view->tsptr = phys & ~MASK_VIEW;
+	view->bpp = geom[TILER_FMT(phys)].bpp;
+	view->width = width;
+	view->height = height;
+	view->h_inc = view->bpp;
+	view->v_inc = tiler_stride(view->tsptr);
+}
+EXPORT_SYMBOL(tilview_create);
+
+void tilview_get(struct tiler_view_t *view, struct tiler_block_t *blk)
+{
+	view->tsptr = blk->phys & ~MASK_VIEW;
+	view->bpp = tiler_bpp(blk);
+	view->width = blk->width;
+	view->height = blk->height;
+	view->h_inc = view->bpp;
+	view->v_inc = tiler_stride(view->tsptr);
+}
+EXPORT_SYMBOL(tilview_get);
+
+s32 tilview_crop(struct tiler_view_t *view, u32 left, u32 top, u32 width,
+								u32 height)
+{
+	/* check for valid crop */
+	if (left + width < left || left + width > view->width ||
+	    top + height < top || top + height > view->height)
+		return -EINVAL;
+
+	view->tsptr += left * view->h_inc + top * view->v_inc;
+	view->width = width;
+	view->height = height;
+	return 0;
+}
+EXPORT_SYMBOL(tilview_crop);
+
+/* calculate tilerspace address and stride after view orientation change */
+static void reorient(struct tiler_view_t *view, u32 orient)
+{
+	u32 x, y;
+
+	tiler_get_natural_xy(view->tsptr, &x, &y);
+	view->tsptr = tiler_get_address(orient,
+					TILER_FMT(view->tsptr), x, y);
+	view->v_inc = tiler_stride(view->tsptr);
+}
+
+s32 tilview_rotate(struct tiler_view_t *view, s32 rotation)
+{
+	u32 orient;
+
+	if (rotation % 90)
+		return -EINVAL;
+
+	/* normalize rotation to quarters */
+	rotation = (rotation / 90) & 3;
+	if (!rotation)
+		return 0; /* nothing to do */
+
+	/* PAGE mode view cannot be rotated */
+	if (TILER_FMT(view->tsptr) == TILFMT_PAGE)
+		return -EPERM;
+
+	/*
+	 * first adjust top-left corner. NOTE: it rotates counter-clockwise:
+	 * 0 < 3
+	 * v   ^
+	 * 1 > 2
+	 */
+	if (rotation < 3)
+		view->tsptr += (view->height - 1) * view->v_inc;
+	if (rotation > 1)
+		view->tsptr += (view->width - 1) * view->h_inc;
+
+	/* then rotate view itself */
+	orient = view->tsptr & MASK_VIEW;
+
+	/* rotate first 2 quarters */
+	if (rotation & 2) {
+		orient ^= MASK_X_INVERT;
+		orient ^= MASK_Y_INVERT;
+	}
+
+	/* rotate last quarter */
+	if (rotation & 1) {
+		orient ^= (orient & MASK_XY_FLIP) ?
+			MASK_X_INVERT : MASK_Y_INVERT;
+
+		/* swap x & y */
+		orient ^= MASK_XY_FLIP;
+		swap(view->height, view->width);
+	}
+
+	/* finally reorient view */
+	reorient(view, orient);
+	return 0;
+}
+EXPORT_SYMBOL(tilview_rotate);
+
+s32 tilview_flip(struct tiler_view_t *view, bool flip_x, bool flip_y)
+{
+	u32 orient;
+	orient = view->tsptr & MASK_VIEW;
+
+	if (!flip_x && !flip_y)
+		return 0; /* nothing to do */
+
+	/* PAGE mode view cannot be flipped */
+	if (TILER_FMT(view->tsptr) == TILFMT_PAGE)
+		return -EPERM;
+
+	/* adjust top-left corner */
+	if (flip_x) {
+		orient ^= MASK_X_INVERT;
+		view->tsptr += (view->width - 1) * view->h_inc;
+	}
+	if (flip_y) {
+		orient ^= MASK_Y_INVERT;
+		view->tsptr += (view->height - 1) * view->v_inc;
+	}
+
+	/* finally reorient view */
+	reorient(view, orient);
+	return 0;
+}
+EXPORT_SYMBOL(tilview_flip);
+
+/* return the alias address for a coordinate */
+static inline u32 alias_address(enum tiler_fmt fmt, u32 x, u32 y)
+{
+	return tiler_get_address(0, fmt, x, y) + TILVIEW_8BIT;
+}
+
+/* get the coordinates for an alias address */
+static inline void alias_xy(u32 ssptr, u32 *x, u32 *y)
+{
+	tiler_get_natural_xy(ssptr & ~MASK_VIEW, x, y);
+}
+
+/* initialize shared geometric data */
+void tiler_geom_init(struct tiler_ops *tiler)
+{
+	struct tiler_geom *g;
+
+	tiler->xy = alias_xy;
+	tiler->addr = alias_address;
+	tiler->geom = get_geom;
+
+	tiler->page   = TILER_PAGE;
+	tiler->width  = TILER_WIDTH;
+	tiler->height = TILER_HEIGHT;
+
+	/* calculate geometry */
+	for (g = geom; g < geom + TILER_FORMATS; g++) {
+		g->bpp = 1 << (g->x_shft + g->y_shft);
+		g->slot_w = 1 << (SLOT_WIDTH_BITS - g->x_shft);
+		g->slot_h = 1 << (SLOT_HEIGHT_BITS - g->y_shft);
+	}
+}
-- 
1.6.3.3


^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [RFC 7/8] TILER-DMM: Main TILER driver implementation.
  2010-07-23 23:22           ` [RFC 6/8] TILER-DMM: Geometry and view manipulation functions David Sin
@ 2010-07-23 23:22             ` David Sin
  2010-07-23 23:22               ` [RFC 8/8] TILER-DMM: Linking TILER driver into the Linux kernel build David Sin
                                 ` (2 more replies)
  0 siblings, 3 replies; 46+ messages in thread
From: David Sin @ 2010-07-23 23:22 UTC (permalink / raw)
  To: linux-arm-kernel, linux-omap, Tony Lindgren, Russell King
  Cc: Hari Kanigeri, Ohad Ben-Cohen, Vaibhav Hiremath,
	Santosh Shilimkar, Lajos Molnar, David Sin

From: Lajos Molnar <molnar@ti.com>

This patch contains the TILER driver and implementation of the TILER
block manipulation and mapping functions.

It also contains the makefile and config file for the TILER driver.

Signed-off-by: Lajos Molnar <molnar@ti.com>
Signed-off-by: David Sin <davidsin@ti.com>
---
 drivers/media/video/tiler/Kconfig       |   65 +++++
 drivers/media/video/tiler/Makefile      |    7 +
 drivers/media/video/tiler/tiler-iface.c |  106 ++++++++
 drivers/media/video/tiler/tiler-main.c  |  426 +++++++++++++++++++++++++++++++
 4 files changed, 604 insertions(+), 0 deletions(-)
 create mode 100644 drivers/media/video/tiler/Kconfig
 create mode 100644 drivers/media/video/tiler/Makefile
 create mode 100644 drivers/media/video/tiler/tiler-iface.c
 create mode 100644 drivers/media/video/tiler/tiler-main.c

diff --git a/drivers/media/video/tiler/Kconfig b/drivers/media/video/tiler/Kconfig
new file mode 100644
index 0000000..2c61471
--- /dev/null
+++ b/drivers/media/video/tiler/Kconfig
@@ -0,0 +1,65 @@
+config HAVE_TI_TILER
+        bool
+        default y
+        depends on ARCH_OMAP4
+
+menuconfig TI_TILER
+        tristate "TI TILER support"
+        default y
+        depends on HAVE_TI_TILER
+        help
+           TILER and TILER-DMM driver for TI chips.  The TI TILER device
+           enables video rotation on certain TI chips such as OMAP4 or
+           Netra.  Video rotation will be limited without TILER support.
+
+config TILER_GRANULARITY
+        int "Allocation granularity (2^n)"
+        range 1 4096
+        default 128
+        depends on TI_TILER
+        help
+           This option sets the default TILER allocation granularity.  It can
+           be overriden by the tiler.grain boot argument.
+
+           The allocation granularity is the smallest TILER block size (in
+           bytes) managed distinctly by the TILER driver.  TILER blocks of any
+           size are managed in chunks of at least this size.
+
+           Must be a 2^n in the range of 1 to 4096; however, the TILER driver
+           may use a larger supported granularity.
+
+           Supported values are: 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024,
+           2048, 4096.
+
+config TILER_ALIGNMENT
+        int "Allocation alignment (2^n)"
+        range 1 4096
+        default 4096
+        depends on TI_TILER
+        help
+           This option sets the default TILER allocation alignment.  It can
+           be overriden by the tiler.align boot argument.
+
+           Must be a 2^n in the range of 1 to 4096; however, it is naturally
+           aligned to the TILER granularity.
+
+           Supported values are: 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024,
+           2048, 4096.
+
+config TILER_CACHE_LIMIT
+        int "Memory limit to cache free pages in MBytes"
+        range 0 128
+        default 40
+        depends on TI_TILER
+        help
+           This option sets the minimum memory that TILER retains even if
+           there is less TILER allocated memory is use.  The unused memory is
+           instead stored in a cache to speed up allocation and freeing of
+           physical pages.
+
+           This option can be overriden by the tiler.cache boot argument.
+
+           While initially TILER will use less memory than this limit (0), it
+           will not release any memory used until it reaches this limit.
+           Thereafter, TILER will release any unused memory immediately as
+           long as there it is above this threshold.
diff --git a/drivers/media/video/tiler/Makefile b/drivers/media/video/tiler/Makefile
new file mode 100644
index 0000000..4a6495e
--- /dev/null
+++ b/drivers/media/video/tiler/Makefile
@@ -0,0 +1,7 @@
+obj-$(CONFIG_TI_TILER) += tcm/
+
+obj-$(CONFIG_TI_TILER) += tiler.o
+tiler-objs = tiler-geom.o tiler-main.o tiler-iface.o tmm-pat.o
+
+obj-$(CONFIG_TI_TILER) += tiler_dmm.o
+tiler_dmm-objs = dmm.o
diff --git a/drivers/media/video/tiler/tiler-iface.c b/drivers/media/video/tiler/tiler-iface.c
new file mode 100644
index 0000000..0b10fae
--- /dev/null
+++ b/drivers/media/video/tiler/tiler-iface.c
@@ -0,0 +1,106 @@
+/*
+ * tiler-iface.c
+ *
+ * TILER driver interace functions for TI TILER hardware block.
+ *
+ * Authors: Lajos Molnar <molnar@ti.com>
+ *          David Sin <davidsin@ti.com>
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>		/* kmalloc */
+#include <linux/mm.h>
+#include <linux/mm_types.h>
+#include <asm/mach/map.h>	/* for ioremap_page */
+
+#include "_tiler.h"
+
+/*
+ *  Memory-Map Kernel APIs
+ *  ==========================================================================
+ */
+
+s32 tiler_mmap_blk(struct tiler_block_t *blk, u32 offs, u32 size,
+				struct vm_area_struct *vma, u32 voffs)
+{
+	u32 v, p, len;
+
+	/* don't allow mremap */
+	vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED;
+
+	/* mapping must fit into vma */
+	BUG_ON(vma->vm_start > vma->vm_start + voffs ||
+		vma->vm_start + voffs > vma->vm_start + voffs + size ||
+		vma->vm_start + voffs + size > vma->vm_end);
+
+	/* mapping must fit into block */
+	BUG_ON(offs > offs + size || offs + size > tiler_size(blk));
+
+	v = tiler_vstride(blk);
+	p = tiler_pstride(blk);
+
+	/* remap block portion */
+	len = v - (offs % v);	/* initial area to map */
+	while (size) {
+		/* restrict to size still needs mapping */
+		if (len > size)
+			len = size;
+
+		vma->vm_pgoff = (blk->phys + offs) >> PAGE_SHIFT;
+		if (remap_pfn_range(vma, vma->vm_start + voffs, vma->vm_pgoff,
+				    len, vma->vm_page_prot))
+			return -EAGAIN;
+		voffs += len;
+		offs += len + p - v;
+		size -= len;
+		len = v;	/* subsequent area to map */
+	}
+	return 0;
+}
+EXPORT_SYMBOL(tiler_mmap_blk);
+
+s32 tiler_ioremap_blk(struct tiler_block_t *blk, u32 offs, u32 size,
+				u32 addr, u32 mtype)
+{
+	u32 v, p;
+	u32 len;		/* area to map */
+	const struct mem_type *type = get_mem_type(mtype);
+
+	/* mapping must fit into address space */
+	BUG_ON(addr > addr + size);
+
+	/* mapping must fit into block */
+	BUG_ON(offs > offs + size || offs + size > tiler_size(blk));
+
+	v = tiler_vstride(blk);
+	p = tiler_pstride(blk);
+
+	/* move offset and address to end */
+	offs += blk->phys + size;
+	addr += size;
+
+	len = v - (offs % v);	/* initial area to map */
+	while (size) {
+		while (len && size) {
+			if (ioremap_page(addr - size, offs - size, type))
+				return -EAGAIN;
+			len  -= PAGE_SIZE;
+			size -= PAGE_SIZE;
+		}
+
+		offs += p - v;
+		len = v;	/* subsequent area to map */
+	}
+	return 0;
+}
+EXPORT_SYMBOL(tiler_ioremap_blk);
diff --git a/drivers/media/video/tiler/tiler-main.c b/drivers/media/video/tiler/tiler-main.c
new file mode 100644
index 0000000..cbd84d1
--- /dev/null
+++ b/drivers/media/video/tiler/tiler-main.c
@@ -0,0 +1,426 @@
+/*
+ * tiler-main.c
+ *
+ * TILER driver main support functions for TI TILER hardware block.
+ *
+ * Authors: Lajos Molnar <molnar@ti.com>
+ *          David Sin <davidsin@ti.com>
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>	/* platform_device() */
+#include <linux/errno.h>
+#include <linux/mutex.h>
+#include <linux/dma-mapping.h>		/* dma_alloc_coherent */
+#include <linux/pagemap.h>		/* page_cache_release() */
+#include <linux/slab.h>
+
+#include <mach/dmm.h>
+#include "tmm.h"
+#include "_tiler.h"
+#include "tcm/tcm-sita.h"		/* TCM algorithm */
+
+static uint default_align = CONFIG_TILER_ALIGNMENT;
+static uint granularity = CONFIG_TILER_GRANULARITY;
+
+module_param_named(align, default_align, uint, 0444);
+MODULE_PARM_DESC(align, "Default block ssptr alignment");
+module_param_named(grain, granularity, uint, 0444);
+MODULE_PARM_DESC(grain, "Granularity (bytes)");
+
+struct platform_driver tiler_driver_ldm = {
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "tiler",
+	},
+	.probe = NULL,
+	.shutdown = NULL,
+	.remove = NULL,
+};
+
+static struct tiler_ops tiler;		/* shared methods and variables */
+
+static struct list_head blocks;		/* all tiler blocks */
+
+static struct mutex mtx;
+static struct tcm *tcm[TILER_FORMATS];
+static struct tmm *tmm[TILER_FORMATS];
+static u32 *dmac_va;
+static dma_addr_t dmac_pa;
+
+/* info for a block */
+struct mem_info {
+	struct list_head global;	/* global blocks */
+	struct tiler_block_t blk;	/* block info */
+	struct tcm_area area;
+	u32 *mem;			/* list of alloced phys addresses */
+};
+
+/*
+ *  TMM connectors
+ *  ==========================================================================
+ */
+/* wrapper around tmm_map */
+static s32 refill_pat(struct tmm *tmm, struct tcm_area *area, u32 *ptr)
+{
+	s32 res = 0;
+	struct pat_area p_area = {0};
+
+	p_area.x0 = area->p0.x;
+	p_area.y0 = area->p0.y;
+	p_area.x1 = area->p1.x;
+	p_area.y1 = area->p1.y;
+
+	memcpy(dmac_va, ptr, sizeof(*ptr) * tcm_sizeof(*area));
+
+	if (tmm_map(tmm, p_area, dmac_pa))
+		res = -EFAULT;
+
+	return res;
+}
+
+/* wrapper around tmm_clear */
+static void clear_pat(struct tmm *tmm, struct tcm_area *area)
+{
+	struct pat_area p_area = {0};
+
+	p_area.x0 = area->p0.x;
+	p_area.y0 = area->p0.y;
+	p_area.x1 = area->p1.x;
+	p_area.y1 = area->p1.y;
+
+	tmm_clear(tmm, p_area);
+}
+
+/*
+ *  Area handling methods
+ *  ==========================================================================
+ */
+
+/* verify input params and calculate tiler container params for a block */
+static s32 __analize_area(enum tiler_fmt fmt, u32 width, u32 height,
+			  u16 *x_area, u16 *y_area, u16 *align, u16 *offs)
+{
+	/* input: width, height is in pixels, *align, *offs in bytes */
+	/* output: x_area, y_area, *align in slots */
+
+	/* slot width, height, and row size */
+	u32 slot_row, min_align;
+	const struct tiler_geom *g;
+
+	/* width and height must be positive, format must be 2D */
+	if (!width || !height || fmt == TILFMT_PAGE)
+		return -EINVAL;
+
+	/* align must be 2 power */
+	if (*align & (*align - 1))
+		return -EINVAL;
+
+	/* format must be valid */
+	g = tiler.geom(fmt);
+	if (!g)
+		return -EINVAL;
+
+	/* get the # of bytes per row in 1 slot */
+	slot_row = g->slot_w * g->bpp;
+
+	/* minimum alignment is at least 1 slot.  Use default if needed */
+	min_align = max(slot_row, granularity);
+	*align = ALIGN(*align ? : default_align, min_align);
+
+	/* offset must be multiple of bpp */
+	if (*offs & (g->bpp - 1) || *offs >= *align)
+		return -EINVAL;
+
+	/* round down the offset to the nearest slot size, and increase width
+	   to allow space for having the correct offset */
+	width += (*offs & (min_align - 1)) / g->bpp;
+
+	/* expand width to block size */
+	width = ALIGN(width, min_align / g->bpp);
+
+	/* adjust to slots */
+	*x_area = DIV_ROUND_UP(width, g->slot_w);
+	*y_area = DIV_ROUND_UP(height, g->slot_h);
+	*align /= slot_row;
+
+	if (*x_area > tiler.width || *y_area > tiler.height)
+		return -ENOMEM;
+	return 0;
+}
+
+/* allocate a mem_info structure and reserves a 2d container area */
+static struct mem_info *get_2d_area(u16 w, u16 h, u16 align, struct tcm *tcm)
+{
+	struct mem_info *mi = NULL;
+
+	/* reserve a block struct */
+	mi = kmalloc(sizeof(*mi), GFP_KERNEL);
+	if (!mi)
+		return mi;
+	memset(mi, 0, sizeof(*mi));
+
+	/* reserve an area */
+	if (tcm_reserve_2d(tcm, w, h, align, &mi->area)) {
+		kfree(mi);
+		return NULL;
+	}
+
+	return mi;
+}
+
+/*
+ *  Block operations
+ *  ==========================================================================
+ */
+
+/* free a block */
+static s32 free_block(struct mem_info *mi)
+{
+	/* release memory */
+	if (mi->mem)
+		tmm_free(tmm[tiler_fmt(mi->blk.phys)], mi->mem);
+	clear_pat(tmm[tiler_fmt(mi->blk.phys)], &mi->area);
+
+	/* unreserve area */
+	tcm_free(&mi->area);
+
+	/* have mutex */
+
+	/* safe deletion as list may not have been assigned */
+	if (mi->global.next)
+		list_del(&mi->global);
+
+	kfree(mi);
+	return 0;
+}
+
+/* create an empty block with just an area and add it to the global list */
+static struct mem_info *get_area(enum tiler_fmt fmt, u32 width, u32 height,
+							u16 align, u16 offs)
+{
+	u16 x, y;
+	struct mem_info *mi = NULL;
+	const struct tiler_geom *g = tiler.geom(fmt);
+
+	/* calculate dimensions and alignment in slots */
+	if (__analize_area(fmt, width, height, &x, &y, &align, &offs))
+		return NULL;
+
+	mi = get_2d_area(x, y, align, tcm[fmt]);
+	if (!mi)
+		return NULL;
+
+	/* have mutex */
+	list_add(&mi->global, &blocks);
+
+	mi->blk.phys = tiler.addr(fmt,
+		mi->area.p0.x * g->slot_w, mi->area.p0.y * g->slot_h)
+		+ offs;
+	return mi;
+}
+
+/* allocate a new tiler block */
+static s32 alloc_block(enum tiler_fmt fmt, u32 width, u32 height,
+		u32 align, u32 offs, struct mem_info **info)
+{
+	struct mem_info *mi = NULL;
+
+	*info = NULL;
+
+	/* only support up to page alignment */
+	if (align > PAGE_SIZE || offs >= (align ? : default_align))
+		return -EINVAL;
+
+	mutex_lock(&mtx);
+
+	/* reserve area in tiler container */
+	mi = get_area(fmt, width, height, align, offs);
+	if (!mi)
+		goto nomem;
+
+	mi->blk.width = width;
+	mi->blk.height = height;
+
+	/* allocate and map if mapping is supported */
+	if (tmm_can_map(tmm[fmt])) {
+		mi->mem = tmm_get(tmm[fmt], tcm_sizeof(mi->area));
+		if (!mi->mem)
+			goto cleanup;
+
+		/* Ensure the data reaches to main memory before PAT refill */
+		wmb();
+
+		/* program PAT */
+		if (refill_pat(tmm[fmt], &mi->area, mi->mem))
+			goto cleanup;
+	}
+	*info = mi;
+	mutex_unlock(&mtx);
+	return 0;
+
+cleanup:
+	free_block(mi);
+nomem:
+	mutex_unlock(&mtx);
+	return -ENOMEM;
+}
+
+/*
+ *  Driver code
+ *  ==========================================================================
+ */
+
+/* driver initialization */
+static s32 __init tiler_init(void)
+{
+	s32 r = -1;
+	struct tcm *sita = NULL;
+	struct tmm *tmm_pat = NULL;
+
+	tiler_geom_init(&tiler);
+
+	/* check module parameters for correctness */
+	if (default_align > PAGE_SIZE ||
+	    default_align & (default_align - 1) ||
+	    granularity < 1 || granularity > PAGE_SIZE ||
+	    granularity & (granularity - 1))
+		return -EINVAL;
+
+	/*
+	 * Array of physical pages for PAT programming, which must be a 16-byte
+	 * aligned physical address.
+	 */
+	dmac_va = dma_alloc_coherent(NULL, tiler.width * tiler.height *
+					sizeof(*dmac_va), &dmac_pa, GFP_ATOMIC);
+	if (!dmac_va)
+		return -ENOMEM;
+
+	/* Allocate tiler container manager (we share 1 on OMAP4) */
+	sita = sita_init(tiler.width, tiler.height, NULL);
+
+	tcm[TILFMT_8BIT]  = sita;
+	tcm[TILFMT_16BIT] = sita;
+	tcm[TILFMT_32BIT] = sita;
+
+	/* Allocate tiler memory manager (must have 1 unique TMM per TCM ) */
+	tmm_pat = tmm_pat_init(0);
+	tmm[TILFMT_8BIT]  = tmm_pat;
+	tmm[TILFMT_16BIT] = tmm_pat;
+	tmm[TILFMT_32BIT] = tmm_pat;
+
+	if (!sita || !tmm_pat) {
+		r = -ENOMEM;
+		goto error;
+	}
+
+	r = platform_driver_register(&tiler_driver_ldm);
+
+	mutex_init(&mtx);
+	INIT_LIST_HEAD(&blocks);
+
+error:
+	if (r) {
+		tcm_deinit(sita);
+		tmm_deinit(tmm_pat);
+		dma_free_coherent(NULL, tiler.width * tiler.height *
+					sizeof(*dmac_va), dmac_va, dmac_pa);
+	}
+
+	return r;
+}
+
+/* driver cleanup */
+static void __exit tiler_exit(void)
+{
+	int i, j;
+	struct mem_info *mi, *mi_;
+
+	mutex_lock(&mtx);
+
+	/* free all blocks */
+	list_for_each_entry_safe(mi, mi_, &blocks, global)
+		free_block(mi);
+
+	/* all lists should have cleared */
+	BUG_ON(!list_empty(&blocks));
+
+	mutex_unlock(&mtx);
+
+	dma_free_coherent(NULL, tiler.width * tiler.height * sizeof(*dmac_va),
+							dmac_va, dmac_pa);
+
+	/* close containers only once */
+	for (i = TILFMT_MIN; i <= TILFMT_MAX; i++) {
+		/* remove identical containers (tmm is unique per tcm) */
+		for (j = i + 1; j <= TILFMT_MAX; j++)
+			if (tcm[i] == tcm[j]) {
+				tcm[j] = NULL;
+				tmm[j] = NULL;
+			}
+
+		tcm_deinit(tcm[i]);
+		tmm_deinit(tmm[i]);
+	}
+
+	mutex_destroy(&mtx);
+	platform_driver_unregister(&tiler_driver_ldm);
+}
+
+/*
+ *  Block Kernel APIs
+ *  ==========================================================================
+ */
+
+s32 tiler_alloc(struct tiler_block_t *blk, enum tiler_fmt fmt,
+		u32 align, u32 offs)
+{
+	struct mem_info *mi;
+	s32 res;
+
+	/* blk must be valid, and blk->phys must be 0 */
+	BUG_ON(!blk || blk->phys);
+
+	res = alloc_block(fmt, blk->width, blk->height, align, offs, &mi);
+	if (mi)
+		blk->phys = mi->blk.phys;
+	return res;
+}
+EXPORT_SYMBOL(tiler_alloc);
+
+void tiler_free(struct tiler_block_t *blk)
+{
+	struct mem_info *mi;
+
+	mutex_lock(&mtx);
+
+	/* find block */
+	list_for_each_entry(mi, &blocks, global) {
+		if (mi->blk.phys == blk->phys) {
+			free_block(mi);
+			break;
+		}
+	}
+
+	blk->phys = 0;
+
+	mutex_unlock(&mtx);
+}
+EXPORT_SYMBOL(tiler_free);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Lajos Molnar <molnar@ti.com>");
+MODULE_AUTHOR("David Sin <davidsin@ti.com>");
+module_init(tiler_init);
+module_exit(tiler_exit);
-- 
1.6.3.3


^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [RFC 8/8] TILER-DMM: Linking TILER driver into the Linux kernel build
  2010-07-23 23:22             ` [RFC 7/8] TILER-DMM: Main TILER driver implementation David Sin
@ 2010-07-23 23:22               ` David Sin
  2010-07-24  7:32               ` [RFC 7/8] TILER-DMM: Main TILER driver implementation Shilimkar, Santosh
  2010-07-24  7:55               ` Russell King - ARM Linux
  2 siblings, 0 replies; 46+ messages in thread
From: David Sin @ 2010-07-23 23:22 UTC (permalink / raw)
  To: linux-arm-kernel, linux-omap, Tony Lindgren, Russell King
  Cc: Hari Kanigeri, Ohad Ben-Cohen, Vaibhav Hiremath,
	Santosh Shilimkar, Lajos Molnar, David Sin

From: Lajos Molnar <molnar@ti.com>

This patch links the TILER driver into the Linux kernel build
and config system.

Signed-off-by: Lajos Molnar <molnar@ti.com>
Signed-off-by: David Sin <davidsin@ti.com>
---
 drivers/media/Kconfig  |    6 ++++++
 drivers/media/Makefile |    2 ++
 2 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
index a28541b..96ebc1d 100644
--- a/drivers/media/Kconfig
+++ b/drivers/media/Kconfig
@@ -98,6 +98,12 @@ config VIDEO_MEDIA
 
 comment "Multimedia drivers"
 
+#
+# TI TILER driver support
+#
+
+source "drivers/media/video/tiler/Kconfig"
+
 source "drivers/media/common/Kconfig"
 source "drivers/media/IR/Kconfig"
 
diff --git a/drivers/media/Makefile b/drivers/media/Makefile
index 499b081..922d71c 100644
--- a/drivers/media/Makefile
+++ b/drivers/media/Makefile
@@ -4,5 +4,7 @@
 
 obj-y += common/ IR/ video/
 
+obj-${CONFIG_TI_TILER} += video/tiler/
+
 obj-$(CONFIG_VIDEO_DEV) += radio/
 obj-$(CONFIG_DVB_CORE)  += dvb/
-- 
1.6.3.3


^ permalink raw reply related	[flat|nested] 46+ messages in thread

* RE: [RFC 1/8] TILER-DMM: DMM-PAT driver for TI TILER
  2010-07-23 23:22 ` [RFC 1/8] TILER-DMM: DMM-PAT driver for TI TILER David Sin
  2010-07-23 23:22   ` [RFC 2/8] TILER-DMM: Container manager interface and utility definitons David Sin
@ 2010-07-24  6:51   ` Shilimkar, Santosh
  2010-07-24  8:09   ` Russell King - ARM Linux
  2010-07-27 18:37   ` Hiremath, Vaibhav
  3 siblings, 0 replies; 46+ messages in thread
From: Shilimkar, Santosh @ 2010-07-24  6:51 UTC (permalink / raw)
  To: Sin, David, linux-arm-kernel@lists.arm.linux.org.uk,
	linux-omap@vger.kernel.org, Tony
  Cc: Kanigeri, Hari, Ohad Ben-Cohen, Hiremath, Vaibhav, Molnar, Lajos

[-- Attachment #1: Type: text/plain, Size: 11088 bytes --]

Good to see this driver on list.
Few comments.
> -----Original Message-----
> From: Sin, David
> Sent: Saturday, July 24, 2010 4:52 AM
> To: linux-arm-kernel@lists.arm.linux.org.uk; linux-omap@vger.kernel.org;
> Tony Lindgren; Russell King
> Cc: Kanigeri, Hari; Ohad Ben-Cohen; Hiremath, Vaibhav; Shilimkar, Santosh;
> Sin, David; Molnar, Lajos
> Subject: [RFC 1/8] TILER-DMM: DMM-PAT driver for TI TILER
> 
> This patch adds support for DMM-PAT initialization and programming.
> 
> Signed-off-by: David Sin <davidsin@ti.com>
> Signed-off-by: Lajos Molnar <molnar@ti.com>
> ---
>  arch/arm/mach-omap2/include/mach/dmm.h |  128 ++++++++++++++++++++
>  drivers/media/video/tiler/dmm.c        |  200
> ++++++++++++++++++++++++++++++++
>  2 files changed, 328 insertions(+), 0 deletions(-)
>  create mode 100644 arch/arm/mach-omap2/include/mach/dmm.h
>  create mode 100644 drivers/media/video/tiler/dmm.c
> 
> diff --git a/arch/arm/mach-omap2/include/mach/dmm.h b/arch/arm/mach-
> omap2/include/mach/dmm.h
> new file mode 100644
> index 0000000..68b798a
> --- /dev/null
> +++ b/arch/arm/mach-omap2/include/mach/dmm.h
> @@ -0,0 +1,128 @@
> +/*
> + * dmm.h
> + *
> + * DMM driver support functions for TI DMM-TILER hardware block.
> + *
> + * Author: David Sin <davidsin@ti.com>
> + *
> + * Copyright (C) 2009-2010 Texas Instruments, Inc.
> + *
> + * This package is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
> + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
> + */
> +
> +#ifndef DMM_H
> +#define DMM_H
> +
> +#define DMM_BASE 0x4E000000
> +#define DMM_SIZE 0x800
> +
> +#define DMM_REVISION          0x000
> +#define DMM_HWINFO            0x004
> +#define DMM_LISA_HWINFO       0x008
> +#define DMM_DMM_SYSCONFIG     0x010
> +#define DMM_LISA_LOCK         0x01C
> +#define DMM_LISA_MAP__0       0x040
> +#define DMM_LISA_MAP__1       0x044
> +#define DMM_TILER_HWINFO      0x208
> +#define DMM_TILER_OR__0       0x220
> +#define DMM_TILER_OR__1       0x224
> +#define DMM_PAT_HWINFO        0x408
> +#define DMM_PAT_GEOMETRY      0x40C
> +#define DMM_PAT_CONFIG        0x410
> +#define DMM_PAT_VIEW__0       0x420
> +#define DMM_PAT_VIEW__1       0x424
> +#define DMM_PAT_VIEW_MAP__0   0x440
> +#define DMM_PAT_VIEW_MAP_BASE 0x460
> +#define DMM_PAT_IRQ_EOI       0x478
> +#define DMM_PAT_IRQSTATUS_RAW 0x480
> +#define DMM_PAT_IRQSTATUS     0x490
> +#define DMM_PAT_IRQENABLE_SET 0x4A0
> +#define DMM_PAT_IRQENABLE_CLR 0x4B0
> +#define DMM_PAT_STATUS__0     0x4C0
> +#define DMM_PAT_STATUS__1     0x4C4
> +#define DMM_PAT_STATUS__2     0x4C8
> +#define DMM_PAT_STATUS__3     0x4CC
> +#define DMM_PAT_DESCR__0      0x500
> +#define DMM_PAT_AREA__0       0x504
> +#define DMM_PAT_CTRL__0       0x508
> +#define DMM_PAT_DATA__0       0x50C
> +#define DMM_PEG_HWINFO        0x608
> +#define DMM_PEG_PRIO          0x620
> +#define DMM_PEG_PRIO_PAT      0x640
We have above information auto generated. Find attached patch for the same

> +
> +/**
> + * PAT refill programming mode.
> + */
> +enum pat_mode {
> +	MANUAL,
> +	AUTO
> +};
> +
> +/**
> + * Area definition for DMM physical address translator.
> + */
> +struct pat_area {
> +	s32 x0:8;
Any particular reason of choosing s32 ? 
> +	s32 y0:8;
> +	s32 x1:8;
> +	s32 y1:8;
> +};
> +
> +/**
> + * DMM physical address translator control.
> + */
> +struct pat_ctrl {
> +	s32 start:4;
> +	s32 dir:4;
> +	s32 lut_id:8;
> +	s32 sync:12;
> +	s32 ini:4;
> +};
> +
> +/**
> + * PAT descriptor.
> + */
> +struct pat {
> +	struct pat *next;
> +	struct pat_area area;
> +	struct pat_ctrl ctrl;
> +	u32 data;
> +};
> +
> +/**
> + * DMM device data
> + */
> +struct dmm {
> +	void __iomem *base;
> +};
You may not want to have structure for a single field.
> +
> +/**
> + * Create and initialize the physical address translator.
> + * @param id    PAT id
> + * @return pointer to device data
> + */
> +struct dmm *dmm_pat_init(u32 id);
> +
> +/**
> + * Program the physical address translator.
> + * @param dmm   Device data
> + * @param desc  PAT descriptor
> + * @param mode  programming mode
> + * @return an error status.
> + */
> +s32 dmm_pat_refill(struct dmm *dmm, struct pat *desc, enum pat_mode
> mode);
Can't you use normal int here instead of s32 ?
> +
> +/**
> + * Clean up the physical address translator.
> + * @param dmm    Device data
> + * @return an error status.
> + */
> +void dmm_pat_release(struct dmm *dmm);
> +
> +#endif
> diff --git a/drivers/media/video/tiler/dmm.c
> b/drivers/media/video/tiler/dmm.c
> new file mode 100644
> index 0000000..e715936
> --- /dev/null
> +++ b/drivers/media/video/tiler/dmm.c
> @@ -0,0 +1,200 @@
> +/*
> + * dmm.c
> + *
> + * DMM driver support functions for TI OMAP processors.
> + *
> + * Authors: David Sin <davidsin@ti.com>
> + *          Lajos Molnar <molnar@ti.com>
> + *
> + * Copyright (C) 2009-2010 Texas Instruments, Inc.
> + *
> + * This package is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
> + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h> /* platform_device() */
The comment is useless because header does tell why it is needed
> +#include <linux/io.h>              /* ioremap() */
ditto
> +#include <linux/errno.h>
> +#include <linux/slab.h>
> +
> +#include <mach/dmm.h>
> +
> +#define MASK(msb, lsb) (((1 << ((msb) + 1 - (lsb))) - 1) << (lsb))
> +#define SET_FLD(reg, msb, lsb, val) \
> +(((reg) & ~MASK((msb), (lsb))) | (((val) << (lsb)) & MASK((msb), (lsb))))
> +
> +static struct platform_driver dmm_driver_ldm = {
> +	.driver = {
> +		.owner = THIS_MODULE,
> +		.name = "dmm",
> +	},
> +	.probe = NULL,
> +	.shutdown = NULL,
> +	.remove = NULL,
> +};
> +
> +s32 dmm_pat_refill(struct dmm *dmm, struct pat *pd, enum pat_mode mode)
> +{
> +	void __iomem *r;
> +	u32 v;
> +
> +	/* Only manual refill supported */
> +	if (mode != MANUAL)
> +		return -EFAULT;
> +
> +	/* Check that the DMM_PAT_STATUS register has not reported an error
> */
> +	r = dmm->base + DMM_PAT_STATUS__0;
> +	v = __raw_readl(r);
> +	if (WARN(v & 0xFC00, KERN_ERR "dmm_pat_refill() error.\n"))
> +		return -EIO;
> +
> +	/* Set "next" register to NULL */
> +	r = dmm->base + DMM_PAT_DESCR__0;
> +	v = __raw_readl(r);
> +	v = SET_FLD(v, 31, 4, (u32) NULL);
> +	__raw_writel(v, r);
> +
> +	/* Set area to be refilled */
> +	r = dmm->base + DMM_PAT_AREA__0;
> +	v = __raw_readl(r);
> +	v = SET_FLD(v, 30, 24, pd->area.y1);
> +	v = SET_FLD(v, 23, 16, pd->area.x1);
> +	v = SET_FLD(v, 14, 8, pd->area.y0);
> +	v = SET_FLD(v, 7, 0, pd->area.x0);
> +	__raw_writel(v, r);
> +	wmb();
> +
> +	/* First, clear the DMM_PAT_IRQSTATUS register */
> +	r = dmm->base + DMM_PAT_IRQSTATUS;
> +	__raw_writel(0xFFFFFFFF, r);
> +	wmb();
> +
> +	r = dmm->base + DMM_PAT_IRQSTATUS_RAW;
> +	while (__raw_readl(r) != 0)
> +		;
> +
> +	/* Fill data register */
> +	r = dmm->base + DMM_PAT_DATA__0;
> +	v = __raw_readl(r);
> +
> +	v = SET_FLD(v, 31, 4, pd->data >> 4);
> +	__raw_writel(v, r);
> +	wmb();
> +
> +	/* Read back PAT_DATA__0 to see if write was successful */
> +	while (__raw_readl(r) != pd->data)
> +		;
> +
> +	r = dmm->base + DMM_PAT_CTRL__0;
> +	v = __raw_readl(r);
> +	v = SET_FLD(v, 31, 28, pd->ctrl.ini);
> +	v = SET_FLD(v, 16, 16, pd->ctrl.sync);
> +	v = SET_FLD(v, 9, 8, pd->ctrl.lut_id);
> +	v = SET_FLD(v, 6, 4, pd->ctrl.dir);
> +	v = SET_FLD(v, 0, 0, pd->ctrl.start);
> +	__raw_writel(v, r);
> +	wmb();
> +
> +	/* Check if PAT_IRQSTATUS_RAW is set after the PAT has been refilled
> */
> +	r = dmm->base + DMM_PAT_IRQSTATUS_RAW;
> +	while ((__raw_readl(r) & 0x3) != 0x3)
> +		;
> +
> +	/* Again, clear the DMM_PAT_IRQSTATUS register */
> +	r = dmm->base + DMM_PAT_IRQSTATUS;
> +	__raw_writel(0xFFFFFFFF, r);
> +	wmb();
> +
> +	r = dmm->base + DMM_PAT_IRQSTATUS_RAW;
> +	while (__raw_readl(r) != 0)
> +		;
> +
> +	/* Again, set "next" register to NULL to clear any PAT STATUS errors
> */
> +	r = dmm->base + DMM_PAT_DESCR__0;
> +	v = __raw_readl(r);
> +	v = SET_FLD(v, 31, 4, (u32) NULL);
> +	__raw_writel(v, r);
> +
> +	/*
> +	 * Now, check that the DMM_PAT_STATUS register
> +	 * has not reported an error before exiting.
> +	*/
> +	r = dmm->base + DMM_PAT_STATUS__0;
> +	v = __raw_readl(r);
> +	if (WARN(v & 0xFC00, KERN_ERR "dmm_pat_refill() error.\n"))
> +		return -EIO;
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(dmm_pat_refill);
> +
> +struct dmm *dmm_pat_init(u32 id)
> +{
> +	u32 base;
> +	struct dmm *dmm;
> +	switch (id) {
> +	case 0:
> +		/* only support id 0 for now */
> +		base = DMM_BASE;
Instead of hard coding this way use "platform_get_resource" 
For better scalability
> +		break;
> +	default:
> +		return NULL;
> +	}
> +
> +	dmm = kzalloc(sizeof(*dmm), GFP_KERNEL);
> +	if (!dmm)
> +		return NULL;
> +
> +	dmm->base = ioremap(base, DMM_SIZE);
> +	if (!dmm->base) {
> +		kfree(dmm);
> +		return NULL;
> +	}
Generally these things are done in driver probe.  May be you
should move this code to probe, which you have made as NULL at 
this moment
> +
> +	__raw_writel(0x88888888, dmm->base + DMM_PAT_VIEW__0);
> +	__raw_writel(0x88888888, dmm->base + DMM_PAT_VIEW__1);
> +	__raw_writel(0x80808080, dmm->base + DMM_PAT_VIEW_MAP__0);
> +	__raw_writel(0x80000000, dmm->base + DMM_PAT_VIEW_MAP_BASE);
> +	__raw_writel(0x88888888, dmm->base + DMM_TILER_OR__0);
> +	__raw_writel(0x88888888, dmm->base + DMM_TILER_OR__1);
> +
> +	return dmm;
> +}
> +EXPORT_SYMBOL(dmm_pat_init);
> +
> +/**
> + * Clean up the physical address translator.
> + * @param dmm    Device data
> + * @return an error status.
> + */
> +void dmm_pat_release(struct dmm *dmm)
> +{
> +	if (dmm) {
> +		iounmap(dmm->base);
> +		kfree(dmm);
> +	}
> +}
> +EXPORT_SYMBOL(dmm_pat_release);
> +
> +static s32 __init dmm_init(void)
> +{
> +	return platform_driver_register(&dmm_driver_ldm);
> +}
> +
How about registering the driver using hwmod framework??
Very few changes are needed.
> +static void __exit dmm_exit(void)
> +{
> +	platform_driver_unregister(&dmm_driver_ldm);
> +}
> +
> +MODULE_LICENSE("GPL v2");
> +MODULE_AUTHOR("davidsin@ti.com");
> +MODULE_AUTHOR("molnar@ti.com");
> +module_init(dmm_init);
> +module_exit(dmm_exit);
> --
> 1.6.3.3


[-- Attachment #2: 0001-omap4-Add-DMM-and-EMIF-auto-generated-headers.patch --]
[-- Type: application/octet-stream, Size: 34186 bytes --]

From a931e4e28385549896c93aee14d245b2c0500344 Mon Sep 17 00:00:00 2001
From: Santosh Shilimkar <santosh.shilimkar@ti.com>
Date: Wed, 7 Jul 2010 16:28:03 +0530
Subject: [PATCH] omap4: Add DMM and EMIF auto-generated headers

This patch adds auto-generated header files for EMIF and
DMM IP blocks. The scripts is updated accordingly

Signed-off-by: Benoit Cousson <b-cousson@ti.com>
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
---
 arch/arm/mach-omap2/include/mach/dmm-44xx.h  |  363 ++++++++++++++++++
 arch/arm/mach-omap2/include/mach/emif-44xx.h |  518 ++++++++++++++++++++++++++
 2 files changed, 881 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-omap2/include/mach/dmm-44xx.h
 create mode 100644 arch/arm/mach-omap2/include/mach/emif-44xx.h

diff --git a/arch/arm/mach-omap2/include/mach/dmm-44xx.h b/arch/arm/mach-omap2/include/mach/dmm-44xx.h
new file mode 100644
index 0000000..c25dda5
--- /dev/null
+++ b/arch/arm/mach-omap2/include/mach/dmm-44xx.h
@@ -0,0 +1,363 @@
+/*
+ * OMAP44xx DMM_CORE registers and bitfields
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ *
+ * Benoit Cousson (b-cousson@ti.com)
+ * Santosh Shilimkar (santosh.shilimkar@ti.com)
+ *
+ * This file is automatically generated from the OMAP hardware databases.
+ * We respectfully ask that any modifications to this file be coordinated
+ * with the public linux-omap@vger.kernel.org mailing list and the
+ * authors above to ensure that the autogeneration scripts are kept
+ * up-to-date with the file contents.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP2_DMM_CORE_44XX_H
+#define __ARCH_ARM_MACH_OMAP2_DMM_CORE_44XX_H
+
+
+/* Base address */
+#define OMAP44XX_DMM__DMM		0x4e000000
+
+/* Registers offset */
+#define OMAP44XX_DMM_REVISION		0x0000
+#define OMAP44XX_DMM_HWINFO		0x0004
+#define OMAP44XX_DMM_LISA_HWINFO	0x0008
+#define OMAP44XX_DMM_SYSCONFIG		0x0010
+#define OMAP44XX_DMM_LISA_LOCK		0x001c
+#define OMAP44XX_DMM_LISA_MAP		0x0040
+#define OMAP44XX_DMM_TILER_HWINFO	0x0208
+#define OMAP44XX_DMM_TILER_OR		0x0220
+#define OMAP44XX_DMM_PAT_HWINFO		0x0408
+#define OMAP44XX_DMM_PAT_GEOMETRY	0x040c
+#define OMAP44XX_DMM_PAT_CONFIG		0x0410
+#define OMAP44XX_DMM_PAT_VIEW		0x0420
+#define OMAP44XX_DMM_PAT_VIEW_MAP	0x0440
+#define OMAP44XX_DMM_PAT_VIEW_MAP_BASE	0x0460
+#define OMAP44XX_DMM_PAT_IRQ_EOI	0x0478
+#define OMAP44XX_DMM_PAT_IRQSTATUS_RAW	0x0480
+#define OMAP44XX_DMM_PAT_IRQSTATUS	0x0490
+#define OMAP44XX_DMM_PAT_IRQENABLE_SET	0x04a0
+#define OMAP44XX_DMM_PAT_IRQENABLE_CLR	0x04b0
+#define OMAP44XX_DMM_PAT_STATUS		0x04c0
+#define OMAP44XX_DMM_PAT_DESCR		0x0500
+#define OMAP44XX_DMM_PAT_AREA		0x0504
+#define OMAP44XX_DMM_PAT_CTRL		0x0508
+#define OMAP44XX_DMM_PAT_DATA		0x050c
+#define OMAP44XX_DMM_PEG_HWINFO		0x0608
+#define OMAP44XX_DMM_PEG_PRIO		0x0620
+#define OMAP44XX_DMM_PEG_PRIO_PAT	0x0640
+
+/* Registers shifts and masks */
+
+/* DMM_REVISION */
+#define OMAP44XX_SCHEME_SHIFT		30
+#define OMAP44XX_SCHEME_MASK		(0x3 << 30)
+#define OMAP44XX_FUNC_SHIFT		16
+#define OMAP44XX_FUNC_MASK		(0xfff << 16)
+#define OMAP44XX_R_RTL_SHIFT		11
+#define OMAP44XX_R_RTL_MASK		(0x1f << 11)
+#define OMAP44XX_X_MAJOR_SHIFT		8
+#define OMAP44XX_X_MAJOR_MASK		(0x7 << 8)
+#define OMAP44XX_CUSTOM_SHIFT		6
+#define OMAP44XX_CUSTOM_MASK		(0x3 << 6)
+#define OMAP44XX_Y_MINOR_SHIFT		0
+#define OMAP44XX_Y_MINOR_MASK		(0x3f << 0)
+
+/* DMM_HWINFO */
+#define OMAP44XX_ROBIN_CNT_SHIFT	16
+#define OMAP44XX_ROBIN_CNT_MASK		(0xf << 16)
+#define OMAP44XX_ELLA_CNT_SHIFT		8
+#define OMAP44XX_ELLA_CNT_MASK		(0xf << 8)
+#define OMAP44XX_TILER_CNT_SHIFT	0
+#define OMAP44XX_TILER_CNT_MASK		(0xf << 0)
+
+/* DMM_LISA_HWINFO */
+#define OMAP44XX_SDRC_CNT_SHIFT		8
+#define OMAP44XX_SDRC_CNT_MASK		(0xf << 8)
+#define OMAP44XX_SECTION_CNT_SHIFT	0
+#define OMAP44XX_SECTION_CNT_MASK	(0x1f << 0)
+
+/* DMM_SYSCONFIG */
+#define OMAP44XX_IDLE_MODE_SHIFT	2
+#define OMAP44XX_IDLE_MODE_MASK		(0x3 << 2)
+
+/* DMM_LISA_LOCK */
+#define OMAP44XX_LOCK_SHIFT		0
+#define OMAP44XX_LOCK_MASK		(1 << 0)
+
+/* DMM_LISA_MAP */
+#define OMAP44XX_SYS_ADDR_SHIFT		24
+#define OMAP44XX_SYS_ADDR_MASK		(0xff << 24)
+#define OMAP44XX_SYS_SIZE_SHIFT		20
+#define OMAP44XX_SYS_SIZE_MASK		(0x7 << 20)
+#define OMAP44XX_SDRC_INTL_SHIFT	18
+#define OMAP44XX_SDRC_INTL_MASK		(0x3 << 18)
+#define OMAP44XX_SDRC_ADDRSPC_SHIFT	16
+#define OMAP44XX_SDRC_ADDRSPC_MASK	(0x3 << 16)
+#define OMAP44XX_SDRC_MAP_SHIFT		8
+#define OMAP44XX_SDRC_MAP_MASK		(0x3 << 8)
+#define OMAP44XX_SDRC_ADDR_SHIFT	0
+#define OMAP44XX_SDRC_ADDR_MASK		(0xff << 0)
+
+/* DMM_TILER_HWINFO */
+#define OMAP44XX_OR_CNT_SHIFT		0
+#define OMAP44XX_OR_CNT_MASK		(0x7f << 0)
+
+/* DMM_TILER_OR */
+#define OMAP44XX_W7_SHIFT		31
+#define OMAP44XX_W7_MASK		(1 << 31)
+#define OMAP44XX_OR7_SHIFT		28
+#define OMAP44XX_OR7_MASK		(0x7 << 28)
+#define OMAP44XX_W6_SHIFT		27
+#define OMAP44XX_W6_MASK		(1 << 27)
+#define OMAP44XX_OR6_SHIFT		24
+#define OMAP44XX_OR6_MASK		(0x7 << 24)
+#define OMAP44XX_W5_SHIFT		23
+#define OMAP44XX_W5_MASK		(1 << 23)
+#define OMAP44XX_OR5_SHIFT		20
+#define OMAP44XX_OR5_MASK		(0x7 << 20)
+#define OMAP44XX_W4_SHIFT		19
+#define OMAP44XX_W4_MASK		(1 << 19)
+#define OMAP44XX_OR4_SHIFT		16
+#define OMAP44XX_OR4_MASK		(0x7 << 16)
+#define OMAP44XX_W3_SHIFT		15
+#define OMAP44XX_W3_MASK		(1 << 15)
+#define OMAP44XX_OR3_SHIFT		12
+#define OMAP44XX_OR3_MASK		(0x7 << 12)
+#define OMAP44XX_W2_SHIFT		11
+#define OMAP44XX_W2_MASK		(1 << 11)
+#define OMAP44XX_OR2_SHIFT		8
+#define OMAP44XX_OR2_MASK		(0x7 << 8)
+#define OMAP44XX_W1_SHIFT		7
+#define OMAP44XX_W1_MASK		(1 << 7)
+#define OMAP44XX_OR1_SHIFT		4
+#define OMAP44XX_OR1_MASK		(0x7 << 4)
+#define OMAP44XX_W0_SHIFT		3
+#define OMAP44XX_W0_MASK		(1 << 3)
+#define OMAP44XX_OR0_SHIFT		0
+#define OMAP44XX_OR0_MASK		(0x7 << 0)
+
+/* DMM_PAT_HWINFO */
+#define OMAP44XX_ENGINE_CNT_SHIFT	24
+#define OMAP44XX_ENGINE_CNT_MASK	(0x1f << 24)
+#define OMAP44XX_LUT_CNT_SHIFT		16
+#define OMAP44XX_LUT_CNT_MASK		(0x1f << 16)
+#define OMAP44XX_VIEW_MAP_CNT_SHIFT	8
+#define OMAP44XX_VIEW_MAP_CNT_MASK	(0xf << 8)
+#define OMAP44XX_VIEW_CNT_SHIFT		0
+#define OMAP44XX_VIEW_CNT_MASK		(0x7f << 0)
+
+/* DMM_PAT_GEOMETRY */
+#define OMAP44XX_CONT_HGHT_SHIFT	24
+#define OMAP44XX_CONT_HGHT_MASK		(0x7 << 24)
+#define OMAP44XX_CONT_WDTH_SHIFT	16
+#define OMAP44XX_CONT_WDTH_MASK		(0xf << 16)
+#define OMAP44XX_ADDR_RANGE_SHIFT	8
+#define OMAP44XX_ADDR_RANGE_MASK	(0x3f << 8)
+#define OMAP44XX_PAGE_SZ_SHIFT		0
+#define OMAP44XX_PAGE_SZ_MASK		(0x1f << 0)
+
+/* DMM_PAT_CONFIG */
+#define OMAP44XX_MODE3_SHIFT		3
+#define OMAP44XX_MODE3_MASK		(1 << 3)
+#define OMAP44XX_MODE2_SHIFT		2
+#define OMAP44XX_MODE2_MASK		(1 << 2)
+#define OMAP44XX_MODE1_SHIFT		1
+#define OMAP44XX_MODE1_MASK		(1 << 1)
+#define OMAP44XX_MODE0_SHIFT		0
+#define OMAP44XX_MODE0_MASK		(1 << 0)
+
+/* DMM_PAT_VIEW */
+#define OMAP44XX_V7_SHIFT		28
+#define OMAP44XX_V7_MASK		(0x3 << 28)
+#define OMAP44XX_V6_SHIFT		24
+#define OMAP44XX_V6_MASK		(0x3 << 24)
+#define OMAP44XX_V5_SHIFT		20
+#define OMAP44XX_V5_MASK		(0x3 << 20)
+#define OMAP44XX_V4_SHIFT		16
+#define OMAP44XX_V4_MASK		(0x3 << 16)
+#define OMAP44XX_V3_SHIFT		12
+#define OMAP44XX_V3_MASK		(0x3 << 12)
+#define OMAP44XX_V2_SHIFT		8
+#define OMAP44XX_V2_MASK		(0x3 << 8)
+#define OMAP44XX_V1_SHIFT		4
+#define OMAP44XX_V1_MASK		(0x3 << 4)
+#define OMAP44XX_V0_SHIFT		0
+#define OMAP44XX_V0_MASK		(0x3 << 0)
+
+/* DMM_PAT_VIEW_MAP */
+#define OMAP44XX_ACCESS_PAGE_SHIFT	31
+#define OMAP44XX_ACCESS_PAGE_MASK	(1 << 31)
+#define OMAP44XX_CONT_PAGE_SHIFT	24
+#define OMAP44XX_CONT_PAGE_MASK		(0xf << 24)
+#define OMAP44XX_ACCESS_32_SHIFT	23
+#define OMAP44XX_ACCESS_32_MASK		(1 << 23)
+#define OMAP44XX_CONT_32_SHIFT		16
+#define OMAP44XX_CONT_32_MASK		(0xf << 16)
+#define OMAP44XX_ACCESS_16_SHIFT	15
+#define OMAP44XX_ACCESS_16_MASK		(1 << 15)
+#define OMAP44XX_CONT_16_SHIFT		8
+#define OMAP44XX_CONT_16_MASK		(0xf << 8)
+#define OMAP44XX_ACCESS_8_SHIFT		7
+#define OMAP44XX_ACCESS_8_MASK		(1 << 7)
+#define OMAP44XX_CONT_8_SHIFT		0
+#define OMAP44XX_CONT_8_MASK		(0xf << 0)
+
+/* DMM_PAT_VIEW_MAP_BASE */
+#define OMAP44XX_BASE_ADDR_SHIFT	31
+#define OMAP44XX_BASE_ADDR_MASK		(1 << 31)
+
+/* DMM_PAT_IRQ_EOI */
+#define OMAP44XX_EOI_SHIFT		0
+#define OMAP44XX_EOI_MASK		(1 << 0)
+
+/* DMM_PAT_IRQSTATUS_RAW */
+#define OMAP44XX_ERR_LUT_MISS3_SHIFT	31
+#define OMAP44XX_ERR_LUT_MISS3_MASK	(1 << 31)
+#define OMAP44XX_ERR_UPD_DATA3_SHIFT	30
+#define OMAP44XX_ERR_UPD_DATA3_MASK	(1 << 30)
+#define OMAP44XX_ERR_UPD_CTRL3_SHIFT	29
+#define OMAP44XX_ERR_UPD_CTRL3_MASK	(1 << 29)
+#define OMAP44XX_ERR_UPD_AREA3_SHIFT	28
+#define OMAP44XX_ERR_UPD_AREA3_MASK	(1 << 28)
+#define OMAP44XX_ERR_INV_DATA3_SHIFT	27
+#define OMAP44XX_ERR_INV_DATA3_MASK	(1 << 27)
+#define OMAP44XX_ERR_INV_DSC3_SHIFT	26
+#define OMAP44XX_ERR_INV_DSC3_MASK	(1 << 26)
+#define OMAP44XX_FILL_LST3_SHIFT	25
+#define OMAP44XX_FILL_LST3_MASK		(1 << 25)
+#define OMAP44XX_FILL_DSC3_SHIFT	24
+#define OMAP44XX_FILL_DSC3_MASK		(1 << 24)
+#define OMAP44XX_ERR_LUT_MISS2_SHIFT	23
+#define OMAP44XX_ERR_LUT_MISS2_MASK	(1 << 23)
+#define OMAP44XX_ERR_UPD_DATA2_SHIFT	22
+#define OMAP44XX_ERR_UPD_DATA2_MASK	(1 << 22)
+#define OMAP44XX_ERR_UPD_CTRL2_SHIFT	21
+#define OMAP44XX_ERR_UPD_CTRL2_MASK	(1 << 21)
+#define OMAP44XX_ERR_UPD_AREA2_SHIFT	20
+#define OMAP44XX_ERR_UPD_AREA2_MASK	(1 << 20)
+#define OMAP44XX_ERR_INV_DATA2_SHIFT	19
+#define OMAP44XX_ERR_INV_DATA2_MASK	(1 << 19)
+#define OMAP44XX_ERR_INV_DSC2_SHIFT	18
+#define OMAP44XX_ERR_INV_DSC2_MASK	(1 << 18)
+#define OMAP44XX_FILL_LST2_SHIFT	17
+#define OMAP44XX_FILL_LST2_MASK		(1 << 17)
+#define OMAP44XX_FILL_DSC2_SHIFT	16
+#define OMAP44XX_FILL_DSC2_MASK		(1 << 16)
+#define OMAP44XX_ERR_LUT_MISS1_SHIFT	15
+#define OMAP44XX_ERR_LUT_MISS1_MASK	(1 << 15)
+#define OMAP44XX_ERR_UPD_DATA1_SHIFT	14
+#define OMAP44XX_ERR_UPD_DATA1_MASK	(1 << 14)
+#define OMAP44XX_ERR_UPD_CTRL1_SHIFT	13
+#define OMAP44XX_ERR_UPD_CTRL1_MASK	(1 << 13)
+#define OMAP44XX_ERR_UPD_AREA1_SHIFT	12
+#define OMAP44XX_ERR_UPD_AREA1_MASK	(1 << 12)
+#define OMAP44XX_ERR_INV_DATA1_SHIFT	11
+#define OMAP44XX_ERR_INV_DATA1_MASK	(1 << 11)
+#define OMAP44XX_ERR_INV_DSC1_SHIFT	10
+#define OMAP44XX_ERR_INV_DSC1_MASK	(1 << 10)
+#define OMAP44XX_FILL_LST1_SHIFT	9
+#define OMAP44XX_FILL_LST1_MASK		(1 << 9)
+#define OMAP44XX_FILL_DSC1_SHIFT	8
+#define OMAP44XX_FILL_DSC1_MASK		(1 << 8)
+#define OMAP44XX_ERR_LUT_MISS0_SHIFT	7
+#define OMAP44XX_ERR_LUT_MISS0_MASK	(1 << 7)
+#define OMAP44XX_ERR_UPD_DATA0_SHIFT	6
+#define OMAP44XX_ERR_UPD_DATA0_MASK	(1 << 6)
+#define OMAP44XX_ERR_UPD_CTRL0_SHIFT	5
+#define OMAP44XX_ERR_UPD_CTRL0_MASK	(1 << 5)
+#define OMAP44XX_ERR_UPD_AREA0_SHIFT	4
+#define OMAP44XX_ERR_UPD_AREA0_MASK	(1 << 4)
+#define OMAP44XX_ERR_INV_DATA0_SHIFT	3
+#define OMAP44XX_ERR_INV_DATA0_MASK	(1 << 3)
+#define OMAP44XX_ERR_INV_DSC0_SHIFT	2
+#define OMAP44XX_ERR_INV_DSC0_MASK	(1 << 2)
+#define OMAP44XX_FILL_LST0_SHIFT	1
+#define OMAP44XX_FILL_LST0_MASK		(1 << 1)
+#define OMAP44XX_FILL_DSC0_SHIFT	0
+#define OMAP44XX_FILL_DSC0_MASK		(1 << 0)
+
+/* DMM_PAT_IRQSTATUS */
+
+/* DMM_PAT_IRQENABLE_SET */
+
+/* DMM_PAT_IRQENABLE_CLR */
+
+/* DMM_PAT_STATUS */
+#define OMAP44XX_CNT_SHIFT		16
+#define OMAP44XX_CNT_MASK		(0x1ff << 16)
+#define OMAP44XX_ERROR_SHIFT		10
+#define OMAP44XX_ERROR_MASK		(0x3f << 10)
+#define OMAP44XX_BYPASSED_SHIFT		7
+#define OMAP44XX_BYPASSED_MASK		(1 << 7)
+#define OMAP44XX_LINKED_SHIFT		4
+#define OMAP44XX_LINKED_MASK		(1 << 4)
+#define OMAP44XX_DONE_SHIFT		3
+#define OMAP44XX_DONE_MASK		(1 << 3)
+#define OMAP44XX_RUN_SHIFT		2
+#define OMAP44XX_RUN_MASK		(1 << 2)
+#define OMAP44XX_VALID_SHIFT		1
+#define OMAP44XX_VALID_MASK		(1 << 1)
+#define OMAP44XX_READY_SHIFT		0
+#define OMAP44XX_READY_MASK		(1 << 0)
+
+/* DMM_PAT_DESCR */
+#define OMAP44XX_ADDR_SHIFT		4
+#define OMAP44XX_ADDR_MASK		(0xfffffff << 4)
+
+/* DMM_PAT_AREA */
+#define OMAP44XX_Y1_SHIFT		24
+#define OMAP44XX_Y1_MASK		(0x7f << 24)
+#define OMAP44XX_X1_SHIFT		16
+#define OMAP44XX_X1_MASK		(0xff << 16)
+#define OMAP44XX_Y0_SHIFT		8
+#define OMAP44XX_Y0_MASK		(0x7f << 8)
+#define OMAP44XX_X0_SHIFT		0
+#define OMAP44XX_X0_MASK		(0xff << 0)
+
+/* DMM_PAT_CTRL */
+#define OMAP44XX_INITIATOR_SHIFT	28
+#define OMAP44XX_INITIATOR_MASK		(0xf << 28)
+#define OMAP44XX_SYNC_SHIFT		16
+#define OMAP44XX_SYNC_MASK		(1 << 16)
+#define OMAP44XX_DIRECTION_SHIFT	4
+#define OMAP44XX_DIRECTION_MASK		(0x7 << 4)
+#define OMAP44XX_START_SHIFT		0
+#define OMAP44XX_START_MASK		(1 << 0)
+
+/* DMM_PAT_DATA */
+
+/* DMM_PEG_HWINFO */
+#define OMAP44XX_PRIO_CNT_SHIFT		0
+#define OMAP44XX_PRIO_CNT_MASK		(0x7f << 0)
+
+/* DMM_PEG_PRIO */
+#define OMAP44XX_P7_SHIFT		28
+#define OMAP44XX_P7_MASK		(0x7 << 28)
+#define OMAP44XX_P6_SHIFT		24
+#define OMAP44XX_P6_MASK		(0x7 << 24)
+#define OMAP44XX_P5_SHIFT		20
+#define OMAP44XX_P5_MASK		(0x7 << 20)
+#define OMAP44XX_P4_SHIFT		16
+#define OMAP44XX_P4_MASK		(0x7 << 16)
+#define OMAP44XX_P3_SHIFT		12
+#define OMAP44XX_P3_MASK		(0x7 << 12)
+#define OMAP44XX_P2_SHIFT		8
+#define OMAP44XX_P2_MASK		(0x7 << 8)
+#define OMAP44XX_P1_SHIFT		4
+#define OMAP44XX_P1_MASK		(0x7 << 4)
+#define OMAP44XX_P0_SHIFT		0
+#define OMAP44XX_P0_MASK		(0x7 << 0)
+
+/* DMM_PEG_PRIO_PAT */
+#define OMAP44XX_W_PAT_SHIFT		3
+#define OMAP44XX_W_PAT_MASK		(1 << 3)
+#define OMAP44XX_P_PAT_SHIFT		0
+#define OMAP44XX_P_PAT_MASK		(0x7 << 0)
+#endif
diff --git a/arch/arm/mach-omap2/include/mach/emif-44xx.h b/arch/arm/mach-omap2/include/mach/emif-44xx.h
new file mode 100644
index 0000000..a23a8d3
--- /dev/null
+++ b/arch/arm/mach-omap2/include/mach/emif-44xx.h
@@ -0,0 +1,518 @@
+/*
+ * OMAP44xx EMIF registers and bitfields
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ *
+ * Benoit Cousson (b-cousson@ti.com)
+ * Santosh Shilimkar (santosh.shilimkar@ti.com)
+ *
+ * This file is automatically generated from the OMAP hardware databases.
+ * We respectfully ask that any modifications to this file be coordinated
+ * with the public linux-omap@vger.kernel.org mailing list and the
+ * authors above to ensure that the autogeneration scripts are kept
+ * up-to-date with the file contents.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP2_EMIF_44XX_H
+#define __ARCH_ARM_MACH_OMAP2_EMIF_44XX_H
+
+
+/* Base address */
+#define OMAP44XX_EMIF1				0x4c000000
+#define OMAP44XX_EMIF2				0x4d000000
+
+/* Registers offset */
+#define OMAP44XX_EMIF_MOD_ID_REV		0x0000
+#define OMAP44XX_EMIF_STATUS			0x0004
+#define OMAP44XX_EMIF_SDRAM_CONFIG		0x0008
+#define OMAP44XX_EMIF_SDRAM_CONFIG_2		0x000c
+#define OMAP44XX_EMIF_SDRAM_REF_CTRL		0x0010
+#define OMAP44XX_EMIF_SDRAM_REF_CTRL_SHDW	0x0014
+#define OMAP44XX_EMIF_SDRAM_TIM_1		0x0018
+#define OMAP44XX_EMIF_SDRAM_TIM_1_SHDW		0x001c
+#define OMAP44XX_EMIF_SDRAM_TIM_2		0x0020
+#define OMAP44XX_EMIF_SDRAM_TIM_2_SHDW		0x0024
+#define OMAP44XX_EMIF_SDRAM_TIM_3		0x0028
+#define OMAP44XX_EMIF_SDRAM_TIM_3_SHDW		0x002c
+#define OMAP44XX_EMIF_LPDDR2_NVM_TIM		0x0030
+#define OMAP44XX_EMIF_LPDDR2_NVM_TIM_SHDW	0x0034
+#define OMAP44XX_EMIF_PWR_MGMT_CTRL		0x0038
+#define OMAP44XX_EMIF_PWR_MGMT_CTRL_SHDW	0x003c
+#define OMAP44XX_EMIF_LPDDR2_MODE_REG_DATA	0x0040
+#define OMAP44XX_EMIF_LPDDR2_MODE_REG_CFG	0x0050
+#define OMAP44XX_EMIF_OCP_CONFIG		0x0054
+#define OMAP44XX_EMIF_OCP_CFG_VAL_1		0x0058
+#define OMAP44XX_EMIF_OCP_CFG_VAL_2		0x005c
+#define OMAP44XX_EMIF_IODFT_TLGC		0x0060
+#define OMAP44XX_EMIF_IODFT_CTRL_MISR_RSLT	0x0064
+#define OMAP44XX_EMIF_IODFT_ADDR_MISR_RSLT	0x0068
+#define OMAP44XX_EMIF_IODFT_DATA_MISR_RSLT_1	0x006c
+#define OMAP44XX_EMIF_IODFT_DATA_MISR_RSLT_2	0x0070
+#define OMAP44XX_EMIF_IODFT_DATA_MISR_RSLT_3	0x0074
+#define OMAP44XX_EMIF_PERF_CNT_1		0x0080
+#define OMAP44XX_EMIF_PERF_CNT_2		0x0084
+#define OMAP44XX_EMIF_PERF_CNT_CFG		0x0088
+#define OMAP44XX_EMIF_PERF_CNT_SEL		0x008c
+#define OMAP44XX_EMIF_PERF_CNT_TIM		0x0090
+#define OMAP44XX_EMIF_READ_IDLE_CTRL		0x0098
+#define OMAP44XX_EMIF_READ_IDLE_CTRL_SHDW	0x009c
+#define OMAP44XX_EMIF_IRQ_EOI			0x00a0
+#define OMAP44XX_EMIF_IRQSTATUS_RAW_SYS		0x00a4
+#define OMAP44XX_EMIF_IRQSTATUS_RAW_LL		0x00a8
+#define OMAP44XX_EMIF_IRQSTATUS_SYS		0x00ac
+#define OMAP44XX_EMIF_IRQSTATUS_LL		0x00b0
+#define OMAP44XX_EMIF_IRQENABLE_SET_SYS		0x00b4
+#define OMAP44XX_EMIF_IRQENABLE_SET_LL		0x00b8
+#define OMAP44XX_EMIF_IRQENABLE_CLR_SYS		0x00bc
+#define OMAP44XX_EMIF_IRQENABLE_CLR_LL		0x00c0
+#define OMAP44XX_EMIF_ZQ_CONFIG			0x00c8
+#define OMAP44XX_EMIF_TEMP_ALERT_CONFIG		0x00cc
+#define OMAP44XX_EMIF_OCP_ERR_LOG		0x00d0
+#define OMAP44XX_EMIF_DDR_PHY_CTRL_1		0x00e4
+#define OMAP44XX_EMIF_DDR_PHY_CTRL_1_SHDW	0x00e8
+#define OMAP44XX_EMIF_DDR_PHY_CTRL_2		0x00ec
+
+/* Registers shifts and masks */
+
+/* EMIF_MOD_ID_REV */
+#define OMAP44XX_REG_SCHEME_SHIFT			30
+#define OMAP44XX_REG_SCHEME_MASK			(0x3 << 30)
+#define OMAP44XX_REG_MODULE_ID_SHIFT			16
+#define OMAP44XX_REG_MODULE_ID_MASK			(0xfff << 16)
+#define OMAP44XX_REG_RTL_VERSION_SHIFT			11
+#define OMAP44XX_REG_RTL_VERSION_MASK			(0x1f << 11)
+#define OMAP44XX_REG_MAJOR_REVISION_SHIFT		8
+#define OMAP44XX_REG_MAJOR_REVISION_MASK		(0x7 << 8)
+#define OMAP44XX_REG_MINOR_REVISION_SHIFT		0
+#define OMAP44XX_REG_MINOR_REVISION_MASK		(0x3f << 0)
+
+/* STATUS */
+#define OMAP44XX_REG_BE_SHIFT				31
+#define OMAP44XX_REG_BE_MASK				(1 << 31)
+#define OMAP44XX_REG_DUAL_CLK_MODE_SHIFT		30
+#define OMAP44XX_REG_DUAL_CLK_MODE_MASK			(1 << 30)
+#define OMAP44XX_REG_FAST_INIT_SHIFT			29
+#define OMAP44XX_REG_FAST_INIT_MASK			(1 << 29)
+#define OMAP44XX_REG_PHY_DLL_READY_SHIFT		2
+#define OMAP44XX_REG_PHY_DLL_READY_MASK			(1 << 2)
+
+/* SDRAM_CONFIG */
+#define OMAP44XX_REG_SDRAM_TYPE_SHIFT			29
+#define OMAP44XX_REG_SDRAM_TYPE_MASK			(0x7 << 29)
+#define OMAP44XX_REG_IBANK_POS_SHIFT			27
+#define OMAP44XX_REG_IBANK_POS_MASK			(0x3 << 27)
+#define OMAP44XX_REG_DDR_TERM_SHIFT			24
+#define OMAP44XX_REG_DDR_TERM_MASK			(0x7 << 24)
+#define OMAP44XX_REG_DDR2_DDQS_SHIFT			23
+#define OMAP44XX_REG_DDR2_DDQS_MASK			(1 << 23)
+#define OMAP44XX_REG_DYN_ODT_SHIFT			21
+#define OMAP44XX_REG_DYN_ODT_MASK			(0x3 << 21)
+#define OMAP44XX_REG_DDR_DISABLE_DLL_SHIFT		20
+#define OMAP44XX_REG_DDR_DISABLE_DLL_MASK		(1 << 20)
+#define OMAP44XX_REG_SDRAM_DRIVE_SHIFT			18
+#define OMAP44XX_REG_SDRAM_DRIVE_MASK			(0x3 << 18)
+#define OMAP44XX_REG_CWL_SHIFT				16
+#define OMAP44XX_REG_CWL_MASK				(0x3 << 16)
+#define OMAP44XX_REG_NARROW_MODE_SHIFT			14
+#define OMAP44XX_REG_NARROW_MODE_MASK			(0x3 << 14)
+#define OMAP44XX_REG_CL_SHIFT				10
+#define OMAP44XX_REG_CL_MASK				(0xf << 10)
+#define OMAP44XX_REG_ROWSIZE_SHIFT			7
+#define OMAP44XX_REG_ROWSIZE_MASK			(0x7 << 7)
+#define OMAP44XX_REG_IBANK_SHIFT			4
+#define OMAP44XX_REG_IBANK_MASK				(0x7 << 4)
+#define OMAP44XX_REG_EBANK_SHIFT			3
+#define OMAP44XX_REG_EBANK_MASK				(1 << 3)
+#define OMAP44XX_REG_PAGESIZE_SHIFT			0
+#define OMAP44XX_REG_PAGESIZE_MASK			(0x7 << 0)
+
+/* SDRAM_CONFIG_2 */
+#define OMAP44XX_REG_CS1NVMEN_SHIFT			30
+#define OMAP44XX_REG_CS1NVMEN_MASK			(1 << 30)
+#define OMAP44XX_REG_EBANK_POS_SHIFT			27
+#define OMAP44XX_REG_EBANK_POS_MASK			(1 << 27)
+#define OMAP44XX_REG_RDBNUM_SHIFT			4
+#define OMAP44XX_REG_RDBNUM_MASK			(0x3 << 4)
+#define OMAP44XX_REG_RDBSIZE_SHIFT			0
+#define OMAP44XX_REG_RDBSIZE_MASK			(0x7 << 0)
+
+/* SDRAM_REF_CTRL */
+#define OMAP44XX_REG_INITREF_DIS_SHIFT			31
+#define OMAP44XX_REG_INITREF_DIS_MASK			(1 << 31)
+#define OMAP44XX_REG_SRT_SHIFT				29
+#define OMAP44XX_REG_SRT_MASK				(1 << 29)
+#define OMAP44XX_REG_ASR_SHIFT				28
+#define OMAP44XX_REG_ASR_MASK				(1 << 28)
+#define OMAP44XX_REG_PASR_SHIFT				24
+#define OMAP44XX_REG_PASR_MASK				(0x7 << 24)
+#define OMAP44XX_REG_REFRESH_RATE_SHIFT			0
+#define OMAP44XX_REG_REFRESH_RATE_MASK			(0xffff << 0)
+
+/* SDRAM_REF_CTRL_SHDW */
+#define OMAP44XX_REG_REFRESH_RATE_SHDW_SHIFT		0
+#define OMAP44XX_REG_REFRESH_RATE_SHDW_MASK		(0xffff << 0)
+
+/* SDRAM_TIM_1 */
+#define OMAP44XX_REG_T_RP_SHIFT				25
+#define OMAP44XX_REG_T_RP_MASK				(0xf << 25)
+#define OMAP44XX_REG_T_RCD_SHIFT			21
+#define OMAP44XX_REG_T_RCD_MASK				(0xf << 21)
+#define OMAP44XX_REG_T_WR_SHIFT				17
+#define OMAP44XX_REG_T_WR_MASK				(0xf << 17)
+#define OMAP44XX_REG_T_RAS_SHIFT			12
+#define OMAP44XX_REG_T_RAS_MASK				(0x1f << 12)
+#define OMAP44XX_REG_T_RC_SHIFT				6
+#define OMAP44XX_REG_T_RC_MASK				(0x3f << 6)
+#define OMAP44XX_REG_T_RRD_SHIFT			3
+#define OMAP44XX_REG_T_RRD_MASK				(0x7 << 3)
+#define OMAP44XX_REG_T_WTR_SHIFT			0
+#define OMAP44XX_REG_T_WTR_MASK				(0x7 << 0)
+
+/* SDRAM_TIM_1_SHDW */
+#define OMAP44XX_REG_T_RP_SHDW_SHIFT			25
+#define OMAP44XX_REG_T_RP_SHDW_MASK			(0xf << 25)
+#define OMAP44XX_REG_T_RCD_SHDW_SHIFT			21
+#define OMAP44XX_REG_T_RCD_SHDW_MASK			(0xf << 21)
+#define OMAP44XX_REG_T_WR_SHDW_SHIFT			17
+#define OMAP44XX_REG_T_WR_SHDW_MASK			(0xf << 17)
+#define OMAP44XX_REG_T_RAS_SHDW_SHIFT			12
+#define OMAP44XX_REG_T_RAS_SHDW_MASK			(0x1f << 12)
+#define OMAP44XX_REG_T_RC_SHDW_SHIFT			6
+#define OMAP44XX_REG_T_RC_SHDW_MASK			(0x3f << 6)
+#define OMAP44XX_REG_T_RRD_SHDW_SHIFT			3
+#define OMAP44XX_REG_T_RRD_SHDW_MASK			(0x7 << 3)
+#define OMAP44XX_REG_T_WTR_SHDW_SHIFT			0
+#define OMAP44XX_REG_T_WTR_SHDW_MASK			(0x7 << 0)
+
+/* SDRAM_TIM_2 */
+#define OMAP44XX_REG_T_XP_SHIFT				28
+#define OMAP44XX_REG_T_XP_MASK				(0x7 << 28)
+#define OMAP44XX_REG_T_ODT_SHIFT			25
+#define OMAP44XX_REG_T_ODT_MASK				(0x7 << 25)
+#define OMAP44XX_REG_T_XSNR_SHIFT			16
+#define OMAP44XX_REG_T_XSNR_MASK			(0x1ff << 16)
+#define OMAP44XX_REG_T_XSRD_SHIFT			6
+#define OMAP44XX_REG_T_XSRD_MASK			(0x3ff << 6)
+#define OMAP44XX_REG_T_RTP_SHIFT			3
+#define OMAP44XX_REG_T_RTP_MASK				(0x7 << 3)
+#define OMAP44XX_REG_T_CKE_SHIFT			0
+#define OMAP44XX_REG_T_CKE_MASK				(0x7 << 0)
+
+/* SDRAM_TIM_2_SHDW */
+#define OMAP44XX_REG_T_XP_SHDW_SHIFT			28
+#define OMAP44XX_REG_T_XP_SHDW_MASK			(0x7 << 28)
+#define OMAP44XX_REG_T_ODT_SHDW_SHIFT			25
+#define OMAP44XX_REG_T_ODT_SHDW_MASK			(0x7 << 25)
+#define OMAP44XX_REG_T_XSNR_SHDW_SHIFT			16
+#define OMAP44XX_REG_T_XSNR_SHDW_MASK			(0x1ff << 16)
+#define OMAP44XX_REG_T_XSRD_SHDW_SHIFT			6
+#define OMAP44XX_REG_T_XSRD_SHDW_MASK			(0x3ff << 6)
+#define OMAP44XX_REG_T_RTP_SHDW_SHIFT			3
+#define OMAP44XX_REG_T_RTP_SHDW_MASK			(0x7 << 3)
+#define OMAP44XX_REG_T_CKE_SHDW_SHIFT			0
+#define OMAP44XX_REG_T_CKE_SHDW_MASK			(0x7 << 0)
+
+/* SDRAM_TIM_3 */
+#define OMAP44XX_REG_T_CKESR_SHIFT			21
+#define OMAP44XX_REG_T_CKESR_MASK			(0x7 << 21)
+#define OMAP44XX_REG_ZQ_ZQCS_SHIFT			15
+#define OMAP44XX_REG_ZQ_ZQCS_MASK			(0x3f << 15)
+#define OMAP44XX_REG_T_TDQSCKMAX_SHIFT			13
+#define OMAP44XX_REG_T_TDQSCKMAX_MASK			(0x3 << 13)
+#define OMAP44XX_REG_T_RFC_SHIFT			4
+#define OMAP44XX_REG_T_RFC_MASK				(0x1ff << 4)
+#define OMAP44XX_REG_T_RAS_MAX_SHIFT			0
+#define OMAP44XX_REG_T_RAS_MAX_MASK			(0xf << 0)
+
+/* SDRAM_TIM_3_SHDW */
+#define OMAP44XX_REG_T_CKESR_SHDW_SHIFT			21
+#define OMAP44XX_REG_T_CKESR_SHDW_MASK			(0x7 << 21)
+#define OMAP44XX_REG_ZQ_ZQCS_SHDW_SHIFT			15
+#define OMAP44XX_REG_ZQ_ZQCS_SHDW_MASK			(0x3f << 15)
+#define OMAP44XX_REG_T_TDQSCKMAX_SHDW_SHIFT		13
+#define OMAP44XX_REG_T_TDQSCKMAX_SHDW_MASK		(0x3 << 13)
+#define OMAP44XX_REG_T_RFC_SHDW_SHIFT			4
+#define OMAP44XX_REG_T_RFC_SHDW_MASK			(0x1ff << 4)
+#define OMAP44XX_REG_T_RAS_MAX_SHDW_SHIFT		0
+#define OMAP44XX_REG_T_RAS_MAX_SHDW_MASK		(0xf << 0)
+
+/* LPDDR2_NVM_TIM */
+#define OMAP44XX_REG_NVM_T_XP_SHIFT			28
+#define OMAP44XX_REG_NVM_T_XP_MASK			(0x7 << 28)
+#define OMAP44XX_REG_NVM_T_WTR_SHIFT			24
+#define OMAP44XX_REG_NVM_T_WTR_MASK			(0x7 << 24)
+#define OMAP44XX_REG_NVM_T_RP_SHIFT			20
+#define OMAP44XX_REG_NVM_T_RP_MASK			(0xf << 20)
+#define OMAP44XX_REG_NVM_T_WRA_SHIFT			16
+#define OMAP44XX_REG_NVM_T_WRA_MASK			(0xf << 16)
+#define OMAP44XX_REG_NVM_T_RRD_SHIFT			8
+#define OMAP44XX_REG_NVM_T_RRD_MASK			(0xff << 8)
+#define OMAP44XX_REG_NVM_T_RCDMIN_SHIFT			0
+#define OMAP44XX_REG_NVM_T_RCDMIN_MASK			(0xff << 0)
+
+/* LPDDR2_NVM_TIM_SHDW */
+#define OMAP44XX_REG_NVM_T_XP_SHDW_SHIFT		28
+#define OMAP44XX_REG_NVM_T_XP_SHDW_MASK			(0x7 << 28)
+#define OMAP44XX_REG_NVM_T_WTR_SHDW_SHIFT		24
+#define OMAP44XX_REG_NVM_T_WTR_SHDW_MASK		(0x7 << 24)
+#define OMAP44XX_REG_NVM_T_RP_SHDW_SHIFT		20
+#define OMAP44XX_REG_NVM_T_RP_SHDW_MASK			(0xf << 20)
+#define OMAP44XX_REG_NVM_T_WRA_SHDW_SHIFT		16
+#define OMAP44XX_REG_NVM_T_WRA_SHDW_MASK		(0xf << 16)
+#define OMAP44XX_REG_NVM_T_RRD_SHDW_SHIFT		8
+#define OMAP44XX_REG_NVM_T_RRD_SHDW_MASK		(0xff << 8)
+#define OMAP44XX_REG_NVM_T_RCDMIN_SHDW_SHIFT		0
+#define OMAP44XX_REG_NVM_T_RCDMIN_SHDW_MASK		(0xff << 0)
+
+/* PWR_MGMT_CTRL */
+#define OMAP44XX_REG_PD_TIM_SHIFT			12
+#define OMAP44XX_REG_PD_TIM_MASK			(0xf << 12)
+#define OMAP44XX_REG_DPD_EN_SHIFT			11
+#define OMAP44XX_REG_DPD_EN_MASK			(1 << 11)
+#define OMAP44XX_REG_LP_MODE_SHIFT			8
+#define OMAP44XX_REG_LP_MODE_MASK			(0x7 << 8)
+#define OMAP44XX_REG_SR_TIM_SHIFT			4
+#define OMAP44XX_REG_SR_TIM_MASK			(0xf << 4)
+#define OMAP44XX_REG_CS_TIM_SHIFT			0
+#define OMAP44XX_REG_CS_TIM_MASK			(0xf << 0)
+
+/* PWR_MGMT_CTRL_SHDW */
+#define OMAP44XX_REG_PD_TIM_SHDW_SHIFT			8
+#define OMAP44XX_REG_PD_TIM_SHDW_MASK			(0xf << 8)
+#define OMAP44XX_REG_SR_TIM_SHDW_SHIFT			4
+#define OMAP44XX_REG_SR_TIM_SHDW_MASK			(0xf << 4)
+#define OMAP44XX_REG_CS_TIM_SHDW_SHIFT			0
+#define OMAP44XX_REG_CS_TIM_SHDW_MASK			(0xf << 0)
+
+/* LPDDR2_MODE_REG_DATA */
+#define OMAP44XX_REG_VALUE_0_SHIFT			0
+#define OMAP44XX_REG_VALUE_0_MASK			(0x7f << 0)
+
+/* LPDDR2_MODE_REG_CFG */
+#define OMAP44XX_REG_CS_SHIFT				31
+#define OMAP44XX_REG_CS_MASK				(1 << 31)
+#define OMAP44XX_REG_REFRESH_EN_SHIFT			30
+#define OMAP44XX_REG_REFRESH_EN_MASK			(1 << 30)
+#define OMAP44XX_REG_ADDRESS_SHIFT			0
+#define OMAP44XX_REG_ADDRESS_MASK			(0xff << 0)
+
+/* OCP_CONFIG */
+#define OMAP44XX_REG_SYS_THRESH_MAX_SHIFT		24
+#define OMAP44XX_REG_SYS_THRESH_MAX_MASK		(0xf << 24)
+#define OMAP44XX_REG_LL_THRESH_MAX_SHIFT		16
+#define OMAP44XX_REG_LL_THRESH_MAX_MASK			(0xf << 16)
+#define OMAP44XX_REG_PR_OLD_COUNT_SHIFT			0
+#define OMAP44XX_REG_PR_OLD_COUNT_MASK			(0xff << 0)
+
+/* OCP_CFG_VAL_1 */
+#define OMAP44XX_REG_SYS_BUS_WIDTH_SHIFT		30
+#define OMAP44XX_REG_SYS_BUS_WIDTH_MASK			(0x3 << 30)
+#define OMAP44XX_REG_LL_BUS_WIDTH_SHIFT			28
+#define OMAP44XX_REG_LL_BUS_WIDTH_MASK			(0x3 << 28)
+#define OMAP44XX_REG_WR_FIFO_DEPTH_SHIFT		8
+#define OMAP44XX_REG_WR_FIFO_DEPTH_MASK			(0xff << 8)
+#define OMAP44XX_REG_CMD_FIFO_DEPTH_SHIFT		0
+#define OMAP44XX_REG_CMD_FIFO_DEPTH_MASK		(0xff << 0)
+
+/* OCP_CFG_VAL_2 */
+#define OMAP44XX_REG_RREG_FIFO_DEPTH_SHIFT		16
+#define OMAP44XX_REG_RREG_FIFO_DEPTH_MASK		(0xff << 16)
+#define OMAP44XX_REG_RSD_FIFO_DEPTH_SHIFT		8
+#define OMAP44XX_REG_RSD_FIFO_DEPTH_MASK		(0xff << 8)
+#define OMAP44XX_REG_RCMD_FIFO_DEPTH_SHIFT		0
+#define OMAP44XX_REG_RCMD_FIFO_DEPTH_MASK		(0xff << 0)
+
+/* IODFT_TLGC */
+#define OMAP44XX_REG_TLEC_SHIFT				16
+#define OMAP44XX_REG_TLEC_MASK				(0xffff << 16)
+#define OMAP44XX_REG_MT_SHIFT				14
+#define OMAP44XX_REG_MT_MASK				(1 << 14)
+#define OMAP44XX_REG_ACT_CAP_EN_SHIFT			13
+#define OMAP44XX_REG_ACT_CAP_EN_MASK			(1 << 13)
+#define OMAP44XX_REG_OPG_LD_SHIFT			12
+#define OMAP44XX_REG_OPG_LD_MASK			(1 << 12)
+#define OMAP44XX_REG_RESET_PHY_SHIFT			10
+#define OMAP44XX_REG_RESET_PHY_MASK			(1 << 10)
+#define OMAP44XX_REG_MMS_SHIFT				8
+#define OMAP44XX_REG_MMS_MASK				(1 << 8)
+#define OMAP44XX_REG_MC_SHIFT				4
+#define OMAP44XX_REG_MC_MASK				(0x3 << 4)
+#define OMAP44XX_REG_PC_SHIFT				1
+#define OMAP44XX_REG_PC_MASK				(0x7 << 1)
+#define OMAP44XX_REG_TM_SHIFT				0
+#define OMAP44XX_REG_TM_MASK				(1 << 0)
+
+/* IODFT_CTRL_MISR_RSLT */
+#define OMAP44XX_REG_DQM_TLMR_SHIFT			16
+#define OMAP44XX_REG_DQM_TLMR_MASK			(0x3ff << 16)
+#define OMAP44XX_REG_CTL_TLMR_SHIFT			0
+#define OMAP44XX_REG_CTL_TLMR_MASK			(0x7ff << 0)
+
+/* IODFT_ADDR_MISR_RSLT */
+#define OMAP44XX_REG_ADDR_TLMR_SHIFT			0
+#define OMAP44XX_REG_ADDR_TLMR_MASK			(0x1fffff << 0)
+
+/* IODFT_DATA_MISR_RSLT_1 */
+#define OMAP44XX_REG_DATA_TLMR_31_0_SHIFT		0
+#define OMAP44XX_REG_DATA_TLMR_31_0_MASK		(0xffffffff << 0)
+
+/* IODFT_DATA_MISR_RSLT_2 */
+#define OMAP44XX_REG_DATA_TLMR_63_32_SHIFT		0
+#define OMAP44XX_REG_DATA_TLMR_63_32_MASK		(0xffffffff << 0)
+
+/* IODFT_DATA_MISR_RSLT_3 */
+#define OMAP44XX_REG_DATA_TLMR_66_64_SHIFT		0
+#define OMAP44XX_REG_DATA_TLMR_66_64_MASK		(0x7 << 0)
+
+/* PERF_CNT_1 */
+#define OMAP44XX_REG_COUNTER1_SHIFT			0
+#define OMAP44XX_REG_COUNTER1_MASK			(0xffffffff << 0)
+
+/* PERF_CNT_2 */
+#define OMAP44XX_REG_COUNTER2_SHIFT			0
+#define OMAP44XX_REG_COUNTER2_MASK			(0xffffffff << 0)
+
+/* PERF_CNT_CFG */
+#define OMAP44XX_REG_CNTR2_MCONNID_EN_SHIFT		31
+#define OMAP44XX_REG_CNTR2_MCONNID_EN_MASK		(1 << 31)
+#define OMAP44XX_REG_CNTR2_REGION_EN_SHIFT		30
+#define OMAP44XX_REG_CNTR2_REGION_EN_MASK		(1 << 30)
+#define OMAP44XX_REG_CNTR2_CFG_SHIFT			16
+#define OMAP44XX_REG_CNTR2_CFG_MASK			(0xf << 16)
+#define OMAP44XX_REG_CNTR1_MCONNID_EN_SHIFT		15
+#define OMAP44XX_REG_CNTR1_MCONNID_EN_MASK		(1 << 15)
+#define OMAP44XX_REG_CNTR1_REGION_EN_SHIFT		14
+#define OMAP44XX_REG_CNTR1_REGION_EN_MASK		(1 << 14)
+#define OMAP44XX_REG_CNTR1_CFG_SHIFT			0
+#define OMAP44XX_REG_CNTR1_CFG_MASK			(0xf << 0)
+
+/* PERF_CNT_SEL */
+#define OMAP44XX_REG_MCONNID2_SHIFT			24
+#define OMAP44XX_REG_MCONNID2_MASK			(0xff << 24)
+#define OMAP44XX_REG_REGION_SEL2_SHIFT			16
+#define OMAP44XX_REG_REGION_SEL2_MASK			(0x3 << 16)
+#define OMAP44XX_REG_MCONNID1_SHIFT			8
+#define OMAP44XX_REG_MCONNID1_MASK			(0xff << 8)
+#define OMAP44XX_REG_REGION_SEL1_SHIFT			0
+#define OMAP44XX_REG_REGION_SEL1_MASK			(0x3 << 0)
+
+/* PERF_CNT_TIM */
+#define OMAP44XX_REG_TOTAL_TIME_SHIFT			0
+#define OMAP44XX_REG_TOTAL_TIME_MASK			(0xffffffff << 0)
+
+/* READ_IDLE_CTRL */
+#define OMAP44XX_REG_READ_IDLE_LEN_SHIFT		16
+#define OMAP44XX_REG_READ_IDLE_LEN_MASK			(0xf << 16)
+#define OMAP44XX_REG_READ_IDLE_INTERVAL_SHIFT		0
+#define OMAP44XX_REG_READ_IDLE_INTERVAL_MASK		(0x1ff << 0)
+
+/* READ_IDLE_CTRL_SHDW */
+#define OMAP44XX_REG_READ_IDLE_LEN_SHDW_SHIFT		16
+#define OMAP44XX_REG_READ_IDLE_LEN_SHDW_MASK		(0xf << 16)
+#define OMAP44XX_REG_READ_IDLE_INTERVAL_SHDW_SHIFT	0
+#define OMAP44XX_REG_READ_IDLE_INTERVAL_SHDW_MASK	(0x1ff << 0)
+
+/* IRQ_EOI */
+#define OMAP44XX_REG_EOI_SHIFT				0
+#define OMAP44XX_REG_EOI_MASK				(1 << 0)
+
+/* IRQSTATUS_RAW_SYS */
+#define OMAP44XX_REG_DNV_SYS_SHIFT			2
+#define OMAP44XX_REG_DNV_SYS_MASK			(1 << 2)
+#define OMAP44XX_REG_TA_SYS_SHIFT			1
+#define OMAP44XX_REG_TA_SYS_MASK			(1 << 1)
+#define OMAP44XX_REG_ERR_SYS_SHIFT			0
+#define OMAP44XX_REG_ERR_SYS_MASK			(1 << 0)
+
+/* IRQSTATUS_RAW_LL */
+#define OMAP44XX_REG_DNV_LL_SHIFT			2
+#define OMAP44XX_REG_DNV_LL_MASK			(1 << 2)
+#define OMAP44XX_REG_TA_LL_SHIFT			1
+#define OMAP44XX_REG_TA_LL_MASK				(1 << 1)
+#define OMAP44XX_REG_ERR_LL_SHIFT			0
+#define OMAP44XX_REG_ERR_LL_MASK			(1 << 0)
+
+/* IRQSTATUS_SYS */
+
+/* IRQSTATUS_LL */
+
+/* IRQENABLE_SET_SYS */
+#define OMAP44XX_REG_EN_DNV_SYS_SHIFT			2
+#define OMAP44XX_REG_EN_DNV_SYS_MASK			(1 << 2)
+#define OMAP44XX_REG_EN_TA_SYS_SHIFT			1
+#define OMAP44XX_REG_EN_TA_SYS_MASK			(1 << 1)
+#define OMAP44XX_REG_EN_ERR_SYS_SHIFT			0
+#define OMAP44XX_REG_EN_ERR_SYS_MASK			(1 << 0)
+
+/* IRQENABLE_SET_LL */
+#define OMAP44XX_REG_EN_DNV_LL_SHIFT			2
+#define OMAP44XX_REG_EN_DNV_LL_MASK			(1 << 2)
+#define OMAP44XX_REG_EN_TA_LL_SHIFT			1
+#define OMAP44XX_REG_EN_TA_LL_MASK			(1 << 1)
+#define OMAP44XX_REG_EN_ERR_LL_SHIFT			0
+#define OMAP44XX_REG_EN_ERR_LL_MASK			(1 << 0)
+
+/* IRQENABLE_CLR_SYS */
+
+/* IRQENABLE_CLR_LL */
+
+/* ZQ_CONFIG */
+#define OMAP44XX_REG_ZQ_CS1EN_SHIFT			31
+#define OMAP44XX_REG_ZQ_CS1EN_MASK			(1 << 31)
+#define OMAP44XX_REG_ZQ_CS0EN_SHIFT			30
+#define OMAP44XX_REG_ZQ_CS0EN_MASK			(1 << 30)
+#define OMAP44XX_REG_ZQ_DUALCALEN_SHIFT			29
+#define OMAP44XX_REG_ZQ_DUALCALEN_MASK			(1 << 29)
+#define OMAP44XX_REG_ZQ_SFEXITEN_SHIFT			28
+#define OMAP44XX_REG_ZQ_SFEXITEN_MASK			(1 << 28)
+#define OMAP44XX_REG_ZQ_ZQINIT_MULT_SHIFT		18
+#define OMAP44XX_REG_ZQ_ZQINIT_MULT_MASK		(0x3 << 18)
+#define OMAP44XX_REG_ZQ_ZQCL_MULT_SHIFT			16
+#define OMAP44XX_REG_ZQ_ZQCL_MULT_MASK			(0x3 << 16)
+#define OMAP44XX_REG_ZQ_REFINTERVAL_SHIFT		0
+#define OMAP44XX_REG_ZQ_REFINTERVAL_MASK		(0xffff << 0)
+
+/* TEMP_ALERT_CONFIG */
+#define OMAP44XX_REG_TA_CS1EN_SHIFT			31
+#define OMAP44XX_REG_TA_CS1EN_MASK			(1 << 31)
+#define OMAP44XX_REG_TA_CS0EN_SHIFT			30
+#define OMAP44XX_REG_TA_CS0EN_MASK			(1 << 30)
+#define OMAP44XX_REG_TA_SFEXITEN_SHIFT			28
+#define OMAP44XX_REG_TA_SFEXITEN_MASK			(1 << 28)
+#define OMAP44XX_REG_TA_DEVWDT_SHIFT			26
+#define OMAP44XX_REG_TA_DEVWDT_MASK			(0x3 << 26)
+#define OMAP44XX_REG_TA_DEVCNT_SHIFT			24
+#define OMAP44XX_REG_TA_DEVCNT_MASK			(0x3 << 24)
+#define OMAP44XX_REG_TA_REFINTERVAL_SHIFT		0
+#define OMAP44XX_REG_TA_REFINTERVAL_MASK		(0x3fffff << 0)
+
+/* OCP_ERR_LOG */
+#define OMAP44XX_REG_MADDRSPACE_SHIFT			14
+#define OMAP44XX_REG_MADDRSPACE_MASK			(0x3 << 14)
+#define OMAP44XX_REG_MBURSTSEQ_SHIFT			11
+#define OMAP44XX_REG_MBURSTSEQ_MASK			(0x7 << 11)
+#define OMAP44XX_REG_MCMD_SHIFT				8
+#define OMAP44XX_REG_MCMD_MASK				(0x7 << 8)
+#define OMAP44XX_REG_MCONNID_SHIFT			0
+#define OMAP44XX_REG_MCONNID_MASK			(0xff << 0)
+
+/* DDR_PHY_CTRL_1 */
+#define OMAP44XX_REG_DDR_PHY_CTRL_1_SHIFT		4
+#define OMAP44XX_REG_DDR_PHY_CTRL_1_MASK		(0xfffffff << 4)
+#define OMAP44XX_REG_READ_LATENCY_SHIFT			0
+#define OMAP44XX_REG_READ_LATENCY_MASK			(0xf << 0)
+
+/* DDR_PHY_CTRL_1_SHDW */
+#define OMAP44XX_REG_DDR_PHY_CTRL_1_SHDW_SHIFT		4
+#define OMAP44XX_REG_DDR_PHY_CTRL_1_SHDW_MASK		(0xfffffff << 4)
+#define OMAP44XX_REG_READ_LATENCY_SHDW_SHIFT		0
+#define OMAP44XX_REG_READ_LATENCY_SHDW_MASK		(0xf << 0)
+
+/* DDR_PHY_CTRL_2 */
+#define OMAP44XX_REG_DDR_PHY_CTRL_2_SHIFT		0
+#define OMAP44XX_REG_DDR_PHY_CTRL_2_MASK		(0xffffffff << 0)
+#endif
-- 
1.6.0.4


^ permalink raw reply related	[flat|nested] 46+ messages in thread

* RE: [RFC 2/8] TILER-DMM: Container manager interface and utility definitons
  2010-07-23 23:22   ` [RFC 2/8] TILER-DMM: Container manager interface and utility definitons David Sin
  2010-07-23 23:22     ` [RFC 3/8] TILER-DMM: Sample TCM implementation: Simple TILER Allocator David Sin
@ 2010-07-24  6:56     ` Shilimkar, Santosh
  2010-07-27 20:21     ` Hiremath, Vaibhav
  2 siblings, 0 replies; 46+ messages in thread
From: Shilimkar, Santosh @ 2010-07-24  6:56 UTC (permalink / raw)
  To: Sin, David, linux-arm-kernel@lists.arm.linux.org.uk,
	linux-omap@vger.kernel.org, Tony
  Cc: Kanigeri, Hari, Ohad Ben-Cohen, Hiremath, Vaibhav, Molnar, Lajos,
	Ramachandra, Ravikiran

> -----Original Message-----
> From: Sin, David
> Sent: Saturday, July 24, 2010 4:52 AM
> To: linux-arm-kernel@lists.arm.linux.org.uk; linux-omap@vger.kernel.org;
> Tony Lindgren; Russell King
> Cc: Kanigeri, Hari; Ohad Ben-Cohen; Hiremath, Vaibhav; Shilimkar, Santosh;
> Molnar, Lajos; Sin, David; Ramachandra, Ravikiran
> Subject: [RFC 2/8] TILER-DMM: Container manager interface and utility
> definitons
> 
> From: Lajos Molnar <molnar@ti.com>
> 
> This patch defined the TILER Container Manager (TCM) interface and
> provides utility methods for implementing a TCM.
> 
> Signed-off-by: Lajos Molnar <molnar@ti.com>
> Signed-off-by: David Sin <davidsin@ti.com>
> Signed-off-by: Ravi Ramachandra <r.ramachandra@ti.com>
> ---
>  drivers/media/video/tiler/tcm.h           |  209
> +++++++++++++++++++++++++++++
>  drivers/media/video/tiler/tcm/tcm-utils.h |   54 ++++++++
>  2 files changed, 263 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/media/video/tiler/tcm.h
>  create mode 100644 drivers/media/video/tiler/tcm/tcm-utils.h
> 
> diff --git a/drivers/media/video/tiler/tcm.h
> b/drivers/media/video/tiler/tcm.h
> new file mode 100644
> index 0000000..52a022a
> --- /dev/null
> +++ b/drivers/media/video/tiler/tcm.h
> @@ -0,0 +1,209 @@
> +/*
> + * tcm.h
> + *
> + * TILER container manager specification and support functions for TI
> + * TILER driver.
> + *
> + * Author: Lajos Molnar <molnar@ti.com>
> + *
> + * Copyright (C) 2009-2010 Texas Instruments, Inc.
> + *
> + * This package is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
> + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
> + */
> +
> +#ifndef TCM_H
> +#define TCM_H
> +
> +struct tcm;
> +
> +/* point */
> +struct tcm_pt {
> +	u16 x;
> +	u16 y;
> +};
> +
> +/* 2d area */
> +struct tcm_area {
> +	struct tcm    *tcm;	/* parent */
> +	struct tcm_pt  p0;
> +	struct tcm_pt  p1;
> +};
> +
> +struct tcm {
> +	u16 width, height;	/* container dimensions */
> +
> +	/* '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
> +	any changes to the publicly available width and height fields. */
Commenting style ...

> +	void *pvt;
> +
> +	/* function table */
> +	s32 (*reserve_2d)(struct tcm *tcm, u16 height, u16 width, u8 align,
> +			  struct tcm_area *area);
> +	s32 (*free)      (struct tcm *tcm, struct tcm_area *area);
> +	void (*deinit)   (struct tcm *tcm);
> +};
> +
> +/*=======================================================================
> ======
> +    BASIC TILER CONTAINER MANAGER INTERFACE
> +=========================================================================
> ====*/
Commenting style.
> +
> +/*
> + * NOTE:
> + *
> + * Since some basic parameter checking is done outside the TCM
> algorithms,
> + * TCM implementation do NOT have to check the following:
> + *
> + *   area pointer is NULL
> + *   width and height fits within container
> + *   number of pages is more than the size of the container
> + *
> + */
> +
> +/**
> + * Template for <ALGO_NAME>_tcm_init method.  Define as:
> + * TCM_INIT(<ALGO_NAME>_tcm_init)
> + *
> + * Allocates and initializes a tiler container manager.
> + *
> + * @param width		Width of container
> + * @param height	Height of container
> + * @param attr		Container manager specific configuration
> + *			arguments.  Please describe these in
> + *			your header file.
> + *
> + * @return Pointer to the allocated and initialized container
> + *	   manager.  NULL on failure.  DO NOT leak any memory on
> + *	   failure!
> + */
> +#define TCM_INIT(name, attr_t) \
> +struct tcm *name(u16 width, u16 height, typeof(attr_t) *attr);
> +
> +/**
> + * Deinitialize tiler container manager.
> + *
> + * @param tcm	Pointer to container manager.
> + *
> + * @return 0 on success, non-0 error value on error.  The call
> + *	   should free as much memory as possible and meaningful
> + *	   even on failure.  Some error codes: -ENODEV: invalid
> + *	   manager.
> + */
> +static inline void tcm_deinit(struct tcm *tcm)
> +{
> +	if (tcm)
> +		tcm->deinit(tcm);
> +}
> +
> +/**
> + * Reserves a 2D area in the container.
> + *
> + * @param tcm		Pointer to container manager.
> + * @param height	Height(in pages) of area to be reserved.
> + * @param width		Width(in pages) of area to be reserved.
> + * @param align		Alignment requirement for top-left corner of area.
> Not
> + *			all values may be supported by the container manager,
> + *			but it must support 0 (1), 32 and 64.
> + *			0 value is equivalent to 1.
> + * @param area		Pointer to where the reserved area should be
> stored.
> + *
> + * @return 0 on success.  Non-0 error code on failure.  Also,
> + *	   the tcm field of the area will be set to NULL on
> + *	   failure.  Some error codes: -ENODEV: invalid manager,
> + *	   -EINVAL: invalid area, -ENOMEM: not enough space for
> + *	    allocation.
> + */
> +static inline s32 tcm_reserve_2d(struct tcm *tcm, u16 width, u16 height,
> +				 u16 align, struct tcm_area *area)
> +{
> +	/* perform rudimentary error checking */
> +	s32 res = (tcm  == NULL ? -ENODEV :
> +		(area == NULL || width == 0 || height == 0 ||
> +		 /* align must be a 2 power */
> +		 align & (align - 1)) ? -EINVAL :
> +		(height > tcm->height || width > tcm->width) ? -ENOMEM :
> +		tcm->reserve_2d(tcm, height, width, align, area));
> +
> +	if (area)
> +		area->tcm = res ? NULL : tcm;
> +
> +	return res;
> +}
> +
> +/**
> + * Free a previously reserved area from the container.
> + *
> + * @param area	Pointer to area reserved by a prior call to
> tcm_reserve_2d call,
> + *		whether it was successful or not. (Note: all fields of
> + *		the structure must match.)
> + *
> + * @return 0 on success.  Non-0 error code on failure.  Also, the tcm
> + *	   field of the area is set to NULL on success to avoid subsequent
> + *	   freeing.  This call will succeed even if supplying
> + *	   the area from a failed reserved call.
> + */
> +static inline s32 tcm_free(struct tcm_area *area)
> +{
> +	s32 res = 0; /* free succeeds by default */
> +
> +	if (area && area->tcm) {
> +		res = area->tcm->free(area->tcm, area);
> +		if (res == 0)
> +			area->tcm = NULL;
> +	}
> +
> +	return res;
> +}
> +
> +/*=======================================================================
> ======
> +    HELPER FUNCTION FOR ANY TILER CONTAINER MANAGER
> +=========================================================================
> ====*/
> +
> +/* Verify if a tcm area is logically valid */
> +static inline bool tcm_area_is_valid(struct tcm_area *area)
> +{
> +	return area && area->tcm &&
> +		/* coordinate bounds */
> +		area->p1.x < area->tcm->width &&
> +		area->p1.y < area->tcm->height &&
> +		area->p0.y <= area->p1.y &&
> +		area->p0.x <= area->p1.x;
> +}
> +
> +/* see if a coordinate is within an area */
> +static inline bool __tcm_is_in(struct tcm_pt *p, struct tcm_area *a)
> +{
> +	return p->x >= a->p0.x && p->x <= a->p1.x &&
> +		p->y >= a->p0.y && p->y <= a->p1.y;
> +}
> +
> +/* calculate area width */
> +static inline u16 __tcm_area_width(struct tcm_area *area)
> +{
> +	return area->p1.x - area->p0.x + 1;
> +}
> +
> +/* calculate area height */
> +static inline u16 __tcm_area_height(struct tcm_area *area)
> +{
> +	return area->p1.y - area->p0.y + 1;
> +}
> +
> +/* calculate number of slots in an area */
> +static inline u16 __tcm_sizeof(struct tcm_area *area)
> +{
> +	return __tcm_area_width(area) * __tcm_area_height(area);
> +}
> +#define tcm_sizeof(area) __tcm_sizeof(&(area))
> +#define tcm_awidth(area) __tcm_area_width(&(area))
> +#define tcm_aheight(area) __tcm_area_height(&(area))
> +#define tcm_is_in(pt, area) __tcm_is_in(&(pt), &(area))
> +
> +#endif
> diff --git a/drivers/media/video/tiler/tcm/tcm-utils.h
> b/drivers/media/video/tiler/tcm/tcm-utils.h
> new file mode 100644
> index 0000000..0d1260a
> --- /dev/null
> +++ b/drivers/media/video/tiler/tcm/tcm-utils.h
> @@ -0,0 +1,54 @@
> +/*
> + * tcm_utils.h
> + *
> + * Utility functions for implementing TILER container managers.
> + *
> + * Author: Lajos Molnar <molnar@ti.com>
> + *
> + * Copyright (C) 2009-2010 Texas Instruments, Inc.
> + *
> + * This package is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
> + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
> + */
> +
> +#ifndef TCM_UTILS_H
> +#define TCM_UTILS_H
> +
> +#include "../tcm.h"
Should avoid this type
> +
> +/* TCM_ALG_NAME must be defined to use the debug methods */
> +
> +#ifdef DEBUG
> +#define IFDEBUG(x) x
> +#else
> +/* compile-check debug statements even if not DEBUG */
> +#define IFDEBUG(x) do { if (0) x; } while (0)
> +#endif
> +
> +#define P(level, fmt, ...) \
> +	IFDEBUG(printk(level TCM_ALG_NAME ":%d:%s()" fmt "\n", \
> +			__LINE__, __func__, ##__VA_ARGS__))
> +
> +#define P1(fmt, ...) P(KERN_NOTICE, fmt, ##__VA_ARGS__)
> +#define P2(fmt, ...) P(KERN_INFO, fmt, ##__VA_ARGS__)
> +#define P3(fmt, ...) P(KERN_DEBUG, fmt, ##__VA_ARGS__)
Macro names can be bit more informative than p1 , P2 , P etc
> +
> +#define PA(level, msg, p_area) P##level(msg " (%03d %03d)-(%03d %03d)\n",
> \
> +	(p_area)->p0.x, (p_area)->p0.y, (p_area)->p1.x, (p_area)->p1.y)
> +
> +/* assign coordinates to area */
> +static inline
> +void assign(struct tcm_area *a, u16 x0, u16 y0, u16 x1, u16 y1)
> +{
> +	a->p0.x = x0;
> +	a->p0.y = y0;
> +	a->p1.x = x1;
> +	a->p1.y = y1;
> +}
> +
> +#endif
> --
> 1.6.3.3


^ permalink raw reply	[flat|nested] 46+ messages in thread

* RE: [RFC 3/8] TILER-DMM: Sample TCM implementation: Simple TILER Allocator
  2010-07-23 23:22     ` [RFC 3/8] TILER-DMM: Sample TCM implementation: Simple TILER Allocator David Sin
  2010-07-23 23:22       ` [RFC 4/8] TILER-DMM: TILER Memory Manager interface and implementation David Sin
@ 2010-07-24  7:13       ` Shilimkar, Santosh
  2010-07-25 15:45         ` Molnar, Lajos
  2010-07-26 19:33         ` Sin, David
  2010-07-27 20:41       ` Hiremath, Vaibhav
  2 siblings, 2 replies; 46+ messages in thread
From: Shilimkar, Santosh @ 2010-07-24  7:13 UTC (permalink / raw)
  To: Sin, David, linux-arm-kernel@lists.arm.linux.org.uk,
	linux-omap@vger.kernel.org, Tony
  Cc: Kanigeri, Hari, Ohad Ben-Cohen, Hiremath, Vaibhav,
	Ramachandra, Ravikiran, Molnar, Lajos

> -----Original Message-----
> From: Sin, David
> Sent: Saturday, July 24, 2010 4:52 AM
> To: linux-arm-kernel@lists.arm.linux.org.uk; linux-omap@vger.kernel.org;
> Tony Lindgren; Russell King
> Cc: Kanigeri, Hari; Ohad Ben-Cohen; Hiremath, Vaibhav; Shilimkar, Santosh;
> Ramachandra, Ravikiran; Molnar, Lajos; Sin, David
> Subject: [RFC 3/8] TILER-DMM: Sample TCM implementation: Simple TILER
> Allocator
>
> From: Ravi Ramachandra <r.ramachandra@ti.com>
>
> This patch implements a simple TILER Container Manager.
>
> Signed-off-by: Ravi Ramachandra <r.ramachandra@ti.com>
> Signed-off-by: Lajos Molnar <molnar@ti.com>
> Signed-off-by: David Sin <davidsin@ti.com>
> ---
>  drivers/media/video/tiler/tcm/Makefile    |    1 +
>  drivers/media/video/tiler/tcm/_tcm-sita.h |   64 ++++
Why is such a header file name. Can't you club
>  drivers/media/video/tiler/tcm/tcm-sita.c  |  459
> +++++++++++++++++++++++++++++
>  drivers/media/video/tiler/tcm/tcm-sita.h  |   37 +++
You should club _tcm-sita.h and tcm-sita.h together
>  4 files changed, 561 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/media/video/tiler/tcm/Makefile
>  create mode 100644 drivers/media/video/tiler/tcm/_tcm-sita.h
>  create mode 100644 drivers/media/video/tiler/tcm/tcm-sita.c
>  create mode 100644 drivers/media/video/tiler/tcm/tcm-sita.h
>
> diff --git a/drivers/media/video/tiler/tcm/Makefile
> b/drivers/media/video/tiler/tcm/Makefile
> new file mode 100644
> index 0000000..8434607
> --- /dev/null
> +++ b/drivers/media/video/tiler/tcm/Makefile
> @@ -0,0 +1 @@
> +obj-$(CONFIG_TI_TILER) += tcm-sita.o
> diff --git a/drivers/media/video/tiler/tcm/_tcm-sita.h
> b/drivers/media/video/tiler/tcm/_tcm-sita.h
> new file mode 100644
> index 0000000..4ede1ab
> --- /dev/null
> +++ b/drivers/media/video/tiler/tcm/_tcm-sita.h
> @@ -0,0 +1,64 @@
> +/*
> + * _tcm_sita.h
> + *
> + * SImple Tiler Allocator (SiTA) private structures.
> + *
> + * Author: Ravi Ramachandra <r.ramachandra@ti.com>
> + *
> + * Copyright (C) 2009-2010 Texas Instruments, Inc.
> + *
> + * This package is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
> + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
> + */
> +
> +#ifndef _TCM_SITA_H
> +#define _TCM_SITA_H
> +
> +#include "../tcm.h"
Header inclusion
> +
> +/* length between two coordinates */
> +#define LEN(a, b) ((a) > (b) ? (a) - (b) + 1 : (b) - (a) + 1)
> +
> +enum criteria {
> +     CR_MAX_NEIGHS           = 0x01,
> +     CR_FIRST_FOUND          = 0x10,
> +     CR_BIAS_HORIZONTAL      = 0x20,
> +     CR_BIAS_VERTICAL        = 0x40,
> +     CR_DIAGONAL_BALANCE     = 0x80
> +};
> +
> +/* nearness to the beginning of the search field from 0 to 1000 */
> +struct nearness_factor {
> +     s32 x;
> +     s32 y;
> +};
> +
> +/*
> + * Statistics on immediately neighboring slots.  Edge is the number of
> + * border segments that are also border segments of the scan field.  Busy
> + * refers to the number of neighbors that are occupied.
> + */
> +struct neighbor_stats {
> +     u16 edge;
> +     u16 busy;
> +};
> +
> +/* structure to keep the score of a potential allocation */
> +struct score {
> +     struct nearness_factor  f;
> +     struct neighbor_stats   n;
> +     struct tcm_area         a;
> +     u16    neighs;          /* number of busy neighbors */
> +};
> +
> +struct sita_pvt {
> +     struct mutex mtx;
> +     struct tcm_area ***map; /* pointers to the parent area for each slot
> */
> +};
> +
> +#endif
> diff --git a/drivers/media/video/tiler/tcm/tcm-sita.c
> b/drivers/media/video/tiler/tcm/tcm-sita.c
> new file mode 100644
> index 0000000..93be3e6
> --- /dev/null
> +++ b/drivers/media/video/tiler/tcm/tcm-sita.c
> @@ -0,0 +1,459 @@
> +/*
> + * tcm-sita.c
> + *
> + * SImple Tiler Allocator (SiTA): 2D and 1D allocation(reservation)
> algorithm
> + *
> + * Authors: Ravi Ramachandra <r.ramachandra@ti.com>,
> + *          Lajos Molnar <molnar@ti.com>
> + *
> + * Copyright (C) 2009-2010 Texas Instruments, Inc.
> + *
> + * This package is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
> + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
> + *
> + */
> +#include <linux/slab.h>
> +
> +#include "_tcm-sita.h"
> +#include "tcm-sita.h"
> +
> +#define TCM_ALG_NAME "tcm_sita"
> +#include "tcm-utils.h"
> +
> +#define ALIGN_DOWN(value, align) ((value) & ~((align) - 1))
> +
> +/* Individual selection criteria for different scan areas */
> +static s32 CR_L2R_T2B = CR_BIAS_HORIZONTAL;
> +
> +/*********************************************
> + *   TCM API - Sita Implementation
> + *********************************************/
Commenting style
> +static s32 sita_reserve_2d(struct tcm *tcm, u16 h, u16 w, u8 align,
> +                        struct tcm_area *area);
> +static s32 sita_free(struct tcm *tcm, struct tcm_area *area);
> +static void sita_deinit(struct tcm *tcm);
> +
> +/*********************************************
> + *   Main Scanner functions
> + *********************************************/
ditto
> +static s32 scan_areas_and_find_fit(struct tcm *tcm, u16 w, u16 h, u16
> align,
> +                                struct tcm_area *area);
> +
> +static s32 scan_l2r_t2b(struct tcm *tcm, u16 w, u16 h, u16 align,
> +                     struct tcm_area *field, struct tcm_area *area);
> +
> +/*********************************************
> + *   Support Infrastructure Methods
> + *********************************************/
ditto
> +static s32 is_area_free(struct tcm_area ***map, u16 x0, u16 y0, u16 w,
> u16 h);
> +
> +static s32 update_candidate(struct tcm *tcm, u16 x0, u16 y0, u16 w, u16
> h,
> +                         struct tcm_area *field, s32 criteria,
> +                         struct score *best);
> +
> +static void get_nearness_factor(struct tcm_area *field,
> +                             struct tcm_area *candidate,
> +                             struct nearness_factor *nf);
> +
> +static void get_neighbor_stats(struct tcm *tcm, struct tcm_area *area,
> +                            struct neighbor_stats *stat);
> +
> +static void fill_area(struct tcm *tcm,
> +                             struct tcm_area *area, struct tcm_area *parent);
> +
> +/*********************************************/
> +
> +/*********************************************
> + *   Utility Methods
> + *********************************************/
> +struct tcm *sita_init(u16 width, u16 height, void *attr)
> +{
> +     struct tcm *tcm;
> +     struct sita_pvt *pvt;
> +     struct tcm_area area = {0};
> +     s32 i;
> +
> +     if (width == 0 || height == 0)
> +             return NULL;
> +
> +     tcm = kzalloc(sizeof(*tcm), GFP_KERNEL);
> +     pvt = kzalloc(sizeof(*pvt), GFP_KERNEL);
> +     if (!tcm || !pvt)
> +             goto error;
> +
> +     /* Updating the pointers to SiTA implementation APIs */
> +     tcm->height = height;
> +     tcm->width = width;
> +     tcm->reserve_2d = sita_reserve_2d;
> +     tcm->free = sita_free;
> +     tcm->deinit = sita_deinit;
> +     tcm->pvt = (void *)pvt;
> +
> +     mutex_init(&(pvt->mtx));
> +
> +     /* Creating tam map */
> +     pvt->map = kzalloc(sizeof(*pvt->map) * tcm->width, GFP_KERNEL);
> +     if (!pvt->map)
> +             goto error;
> +
> +     for (i = 0; i < tcm->width; i++) {
> +             pvt->map[i] =
> +                     kzalloc(sizeof(**pvt->map) * tcm->height,
> +                                                             GFP_KERNEL);
> +             if (pvt->map[i] == NULL) {
> +                     while (i--)
> +                             kfree(pvt->map[i]);
> +                     kfree(pvt->map);
> +                     goto error;
> +             }
> +     }
> +
> +     mutex_lock(&(pvt->mtx));
> +     assign(&area, 0, 0, width - 1, height - 1);
> +     fill_area(tcm, &area, NULL);
> +     mutex_unlock(&(pvt->mtx));
> +     return tcm;
> +
> +error:
> +     kfree(tcm);
> +     kfree(pvt);
If only one of the allocation was successful, then you
are freeing a NULL pointer.
May be have something like this

        tcm = kzalloc(sizeof(*tcm), GFP_KERNEL);
        if (!tcm)
                goto error1;
        pvt = kzalloc(sizeof(*pvt), GFP_KERNEL);
        if (!pvt)
                goto error2;
        .
        .
        .
error1:
        kfree(tcm);
error2:
        kfree(pvt);

> +     return NULL;
> +}
> +
> +static void sita_deinit(struct tcm *tcm)
> +{
> +     struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
> +     struct tcm_area area = {0};
> +     s32 i;
> +
> +     area.p1.x = tcm->width - 1;
> +     area.p1.y = tcm->height - 1;
> +
> +     mutex_lock(&(pvt->mtx));
> +     fill_area(tcm, &area, NULL);
> +     mutex_unlock(&(pvt->mtx));
> +
> +     mutex_destroy(&(pvt->mtx));
> +
> +     for (i = 0; i < tcm->height; i++)
> +             kfree(pvt->map[i]);
> +     kfree(pvt->map);
> +     kfree(pvt);
> +}
> +
> +/**
> + * Reserve a 2D area in the container
> + *
> + * @param w  width
> + * @param h  height
> + * @param area       pointer to the area that will be populated with the
> reesrved
> + *           area
> + *
> + * @return 0 on success, non-0 error value on failure.
> + */
> +static s32 sita_reserve_2d(struct tcm *tcm, u16 h, u16 w, u8 align,
> +                        struct tcm_area *area)
> +{
> +     s32 ret;
> +     struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
> +
> +     /* not supporting more than 64 as alignment */
> +     if (align > 64)
> +             return -EINVAL;
> +
> +     /* we prefer 1, 32 and 64 as alignment */
> +     align = align <= 1 ? 1 : align <= 32 ? 32 : 64;
> +
> +     mutex_lock(&(pvt->mtx));
> +     ret = scan_areas_and_find_fit(tcm, w, h, align, area);
> +     if (!ret)
> +             /* update map */
> +             fill_area(tcm, area, area);
> +
> +     mutex_unlock(&(pvt->mtx));
> +     return ret;
> +}
> +
> +/**
> + * Unreserve a previously allocated 2D or 1D area
> + * @param area       area to be freed
> + * @return 0 - success
> + */
> +static s32 sita_free(struct tcm *tcm, struct tcm_area *area)
> +{
> +     struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
> +
> +     mutex_lock(&(pvt->mtx));
> +
> +     /* Clear the contents of the associated tiles in the map */
> +     fill_area(tcm, area, NULL);
> +
> +     mutex_unlock(&(pvt->mtx));
> +
> +     return 0;
> +}
> +
> +/**
> + * Note: In general the cordinates in the scan field area relevant to the
> can
> + * sweep directions. The scan origin (e.g. top-left corner) will always
> be
> + * the p0 member of the field.  Therfore, for a scan from top-left p0.x
> <= p1.x
> + * and p0.y <= p1.y; whereas, for a scan from bottom-right p1.x <= p0.x
> and p1.y
> + * <= p0.y
> + */
> +
> +/**
> + * Raster scan horizontally left to right from top to bottom to find a
> place for
> + * a 2D area of given size inside a scan field.
> + *
> + * @param w  width of desired area
> + * @param h  height of desired area
> + * @param align      desired area alignment
> + * @param area       pointer to the area that will be set to the best
> position
> + * @param field      area to scan (inclusive)
> + *
> + * @return 0 on success, non-0 error value on failure.
> + */
> +static s32 scan_l2r_t2b(struct tcm *tcm, u16 w, u16 h, u16 align,
> +                     struct tcm_area *field, struct tcm_area *area)
> +{
> +     s32 x, y;
> +     s16 start_x, end_x, start_y, end_y;
> +     struct tcm_area ***map = ((struct sita_pvt *)tcm->pvt)->map;
> +     struct score best = {{0}, {0}, {0}, 0};
> +
> +     PA(2, "scan_l2r_t2b:", field);
> +
> +     start_x = field->p0.x;
> +     end_x = field->p1.x;
> +     start_y = field->p0.y;
> +     end_y = field->p1.y;
> +
> +     /* check scan area co-ordinates */
> +     if (field->p1.x < field->p0.x ||
> +         field->p1.y < field->p0.y)
> +             return -EINVAL;
> +
> +     /* check if allocation would fit in scan area */
> +     if (w > LEN(end_x, start_x) || h > LEN(end_y, start_y))
> +             return -ENOSPC;
> +
> +     start_x = ALIGN(start_x, align);
> +
> +     /* check if allocation would still fit in scan area */
> +     if (w > LEN(end_x, start_x))
> +             return -ENOSPC;
> +
> +     /* adjust end_x and end_y, as allocation would not fit beyond */
> +     end_x = end_x - w + 1; /* + 1 to be inclusive */
> +     end_y = end_y - h + 1;
> +
> +     P2("ali=%d x=%d..%d y=%d..%d", align, start_x, end_x, start_y,
> end_y);
> +
> +     /* scan field top-to-bottom, left-to-right */
> +     for (y = start_y; y <= end_y; y++) {
> +             for (x = start_x; x <= end_x; x += align) {
> +                     if (is_area_free(map, x, y, w, h)) {
> +                             P3("found shoulder: %d,%d", x, y);
> +
> +                             /* update best candidate */
> +                             if (update_candidate(tcm, x, y, w, h, field,
> +                                                     CR_L2R_T2B, &best))
> +                                     goto done;
> +                             break;
> +                     } else if (map[x][y]) {
> +                             /* step over 2D areas */
> +                             x = ALIGN_DOWN(map[x][y]->p1.x, align);
> +                             P3("moving to: %d,%d", x, y);
> +                     }
> +             }
> +     }
> +
> +     if (!best.a.tcm)
> +             return -ENOSPC;
> +done:
> +     assign(area, best.a.p0.x, best.a.p0.y, best.a.p1.x, best.a.p1.y);
> +     return 0;
> +}
> +
> +/**
> + * Find a place for a 2D area of given size inside a scan field based on
> its
> + * alignment needs.
> + *
> + * @param w  width of desired area
> + * @param h  height of desired area
> + * @param align      desired area alignment
> + * @param area       pointer to the area that will be set to the best
> position
> + *
> + * @return 0 on success, non-0 error value on failure.
> + */
> +static s32 scan_areas_and_find_fit(struct tcm *tcm, u16 w, u16 h, u16
> align,
> +                                struct tcm_area *area)
> +{
> +     struct tcm_area field = {0};
> +
> +     /* scan whole container left to right, top to bottom */
> +     assign(&field, 0, 0, tcm->width - 1, tcm->height - 1);
> +     return scan_l2r_t2b(tcm, w, h, align, &field, area);
> +}
> +
> +/* check if an entire area is free */
> +static s32 is_area_free(struct tcm_area ***map, u16 x0, u16 y0, u16 w,
> u16 h)
> +{
> +     u16 x = 0, y = 0;
> +     for (y = y0; y < y0 + h; y++) {
> +             for (x = x0; x < x0 + w; x++) {
> +                     if (map[x][y])
> +                             return false;
> +             }
> +     }
> +     return true;
> +}
> +
> +/* fills an area with a parent tcm_area */
> +static void fill_area(struct tcm *tcm, struct tcm_area *area,
> +                     struct tcm_area *parent)
> +{
> +     s32 x, y;
> +     struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
> +
> +     PA(2, "fill 2d area", area);
> +     for (x = area->p0.x; x <= area->p1.x; ++x)
> +             for (y = area->p0.y; y <= area->p1.y; ++y)
> +                     pvt->map[x][y] = parent;
> +}
> +
> +/**
> + * Compares a candidate area to the current best area, and if it is a
> better
> + * fit, it updates the best to this one.
> + *
> + * @param x0, y0, w, h               top, left, width, height of candidate area
> + * @param field                      scan field
> + * @param criteria           scan criteria
> + * @param best                       best candidate and its scores
> + *
> + * @return 1 (true) if the candidate area is known to be the final best,
> so no
> + * more searching should be performed
> + */
> +static s32 update_candidate(struct tcm *tcm, u16 x0, u16 y0, u16 w, u16
> h,
> +                         struct tcm_area *field, s32 criteria,
> +                         struct score *best)
> +{
> +     struct score me;        /* score for area */
> +
> +     /*
> +      * If first found is enabled then we stop looking
> +      * NOTE: For horizontal bias we always give the first found, because
> our
> +      * scan is horizontal-raster-based and the first candidate will
> always
> +      * have the horizontal bias.
> +      */
> +     bool first = criteria & (CR_FIRST_FOUND | CR_BIAS_HORIZONTAL);
> +
> +     assign(&me.a, x0, y0, x0 + w - 1, y0 + h - 1);
> +
> +     /* calculate score for current candidate */
> +     if (!first) {
> +             get_neighbor_stats(tcm, &me.a, &me.n);
> +             me.neighs = me.n.edge + me.n.busy;
> +             get_nearness_factor(field, &me.a, &me.f);
> +     }
> +
> +     /* the 1st candidate is always the best */
> +     if (!best->a.tcm)
> +             goto better;
> +
> +     /* see if this are is better than the best so far */
> +
> +     /* neighbor check */
> +     if ((criteria & CR_MAX_NEIGHS) &&
> +             me.neighs > best->neighs)
> +             goto better;
> +
> +     /* vertical bias check */
> +     if ((criteria & CR_BIAS_VERTICAL) &&
> +     /*
> +      * NOTE: not checking if lengths are same, because that does not
> +      * find new shoulders on the same row after a fit
> +      */
> +             LEN(me.a.p0.y, field->p0.y) >
> +             LEN(best->a.p0.y, field->p0.y))
> +             goto better;
> +
> +     /* diagonal balance check */
> +     if ((criteria & CR_DIAGONAL_BALANCE) &&
> +             best->neighs <= me.neighs &&
> +             (best->neighs < me.neighs ||
> +              /* this implies that neighs and occupied match */
> +              best->n.busy < me.n.busy ||
> +              (best->n.busy == me.n.busy &&
> +               /* check the nearness factor */
> +               best->f.x + best->f.y > me.f.x + me.f.y)))
> +             goto better;
> +
> +     /* not better, keep going */
> +     return 0;
> +
> +better:
> +     /* save current area as best */
> +     memcpy(best, &me, sizeof(me));
> +     best->a.tcm = tcm;
> +     return first;
> +}
> +
> +/**
> + * Calculate the nearness factor of an area in a search field.  The
> nearness
> + * factor is smaller if the area is closer to the search origin.
> + */
> +static void get_nearness_factor(struct tcm_area *field, struct tcm_area
> *area,
> +                             struct nearness_factor *nf)
> +{
> +     /**
> +      * Using signed math as field coordinates may be reversed if
> +      * search direction is right-to-left or bottom-to-top.
> +      */
> +     nf->x = (s32)(area->p0.x - field->p0.x) * 1000 /
> +             (field->p1.x - field->p0.x);
> +     nf->y = (s32)(area->p0.y - field->p0.y) * 1000 /
> +             (field->p1.y - field->p0.y);
> +}
> +
> +/* get neighbor statistics */
> +static void get_neighbor_stats(struct tcm *tcm, struct tcm_area *area,
> +                      struct neighbor_stats *stat)
> +{
> +     s16 x = 0, y = 0;
> +     struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
> +
> +     /* Clearing any exisiting values */
> +     memset(stat, 0, sizeof(*stat));
> +
> +     /* process top & bottom edges */
> +     for (x = area->p0.x; x <= area->p1.x; x++) {
> +             if (area->p0.y == 0)
> +                     stat->edge++;
> +             else if (pvt->map[x][area->p0.y - 1])
> +                     stat->busy++;
> +
> +             if (area->p1.y == tcm->height - 1)
> +                     stat->edge++;
> +             else if (pvt->map[x][area->p1.y + 1])
> +                     stat->busy++;
> +     }
> +
> +     /* process left & right edges */
> +     for (y = area->p0.y; y <= area->p1.y; ++y) {
> +             if (area->p0.x == 0)
> +                     stat->edge++;
> +             else if (pvt->map[area->p0.x - 1][y])
> +                     stat->busy++;
> +
> +             if (area->p1.x == tcm->width - 1)
> +                     stat->edge++;
> +             else if (pvt->map[area->p1.x + 1][y])
> +                     stat->busy++;
> +     }
> +}
> diff --git a/drivers/media/video/tiler/tcm/tcm-sita.h
> b/drivers/media/video/tiler/tcm/tcm-sita.h
> new file mode 100644
> index 0000000..ab2d05b
> --- /dev/null
> +++ b/drivers/media/video/tiler/tcm/tcm-sita.h
> @@ -0,0 +1,37 @@
> +/*
> + * tcm_sita.h
> + *
> + * SImple Tiler Allocator (SiTA) interface.
> + *
> + * Author: Ravi Ramachandra <r.ramachandra@ti.com>
> + *
> + * Copyright (C) 2009-2010 Texas Instruments, Inc.
> + *
> + * This package is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
> + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
> + */
> +
> +#ifndef TCM_SITA_H
> +#define TCM_SITA_H
> +
> +#include "../tcm.h"
> +
> +/**
> + * Create a SiTA tiler container manager.
> + *
> + * @param width  Container width
> + * @param height Container height
> + * @param attr   unused
> + *
> + * @return TCM instance
> + */
> +struct tcm *sita_init(u16 width, u16 height, void *attr);
> +
> +TCM_INIT(sita_init, void);
Function name appears like a macro.
> +
> +#endif /* TCM_SITA_H_ */
> --
> 1.6.3.3


^ permalink raw reply	[flat|nested] 46+ messages in thread

* RE: [RFC 5/8] TILER-DMM: TILER interface file and documentation
  2010-07-23 23:22         ` [RFC 5/8] TILER-DMM: TILER interface file and documentation David Sin
  2010-07-23 23:22           ` [RFC 6/8] TILER-DMM: Geometry and view manipulation functions David Sin
@ 2010-07-24  7:21           ` Shilimkar, Santosh
  1 sibling, 0 replies; 46+ messages in thread
From: Shilimkar, Santosh @ 2010-07-24  7:21 UTC (permalink / raw)
  To: Sin, David, linux-arm-kernel@lists.arm.linux.org.uk,
	linux-omap@vger.kernel.org, Tony
  Cc: Kanigeri, Hari, Ohad Ben-Cohen, Hiremath, Vaibhav, Molnar, Lajos

> -----Original Message-----
> From: Sin, David
> Sent: Saturday, July 24, 2010 4:52 AM
> To: linux-arm-kernel@lists.arm.linux.org.uk; linux-omap@vger.kernel.org;
> Tony Lindgren; Russell King
> Cc: Kanigeri, Hari; Ohad Ben-Cohen; Hiremath, Vaibhav; Shilimkar, Santosh;
> Molnar, Lajos; Sin, David
> Subject: [RFC 5/8] TILER-DMM: TILER interface file and documentation
> 
> From: Lajos Molnar <molnar@ti.com>
> 
> This patch contains the TILER interface file and the documentation.
> 
> Signed-off-by: Lajos Molnar <molnar@ti.com>
> Signed-off-by: David Sin <davidsin@ti.com>
> ---
>  Documentation/arm/TILER                  |  144 +++++++++++++++++++++
>  arch/arm/mach-omap2/include/mach/tiler.h |  201
> ++++++++++++++++++++++++++++++
>  2 files changed, 345 insertions(+), 0 deletions(-)
>  create mode 100644 Documentation/arm/TILER
>  create mode 100644 arch/arm/mach-omap2/include/mach/tiler.h
> 
> diff --git a/Documentation/arm/TILER b/Documentation/arm/TILER
> new file mode 100644
> index 0000000..9c54037
> --- /dev/null
> +++ b/Documentation/arm/TILER
Documentation/arm/omap/TILER is better place for this.

> @@ -0,0 +1,144 @@
> +TILER driver
> +
> +TILER is a hardware block made by Texas Instruments.  Its purpose is to
> +organize video/image memory in a 2-dimensional fashion to limit memory
> +bandwidth and facilitate 0 effort rotation and mirroring.  The TILER
> driver
> +facilitates allocating, freeing, as well as mapping 2D blocks (areas) in
> the
> +TILER container(s).  It also facilitates rotating and mirroring the
> allocated
> +blocks or its rectangular subsections.
> +
> +TERMINOLOGY
> +
> +"slot"
> +
> +The basic TILER driver operates on blocks of slots.  A slot is the
> granularity
> +of the TILER hardware device.  For all current uses it is 4K, but could
> also be
> +16 or 64K.  The DMM-TILER TRM refers to this as "page" but we want to
> separate
> +this concept from the MMU pages.
> +
> +"page"
> +
> +The granularity of the MMU, used by the kernel.  This is 4K.
> +
> +"block"
> +
> +The TILER hardware block supports 1D and 2D blocks.  A 2D block is a
> rectangular
> +arrangement of slots with arbitrary width and height in a 2D container.
> A
> +1D block is a linear arrangement of slots with arbitrary length in a 1D
> +container.  This TILER driver only supports 2D blocks.
> +
> +"container"
> +
> +The TILER driver supports an arbitrary TILER container size.  However,
> for
> +all current implementations it is 256 by 128 slots.  The container
> currently can
> +only be used as a 2D container.
> +
> +"reserved area"
> +
> +Each block resides within a reserved area in the container.  This area
> may
> +be larger than the actual set of slots that a block occupies.  The reason
> for
> +this is to protect access from one block into another.  Since TILER
> container is
> +mmap-ped into user space as individual pages, all slots that are spanned
> by
> +that page become visible to the user.  The tiler driver allows
> restricting the
> +granularity of the reserved area (default alignment) as well as the
> mapped
> +area (granularity).
> +
> +KERNEL API to the TILER driver.
Do you mean TILER driver KERNEL APIs here ?
> +
> +1. Allocating and freeing a 1080p YUV422 block
> +
> +        struct tiler_block_t blk = {0};
> +        int res;
> +
> +        blk.width = 1920;
> +        blk.height = 1080;
> +        res = tiler_alloc(&blk, TILFMT_16BIT, 0, 0);
> +
> +        tiler_free(&blk);
> +
> +2. Allocating and freeing a 1080p YUV420p block
> +
> +        struct tiler_block_t blk_Y = {0}, blk_UV = {0};
> +        int res;
> +
> +        blk_Y.width = 1920;
> +        blk_Y.height = 1080;
> +        blk_UV.widht = 960;
> +        blk_UV.height = 540;
> +        res = tiler_alloc(&blk_Y, TILFMT_8BIT, 0, 0) ? :
> +                tiler_alloc(&blk_UV, TILFMT_16BIT, PAGE_SIZE,
> +                                blk_y->phys & ~PAGE_MASK);
> +
> +        tiler_free(&blk_Y);
> +        tiler_free(&blk_UV);
> +
> +Note how we allocated the UV block at the same in-page offset as the Y
> buffer.
> +This facilitates mmap-ping both Y and UV blocks into userspace as one
> +contiguous buffer.
> +
> +3. Mmap-ing YUV420p block into user space
> +
> +        static int my_mmap(struct file *file, struct vm_area_struct *vma)
> +        {
> +                unsigned long size = (vma->vm_end - vma->vm_start);
> +                unsigned long start = vma->vm_start;
> +
> +                if (size != tiler_size(&blk_Y) + tiler_size(&blk_UV))
> +                        return -EINVAL;
> +
> +                return tiler_mmap_blk(&blk_Y, 0, tiler_size(&blk_Y), vma,
> 0) ?
> +                        : tiler_mmap_blk(&blk_UV, 0, tiler_size(&blk_UV),
> vma,
> +                                tiler_size(&blk_Y));
> +        }
> +
> +4. Ioremap-ing YUV422 block into kernel space
> +
> +        void *my_ioremap(tiler_block_t *blk) {
> +                struct vm_struct *area;
> +                int res;
> +
> +                area = get_vm_area(tiler_size(&blk), VM_IOREMAP);
> +                if (!area)
> +                        return NULL;
> +
> +                int res = tiler_ioremap_blk(&blk, 0, tiler_size(&block),
> +                                        (u32) area->addr, MT_DEVICE_WC);
Doing ioremap on RAM feature is going away. Russell has a patch queued up
For this.
> +                if (res) {
> +                        vunmap(area->addr);
> +                        return NULL;
> +                }
> +                return area->addr;
> +        }
> +
> +CONFIGURATIONS
> +
> +The TILER driver allows specifying a container manager (tcm) for each
> +pixel format.  The same container manager can be specified for more than
> +one pixel formats.
> +
> +Each container manager also operates on a PAT instance.  One can also
> +specify a "virtual" PAT (with a linear preassigned memory space no actual
> +PAT programming), but it is not implemented.
> +
> +PARAMETERS
> +
> +The TILER driver allows specifying:
> +
> +    granularity (tiler.grain, CONFIG_TILER_GRANULARITY):
> +
> +        Each block is mapped in width-chunks of granularity.
> +
> +    default alignment (tiler.align, CONFIG_TILER_ALIGNMENT):
> +
> +        Default alignment if aligment is not specified (0). Otherwise,
> +        blocks are allocated at an address aligned to the value given
> plus an
> +        offset within the alignment.
> +
> +    cache limit (tiler.cache, CONFIG_TILER_CACHE_LIMIT):
> +
> +        TILER driver keeps a cache of allocated pages to speed up
> allocation of
> +        TILER blocks.  You can set a limit of how much memory the TILER
> driver
> +        should keep if there are no actual TILER allocations.  This also
> means
> +        that if there is less memory used than this limit, the pages of
> freed
> +        tiler blocks will not actually be freed, but instead are put into
> this
> +        cache.
> diff --git a/arch/arm/mach-omap2/include/mach/tiler.h b/arch/arm/mach-
> omap2/include/mach/tiler.h
> new file mode 100644
> index 0000000..8509678
> --- /dev/null
> +++ b/arch/arm/mach-omap2/include/mach/tiler.h
> @@ -0,0 +1,201 @@
> +/*
> + * tiler.h
> + *
> + * TILER driver support functions for TI TILER hardware block.
> + *
> + * Authors: Lajos Molnar <molnar@ti.com>
> + *          David Sin <davidsin@ti.com>
> + *
> + * Copyright (C) 2009-2010 Texas Instruments, Inc.
> + *
> + * This package is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
> + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
> + */
> +
> +#ifndef TILER_H
> +#define TILER_H
> +
> +#include <linux/mm.h>
> +
> +/*
> + * ----------------------------- API Definitions ------------------------
> -----
> + */
Please stick to Linux commenting style
> +
> +/* return true if physical address is in the tiler container */
> +bool is_tiler_addr(u32 phys);
> +
> +enum tiler_fmt {
> +	TILFMT_MIN     = -2,
> +	TILFMT_INVALID = -2,
> +	TILFMT_NONE    = -1,
> +	TILFMT_8BIT    = 0,
> +	TILFMT_16BIT   = 1,
> +	TILFMT_32BIT   = 2,
> +	TILFMT_MAX     = 2,
> +	TILFMT_PAGE    = 3,	/* for completeness */
> +};
> +
> +/* tiler block info */
> +struct tiler_block_t {
> +	u32 phys;		/* system space (L3) tiler addr */
> +	u32 width;		/* width */
> +	u32 height;		/* height */
> +};
> +
> +/* tiler (image/video frame) view */
> +struct tiler_view_t {
> +	u32 tsptr;		/* tiler space addr */
> +	u32 width;		/* width */
> +	u32 height;		/* height */
> +	u32 bpp;		/* bytes per pixel */
> +	s32 h_inc;		/* horizontal increment */
> +	s32 v_inc;		/* vertical increment */
> +};
> +
> +/* get tiler format for a physical address */
> +enum tiler_fmt tiler_fmt(u32 phys);
> +
> +/* get tiler block bytes-per-pixel */
> +u32 tiler_bpp(const struct tiler_block_t *b);
> +
> +/* get tiler block physical stride */
> +u32 tiler_pstride(const struct tiler_block_t *b);
> +
> +/* get tiler block virtual stride */
> +static inline u32 tiler_vstride(const struct tiler_block_t *b)
> +{
> +	return PAGE_ALIGN((b->phys & ~PAGE_MASK) + tiler_bpp(b) * b->width);
> +}
> +
> +/* returns the virtual size of the block (for mmap) */
> +static inline u32 tiler_size(const struct tiler_block_t *b)
> +{
> +	return b->height * tiler_vstride(b);
> +}
> +
> +/**
> + * Reserves a 2D TILER block area and memory.
> + *
> + * @param blk	pointer to tiler block data.  This must be set up
> ('phys' member
> + *		must be 0) with the tiler block information.
> + * @param fmt	TILER block format
> + * @param align	block alignment (default: normally PAGE_SIZE)
> + * @param offs	block offset
> + *
> + * @return error status
> + */
> +s32 tiler_alloc(struct tiler_block_t *blk, enum tiler_fmt fmt, u32 align,
> +		u32 offs);
> +
> +/**
> + * Mmaps a portion of a tiler block to a virtual address.  Use this
> method in
> + * your driver's mmap function to potentially combine multiple tiler
> blocks as
> + * one virtual buffer.
> + *
> + * @param blk		pointer to tiler block data
> + * @param offs		offset from where to map (must be page aligned)
> + * @param size		size of area to map (must be page aligned)
> + * @param vma		VMM memory area to map to
> + * @param voffs		offset (from vm_start) in the VMM memory area to
> start
> + *			mapping at
> + *
> + * @return error status
> + */
> +s32 tiler_mmap_blk(struct tiler_block_t *blk, u32 offs, u32 size,
> +				struct vm_area_struct *vma, u32 voffs);
> +
> +/**
> + * Ioremaps a portion of a tiler block.  Use this method in your driver
> instead
> + * of ioremap to potentially combine multiple tiler blocks as one virtual
> + * buffer.
> + *
> + * @param blk		pointer to tiler block data
> + * @param offs		offset from where to map (must be page aligned)
> + * @param size		size of area to map (must be page aligned)
> + * @param addr		virtual address
> + * @param mtype		ioremap memory type (e.g. MT_DEVICE)
> + *
> + * @return error status
> + */
> +s32 tiler_ioremap_blk(struct tiler_block_t *blk, u32 offs, u32 size, u32
> addr,
> +							u32 mtype);
> +
> +/**
> + * Frees TILER memory.  Since there may be multiple references for the
> same area
> + * if duplicated by tiler_dup, the area is only actually freed if all
> references
> + * have been freed.
> + *
> + * @param blk	pointer to a tiler block data as filled by tiler_alloc,
> + *		tiler_map or tiler_dup.  'phys' member will be set to 0 on
> + *		success.
> + */
> +void tiler_free(struct tiler_block_t *blk);
> +
> +/**
> + * Create a view based on a tiler address and width and height
> + *
> + * This method should only be used as a last resort, e.g. if tilview
> object
> + * cannot be passed because of incoherence with other view 2D objects
> that must
> + * be supported.
> + *
> + * @param view		Pointer to a view where the information will be
> stored
> + * @param ssptr		MUST BE a tiler address
> + * @param width		view width
> + * @param height	view height
> + */
> +void tilview_create(struct tiler_view_t *view, u32 phys, u32 width, u32
> height);
> +
> +/**
> + * Obtains the view information for a tiler block
> + *
> + * @param view		Pointer to a view where the information will be
> stored
> + * @param blk		Pointer to an existing allocated tiler block
> + */
> +void tilview_get(struct tiler_view_t *view, struct tiler_block_t *blk);
> +
> +/**
> + * Crops a tiler view to a rectangular portion. Crop area must be fully
> within
> + * the orginal tiler view: 0 <= left <= left + width <= view->width,
> also:
> + * 0 <= top <= top + height <= view->height.
> + *
> + * @param view		Pointer to tiler view to be cropped
> + * @param left		x of top-left corner
> + * @param top		y of top-left corner
> + * @param width		crop width
> + * @param height	crop height
> + *
> + * @return error status.  The view will be reduced to the crop region if
> the
> + *	   crop region is correct.  Otherwise, no modifications are made.
> + */
> +s32 tilview_crop(struct tiler_view_t *view, u32 left, u32 top, u32 width,
> +								u32 height);
> +
> +/**
> + * Rotates a tiler view clockwise by a specified degree.
> + *
> + * @param view		Pointer to tiler view to be cropped
> + * @param rotate	Degree of rotation (clockwise).  Must be a multiple of
> + *			90.
> + * @return error status.  View is not modified on error; otherwise, it is
> + *	   updated in place.
> + */
> +s32 tilview_rotate(struct tiler_view_t *view, s32 rotation);
> +
> +/**
> + * Mirrors a tiler view horizontally and/or vertically.
> + *
> + * @param view		Pointer to tiler view to be cropped
> + * @param flip_x	Mirror horizontally (left-to-right)
> + * @param flip_y	Mirror vertically (top-to-bottom)
> + *
> + * @return error status.  View is not modified on error; otherwise, it is
> + *	   updated in place.
> + */
> +s32 tilview_flip(struct tiler_view_t *view, bool flip_x, bool flip_y);
> +
> +#endif
> --
> 1.6.3.3


^ permalink raw reply	[flat|nested] 46+ messages in thread

* RE: [RFC 7/8] TILER-DMM: Main TILER driver implementation.
  2010-07-23 23:22             ` [RFC 7/8] TILER-DMM: Main TILER driver implementation David Sin
  2010-07-23 23:22               ` [RFC 8/8] TILER-DMM: Linking TILER driver into the Linux kernel build David Sin
@ 2010-07-24  7:32               ` Shilimkar, Santosh
  2010-07-24 13:41                 ` Hari Kanigeri
  2010-07-24  7:55               ` Russell King - ARM Linux
  2 siblings, 1 reply; 46+ messages in thread
From: Shilimkar, Santosh @ 2010-07-24  7:32 UTC (permalink / raw)
  To: Sin, David, linux-arm-kernel@lists.arm.linux.org.uk,
	linux-omap@vger.kernel.org, Tony
  Cc: Kanigeri, Hari, Ohad Ben-Cohen, Hiremath, Vaibhav, Molnar, Lajos

> -----Original Message-----
> From: Sin, David
> Sent: Saturday, July 24, 2010 4:52 AM
> To: linux-arm-kernel@lists.arm.linux.org.uk; linux-omap@vger.kernel.org;
> Tony Lindgren; Russell King
> Cc: Kanigeri, Hari; Ohad Ben-Cohen; Hiremath, Vaibhav; Shilimkar, Santosh;
> Molnar, Lajos; Sin, David
> Subject: [RFC 7/8] TILER-DMM: Main TILER driver implementation.
>
> From: Lajos Molnar <molnar@ti.com>
>
> This patch contains the TILER driver and implementation of the TILER
> block manipulation and mapping functions.
>
> It also contains the makefile and config file for the TILER driver.
>
> Signed-off-by: Lajos Molnar <molnar@ti.com>
> Signed-off-by: David Sin <davidsin@ti.com>
> ---
>  drivers/media/video/tiler/Kconfig       |   65 +++++
>  drivers/media/video/tiler/Makefile      |    7 +
>  drivers/media/video/tiler/tiler-iface.c |  106 ++++++++
>  drivers/media/video/tiler/tiler-main.c  |  426
> +++++++++++++++++++++++++++++++
>  4 files changed, 604 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/media/video/tiler/Kconfig
>  create mode 100644 drivers/media/video/tiler/Makefile
>  create mode 100644 drivers/media/video/tiler/tiler-iface.c
>  create mode 100644 drivers/media/video/tiler/tiler-main.c
>
> diff --git a/drivers/media/video/tiler/Kconfig
> b/drivers/media/video/tiler/Kconfig
> new file mode 100644
> index 0000000..2c61471
> --- /dev/null
> +++ b/drivers/media/video/tiler/Kconfig
> @@ -0,0 +1,65 @@
> +config HAVE_TI_TILER
> +        bool
> +        default y
> +        depends on ARCH_OMAP4
> +
> +menuconfig TI_TILER
> +        tristate "TI TILER support"
> +        default y
> +        depends on HAVE_TI_TILER
> +        help
> +           TILER and TILER-DMM driver for TI chips.  The TI TILER device
> +           enables video rotation on certain TI chips such as OMAP4 or
> +           Netra.  Video rotation will be limited without TILER support.
Sorry but I don't understand the need of above two entries. Should one entry not sufficient ?
> +
> +config TILER_GRANULARITY
> +        int "Allocation granularity (2^n)"
> +        range 1 4096
> +        default 128
> +        depends on TI_TILER
> +        help
> +           This option sets the default TILER allocation granularity.  It
> can
> +           be overriden by the tiler.grain boot argument.
> +
> +           The allocation granularity is the smallest TILER block size
> (in
> +           bytes) managed distinctly by the TILER driver.  TILER blocks
> of any
> +           size are managed in chunks of at least this size.
> +
> +           Must be a 2^n in the range of 1 to 4096; however, the TILER
> driver
> +           may use a larger supported granularity.
> +
> +           Supported values are: 1, 2, 4, 8, 16, 32, 64, 128, 256, 512,
> 1024,
> +           2048, 4096.
> +
> +config TILER_ALIGNMENT
> +        int "Allocation alignment (2^n)"
> +        range 1 4096
> +        default 4096
> +        depends on TI_TILER
> +        help
> +           This option sets the default TILER allocation alignment.  It
> can
> +           be overriden by the tiler.align boot argument.
Do you want this entry since you already support boot-argument ?
> +
> +           Must be a 2^n in the range of 1 to 4096; however, it is
> naturally
> +           aligned to the TILER granularity.
> +
> +           Supported values are: 1, 2, 4, 8, 16, 32, 64, 128, 256, 512,
> 1024,
> +           2048, 4096.
> +
> +config TILER_CACHE_LIMIT
> +        int "Memory limit to cache free pages in MBytes"
> +        range 0 128
> +        default 40
> +        depends on TI_TILER
> +        help
> +           This option sets the minimum memory that TILER retains even if
> +           there is less TILER allocated memory is use.  The unused
> memory is
> +           instead stored in a cache to speed up allocation and freeing
> of
> +           physical pages.
> +
> +           This option can be overriden by the tiler.cache boot argument.
> +
> +           While initially TILER will use less memory than this limit
> (0), it
> +           will not release any memory used until it reaches this limit.
> +           Thereafter, TILER will release any unused memory immediately
> as
> +           long as there it is above this threshold.
> diff --git a/drivers/media/video/tiler/Makefile
> b/drivers/media/video/tiler/Makefile
> new file mode 100644
> index 0000000..4a6495e
> --- /dev/null
> +++ b/drivers/media/video/tiler/Makefile
> @@ -0,0 +1,7 @@
> +obj-$(CONFIG_TI_TILER) += tcm/
> +
> +obj-$(CONFIG_TI_TILER) += tiler.o
> +tiler-objs = tiler-geom.o tiler-main.o tiler-iface.o tmm-pat.o
> +
> +obj-$(CONFIG_TI_TILER) += tiler_dmm.o
> +tiler_dmm-objs = dmm.o
> diff --git a/drivers/media/video/tiler/tiler-iface.c
> b/drivers/media/video/tiler/tiler-iface.c
> new file mode 100644
> index 0000000..0b10fae
> --- /dev/null
> +++ b/drivers/media/video/tiler/tiler-iface.c
> @@ -0,0 +1,106 @@
> +/*
> + * tiler-iface.c
> + *
> + * TILER driver interace functions for TI TILER hardware block.
> + *
> + * Authors: Lajos Molnar <molnar@ti.com>
> + *          David Sin <davidsin@ti.com>
> + *
> + * Copyright (C) 2009-2010 Texas Instruments, Inc.
> + *
> + * This package is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
> + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/slab.h>              /* kmalloc */
> +#include <linux/mm.h>
> +#include <linux/mm_types.h>
> +#include <asm/mach/map.h>    /* for ioremap_page */
> +
> +#include "_tiler.h"
> +
> +/*
> + *  Memory-Map Kernel APIs
> + *
> ==========================================================================
> + */
> +
> +s32 tiler_mmap_blk(struct tiler_block_t *blk, u32 offs, u32 size,
> +                             struct vm_area_struct *vma, u32 voffs)
> +{
> +     u32 v, p, len;
> +
> +     /* don't allow mremap */
> +     vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED;
Should we add " VM_LOCKED" as well considering the page swapping  ?
> +
> +     /* mapping must fit into vma */
> +     BUG_ON(vma->vm_start > vma->vm_start + voffs ||
> +             vma->vm_start + voffs > vma->vm_start + voffs + size ||
> +             vma->vm_start + voffs + size > vma->vm_end);
> +
> +     /* mapping must fit into block */
> +     BUG_ON(offs > offs + size || offs + size > tiler_size(blk));
> +
> +     v = tiler_vstride(blk);
> +     p = tiler_pstride(blk);
> +
> +     /* remap block portion */
> +     len = v - (offs % v);   /* initial area to map */
> +     while (size) {
> +             /* restrict to size still needs mapping */
> +             if (len > size)
> +                     len = size;
> +
> +             vma->vm_pgoff = (blk->phys + offs) >> PAGE_SHIFT;
> +             if (remap_pfn_range(vma, vma->vm_start + voffs, vma->vm_pgoff,
> +                                 len, vma->vm_page_prot))
> +                     return -EAGAIN;
> +             voffs += len;
> +             offs += len + p - v;
> +             size -= len;
> +             len = v;        /* subsequent area to map */
> +     }
> +     return 0;
> +}
> +EXPORT_SYMBOL(tiler_mmap_blk);
> +
> +s32 tiler_ioremap_blk(struct tiler_block_t *blk, u32 offs, u32 size,
> +                             u32 addr, u32 mtype)
> +{
> +     u32 v, p;
> +     u32 len;                /* area to map */
> +     const struct mem_type *type = get_mem_type(mtype);
> +
> +     /* mapping must fit into address space */
> +     BUG_ON(addr > addr + size);
> +
> +     /* mapping must fit into block */
> +     BUG_ON(offs > offs + size || offs + size > tiler_size(blk));
> +
> +     v = tiler_vstride(blk);
> +     p = tiler_pstride(blk);
> +
> +     /* move offset and address to end */
> +     offs += blk->phys + size;
> +     addr += size;
> +
> +     len = v - (offs % v);   /* initial area to map */
> +     while (size) {
> +             while (len && size) {
> +                     if (ioremap_page(addr - size, offs - size, type))
Same comment about doing iormap on RAM.
> +                             return -EAGAIN;
> +                     len  -= PAGE_SIZE;
> +                     size -= PAGE_SIZE;
> +             }
> +
> +             offs += p - v;
> +             len = v;        /* subsequent area to map */
> +     }
> +     return 0;
> +}
> +EXPORT_SYMBOL(tiler_ioremap_blk);
> diff --git a/drivers/media/video/tiler/tiler-main.c
> b/drivers/media/video/tiler/tiler-main.c
> new file mode 100644
> index 0000000..cbd84d1
> --- /dev/null
> +++ b/drivers/media/video/tiler/tiler-main.c
> @@ -0,0 +1,426 @@
> +/*
> + * tiler-main.c
> + *
> + * TILER driver main support functions for TI TILER hardware block.
> + *
> + * Authors: Lajos Molnar <molnar@ti.com>
> + *          David Sin <davidsin@ti.com>
> + *
> + * Copyright (C) 2009-2010 Texas Instruments, Inc.
> + *
> + * This package is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
> + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>   /* platform_device() */
> +#include <linux/errno.h>
> +#include <linux/mutex.h>
> +#include <linux/dma-mapping.h>               /* dma_alloc_coherent */
> +#include <linux/pagemap.h>           /* page_cache_release() */
> +#include <linux/slab.h>
> +
> +#include <mach/dmm.h>
> +#include "tmm.h"
> +#include "_tiler.h"
> +#include "tcm/tcm-sita.h"            /* TCM algorithm */
> +
> +static uint default_align = CONFIG_TILER_ALIGNMENT;
> +static uint granularity = CONFIG_TILER_GRANULARITY;
> +
> +module_param_named(align, default_align, uint, 0444);
> +MODULE_PARM_DESC(align, "Default block ssptr alignment");
> +module_param_named(grain, granularity, uint, 0444);
> +MODULE_PARM_DESC(grain, "Granularity (bytes)");
> +
> +struct platform_driver tiler_driver_ldm = {
> +     .driver = {
> +             .owner = THIS_MODULE,
> +             .name = "tiler",
> +     },
> +     .probe = NULL,
> +     .shutdown = NULL,
> +     .remove = NULL,
> +};
> +
> +static struct tiler_ops tiler;               /* shared methods and variables
> */
> +
> +static struct list_head blocks;              /* all tiler blocks */
> +
> +static struct mutex mtx;
> +static struct tcm *tcm[TILER_FORMATS];
> +static struct tmm *tmm[TILER_FORMATS];
> +static u32 *dmac_va;
> +static dma_addr_t dmac_pa;
> +
> +/* info for a block */
> +struct mem_info {
> +     struct list_head global;        /* global blocks */
> +     struct tiler_block_t blk;       /* block info */
> +     struct tcm_area area;
> +     u32 *mem;                       /* list of alloced phys addresses */
> +};
> +
> +/*
> + *  TMM connectors
> + *
> ==========================================================================
> + */
> +/* wrapper around tmm_map */
> +static s32 refill_pat(struct tmm *tmm, struct tcm_area *area, u32 *ptr)
> +{
> +     s32 res = 0;
> +     struct pat_area p_area = {0};
> +
> +     p_area.x0 = area->p0.x;
> +     p_area.y0 = area->p0.y;
> +     p_area.x1 = area->p1.x;
> +     p_area.y1 = area->p1.y;
> +
> +     memcpy(dmac_va, ptr, sizeof(*ptr) * tcm_sizeof(*area));
> +
> +     if (tmm_map(tmm, p_area, dmac_pa))
> +             res = -EFAULT;
> +
> +     return res;
> +}
> +
> +/* wrapper around tmm_clear */
> +static void clear_pat(struct tmm *tmm, struct tcm_area *area)
> +{
> +     struct pat_area p_area = {0};
> +
> +     p_area.x0 = area->p0.x;
> +     p_area.y0 = area->p0.y;
> +     p_area.x1 = area->p1.x;
> +     p_area.y1 = area->p1.y;
> +
> +     tmm_clear(tmm, p_area);
> +}
> +
> +/*
> + *  Area handling methods
> + *
> ==========================================================================
> + */
> +
> +/* verify input params and calculate tiler container params for a block
> */
> +static s32 __analize_area(enum tiler_fmt fmt, u32 width, u32 height,
> +                       u16 *x_area, u16 *y_area, u16 *align, u16 *offs)
> +{
> +     /* input: width, height is in pixels, *align, *offs in bytes */
> +     /* output: x_area, y_area, *align in slots */
> +
> +     /* slot width, height, and row size */
> +     u32 slot_row, min_align;
> +     const struct tiler_geom *g;
> +
> +     /* width and height must be positive, format must be 2D */
> +     if (!width || !height || fmt == TILFMT_PAGE)
> +             return -EINVAL;
> +
> +     /* align must be 2 power */
> +     if (*align & (*align - 1))
> +             return -EINVAL;
> +
> +     /* format must be valid */
> +     g = tiler.geom(fmt);
> +     if (!g)
> +             return -EINVAL;
> +
> +     /* get the # of bytes per row in 1 slot */
> +     slot_row = g->slot_w * g->bpp;
> +
> +     /* minimum alignment is at least 1 slot.  Use default if needed */
> +     min_align = max(slot_row, granularity);
> +     *align = ALIGN(*align ? : default_align, min_align);
> +
> +     /* offset must be multiple of bpp */
> +     if (*offs & (g->bpp - 1) || *offs >= *align)
> +             return -EINVAL;
> +
> +     /* round down the offset to the nearest slot size, and increase
> width
> +        to allow space for having the correct offset */
> +     width += (*offs & (min_align - 1)) / g->bpp;
> +
> +     /* expand width to block size */
> +     width = ALIGN(width, min_align / g->bpp);
> +
> +     /* adjust to slots */
> +     *x_area = DIV_ROUND_UP(width, g->slot_w);
> +     *y_area = DIV_ROUND_UP(height, g->slot_h);
> +     *align /= slot_row;
> +
> +     if (*x_area > tiler.width || *y_area > tiler.height)
> +             return -ENOMEM;
> +     return 0;
> +}
> +
> +/* allocate a mem_info structure and reserves a 2d container area */
> +static struct mem_info *get_2d_area(u16 w, u16 h, u16 align, struct tcm
> *tcm)
> +{
> +     struct mem_info *mi = NULL;
> +
> +     /* reserve a block struct */
> +     mi = kmalloc(sizeof(*mi), GFP_KERNEL);
> +     if (!mi)
> +             return mi;
> +     memset(mi, 0, sizeof(*mi));
> +
> +     /* reserve an area */
> +     if (tcm_reserve_2d(tcm, w, h, align, &mi->area)) {
> +             kfree(mi);
> +             return NULL;
> +     }
> +
> +     return mi;
> +}
> +
> +/*
> + *  Block operations
> + *
> ==========================================================================
> + */
> +
> +/* free a block */
> +static s32 free_block(struct mem_info *mi)
> +{
> +     /* release memory */
> +     if (mi->mem)
> +             tmm_free(tmm[tiler_fmt(mi->blk.phys)], mi->mem);
> +     clear_pat(tmm[tiler_fmt(mi->blk.phys)], &mi->area);
> +
> +     /* unreserve area */
> +     tcm_free(&mi->area);
> +
> +     /* have mutex */
> +
> +     /* safe deletion as list may not have been assigned */
> +     if (mi->global.next)
> +             list_del(&mi->global);
> +
> +     kfree(mi);
> +     return 0;
> +}
> +
> +/* create an empty block with just an area and add it to the global list
> */
> +static struct mem_info *get_area(enum tiler_fmt fmt, u32 width, u32
> height,
> +                                                     u16 align, u16 offs)
> +{
> +     u16 x, y;
> +     struct mem_info *mi = NULL;
> +     const struct tiler_geom *g = tiler.geom(fmt);
> +
> +     /* calculate dimensions and alignment in slots */
> +     if (__analize_area(fmt, width, height, &x, &y, &align, &offs))
> +             return NULL;
> +
> +     mi = get_2d_area(x, y, align, tcm[fmt]);
> +     if (!mi)
> +             return NULL;
> +
> +     /* have mutex */
> +     list_add(&mi->global, &blocks);
> +
> +     mi->blk.phys = tiler.addr(fmt,
> +             mi->area.p0.x * g->slot_w, mi->area.p0.y * g->slot_h)
> +             + offs;
> +     return mi;
> +}
> +
> +/* allocate a new tiler block */
> +static s32 alloc_block(enum tiler_fmt fmt, u32 width, u32 height,
> +             u32 align, u32 offs, struct mem_info **info)
> +{
> +     struct mem_info *mi = NULL;
> +
> +     *info = NULL;
> +
> +     /* only support up to page alignment */
> +     if (align > PAGE_SIZE || offs >= (align ? : default_align))
> +             return -EINVAL;
> +
> +     mutex_lock(&mtx);
> +
> +     /* reserve area in tiler container */
> +     mi = get_area(fmt, width, height, align, offs);
> +     if (!mi)
> +             goto nomem;
> +
> +     mi->blk.width = width;
> +     mi->blk.height = height;
> +
> +     /* allocate and map if mapping is supported */
> +     if (tmm_can_map(tmm[fmt])) {
> +             mi->mem = tmm_get(tmm[fmt], tcm_sizeof(mi->area));
> +             if (!mi->mem)
> +                     goto cleanup;
> +
> +             /* Ensure the data reaches to main memory before PAT refill */
> +             wmb();
> +
> +             /* program PAT */
> +             if (refill_pat(tmm[fmt], &mi->area, mi->mem))
> +                     goto cleanup;
> +     }
> +     *info = mi;
> +     mutex_unlock(&mtx);
> +     return 0;
> +
> +cleanup:
> +     free_block(mi);
> +nomem:
> +     mutex_unlock(&mtx);
> +     return -ENOMEM;
> +}
> +
> +/*
> + *  Driver code
> + *
> ==========================================================================
> + */
> +
> +/* driver initialization */
> +static s32 __init tiler_init(void)
> +{
> +     s32 r = -1;
> +     struct tcm *sita = NULL;
> +     struct tmm *tmm_pat = NULL;
> +
> +     tiler_geom_init(&tiler);
> +
> +     /* check module parameters for correctness */
> +     if (default_align > PAGE_SIZE ||
> +         default_align & (default_align - 1) ||
> +         granularity < 1 || granularity > PAGE_SIZE ||
> +         granularity & (granularity - 1))
> +             return -EINVAL;
> +
> +     /*
> +      * Array of physical pages for PAT programming, which must be a 16-
> byte
> +      * aligned physical address.
> +      */
> +     dmac_va = dma_alloc_coherent(NULL, tiler.width * tiler.height *
> +                                     sizeof(*dmac_va), &dmac_pa, GFP_ATOMIC);
> +     if (!dmac_va)
> +             return -ENOMEM;
> +
> +     /* Allocate tiler container manager (we share 1 on OMAP4) */
> +     sita = sita_init(tiler.width, tiler.height, NULL);
> +
> +     tcm[TILFMT_8BIT]  = sita;
> +     tcm[TILFMT_16BIT] = sita;
> +     tcm[TILFMT_32BIT] = sita;
> +
> +     /* Allocate tiler memory manager (must have 1 unique TMM per TCM )
> */
> +     tmm_pat = tmm_pat_init(0);
> +     tmm[TILFMT_8BIT]  = tmm_pat;
> +     tmm[TILFMT_16BIT] = tmm_pat;
> +     tmm[TILFMT_32BIT] = tmm_pat;
> +
> +     if (!sita || !tmm_pat) {
> +             r = -ENOMEM;
> +             goto error;
> +     }
> +
> +     r = platform_driver_register(&tiler_driver_ldm);
> +
> +     mutex_init(&mtx);
> +     INIT_LIST_HEAD(&blocks);
> +
> +error:
> +     if (r) {
> +             tcm_deinit(sita);
> +             tmm_deinit(tmm_pat);
> +             dma_free_coherent(NULL, tiler.width * tiler.height *
> +                                     sizeof(*dmac_va), dmac_va, dmac_pa);
> +     }
> +
> +     return r;
> +}
> +
> +/* driver cleanup */
> +static void __exit tiler_exit(void)
> +{
> +     int i, j;
> +     struct mem_info *mi, *mi_;
> +
> +     mutex_lock(&mtx);
> +
> +     /* free all blocks */
> +     list_for_each_entry_safe(mi, mi_, &blocks, global)
> +             free_block(mi);
> +
> +     /* all lists should have cleared */
> +     BUG_ON(!list_empty(&blocks));
> +
> +     mutex_unlock(&mtx);
> +
> +     dma_free_coherent(NULL, tiler.width * tiler.height *
> sizeof(*dmac_va),
> +                                                     dmac_va, dmac_pa);
> +
> +     /* close containers only once */
> +     for (i = TILFMT_MIN; i <= TILFMT_MAX; i++) {
> +             /* remove identical containers (tmm is unique per tcm) */
> +             for (j = i + 1; j <= TILFMT_MAX; j++)
> +                     if (tcm[i] == tcm[j]) {
> +                             tcm[j] = NULL;
> +                             tmm[j] = NULL;
> +                     }
> +
> +             tcm_deinit(tcm[i]);
> +             tmm_deinit(tmm[i]);
> +     }
> +
> +     mutex_destroy(&mtx);
> +     platform_driver_unregister(&tiler_driver_ldm);
> +}
> +
> +/*
> + *  Block Kernel APIs
> + *
> ==========================================================================
> + */
> +
> +s32 tiler_alloc(struct tiler_block_t *blk, enum tiler_fmt fmt,
> +             u32 align, u32 offs)
> +{
> +     struct mem_info *mi;
> +     s32 res;
> +
> +     /* blk must be valid, and blk->phys must be 0 */
> +     BUG_ON(!blk || blk->phys);
> +
> +     res = alloc_block(fmt, blk->width, blk->height, align, offs, &mi);
> +     if (mi)
> +             blk->phys = mi->blk.phys;
> +     return res;
> +}
> +EXPORT_SYMBOL(tiler_alloc);
> +
> +void tiler_free(struct tiler_block_t *blk)
> +{
> +     struct mem_info *mi;
> +
> +     mutex_lock(&mtx);
> +
> +     /* find block */
> +     list_for_each_entry(mi, &blocks, global) {
> +             if (mi->blk.phys == blk->phys) {
> +                     free_block(mi);
> +                     break;
> +             }
> +     }
> +
> +     blk->phys = 0;
> +
> +     mutex_unlock(&mtx);
> +}
> +EXPORT_SYMBOL(tiler_free);
> +
> +MODULE_LICENSE("GPL v2");
> +MODULE_AUTHOR("Lajos Molnar <molnar@ti.com>");
> +MODULE_AUTHOR("David Sin <davidsin@ti.com>");
> +module_init(tiler_init);
> +module_exit(tiler_exit);
> --
> 1.6.3.3


^ permalink raw reply	[flat|nested] 46+ messages in thread

* RE: [RFC 0/8] TI TILER-DMM driver
  2010-07-23 23:22 [RFC 0/8] TI TILER-DMM driver David Sin
  2010-07-23 23:22 ` [RFC 1/8] TILER-DMM: DMM-PAT driver for TI TILER David Sin
@ 2010-07-24  7:44 ` Shilimkar, Santosh
  2010-07-26 19:20   ` Sin, David
  2010-07-24 11:12 ` Hans Verkuil
  2 siblings, 1 reply; 46+ messages in thread
From: Shilimkar, Santosh @ 2010-07-24  7:44 UTC (permalink / raw)
  To: Sin, David, linux-arm-kernel@lists.arm.linux.org.uk,
	linux-omap@vger.kernel.org, Tony
  Cc: Kanigeri, Hari, Ohad Ben-Cohen, Hiremath, Vaibhav,
	Cousson, Benoit

David, 
> -----Original Message-----
> From: Sin, David
> Sent: Saturday, July 24, 2010 4:52 AM
> To: linux-arm-kernel@lists.arm.linux.org.uk; linux-omap@vger.kernel.org;
> Tony Lindgren; Russell King
> Cc: Kanigeri, Hari; Ohad Ben-Cohen; Hiremath, Vaibhav; Shilimkar, Santosh;
> Sin, David
> Subject: [RFC 0/8] TI TILER-DMM driver
> 
> TILER is a hardware block made by Texas Instruments.  Its purpose is to
> organize video/image memory in a 2-dimensional fashion to limit memory
> bandwidth and facilitate 0 effort rotation and mirroring.  The TILER
> driver facilitates allocating, freeing, as well as mapping 2D blocks
> (areas)
> in the TILER container(s).  It also facilitates rotating and mirroring
> the allocated blocks or its rectangular subsections.
> 
> List of pending items in proposed order:
> 
> * Add area packing support (multiple blocks can reside in the same
> band/area)
>   to optimize area use
> * Add group-ID support (to specify which blocks can reside together in the
>   same area)
> * Add multiple search directions to TCM-SiTA
> * Add 1D block support (including adding 1D search algo to TCM-SiTA)
> * Optimize mutex handling (don.t hold mutex during memory
>   allocation/mapping/cache flushing)
> * Add block reference counting, support for sharing blocks
> * Move all kernel-API-s to tiler-iface.c
> * Support orphaned block support (in preparation for process cleanup
> support)
> * Change block identification from physical address to key-ID pair
>   (in preparation for user space support, and process security)
> * Add support for process security (blocks from separate processes never
>   reside in the same band)
> * Support file interface (ioctl and mmap)
> * Support for buffers (ordered list of blocks that are mapped to userspace
>   together, such as YUV420sp)
> * Support 1D user buffer mapping into TILER container
> * Support for block pre-reservation (to further optimize area use)
> 
> David Sin (1):
>   TILER-DMM: DMM-PAT driver for TI TILER
> 
> Lajos Molnar (6):
>   TILER-DMM: Container manager interface and utility definitons
>   TILER-DMM: TILER Memory Manager interface and implementation
>   TILER-DMM: TILER interface file and documentation
>   TILER-DMM: Geometry and view manipulation functions.
>   TILER-DMM: Main TILER driver implementation.
>   TILER-DMM: Linking TILER driver into the Linux kernel build
> 
> Ravi Ramachandra (1):
>   TILER-DMM: Sample TCM implementation: Simple TILER Allocator
> 
I am just summarizing some of my comments here

1. linux-arm-kernel@lists.arm.linux.org.uk is not operational anymore. The
current list is linux-arm-kernel@lists.infradead.org

2. Thanks for the Documentation patch. Just take care of correct directory for same

3. iormap on RAM will be prohibited. Russell has a patch in the queue so
	we need to look at the alternative.
4. You haven't implemented probe fuction in both of your diver and doing
all work in init itself. You might want to revisit that

5. DMM register info is auto-generated thanks to Benoit. We can use that directly.

6. There are too many header files(8-9) and I think you can re-organise all of them to manage with 3-4

7. Commenting style is not consistent in all patches and does not follow
linux style in few places

8. The DMM driver registration can be done using omap_device framework as
is being done for most of the OMAP4 drivers.

9. Error handling can be improved

10. There is an excessive usage of barriers and may be we can keep 
only the necessary ones.

Thanks for the tiler port.

Regards,
Santosh

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [RFC 7/8] TILER-DMM: Main TILER driver implementation.
  2010-07-23 23:22             ` [RFC 7/8] TILER-DMM: Main TILER driver implementation David Sin
  2010-07-23 23:22               ` [RFC 8/8] TILER-DMM: Linking TILER driver into the Linux kernel build David Sin
  2010-07-24  7:32               ` [RFC 7/8] TILER-DMM: Main TILER driver implementation Shilimkar, Santosh
@ 2010-07-24  7:55               ` Russell King - ARM Linux
  2 siblings, 0 replies; 46+ messages in thread
From: Russell King - ARM Linux @ 2010-07-24  7:55 UTC (permalink / raw)
  To: David Sin
  Cc: linux-arm-kernel, linux-omap, Tony Lindgren, Hari Kanigeri,
	Ohad Ben-Cohen, Vaibhav Hiremath, Santosh Shilimkar, Lajos Molnar

On Fri, Jul 23, 2010 at 06:22:27PM -0500, David Sin wrote:
> +struct platform_driver tiler_driver_ldm = {
> +	.driver = {
> +		.owner = THIS_MODULE,
> +		.name = "tiler",
> +	},
> +	.probe = NULL,
> +	.shutdown = NULL,
> +	.remove = NULL,
> +};

What's the purpose of this apparantly stub driver?

> +static s32 refill_pat(struct tmm *tmm, struct tcm_area *area, u32 *ptr)
> +{
> +	s32 res = 0;
> +	struct pat_area p_area = {0};
> +
> +	p_area.x0 = area->p0.x;
> +	p_area.y0 = area->p0.y;
> +	p_area.x1 = area->p1.x;
> +	p_area.y1 = area->p1.y;
> +
> +	memcpy(dmac_va, ptr, sizeof(*ptr) * tcm_sizeof(*area));
> +
> +	if (tmm_map(tmm, p_area, dmac_pa))
> +		res = -EFAULT;

What's wrong with making tmm_map return an error code and propagating it?
This can be a simple:

	return tmm_map(tmm, p_area, dmac_pa);

In any case, I'm not sure I like all this layered code - it makes it much
harder to follow what's going on when you have to look at multiple files
to find out what X does.

If tmm_map() is only used here, move the contents of tmm_map here.

> +/* verify input params and calculate tiler container params for a block */
> +static s32 __analize_area(enum tiler_fmt fmt, u32 width, u32 height,
> +			  u16 *x_area, u16 *y_area, u16 *align, u16 *offs)

Analyze is spelt like that, not with an i.

> +/* driver initialization */
> +static s32 __init tiler_init(void)
> +{
> +	s32 r = -1;
> +	struct tcm *sita = NULL;
> +	struct tmm *tmm_pat = NULL;
> +
> +	tiler_geom_init(&tiler);
> +
> +	/* check module parameters for correctness */
> +	if (default_align > PAGE_SIZE ||
> +	    default_align & (default_align - 1) ||
> +	    granularity < 1 || granularity > PAGE_SIZE ||
> +	    granularity & (granularity - 1))
> +		return -EINVAL;
> +
> +	/*
> +	 * Array of physical pages for PAT programming, which must be a 16-byte
> +	 * aligned physical address.
> +	 */
> +	dmac_va = dma_alloc_coherent(NULL, tiler.width * tiler.height *
> +					sizeof(*dmac_va), &dmac_pa, GFP_ATOMIC);

Why GFP_ATOMIC?  Surely GFP_KERNEL will work here?

What if there ends up being more than one tiler at some point in the future
and you need two of these?  Shouldn't this be in some driver probe function
so you have a struct device to use with it?

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [RFC 4/8] TILER-DMM: TILER Memory Manager interface and implementation
  2010-07-23 23:22       ` [RFC 4/8] TILER-DMM: TILER Memory Manager interface and implementation David Sin
  2010-07-23 23:22         ` [RFC 5/8] TILER-DMM: TILER interface file and documentation David Sin
@ 2010-07-24  8:01         ` Russell King - ARM Linux
  2010-07-26 19:34           ` Sin, David
  2010-08-02 14:40           ` Sin, David
  2010-07-28  5:53         ` Hiremath, Vaibhav
  2 siblings, 2 replies; 46+ messages in thread
From: Russell King - ARM Linux @ 2010-07-24  8:01 UTC (permalink / raw)
  To: David Sin
  Cc: linux-arm-kernel, linux-omap, Tony Lindgren, Hari Kanigeri,
	Ohad Ben-Cohen, Vaibhav Hiremath, Santosh Shilimkar, Lajos Molnar

On Fri, Jul 23, 2010 at 06:22:24PM -0500, David Sin wrote:
> +/* allocate and flush a page */
> +static struct mem *alloc_mem(void)
> +{
> +	struct mem *m = kzalloc(sizeof(*m), GFP_KERNEL);
> +	if (!m)
> +		return NULL;
> +
> +	m->pg = alloc_page(GFP_KERNEL | GFP_DMA);
> +	if (!m->pg) {
> +		kfree(m);
> +		return NULL;
> +	}
> +
> +	m->pa = page_to_phys(m->pg);
> +
> +	/* flush the cache entry for each page we allocate. */
> +	dmac_flush_range(page_address(m->pg),
> +				page_address(m->pg) + PAGE_SIZE);
> +	outer_flush_range(m->pa, m->pa + PAGE_SIZE);

NAK.  This is an abuse of these interfaces, and is buggy in any case.

ARMv6 and ARMv7 CPUs speculatively prefetch memory, which means that
there's no guarantee that if you flush the caches for a particular
range of virtual space, that it will stay flushed until you decide
to read it.  So flushing the caches in some memory allocator can't
guarantee that when you eventually get around to using the page that
there won't be cache lines associated with it.

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [RFC 1/8] TILER-DMM: DMM-PAT driver for TI TILER
  2010-07-23 23:22 ` [RFC 1/8] TILER-DMM: DMM-PAT driver for TI TILER David Sin
  2010-07-23 23:22   ` [RFC 2/8] TILER-DMM: Container manager interface and utility definitons David Sin
  2010-07-24  6:51   ` [RFC 1/8] TILER-DMM: DMM-PAT driver for TI TILER Shilimkar, Santosh
@ 2010-07-24  8:09   ` Russell King - ARM Linux
  2010-07-24 10:15     ` Russell King - ARM Linux
  2010-07-26 19:28     ` Sin, David
  2010-07-27 18:37   ` Hiremath, Vaibhav
  3 siblings, 2 replies; 46+ messages in thread
From: Russell King - ARM Linux @ 2010-07-24  8:09 UTC (permalink / raw)
  To: David Sin
  Cc: linux-arm-kernel, linux-omap, Tony Lindgren, Hari Kanigeri,
	Ohad Ben-Cohen, Vaibhav Hiremath, Santosh Shilimkar, Lajos Molnar

On Fri, Jul 23, 2010 at 06:22:21PM -0500, David Sin wrote:
> +static struct platform_driver dmm_driver_ldm = {
> +	.driver = {
> +		.owner = THIS_MODULE,
> +		.name = "dmm",
> +	},
> +	.probe = NULL,
> +	.shutdown = NULL,
> +	.remove = NULL,
> +};

What's the point of this driver structure?

> +s32 dmm_pat_refill(struct dmm *dmm, struct pat *pd, enum pat_mode mode)
> +{
> +	void __iomem *r;
> +	u32 v;
> +
> +	/* Only manual refill supported */
> +	if (mode != MANUAL)
> +		return -EFAULT;
> +
> +	/* Check that the DMM_PAT_STATUS register has not reported an error */
> +	r = dmm->base + DMM_PAT_STATUS__0;
> +	v = __raw_readl(r);
> +	if (WARN(v & 0xFC00, KERN_ERR "dmm_pat_refill() error.\n"))
> +		return -EIO;
> +
> +	/* Set "next" register to NULL */
> +	r = dmm->base + DMM_PAT_DESCR__0;
> +	v = __raw_readl(r);
> +	v = SET_FLD(v, 31, 4, (u32) NULL);
> +	__raw_writel(v, r);
> +
> +	/* Set area to be refilled */
> +	r = dmm->base + DMM_PAT_AREA__0;
> +	v = __raw_readl(r);
> +	v = SET_FLD(v, 30, 24, pd->area.y1);
> +	v = SET_FLD(v, 23, 16, pd->area.x1);
> +	v = SET_FLD(v, 14, 8, pd->area.y0);
> +	v = SET_FLD(v, 7, 0, pd->area.x0);
> +	__raw_writel(v, r);
> +	wmb();

Maybe use writel() (which will contain the barrier _before_ the write op.)

> +
> +	/* First, clear the DMM_PAT_IRQSTATUS register */
> +	r = dmm->base + DMM_PAT_IRQSTATUS;
> +	__raw_writel(0xFFFFFFFF, r);
> +	wmb();

And consider using:
	writel(0xffffffff, dmm->base + DMM_PAT_IRQSTATUS);

In any case, writes to devices are ordered, so there's no real need to
add barriers between each write - in which case writel_relaxed() or
__raw_writel() can be used (which'll be added soon.)

> +
> +	r = dmm->base + DMM_PAT_IRQSTATUS_RAW;
> +	while (__raw_readl(r) != 0)
> +		;

It's normal to use cpu_relax() in busy-wait loops.  What if the IRQ status
never becomes zero?

> +MODULE_LICENSE("GPL v2");
> +MODULE_AUTHOR("davidsin@ti.com");
> +MODULE_AUTHOR("molnar@ti.com");

MODULE_AUTHOR("Name <email>"); or just MODULE_AUTHOR("Name");

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [RFC 1/8] TILER-DMM: DMM-PAT driver for TI TILER
  2010-07-24  8:09   ` Russell King - ARM Linux
@ 2010-07-24 10:15     ` Russell King - ARM Linux
  2010-07-26 19:28     ` Sin, David
  1 sibling, 0 replies; 46+ messages in thread
From: Russell King - ARM Linux @ 2010-07-24 10:15 UTC (permalink / raw)
  To: David Sin
  Cc: linux-arm-kernel, linux-omap, Tony Lindgren, Hari Kanigeri,
	Ohad Ben-Cohen, Vaibhav Hiremath, Santosh Shilimkar, Lajos Molnar

This is what I'd expect to see.  This uses a hardware-upwards registration
scheme, so by registering a 'dmm' device, when the driver for 'dmm' gets
registered, it automatically registers with the next level up.

However, you should think carefully about this kind of layered approach.
Would it be more appropriate to turn the 'tmm' and higher layers into a
set of library calls for this driver to use, so that they can be reused
with less modifications when other hardware comes along?

#include <linux/errno.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>

/* RMK: or whatever path to this... */
#include "tmm.h"
/*
 * RMK: which contains at least something like:
 *
 * struct tmm;
 * int tmm_register(struct tmm **tmm, int (*refill)(struct pat *, enum pat_mode, void *), void *priv);
 * void tmm_unregister(struct tmm *tmm);
 */

#define MASK(msb, lsb) (((1 << ((msb) + 1 - (lsb))) - 1) << (lsb))
#define SET_FLD(reg, msb, lsb, val) \
(((reg) & ~MASK((msb), (lsb))) | (((val) << (lsb)) & MASK((msb), (lsb))))

struct dmm {
	void __iomem *base;
	struct tmm *tmm;
};

static int dmm_wait(void __iomem *reg, unsigned mask, unsigned val, unsigned long timeout)
{
	while ((readl(reg) & mask) != val) {
		if (timeout-- == 0)
			return -ETIMEDOUT;
		udelay(1);
	}
	return 0;
}

static int dmm_refill(struct pat *pat, enum pat_mode mode, void *priv)
{
	struct dmm *dmm = priv;
	int ret;
	u32 v;

	if (mode != PAT_MODE_MANUAL || pat->data & 0x0000000f)
		/* RMK: and maybe check the range of other args */
		return -EINVAL;

	/* Check that the DMM_PAT_STATUS register has not reported an error */
	v = readl(dmm->base + DMM_PAT_STATUS__0);
	if (v & 0xfc00)
		return -EIO;

	/* Set "next" register to 0 */
	/* RMK: not null - hardware doesn't take virtual addresses */
	v = readl(dmm->base + DMM_PAT_DESCR__0);
	v = SET_FLD(v, 31, 4, 0);
	writel(v, dmm->base + DMM_PAT_DESCR__0);

	/* Set area to be refilled */
	v = readl(dmm->base + DMM_PAT_AREA__0) & 0xc000c000;
	v = (pat->area.y1 << 24) | (pat->area.x1 << 16) |
	    (pat->area.y0 << 8) | pat->area.x0;
	writel(v, dmm->base + DMM_PAT_AREA__0);

	/* Clear the DMM_PAT_IRQSTATUS register */
	writel(~0, dmm->base + DMM_PAT_IRQSTATUS);

	ret = dmm_wait(dmm->base + DMM_PAT_IRQSTATUS_RAW), ~0, 0, timeout);
	if (ret)
		return ret;

	/* Fill data register */
	v = readl(dmm->base + DMM_PAT_DATA__0) & 0x0000000f;
	v |= pat->data;
	writel(v, dmm->base + DMM_PAT_DATA__0);

	/*
	 * Read back PAT_DATA__0 to see if write was successful
	 * RMK: shouldn't this just check bits 31-4 ?  Is this just
	 * trying to ensure that the value is written before the next one?
	 * if so, writes to devices are ordered with each other, so this
	 * should not be necessary.
	 */
	ret = dmm_wait(dmm->base + DMM_PAT_DATA__0, ~0, pat->data, timeout);
	if (ret)
		return ret;

	v = readl(dmm->base + DMM_PAT_CTRL__0) & 0x0ffefc8e;
	v |= (pat->ctrl.ini << 28) | (pat->ctrl.sync << 16) |
	     (pat->ctrl.lut_id << 8) | (pat->ctrl.dir << 4) | pat->ctrl.start;
	writel(v, dmm->base + DMM_PAT_CTRL__0);

	/* Check if PAT_IRQSTATUS_RAW is set after the PAT has been refilled */
	ret = dmm_wait(dmm->base + DMM_PAT_IRQSTATUS_RAW, 3, 3, timeout);
	if (ret)
		return ret;

	/* Clear the DMM_PAT_IRQSTATUS register */
	writel(~0, dmm->base + DMM_PAT_IRQSTATUS);

	ret = dmm_wait(dmm->base + DMM_PAT_IRQSTATUS_RAW, ~0, 0, timeout);
	if (ret)
		return ret;	

	/* Set "next" register to 0 to clear any PAT STATUS errors */
	v = readl(dmm->base + DMM_PAT_DESCR__0);
	v = SET_FLD(v, 31, 4, 0);
	writel(v, dmm->base + DMM_PAT_DESCR__0);

	/*
	 * Now check that the DMM_PAT_STATUS register has not reported an error
	 */
	v = readl(dmm->base + DMM_PAT_STATUS__0);
	if (v & 0xfc00)
		return -EIO;

	return 0;
}

static int dmm_probe(struct platform_device *pdev)
{
	struct resource *res = platform_get_resource(pdev, 0, IORESOURCE_MEM);
	struct dmm *dmm;
	int ret;

	if (!res)
		return -EINVAL;

	if (request_mem_region(res->start, resource_size(res), "dmm")) {
		ret = -EBUSY;
		goto err_region;
	}

	dmm = kzalloc(sizeof(*dmm), GFP_KERNEL);
	if (!dmm) {
		ret = -ENOMEM;
		goto err_kzalloc;
	}

	dmm->base = ioremap(res->start, resource_size(res));
	if (!dmm->base) {
		ret = -ENOMEM;
		goto err_ioremap;
	}

	__raw_writel(0x88888888, dmm->base + DMM_PAT_VIEW__0);
	__raw_writel(0x88888888, dmm->base + DMM_PAT_VIEW__1);
	__raw_writel(0x80808080, dmm->base + DMM_PAT_VIEW_MAP__0);
	__raw_writel(0x80000000, dmm->base + DMM_PAT_VIEW_MAP_BASE);
	__raw_writel(0x88888888, dmm->base + DMM_TILER_OR__0);
	__raw_writel(0x88888888, dmm->base + DMM_TILER_OR__1);

	/* register with the tiler memory manager */
	ret = tmm_register(&dmm->tmm, dmm_refill, dmm);
	if (ret)
		goto err_tmm_register;

	return 0;

err_tmm_register:
	iounmap(dmm->base);
err_iounmap:
	kfree(dmm);
err_kzalloc:
	release_mem_region(res->start, resource_size(res));
err_region:
	return ret;
}

static void dmm_remove(struct platform_device *pdev)
{
	struct resource *res = platform_get_resource(pdev, 0, IORESOURCE_MEM);
	struct dmm *dmm = platform_get_drvdata(pdev);

	tmm_unregister(dmm->tmm);
	iounmap(dmm->base);
	kfree(dmm);
	release_mem_region(res->start, resource_size(res));
}

static struct platform_driver dmm_driver = {
	.driver = {
		.owner = THIS_MODULE,
		.name = "dmm",
	},
	.probe	= dmm_probe,
	.remove	= dmm_remove,
};

static int __init dmm_init(void)
{
	return platform_driver_register(&dmm_driver);
}
module_init(dmm_init);

static void __exit dmm_exit(void)
{
	platform_driver_unregister(&dmm_driver);
}
module_exit(dmm_exit);

MODULE_AUTHOR("Name <email>");
MODULE_DESCRIPTION("TI OMAP4 tiler hardware driver");
MODULE_LICENSE("GPL v2");


^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [RFC 0/8] TI TILER-DMM driver
  2010-07-23 23:22 [RFC 0/8] TI TILER-DMM driver David Sin
  2010-07-23 23:22 ` [RFC 1/8] TILER-DMM: DMM-PAT driver for TI TILER David Sin
  2010-07-24  7:44 ` [RFC 0/8] TI TILER-DMM driver Shilimkar, Santosh
@ 2010-07-24 11:12 ` Hans Verkuil
  2010-07-28 15:23   ` Sin, David
  2 siblings, 1 reply; 46+ messages in thread
From: Hans Verkuil @ 2010-07-24 11:12 UTC (permalink / raw)
  To: David Sin
  Cc: linux-arm-kernel, linux-omap, Tony Lindgren, Russell King,
	Hari Kanigeri, Ohad Ben-Cohen, Vaibhav Hiremath,
	Santosh Shilimkar

Hi David,

On Saturday 24 July 2010 01:22:20 David Sin wrote:
> TILER is a hardware block made by Texas Instruments.  Its purpose is to 
> organize video/image memory in a 2-dimensional fashion to limit memory 
> bandwidth and facilitate 0 effort rotation and mirroring.  The TILER 
> driver facilitates allocating, freeing, as well as mapping 2D blocks (areas) 
> in the TILER container(s).  It also facilitates rotating and mirroring 
> the allocated blocks or its rectangular subsections.

Since this driver is part of the media/video subsystem you should cross-post
it to the linux-media mailinglist as well.

The main question that I have is how this driver is to be used in practice.
How does it fit into the bigger video4linux picture? Is this something that
is mainly used from other v4l or fb drivers? Or is it controlled by userspace?

Regards,

	Hans

> 
> List of pending items in proposed order:
> 
> * Add area packing support (multiple blocks can reside in the same band/area)
>   to optimize area use
> * Add group-ID support (to specify which blocks can reside together in the
>   same area)
> * Add multiple search directions to TCM-SiTA
> * Add 1D block support (including adding 1D search algo to TCM-SiTA)
> * Optimize mutex handling (don.t hold mutex during memory
>   allocation/mapping/cache flushing)
> * Add block reference counting, support for sharing blocks
> * Move all kernel-API-s to tiler-iface.c
> * Support orphaned block support (in preparation for process cleanup support)
> * Change block identification from physical address to key-ID pair
>   (in preparation for user space support, and process security)
> * Add support for process security (blocks from separate processes never
>   reside in the same band)
> * Support file interface (ioctl and mmap)
> * Support for buffers (ordered list of blocks that are mapped to userspace
>   together, such as YUV420sp)
> * Support 1D user buffer mapping into TILER container
> * Support for block pre-reservation (to further optimize area use)
> 
> David Sin (1):
>   TILER-DMM: DMM-PAT driver for TI TILER
> 
> Lajos Molnar (6):
>   TILER-DMM: Container manager interface and utility definitons
>   TILER-DMM: TILER Memory Manager interface and implementation
>   TILER-DMM: TILER interface file and documentation
>   TILER-DMM: Geometry and view manipulation functions.
>   TILER-DMM: Main TILER driver implementation.
>   TILER-DMM: Linking TILER driver into the Linux kernel build
> 
> Ravi Ramachandra (1):
>   TILER-DMM: Sample TCM implementation: Simple TILER Allocator
> 
>  Documentation/arm/TILER                   |  144 +++++++++
>  arch/arm/mach-omap2/include/mach/dmm.h    |  128 ++++++++
>  arch/arm/mach-omap2/include/mach/tiler.h  |  201 +++++++++++++
>  drivers/media/Kconfig                     |    6 +
>  drivers/media/Makefile                    |    2 +
>  drivers/media/video/tiler/Kconfig         |   65 ++++
>  drivers/media/video/tiler/Makefile        |    7 +
>  drivers/media/video/tiler/_tiler.h        |   51 ++++
>  drivers/media/video/tiler/dmm.c           |  200 +++++++++++++
>  drivers/media/video/tiler/tcm.h           |  209 +++++++++++++
>  drivers/media/video/tiler/tcm/Makefile    |    1 +
>  drivers/media/video/tiler/tcm/_tcm-sita.h |   64 ++++
>  drivers/media/video/tiler/tcm/tcm-sita.c  |  459 +++++++++++++++++++++++++++++
>  drivers/media/video/tiler/tcm/tcm-sita.h  |   37 +++
>  drivers/media/video/tiler/tcm/tcm-utils.h |   54 ++++
>  drivers/media/video/tiler/tiler-geom.c    |  360 ++++++++++++++++++++++
>  drivers/media/video/tiler/tiler-iface.c   |  106 +++++++
>  drivers/media/video/tiler/tiler-main.c    |  426 ++++++++++++++++++++++++++
>  drivers/media/video/tiler/tmm-pat.c       |  274 +++++++++++++++++
>  drivers/media/video/tiler/tmm.h           |  109 +++++++
>  20 files changed, 2903 insertions(+), 0 deletions(-)
>  create mode 100644 Documentation/arm/TILER
>  create mode 100644 arch/arm/mach-omap2/include/mach/dmm.h
>  create mode 100644 arch/arm/mach-omap2/include/mach/tiler.h
>  create mode 100644 drivers/media/video/tiler/Kconfig
>  create mode 100644 drivers/media/video/tiler/Makefile
>  create mode 100644 drivers/media/video/tiler/_tiler.h
>  create mode 100644 drivers/media/video/tiler/dmm.c
>  create mode 100644 drivers/media/video/tiler/tcm.h
>  create mode 100644 drivers/media/video/tiler/tcm/Makefile
>  create mode 100644 drivers/media/video/tiler/tcm/_tcm-sita.h
>  create mode 100644 drivers/media/video/tiler/tcm/tcm-sita.c
>  create mode 100644 drivers/media/video/tiler/tcm/tcm-sita.h
>  create mode 100644 drivers/media/video/tiler/tcm/tcm-utils.h
>  create mode 100644 drivers/media/video/tiler/tiler-geom.c
>  create mode 100644 drivers/media/video/tiler/tiler-iface.c
>  create mode 100644 drivers/media/video/tiler/tiler-main.c
>  create mode 100644 drivers/media/video/tiler/tmm-pat.c
>  create mode 100644 drivers/media/video/tiler/tmm.h
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> 

-- 
Hans Verkuil - video4linux developer - sponsored by TANDBERG, part of Cisco

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [RFC 7/8] TILER-DMM: Main TILER driver implementation.
  2010-07-24  7:32               ` [RFC 7/8] TILER-DMM: Main TILER driver implementation Shilimkar, Santosh
@ 2010-07-24 13:41                 ` Hari Kanigeri
  2010-07-24 13:53                   ` Shilimkar, Santosh
  0 siblings, 1 reply; 46+ messages in thread
From: Hari Kanigeri @ 2010-07-24 13:41 UTC (permalink / raw)
  To: Shilimkar, Santosh
  Cc: Sin, David, linux-arm-kernel@lists.arm.linux.org.uk,
	linux-omap@vger.kernel.org, Tony Lindgren, Russell King,
	Kanigeri, Hari, Ohad Ben-Cohen, Hiremath, Vaibhav, Molnar, Lajos

>> +s32 tiler_mmap_blk(struct tiler_block_t *blk, u32 offs, u32 size,
>> +                             struct vm_area_struct *vma, u32 voffs)
>> +{
>> +     u32 v, p, len;
>> +
>> +     /* don't allow mremap */
>> +     vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED;
> Should we add " VM_LOCKED" as well considering the page swapping  ?

-- VM_RESERVED serves this purpose right ?

>> +
>> +     /* mapping must fit into vma */
>> +     BUG_ON(vma->vm_start > vma->vm_start + voffs ||
>> +             vma->vm_start + voffs > vma->vm_start + voffs + size ||
>> +             vma->vm_start + voffs + size > vma->vm_end);

Hari
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 46+ messages in thread

* RE: [RFC 7/8] TILER-DMM: Main TILER driver implementation.
  2010-07-24 13:41                 ` Hari Kanigeri
@ 2010-07-24 13:53                   ` Shilimkar, Santosh
  0 siblings, 0 replies; 46+ messages in thread
From: Shilimkar, Santosh @ 2010-07-24 13:53 UTC (permalink / raw)
  To: Hari Kanigeri
  Cc: Sin, David, linux-arm-kernel@lists.arm.linux.org.uk,
	linux-omap@vger.kernel.org, Tony Lindgren, Russell King,
	Kanigeri, Hari, Ohad Ben-Cohen, Hiremath, Vaibhav, Molnar, Lajos

> -----Original Message-----
> From: Hari Kanigeri [mailto:hari.kanigeri@gmail.com]
> Sent: Saturday, July 24, 2010 7:12 PM
> To: Shilimkar, Santosh
> Cc: Sin, David; linux-arm-kernel@lists.arm.linux.org.uk; linux-
> omap@vger.kernel.org; Tony Lindgren; Russell King; Kanigeri, Hari; Ohad
> Ben-Cohen; Hiremath, Vaibhav; Molnar, Lajos
> Subject: Re: [RFC 7/8] TILER-DMM: Main TILER driver implementation.
> 
> >> +s32 tiler_mmap_blk(struct tiler_block_t *blk, u32 offs, u32 size,
> >> +                             struct vm_area_struct *vma, u32 voffs)
> >> +{
> >> +     u32 v, p, len;
> >> +
> >> +     /* don't allow mremap */
> >> +     vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED;
> > Should we add " VM_LOCKED" as well considering the page swapping  ?
> 
> -- VM_RESERVED serves this purpose right ?
>
I think you are right.

Regards,
Santosh
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 46+ messages in thread

* RE: [RFC 3/8] TILER-DMM: Sample TCM implementation: Simple TILER Allocator
  2010-07-24  7:13       ` [RFC 3/8] TILER-DMM: Sample TCM implementation: Simple TILER Allocator Shilimkar, Santosh
@ 2010-07-25 15:45         ` Molnar, Lajos
  2010-07-26 19:33         ` Sin, David
  1 sibling, 0 replies; 46+ messages in thread
From: Molnar, Lajos @ 2010-07-25 15:45 UTC (permalink / raw)
  To: Shilimkar, Santosh, Sin, David,
	linux-arm-kernel@lists.arm.linux.org.uk, linux-omap
  Cc: Kanigeri, Hari, Ohad Ben-Cohen, Hiremath, Vaibhav,
	Ramachandra, Ravikiran



> -----Original Message-----
> From: Shilimkar, Santosh
> Sent: Saturday, July 24, 2010 2:13 AM
> > +	kfree(tcm);
> > +	kfree(pvt);
> If only one of the allocation was successful, then you
> are freeing a NULL pointer.
> May be have something like this
> 
> 	tcm = kzalloc(sizeof(*tcm), GFP_KERNEL);
> 	if (!tcm)
> 		goto error1;
> 	pvt = kzalloc(sizeof(*pvt), GFP_KERNEL);
> 	if (!pvt)
> 		goto error2;
> 	.
> 	.
> 	.
> error1:
> 	kfree(tcm);
> error2:
> 	kfree(pvt);

Freeing a NULL pointer is always valid, and simply returns.  This is a C specification.


^ permalink raw reply	[flat|nested] 46+ messages in thread

* RE: [RFC 0/8] TI TILER-DMM driver
  2010-07-24  7:44 ` [RFC 0/8] TI TILER-DMM driver Shilimkar, Santosh
@ 2010-07-26 19:20   ` Sin, David
  0 siblings, 0 replies; 46+ messages in thread
From: Sin, David @ 2010-07-26 19:20 UTC (permalink / raw)
  To: Shilimkar, Santosh, linux-omap@vger.kernel.org, Tony Lindgren,
	Russell King
  Cc: Kanigeri, Hari, Ohad Ben-Cohen, Hiremath, Vaibhav,
	Cousson, Benoit, Hans Verkuil

Thanks, Santosh, for your comments.  I will roll them into an RFC v2.

Also, adding the media list...

-David

-----Original Message-----
From: Shilimkar, Santosh 
Sent: Saturday, July 24, 2010 2:45 AM
To: Sin, David; linux-arm-kernel@lists.arm.linux.org.uk; linux-omap@vger.kernel.org; Tony Lindgren; Russell King
Cc: Kanigeri, Hari; Ohad Ben-Cohen; Hiremath, Vaibhav; Cousson, Benoit
Subject: RE: [RFC 0/8] TI TILER-DMM driver

David, 
> -----Original Message-----
> From: Sin, David
> Sent: Saturday, July 24, 2010 4:52 AM
> To: linux-arm-kernel@lists.arm.linux.org.uk; linux-omap@vger.kernel.org;
> Tony Lindgren; Russell King
> Cc: Kanigeri, Hari; Ohad Ben-Cohen; Hiremath, Vaibhav; Shilimkar, Santosh;
> Sin, David
> Subject: [RFC 0/8] TI TILER-DMM driver
> 
> TILER is a hardware block made by Texas Instruments.  Its purpose is to
> organize video/image memory in a 2-dimensional fashion to limit memory
> bandwidth and facilitate 0 effort rotation and mirroring.  The TILER
> driver facilitates allocating, freeing, as well as mapping 2D blocks
> (areas)
> in the TILER container(s).  It also facilitates rotating and mirroring
> the allocated blocks or its rectangular subsections.
> 
> List of pending items in proposed order:
> 
> * Add area packing support (multiple blocks can reside in the same
> band/area)
>   to optimize area use
> * Add group-ID support (to specify which blocks can reside together in the
>   same area)
> * Add multiple search directions to TCM-SiTA
> * Add 1D block support (including adding 1D search algo to TCM-SiTA)
> * Optimize mutex handling (don.t hold mutex during memory
>   allocation/mapping/cache flushing)
> * Add block reference counting, support for sharing blocks
> * Move all kernel-API-s to tiler-iface.c
> * Support orphaned block support (in preparation for process cleanup
> support)
> * Change block identification from physical address to key-ID pair
>   (in preparation for user space support, and process security)
> * Add support for process security (blocks from separate processes never
>   reside in the same band)
> * Support file interface (ioctl and mmap)
> * Support for buffers (ordered list of blocks that are mapped to userspace
>   together, such as YUV420sp)
> * Support 1D user buffer mapping into TILER container
> * Support for block pre-reservation (to further optimize area use)
> 
> David Sin (1):
>   TILER-DMM: DMM-PAT driver for TI TILER
> 
> Lajos Molnar (6):
>   TILER-DMM: Container manager interface and utility definitons
>   TILER-DMM: TILER Memory Manager interface and implementation
>   TILER-DMM: TILER interface file and documentation
>   TILER-DMM: Geometry and view manipulation functions.
>   TILER-DMM: Main TILER driver implementation.
>   TILER-DMM: Linking TILER driver into the Linux kernel build
> 
> Ravi Ramachandra (1):
>   TILER-DMM: Sample TCM implementation: Simple TILER Allocator
> 
I am just summarizing some of my comments here

1. linux-arm-kernel@lists.arm.linux.org.uk is not operational anymore. The
current list is linux-arm-kernel@lists.infradead.org

2. Thanks for the Documentation patch. Just take care of correct directory for same

3. iormap on RAM will be prohibited. Russell has a patch in the queue so
	we need to look at the alternative.
4. You haven't implemented probe fuction in both of your diver and doing
all work in init itself. You might want to revisit that

5. DMM register info is auto-generated thanks to Benoit. We can use that directly.

6. There are too many header files(8-9) and I think you can re-organise all of them to manage with 3-4

7. Commenting style is not consistent in all patches and does not follow
linux style in few places

8. The DMM driver registration can be done using omap_device framework as
is being done for most of the OMAP4 drivers.

9. Error handling can be improved

10. There is an excessive usage of barriers and may be we can keep 
only the necessary ones.

Thanks for the tiler port.

Regards,
Santosh

^ permalink raw reply	[flat|nested] 46+ messages in thread

* RE: [RFC 1/8] TILER-DMM: DMM-PAT driver for TI TILER
  2010-07-24  8:09   ` Russell King - ARM Linux
  2010-07-24 10:15     ` Russell King - ARM Linux
@ 2010-07-26 19:28     ` Sin, David
  1 sibling, 0 replies; 46+ messages in thread
From: Sin, David @ 2010-07-26 19:28 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-omap@vger.kernel.org, Tony Lindgren, Kanigeri, Hari,
	Ohad Ben-Cohen, Hiremath, Vaibhav, Shilimkar, Santosh,
	Molnar, Lajos, linux-media@vger.kernel.org, Hans Verkuil

Thanks, Russel, for your comments.  I will rework the RFC and send out a v2 soon.  

-----Original Message-----
From: Russell King - ARM Linux [mailto:linux@arm.linux.org.uk] 
Sent: Saturday, July 24, 2010 3:09 AM
To: Sin, David
Cc: linux-arm-kernel@lists.arm.linux.org.uk; linux-omap@vger.kernel.org; Tony Lindgren; Kanigeri, Hari; Ohad Ben-Cohen; Hiremath, Vaibhav; Shilimkar, Santosh; Molnar, Lajos
Subject: Re: [RFC 1/8] TILER-DMM: DMM-PAT driver for TI TILER

On Fri, Jul 23, 2010 at 06:22:21PM -0500, David Sin wrote:
> +static struct platform_driver dmm_driver_ldm = {
> +	.driver = {
> +		.owner = THIS_MODULE,
> +		.name = "dmm",
> +	},
> +	.probe = NULL,
> +	.shutdown = NULL,
> +	.remove = NULL,
> +};

What's the point of this driver structure? [dhs] -- This is pretty much incomplete.  I will revist this based on the suggestions you and Santosh have given in the other e-mail replies. 

> +s32 dmm_pat_refill(struct dmm *dmm, struct pat *pd, enum pat_mode mode)
> +{
> +	void __iomem *r;
> +	u32 v;
> +
> +	/* Only manual refill supported */
> +	if (mode != MANUAL)
> +		return -EFAULT;
> +
> +	/* Check that the DMM_PAT_STATUS register has not reported an error */
> +	r = dmm->base + DMM_PAT_STATUS__0;
> +	v = __raw_readl(r);
> +	if (WARN(v & 0xFC00, KERN_ERR "dmm_pat_refill() error.\n"))
> +		return -EIO;
> +
> +	/* Set "next" register to NULL */
> +	r = dmm->base + DMM_PAT_DESCR__0;
> +	v = __raw_readl(r);
> +	v = SET_FLD(v, 31, 4, (u32) NULL);
> +	__raw_writel(v, r);
> +
> +	/* Set area to be refilled */
> +	r = dmm->base + DMM_PAT_AREA__0;
> +	v = __raw_readl(r);
> +	v = SET_FLD(v, 30, 24, pd->area.y1);
> +	v = SET_FLD(v, 23, 16, pd->area.x1);
> +	v = SET_FLD(v, 14, 8, pd->area.y0);
> +	v = SET_FLD(v, 7, 0, pd->area.x0);
> +	__raw_writel(v, r);
> +	wmb();

Maybe use writel() (which will contain the barrier _before_ the write op.) [dhs] -- I didn't know this.  Thanks for this input.

> +
> +	/* First, clear the DMM_PAT_IRQSTATUS register */
> +	r = dmm->base + DMM_PAT_IRQSTATUS;
> +	__raw_writel(0xFFFFFFFF, r);
> +	wmb();

And consider using:
	writel(0xffffffff, dmm->base + DMM_PAT_IRQSTATUS);

In any case, writes to devices are ordered, so there's no real need to
add barriers between each write - in which case writel_relaxed() or
__raw_writel() can be used (which'll be added soon.) [dhs] -- OK, will incorporate in RFC v2.

> +
> +	r = dmm->base + DMM_PAT_IRQSTATUS_RAW;
> +	while (__raw_readl(r) != 0)
> +		;

It's normal to use cpu_relax() in busy-wait loops.  What if the IRQ status
never becomes zero? [dhs] -- I will revist this as well.

> +MODULE_LICENSE("GPL v2");
> +MODULE_AUTHOR("davidsin@ti.com");
> +MODULE_AUTHOR("molnar@ti.com");

MODULE_AUTHOR("Name <email>"); or just MODULE_AUTHOR("Name");

^ permalink raw reply	[flat|nested] 46+ messages in thread

* RE: [RFC 3/8] TILER-DMM: Sample TCM implementation: Simple TILER Allocator
  2010-07-24  7:13       ` [RFC 3/8] TILER-DMM: Sample TCM implementation: Simple TILER Allocator Shilimkar, Santosh
  2010-07-25 15:45         ` Molnar, Lajos
@ 2010-07-26 19:33         ` Sin, David
  1 sibling, 0 replies; 46+ messages in thread
From: Sin, David @ 2010-07-26 19:33 UTC (permalink / raw)
  To: Shilimkar, Santosh, linux-arm-kernel@lists.arm.linux.org.uk,
	linux-omap@vger.kernel.org
  Cc: Kanigeri, Hari, Ohad Ben-Cohen, Hiremath, Vaibhav,
	Ramachandra, Ravikiran, Molnar, Lajos, Hans Verkuil,
	linux-media@vger.kernel.org

Comments acknowledged.  Adding in media lists also.

-David

-----Original Message-----
From: Shilimkar, Santosh
Sent: Saturday, July 24, 2010 2:13 AM
To: Sin, David; linux-arm-kernel@lists.arm.linux.org.uk; linux-omap@vger.kernel.org; Tony Lindgren; Russell King
Cc: Kanigeri, Hari; Ohad Ben-Cohen; Hiremath, Vaibhav; Ramachandra, Ravikiran; Molnar, Lajos
Subject: RE: [RFC 3/8] TILER-DMM: Sample TCM implementation: Simple TILER Allocator

> -----Original Message-----
> From: Sin, David
> Sent: Saturday, July 24, 2010 4:52 AM
> To: linux-arm-kernel@lists.arm.linux.org.uk; linux-omap@vger.kernel.org;
> Tony Lindgren; Russell King
> Cc: Kanigeri, Hari; Ohad Ben-Cohen; Hiremath, Vaibhav; Shilimkar, Santosh;
> Ramachandra, Ravikiran; Molnar, Lajos; Sin, David
> Subject: [RFC 3/8] TILER-DMM: Sample TCM implementation: Simple TILER
> Allocator
>
> From: Ravi Ramachandra <r.ramachandra@ti.com>
>
> This patch implements a simple TILER Container Manager.
>
> Signed-off-by: Ravi Ramachandra <r.ramachandra@ti.com>
> Signed-off-by: Lajos Molnar <molnar@ti.com>
> Signed-off-by: David Sin <davidsin@ti.com>
> ---
>  drivers/media/video/tiler/tcm/Makefile    |    1 +
>  drivers/media/video/tiler/tcm/_tcm-sita.h |   64 ++++
Why is such a header file name. Can't you club
>  drivers/media/video/tiler/tcm/tcm-sita.c  |  459
> +++++++++++++++++++++++++++++
>  drivers/media/video/tiler/tcm/tcm-sita.h  |   37 +++
You should club _tcm-sita.h and tcm-sita.h together
>  4 files changed, 561 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/media/video/tiler/tcm/Makefile
>  create mode 100644 drivers/media/video/tiler/tcm/_tcm-sita.h
>  create mode 100644 drivers/media/video/tiler/tcm/tcm-sita.c
>  create mode 100644 drivers/media/video/tiler/tcm/tcm-sita.h
>
> diff --git a/drivers/media/video/tiler/tcm/Makefile
> b/drivers/media/video/tiler/tcm/Makefile
> new file mode 100644
> index 0000000..8434607
> --- /dev/null
> +++ b/drivers/media/video/tiler/tcm/Makefile
> @@ -0,0 +1 @@
> +obj-$(CONFIG_TI_TILER) += tcm-sita.o
> diff --git a/drivers/media/video/tiler/tcm/_tcm-sita.h
> b/drivers/media/video/tiler/tcm/_tcm-sita.h
> new file mode 100644
> index 0000000..4ede1ab
> --- /dev/null
> +++ b/drivers/media/video/tiler/tcm/_tcm-sita.h
> @@ -0,0 +1,64 @@
> +/*
> + * _tcm_sita.h
> + *
> + * SImple Tiler Allocator (SiTA) private structures.
> + *
> + * Author: Ravi Ramachandra <r.ramachandra@ti.com>
> + *
> + * Copyright (C) 2009-2010 Texas Instruments, Inc.
> + *
> + * This package is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
> + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
> + */
> +
> +#ifndef _TCM_SITA_H
> +#define _TCM_SITA_H
> +
> +#include "../tcm.h"
Header inclusion
> +
> +/* length between two coordinates */
> +#define LEN(a, b) ((a) > (b) ? (a) - (b) + 1 : (b) - (a) + 1)
> +
> +enum criteria {
> +     CR_MAX_NEIGHS           = 0x01,
> +     CR_FIRST_FOUND          = 0x10,
> +     CR_BIAS_HORIZONTAL      = 0x20,
> +     CR_BIAS_VERTICAL        = 0x40,
> +     CR_DIAGONAL_BALANCE     = 0x80
> +};
> +
> +/* nearness to the beginning of the search field from 0 to 1000 */
> +struct nearness_factor {
> +     s32 x;
> +     s32 y;
> +};
> +
> +/*
> + * Statistics on immediately neighboring slots.  Edge is the number of
> + * border segments that are also border segments of the scan field.  Busy
> + * refers to the number of neighbors that are occupied.
> + */
> +struct neighbor_stats {
> +     u16 edge;
> +     u16 busy;
> +};
> +
> +/* structure to keep the score of a potential allocation */
> +struct score {
> +     struct nearness_factor  f;
> +     struct neighbor_stats   n;
> +     struct tcm_area         a;
> +     u16    neighs;          /* number of busy neighbors */
> +};
> +
> +struct sita_pvt {
> +     struct mutex mtx;
> +     struct tcm_area ***map; /* pointers to the parent area for each slot
> */
> +};
> +
> +#endif
> diff --git a/drivers/media/video/tiler/tcm/tcm-sita.c
> b/drivers/media/video/tiler/tcm/tcm-sita.c
> new file mode 100644
> index 0000000..93be3e6
> --- /dev/null
> +++ b/drivers/media/video/tiler/tcm/tcm-sita.c
> @@ -0,0 +1,459 @@
> +/*
> + * tcm-sita.c
> + *
> + * SImple Tiler Allocator (SiTA): 2D and 1D allocation(reservation)
> algorithm
> + *
> + * Authors: Ravi Ramachandra <r.ramachandra@ti.com>,
> + *          Lajos Molnar <molnar@ti.com>
> + *
> + * Copyright (C) 2009-2010 Texas Instruments, Inc.
> + *
> + * This package is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
> + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
> + *
> + */
> +#include <linux/slab.h>
> +
> +#include "_tcm-sita.h"
> +#include "tcm-sita.h"
> +
> +#define TCM_ALG_NAME "tcm_sita"
> +#include "tcm-utils.h"
> +
> +#define ALIGN_DOWN(value, align) ((value) & ~((align) - 1))
> +
> +/* Individual selection criteria for different scan areas */
> +static s32 CR_L2R_T2B = CR_BIAS_HORIZONTAL;
> +
> +/*********************************************
> + *   TCM API - Sita Implementation
> + *********************************************/
Commenting style
> +static s32 sita_reserve_2d(struct tcm *tcm, u16 h, u16 w, u8 align,
> +                        struct tcm_area *area);
> +static s32 sita_free(struct tcm *tcm, struct tcm_area *area);
> +static void sita_deinit(struct tcm *tcm);
> +
> +/*********************************************
> + *   Main Scanner functions
> + *********************************************/
ditto
> +static s32 scan_areas_and_find_fit(struct tcm *tcm, u16 w, u16 h, u16
> align,
> +                                struct tcm_area *area);
> +
> +static s32 scan_l2r_t2b(struct tcm *tcm, u16 w, u16 h, u16 align,
> +                     struct tcm_area *field, struct tcm_area *area);
> +
> +/*********************************************
> + *   Support Infrastructure Methods
> + *********************************************/
ditto
> +static s32 is_area_free(struct tcm_area ***map, u16 x0, u16 y0, u16 w,
> u16 h);
> +
> +static s32 update_candidate(struct tcm *tcm, u16 x0, u16 y0, u16 w, u16
> h,
> +                         struct tcm_area *field, s32 criteria,
> +                         struct score *best);
> +
> +static void get_nearness_factor(struct tcm_area *field,
> +                             struct tcm_area *candidate,
> +                             struct nearness_factor *nf);
> +
> +static void get_neighbor_stats(struct tcm *tcm, struct tcm_area *area,
> +                            struct neighbor_stats *stat);
> +
> +static void fill_area(struct tcm *tcm,
> +                             struct tcm_area *area, struct tcm_area *parent);
> +
> +/*********************************************/
> +
> +/*********************************************
> + *   Utility Methods
> + *********************************************/
> +struct tcm *sita_init(u16 width, u16 height, void *attr)
> +{
> +     struct tcm *tcm;
> +     struct sita_pvt *pvt;
> +     struct tcm_area area = {0};
> +     s32 i;
> +
> +     if (width == 0 || height == 0)
> +             return NULL;
> +
> +     tcm = kzalloc(sizeof(*tcm), GFP_KERNEL);
> +     pvt = kzalloc(sizeof(*pvt), GFP_KERNEL);
> +     if (!tcm || !pvt)
> +             goto error;
> +
> +     /* Updating the pointers to SiTA implementation APIs */
> +     tcm->height = height;
> +     tcm->width = width;
> +     tcm->reserve_2d = sita_reserve_2d;
> +     tcm->free = sita_free;
> +     tcm->deinit = sita_deinit;
> +     tcm->pvt = (void *)pvt;
> +
> +     mutex_init(&(pvt->mtx));
> +
> +     /* Creating tam map */
> +     pvt->map = kzalloc(sizeof(*pvt->map) * tcm->width, GFP_KERNEL);
> +     if (!pvt->map)
> +             goto error;
> +
> +     for (i = 0; i < tcm->width; i++) {
> +             pvt->map[i] =
> +                     kzalloc(sizeof(**pvt->map) * tcm->height,
> +                                                             GFP_KERNEL);
> +             if (pvt->map[i] == NULL) {
> +                     while (i--)
> +                             kfree(pvt->map[i]);
> +                     kfree(pvt->map);
> +                     goto error;
> +             }
> +     }
> +
> +     mutex_lock(&(pvt->mtx));
> +     assign(&area, 0, 0, width - 1, height - 1);
> +     fill_area(tcm, &area, NULL);
> +     mutex_unlock(&(pvt->mtx));
> +     return tcm;
> +
> +error:
> +     kfree(tcm);
> +     kfree(pvt);
If only one of the allocation was successful, then you
are freeing a NULL pointer.
May be have something like this

        tcm = kzalloc(sizeof(*tcm), GFP_KERNEL);
        if (!tcm)
                goto error1;
        pvt = kzalloc(sizeof(*pvt), GFP_KERNEL);
        if (!pvt)
                goto error2;
        .
        .
        .
error1:
        kfree(tcm);
error2:
        kfree(pvt);

> +     return NULL;
> +}
> +
> +static void sita_deinit(struct tcm *tcm)
> +{
> +     struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
> +     struct tcm_area area = {0};
> +     s32 i;
> +
> +     area.p1.x = tcm->width - 1;
> +     area.p1.y = tcm->height - 1;
> +
> +     mutex_lock(&(pvt->mtx));
> +     fill_area(tcm, &area, NULL);
> +     mutex_unlock(&(pvt->mtx));
> +
> +     mutex_destroy(&(pvt->mtx));
> +
> +     for (i = 0; i < tcm->height; i++)
> +             kfree(pvt->map[i]);
> +     kfree(pvt->map);
> +     kfree(pvt);
> +}
> +
> +/**
> + * Reserve a 2D area in the container
> + *
> + * @param w  width
> + * @param h  height
> + * @param area       pointer to the area that will be populated with the
> reesrved
> + *           area
> + *
> + * @return 0 on success, non-0 error value on failure.
> + */
> +static s32 sita_reserve_2d(struct tcm *tcm, u16 h, u16 w, u8 align,
> +                        struct tcm_area *area)
> +{
> +     s32 ret;
> +     struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
> +
> +     /* not supporting more than 64 as alignment */
> +     if (align > 64)
> +             return -EINVAL;
> +
> +     /* we prefer 1, 32 and 64 as alignment */
> +     align = align <= 1 ? 1 : align <= 32 ? 32 : 64;
> +
> +     mutex_lock(&(pvt->mtx));
> +     ret = scan_areas_and_find_fit(tcm, w, h, align, area);
> +     if (!ret)
> +             /* update map */
> +             fill_area(tcm, area, area);
> +
> +     mutex_unlock(&(pvt->mtx));
> +     return ret;
> +}
> +
> +/**
> + * Unreserve a previously allocated 2D or 1D area
> + * @param area       area to be freed
> + * @return 0 - success
> + */
> +static s32 sita_free(struct tcm *tcm, struct tcm_area *area)
> +{
> +     struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
> +
> +     mutex_lock(&(pvt->mtx));
> +
> +     /* Clear the contents of the associated tiles in the map */
> +     fill_area(tcm, area, NULL);
> +
> +     mutex_unlock(&(pvt->mtx));
> +
> +     return 0;
> +}
> +
> +/**
> + * Note: In general the cordinates in the scan field area relevant to the
> can
> + * sweep directions. The scan origin (e.g. top-left corner) will always
> be
> + * the p0 member of the field.  Therfore, for a scan from top-left p0.x
> <= p1.x
> + * and p0.y <= p1.y; whereas, for a scan from bottom-right p1.x <= p0.x
> and p1.y
> + * <= p0.y
> + */
> +
> +/**
> + * Raster scan horizontally left to right from top to bottom to find a
> place for
> + * a 2D area of given size inside a scan field.
> + *
> + * @param w  width of desired area
> + * @param h  height of desired area
> + * @param align      desired area alignment
> + * @param area       pointer to the area that will be set to the best
> position
> + * @param field      area to scan (inclusive)
> + *
> + * @return 0 on success, non-0 error value on failure.
> + */
> +static s32 scan_l2r_t2b(struct tcm *tcm, u16 w, u16 h, u16 align,
> +                     struct tcm_area *field, struct tcm_area *area)
> +{
> +     s32 x, y;
> +     s16 start_x, end_x, start_y, end_y;
> +     struct tcm_area ***map = ((struct sita_pvt *)tcm->pvt)->map;
> +     struct score best = {{0}, {0}, {0}, 0};
> +
> +     PA(2, "scan_l2r_t2b:", field);
> +
> +     start_x = field->p0.x;
> +     end_x = field->p1.x;
> +     start_y = field->p0.y;
> +     end_y = field->p1.y;
> +
> +     /* check scan area co-ordinates */
> +     if (field->p1.x < field->p0.x ||
> +         field->p1.y < field->p0.y)
> +             return -EINVAL;
> +
> +     /* check if allocation would fit in scan area */
> +     if (w > LEN(end_x, start_x) || h > LEN(end_y, start_y))
> +             return -ENOSPC;
> +
> +     start_x = ALIGN(start_x, align);
> +
> +     /* check if allocation would still fit in scan area */
> +     if (w > LEN(end_x, start_x))
> +             return -ENOSPC;
> +
> +     /* adjust end_x and end_y, as allocation would not fit beyond */
> +     end_x = end_x - w + 1; /* + 1 to be inclusive */
> +     end_y = end_y - h + 1;
> +
> +     P2("ali=%d x=%d..%d y=%d..%d", align, start_x, end_x, start_y,
> end_y);
> +
> +     /* scan field top-to-bottom, left-to-right */
> +     for (y = start_y; y <= end_y; y++) {
> +             for (x = start_x; x <= end_x; x += align) {
> +                     if (is_area_free(map, x, y, w, h)) {
> +                             P3("found shoulder: %d,%d", x, y);
> +
> +                             /* update best candidate */
> +                             if (update_candidate(tcm, x, y, w, h, field,
> +                                                     CR_L2R_T2B, &best))
> +                                     goto done;
> +                             break;
> +                     } else if (map[x][y]) {
> +                             /* step over 2D areas */
> +                             x = ALIGN_DOWN(map[x][y]->p1.x, align);
> +                             P3("moving to: %d,%d", x, y);
> +                     }
> +             }
> +     }
> +
> +     if (!best.a.tcm)
> +             return -ENOSPC;
> +done:
> +     assign(area, best.a.p0.x, best.a.p0.y, best.a.p1.x, best.a.p1.y);
> +     return 0;
> +}
> +
> +/**
> + * Find a place for a 2D area of given size inside a scan field based on
> its
> + * alignment needs.
> + *
> + * @param w  width of desired area
> + * @param h  height of desired area
> + * @param align      desired area alignment
> + * @param area       pointer to the area that will be set to the best
> position
> + *
> + * @return 0 on success, non-0 error value on failure.
> + */
> +static s32 scan_areas_and_find_fit(struct tcm *tcm, u16 w, u16 h, u16
> align,
> +                                struct tcm_area *area)
> +{
> +     struct tcm_area field = {0};
> +
> +     /* scan whole container left to right, top to bottom */
> +     assign(&field, 0, 0, tcm->width - 1, tcm->height - 1);
> +     return scan_l2r_t2b(tcm, w, h, align, &field, area);
> +}
> +
> +/* check if an entire area is free */
> +static s32 is_area_free(struct tcm_area ***map, u16 x0, u16 y0, u16 w,
> u16 h)
> +{
> +     u16 x = 0, y = 0;
> +     for (y = y0; y < y0 + h; y++) {
> +             for (x = x0; x < x0 + w; x++) {
> +                     if (map[x][y])
> +                             return false;
> +             }
> +     }
> +     return true;
> +}
> +
> +/* fills an area with a parent tcm_area */
> +static void fill_area(struct tcm *tcm, struct tcm_area *area,
> +                     struct tcm_area *parent)
> +{
> +     s32 x, y;
> +     struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
> +
> +     PA(2, "fill 2d area", area);
> +     for (x = area->p0.x; x <= area->p1.x; ++x)
> +             for (y = area->p0.y; y <= area->p1.y; ++y)
> +                     pvt->map[x][y] = parent;
> +}
> +
> +/**
> + * Compares a candidate area to the current best area, and if it is a
> better
> + * fit, it updates the best to this one.
> + *
> + * @param x0, y0, w, h               top, left, width, height of candidate area
> + * @param field                      scan field
> + * @param criteria           scan criteria
> + * @param best                       best candidate and its scores
> + *
> + * @return 1 (true) if the candidate area is known to be the final best,
> so no
> + * more searching should be performed
> + */
> +static s32 update_candidate(struct tcm *tcm, u16 x0, u16 y0, u16 w, u16
> h,
> +                         struct tcm_area *field, s32 criteria,
> +                         struct score *best)
> +{
> +     struct score me;        /* score for area */
> +
> +     /*
> +      * If first found is enabled then we stop looking
> +      * NOTE: For horizontal bias we always give the first found, because
> our
> +      * scan is horizontal-raster-based and the first candidate will
> always
> +      * have the horizontal bias.
> +      */
> +     bool first = criteria & (CR_FIRST_FOUND | CR_BIAS_HORIZONTAL);
> +
> +     assign(&me.a, x0, y0, x0 + w - 1, y0 + h - 1);
> +
> +     /* calculate score for current candidate */
> +     if (!first) {
> +             get_neighbor_stats(tcm, &me.a, &me.n);
> +             me.neighs = me.n.edge + me.n.busy;
> +             get_nearness_factor(field, &me.a, &me.f);
> +     }
> +
> +     /* the 1st candidate is always the best */
> +     if (!best->a.tcm)
> +             goto better;
> +
> +     /* see if this are is better than the best so far */
> +
> +     /* neighbor check */
> +     if ((criteria & CR_MAX_NEIGHS) &&
> +             me.neighs > best->neighs)
> +             goto better;
> +
> +     /* vertical bias check */
> +     if ((criteria & CR_BIAS_VERTICAL) &&
> +     /*
> +      * NOTE: not checking if lengths are same, because that does not
> +      * find new shoulders on the same row after a fit
> +      */
> +             LEN(me.a.p0.y, field->p0.y) >
> +             LEN(best->a.p0.y, field->p0.y))
> +             goto better;
> +
> +     /* diagonal balance check */
> +     if ((criteria & CR_DIAGONAL_BALANCE) &&
> +             best->neighs <= me.neighs &&
> +             (best->neighs < me.neighs ||
> +              /* this implies that neighs and occupied match */
> +              best->n.busy < me.n.busy ||
> +              (best->n.busy == me.n.busy &&
> +               /* check the nearness factor */
> +               best->f.x + best->f.y > me.f.x + me.f.y)))
> +             goto better;
> +
> +     /* not better, keep going */
> +     return 0;
> +
> +better:
> +     /* save current area as best */
> +     memcpy(best, &me, sizeof(me));
> +     best->a.tcm = tcm;
> +     return first;
> +}
> +
> +/**
> + * Calculate the nearness factor of an area in a search field.  The
> nearness
> + * factor is smaller if the area is closer to the search origin.
> + */
> +static void get_nearness_factor(struct tcm_area *field, struct tcm_area
> *area,
> +                             struct nearness_factor *nf)
> +{
> +     /**
> +      * Using signed math as field coordinates may be reversed if
> +      * search direction is right-to-left or bottom-to-top.
> +      */
> +     nf->x = (s32)(area->p0.x - field->p0.x) * 1000 /
> +             (field->p1.x - field->p0.x);
> +     nf->y = (s32)(area->p0.y - field->p0.y) * 1000 /
> +             (field->p1.y - field->p0.y);
> +}
> +
> +/* get neighbor statistics */
> +static void get_neighbor_stats(struct tcm *tcm, struct tcm_area *area,
> +                      struct neighbor_stats *stat)
> +{
> +     s16 x = 0, y = 0;
> +     struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
> +
> +     /* Clearing any exisiting values */
> +     memset(stat, 0, sizeof(*stat));
> +
> +     /* process top & bottom edges */
> +     for (x = area->p0.x; x <= area->p1.x; x++) {
> +             if (area->p0.y == 0)
> +                     stat->edge++;
> +             else if (pvt->map[x][area->p0.y - 1])
> +                     stat->busy++;
> +
> +             if (area->p1.y == tcm->height - 1)
> +                     stat->edge++;
> +             else if (pvt->map[x][area->p1.y + 1])
> +                     stat->busy++;
> +     }
> +
> +     /* process left & right edges */
> +     for (y = area->p0.y; y <= area->p1.y; ++y) {
> +             if (area->p0.x == 0)
> +                     stat->edge++;
> +             else if (pvt->map[area->p0.x - 1][y])
> +                     stat->busy++;
> +
> +             if (area->p1.x == tcm->width - 1)
> +                     stat->edge++;
> +             else if (pvt->map[area->p1.x + 1][y])
> +                     stat->busy++;
> +     }
> +}
> diff --git a/drivers/media/video/tiler/tcm/tcm-sita.h
> b/drivers/media/video/tiler/tcm/tcm-sita.h
> new file mode 100644
> index 0000000..ab2d05b
> --- /dev/null
> +++ b/drivers/media/video/tiler/tcm/tcm-sita.h
> @@ -0,0 +1,37 @@
> +/*
> + * tcm_sita.h
> + *
> + * SImple Tiler Allocator (SiTA) interface.
> + *
> + * Author: Ravi Ramachandra <r.ramachandra@ti.com>
> + *
> + * Copyright (C) 2009-2010 Texas Instruments, Inc.
> + *
> + * This package is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
> + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
> + */
> +
> +#ifndef TCM_SITA_H
> +#define TCM_SITA_H
> +
> +#include "../tcm.h"
> +
> +/**
> + * Create a SiTA tiler container manager.
> + *
> + * @param width  Container width
> + * @param height Container height
> + * @param attr   unused
> + *
> + * @return TCM instance
> + */
> +struct tcm *sita_init(u16 width, u16 height, void *attr);
> +
> +TCM_INIT(sita_init, void);
Function name appears like a macro.
> +
> +#endif /* TCM_SITA_H_ */
> --
> 1.6.3.3


^ permalink raw reply	[flat|nested] 46+ messages in thread

* RE: [RFC 4/8] TILER-DMM: TILER Memory Manager interface and implementation
  2010-07-24  8:01         ` [RFC 4/8] TILER-DMM: TILER Memory Manager interface and implementation Russell King - ARM Linux
@ 2010-07-26 19:34           ` Sin, David
  2010-08-02 14:40           ` Sin, David
  1 sibling, 0 replies; 46+ messages in thread
From: Sin, David @ 2010-07-26 19:34 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-omap@vger.kernel.org, Tony Lindgren, Kanigeri, Hari,
	Ohad Ben-Cohen, Hiremath, Vaibhav, Shilimkar, Santosh,
	Molnar, Lajos, Hans Verkuil, linux-media@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org

OK -- I will revisit this.  Thanks for the explanation.

-David

-----Original Message-----
From: Russell King - ARM Linux [mailto:linux@arm.linux.org.uk] 
Sent: Saturday, July 24, 2010 3:01 AM
To: Sin, David
Cc: linux-arm-kernel@lists.arm.linux.org.uk; linux-omap@vger.kernel.org; Tony Lindgren; Kanigeri, Hari; Ohad Ben-Cohen; Hiremath, Vaibhav; Shilimkar, Santosh; Molnar, Lajos
Subject: Re: [RFC 4/8] TILER-DMM: TILER Memory Manager interface and implementation

On Fri, Jul 23, 2010 at 06:22:24PM -0500, David Sin wrote:
> +/* allocate and flush a page */
> +static struct mem *alloc_mem(void)
> +{
> +	struct mem *m = kzalloc(sizeof(*m), GFP_KERNEL);
> +	if (!m)
> +		return NULL;
> +
> +	m->pg = alloc_page(GFP_KERNEL | GFP_DMA);
> +	if (!m->pg) {
> +		kfree(m);
> +		return NULL;
> +	}
> +
> +	m->pa = page_to_phys(m->pg);
> +
> +	/* flush the cache entry for each page we allocate. */
> +	dmac_flush_range(page_address(m->pg),
> +				page_address(m->pg) + PAGE_SIZE);
> +	outer_flush_range(m->pa, m->pa + PAGE_SIZE);

NAK.  This is an abuse of these interfaces, and is buggy in any case.

ARMv6 and ARMv7 CPUs speculatively prefetch memory, which means that
there's no guarantee that if you flush the caches for a particular
range of virtual space, that it will stay flushed until you decide
to read it.  So flushing the caches in some memory allocator can't
guarantee that when you eventually get around to using the page that
there won't be cache lines associated with it.

^ permalink raw reply	[flat|nested] 46+ messages in thread

* RE: [RFC 1/8] TILER-DMM: DMM-PAT driver for TI TILER
  2010-07-23 23:22 ` [RFC 1/8] TILER-DMM: DMM-PAT driver for TI TILER David Sin
                     ` (2 preceding siblings ...)
  2010-07-24  8:09   ` Russell King - ARM Linux
@ 2010-07-27 18:37   ` Hiremath, Vaibhav
  2010-07-27 19:05     ` Sin, David
  3 siblings, 1 reply; 46+ messages in thread
From: Hiremath, Vaibhav @ 2010-07-27 18:37 UTC (permalink / raw)
  To: Sin, David, linux-arm-kernel@lists.arm.linux.org.uk,
	linux-omap@vger.kernel.org, Tony
  Cc: Kanigeri, Hari, Ohad Ben-Cohen, Shilimkar, Santosh, Molnar, Lajos

> -----Original Message-----
> From: Sin, David
> Sent: Saturday, July 24, 2010 4:52 AM
> To: linux-arm-kernel@lists.arm.linux.org.uk; linux-omap@vger.kernel.org;
> Tony Lindgren; Russell King
> Cc: Kanigeri, Hari; Ohad Ben-Cohen; Hiremath, Vaibhav; Shilimkar, Santosh;
> Sin, David; Molnar, Lajos
> Subject: [RFC 1/8] TILER-DMM: DMM-PAT driver for TI TILER
> 
> This patch adds support for DMM-PAT initialization and programming.
> 
[Hiremath, Vaibhav] Sorry for delayed response, always better late than never.


> Signed-off-by: David Sin <davidsin@ti.com>
> Signed-off-by: Lajos Molnar <molnar@ti.com>
> ---
>  arch/arm/mach-omap2/include/mach/dmm.h |  128 ++++++++++++++++++++
>  drivers/media/video/tiler/dmm.c        |  200
> ++++++++++++++++++++++++++++++++
>  2 files changed, 328 insertions(+), 0 deletions(-)
>  create mode 100644 arch/arm/mach-omap2/include/mach/dmm.h
>  create mode 100644 drivers/media/video/tiler/dmm.c
> 
[Hiremath, Vaibhav] If I understand correctly, DMM stands for dynamic memory manager. Is it something which can only be used with Video devices? Any specific reason why this is part of drivers/media/video/ directory,


> diff --git a/arch/arm/mach-omap2/include/mach/dmm.h b/arch/arm/mach-
> omap2/include/mach/dmm.h
> new file mode 100644
> index 0000000..68b798a
> --- /dev/null
> +++ b/arch/arm/mach-omap2/include/mach/dmm.h
> @@ -0,0 +1,128 @@
> +/*
> + * dmm.h
> + *
> + * DMM driver support functions for TI DMM-TILER hardware block.
> + *
> + * Author: David Sin <davidsin@ti.com>
> + *
> + * Copyright (C) 2009-2010 Texas Instruments, Inc.
> + *
> + * This package is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
> + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
> + */
> +
> +#ifndef DMM_H
> +#define DMM_H
> +
> +#define DMM_BASE 0x4E000000
> +#define DMM_SIZE 0x800
[Hiremath, Vaibhav] Unused definition (DMM_SIZE), do we required it?

> +
> +#define DMM_REVISION          0x000
> +#define DMM_HWINFO            0x004
> +#define DMM_LISA_HWINFO       0x008
> +#define DMM_DMM_SYSCONFIG     0x010
> +#define DMM_LISA_LOCK         0x01C
> +#define DMM_LISA_MAP__0       0x040
> +#define DMM_LISA_MAP__1       0x044
> +#define DMM_TILER_HWINFO      0x208
> +#define DMM_TILER_OR__0       0x220
> +#define DMM_TILER_OR__1       0x224
> +#define DMM_PAT_HWINFO        0x408
> +#define DMM_PAT_GEOMETRY      0x40C
> +#define DMM_PAT_CONFIG        0x410
> +#define DMM_PAT_VIEW__0       0x420
> +#define DMM_PAT_VIEW__1       0x424
> +#define DMM_PAT_VIEW_MAP__0   0x440
> +#define DMM_PAT_VIEW_MAP_BASE 0x460
> +#define DMM_PAT_IRQ_EOI       0x478
> +#define DMM_PAT_IRQSTATUS_RAW 0x480
> +#define DMM_PAT_IRQSTATUS     0x490
> +#define DMM_PAT_IRQENABLE_SET 0x4A0
> +#define DMM_PAT_IRQENABLE_CLR 0x4B0
> +#define DMM_PAT_STATUS__0     0x4C0
> +#define DMM_PAT_STATUS__1     0x4C4
> +#define DMM_PAT_STATUS__2     0x4C8
> +#define DMM_PAT_STATUS__3     0x4CC
> +#define DMM_PAT_DESCR__0      0x500
> +#define DMM_PAT_AREA__0       0x504
> +#define DMM_PAT_CTRL__0       0x508
> +#define DMM_PAT_DATA__0       0x50C
[Hiremath, Vaibhav] Not sure whether somebody has given same comment or not, any specific reason behind double _ here?

> +#define DMM_PEG_HWINFO        0x608
> +#define DMM_PEG_PRIO          0x620
> +#define DMM_PEG_PRIO_PAT      0x640
> +
> +/**
> + * PAT refill programming mode.
> + */
> +enum pat_mode {
> +	MANUAL,
> +	AUTO
> +};
> +
> +/**
> + * Area definition for DMM physical address translator.
> + */
> +struct pat_area {
> +	s32 x0:8;
> +	s32 y0:8;
> +	s32 x1:8;
> +	s32 y1:8;
> +};
> +
> +/**
> + * DMM physical address translator control.
> + */
> +struct pat_ctrl {
> +	s32 start:4;
> +	s32 dir:4;
> +	s32 lut_id:8;
> +	s32 sync:12;
> +	s32 ini:4;
> +};
> +
> +/**
> + * PAT descriptor.
> + */
> +struct pat {
> +	struct pat *next;
> +	struct pat_area area;
> +	struct pat_ctrl ctrl;
> +	u32 data;
> +};
> +
> +/**
> + * DMM device data
> + */
> +struct dmm {
> +	void __iomem *base;
> +};
> +
> +/**
> + * Create and initialize the physical address translator.
> + * @param id    PAT id
> + * @return pointer to device data
> + */
> +struct dmm *dmm_pat_init(u32 id);
> +
> +/**
> + * Program the physical address translator.
> + * @param dmm   Device data
> + * @param desc  PAT descriptor
> + * @param mode  programming mode
> + * @return an error status.
> + */
> +s32 dmm_pat_refill(struct dmm *dmm, struct pat *desc, enum pat_mode mode);
> +
> +/**
> + * Clean up the physical address translator.
> + * @param dmm    Device data
> + * @return an error status.
> + */
> +void dmm_pat_release(struct dmm *dmm);
> +
> +#endif
> diff --git a/drivers/media/video/tiler/dmm.c
> b/drivers/media/video/tiler/dmm.c
> new file mode 100644
> index 0000000..e715936
> --- /dev/null
> +++ b/drivers/media/video/tiler/dmm.c
> @@ -0,0 +1,200 @@
> +/*
> + * dmm.c
> + *
> + * DMM driver support functions for TI OMAP processors.
> + *
> + * Authors: David Sin <davidsin@ti.com>
> + *          Lajos Molnar <molnar@ti.com>
> + *
> + * Copyright (C) 2009-2010 Texas Instruments, Inc.
> + *
> + * This package is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
> + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h> /* platform_device() */
> +#include <linux/io.h>              /* ioremap() */
[Hiremath, Vaibhav] No need to specify comments here actually?

> +#include <linux/errno.h>
> +#include <linux/slab.h>
> +
> +#include <mach/dmm.h>
> +
> +#define MASK(msb, lsb) (((1 << ((msb) + 1 - (lsb))) - 1) << (lsb))
> +#define SET_FLD(reg, msb, lsb, val) \
> +(((reg) & ~MASK((msb), (lsb))) | (((val) << (lsb)) & MASK((msb), (lsb))))
> +
> +static struct platform_driver dmm_driver_ldm = {
> +	.driver = {
> +		.owner = THIS_MODULE,
> +		.name = "dmm",
> +	},
> +	.probe = NULL,
> +	.shutdown = NULL,
> +	.remove = NULL,
> +};
> +
> +s32 dmm_pat_refill(struct dmm *dmm, struct pat *pd, enum pat_mode mode)
> +{
> +	void __iomem *r;
> +	u32 v;
> +
> +	/* Only manual refill supported */
> +	if (mode != MANUAL)
> +		return -EFAULT;
> +
> +	/* Check that the DMM_PAT_STATUS register has not reported an error */
> +	r = dmm->base + DMM_PAT_STATUS__0;
> +	v = __raw_readl(r);
> +	if (WARN(v & 0xFC00, KERN_ERR "dmm_pat_refill() error.\n"))
> +		return -EIO;
> +
> +	/* Set "next" register to NULL */
> +	r = dmm->base + DMM_PAT_DESCR__0;
> +	v = __raw_readl(r);
> +	v = SET_FLD(v, 31, 4, (u32) NULL);
> +	__raw_writel(v, r);
> +
> +	/* Set area to be refilled */
> +	r = dmm->base + DMM_PAT_AREA__0;
> +	v = __raw_readl(r);
> +	v = SET_FLD(v, 30, 24, pd->area.y1);
> +	v = SET_FLD(v, 23, 16, pd->area.x1);
> +	v = SET_FLD(v, 14, 8, pd->area.y0);
> +	v = SET_FLD(v, 7, 0, pd->area.x0);
> +	__raw_writel(v, r);
> +	wmb();
> +
> +	/* First, clear the DMM_PAT_IRQSTATUS register */
> +	r = dmm->base + DMM_PAT_IRQSTATUS;
> +	__raw_writel(0xFFFFFFFF, r);
> +	wmb();
> +
> +	r = dmm->base + DMM_PAT_IRQSTATUS_RAW;
> +	while (__raw_readl(r) != 0)
> +		;
> +
[Hiremath, Vaibhav] Get rid of infinite loop??

> +	/* Fill data register */
> +	r = dmm->base + DMM_PAT_DATA__0;
> +	v = __raw_readl(r);
> +
> +	v = SET_FLD(v, 31, 4, pd->data >> 4);
> +	__raw_writel(v, r);
> +	wmb();
> +
> +	/* Read back PAT_DATA__0 to see if write was successful */
> +	while (__raw_readl(r) != pd->data)
> +		;
> +
> +	r = dmm->base + DMM_PAT_CTRL__0;
> +	v = __raw_readl(r);
> +	v = SET_FLD(v, 31, 28, pd->ctrl.ini);
> +	v = SET_FLD(v, 16, 16, pd->ctrl.sync);
> +	v = SET_FLD(v, 9, 8, pd->ctrl.lut_id);
> +	v = SET_FLD(v, 6, 4, pd->ctrl.dir);
> +	v = SET_FLD(v, 0, 0, pd->ctrl.start);
> +	__raw_writel(v, r);
> +	wmb();
> +
> +	/* Check if PAT_IRQSTATUS_RAW is set after the PAT has been refilled
> */
> +	r = dmm->base + DMM_PAT_IRQSTATUS_RAW;
> +	while ((__raw_readl(r) & 0x3) != 0x3)
> +		;
> +
> +	/* Again, clear the DMM_PAT_IRQSTATUS register */
> +	r = dmm->base + DMM_PAT_IRQSTATUS;
> +	__raw_writel(0xFFFFFFFF, r);
> +	wmb();
> +
> +	r = dmm->base + DMM_PAT_IRQSTATUS_RAW;
> +	while (__raw_readl(r) != 0)
> +		;
[Hiremath, Vaibhav] Do you want to wait on whole register value or one specific bit here? 

> +
> +	/* Again, set "next" register to NULL to clear any PAT STATUS errors
> */
> +	r = dmm->base + DMM_PAT_DESCR__0;
> +	v = __raw_readl(r);
> +	v = SET_FLD(v, 31, 4, (u32) NULL);
[Hiremath, Vaibhav] Why NULL, can't pass directly 0 here?

Thanks,
Vaibhav

> +	__raw_writel(v, r);
> +
> +	/*
> +	 * Now, check that the DMM_PAT_STATUS register
> +	 * has not reported an error before exiting.
> +	*/
> +	r = dmm->base + DMM_PAT_STATUS__0;
> +	v = __raw_readl(r);
> +	if (WARN(v & 0xFC00, KERN_ERR "dmm_pat_refill() error.\n"))
> +		return -EIO;
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(dmm_pat_refill);
> +
> +struct dmm *dmm_pat_init(u32 id)
> +{
> +	u32 base;
> +	struct dmm *dmm;
> +	switch (id) {
> +	case 0:
> +		/* only support id 0 for now */
> +		base = DMM_BASE;
> +		break;
> +	default:
> +		return NULL;
> +	}
> +
> +	dmm = kzalloc(sizeof(*dmm), GFP_KERNEL);
> +	if (!dmm)
> +		return NULL;
> +
> +	dmm->base = ioremap(base, DMM_SIZE);
> +	if (!dmm->base) {
> +		kfree(dmm);
> +		return NULL;
> +	}
> +
> +	__raw_writel(0x88888888, dmm->base + DMM_PAT_VIEW__0);
> +	__raw_writel(0x88888888, dmm->base + DMM_PAT_VIEW__1);
> +	__raw_writel(0x80808080, dmm->base + DMM_PAT_VIEW_MAP__0);
> +	__raw_writel(0x80000000, dmm->base + DMM_PAT_VIEW_MAP_BASE);
> +	__raw_writel(0x88888888, dmm->base + DMM_TILER_OR__0);
> +	__raw_writel(0x88888888, dmm->base + DMM_TILER_OR__1);
> +
> +	return dmm;
> +}
> +EXPORT_SYMBOL(dmm_pat_init);
> +
> +/**
> + * Clean up the physical address translator.
> + * @param dmm    Device data
> + * @return an error status.
> + */
> +void dmm_pat_release(struct dmm *dmm)
> +{
> +	if (dmm) {
> +		iounmap(dmm->base);
> +		kfree(dmm);
> +	}
> +}
> +EXPORT_SYMBOL(dmm_pat_release);
> +
> +static s32 __init dmm_init(void)
> +{
> +	return platform_driver_register(&dmm_driver_ldm);
> +}
> +
> +static void __exit dmm_exit(void)
> +{
> +	platform_driver_unregister(&dmm_driver_ldm);
> +}
> +
> +MODULE_LICENSE("GPL v2");
> +MODULE_AUTHOR("davidsin@ti.com");
> +MODULE_AUTHOR("molnar@ti.com");
> +module_init(dmm_init);
> +module_exit(dmm_exit);
> --
> 1.6.3.3


^ permalink raw reply	[flat|nested] 46+ messages in thread

* RE: [RFC 1/8] TILER-DMM: DMM-PAT driver for TI TILER
  2010-07-27 18:37   ` Hiremath, Vaibhav
@ 2010-07-27 19:05     ` Sin, David
  2010-07-27 19:53       ` Hiremath, Vaibhav
  2010-07-28  9:45       ` Laurent Pinchart
  0 siblings, 2 replies; 46+ messages in thread
From: Sin, David @ 2010-07-27 19:05 UTC (permalink / raw)
  To: Hiremath, Vaibhav, linux-arm-kernel@lists.infradead.org,
	linux-omap@vger.kernel.org, Tony
  Cc: Kanigeri, Hari, Ohad Ben-Cohen, Shilimkar, Santosh, Molnar, Lajos

> -----Original Message-----
> From: Hiremath, Vaibhav 
> Sent: Tuesday, July 27, 2010 1:38 PM
> To: Sin, David; linux-arm-kernel@lists.arm.linux.org.uk; 
> linux-omap@vger.kernel.org; Tony Lindgren; Russell King
> Cc: Kanigeri, Hari; Ohad Ben-Cohen; Shilimkar, Santosh; Molnar, Lajos
> Subject: RE: [RFC 1/8] TILER-DMM: DMM-PAT driver for TI TILER
> 
> > -----Original Message-----
> > From: Sin, David
> > Sent: Saturday, July 24, 2010 4:52 AM
> > To: linux-arm-kernel@lists.arm.linux.org.uk; 
> linux-omap@vger.kernel.org;
> > Tony Lindgren; Russell King
> > Cc: Kanigeri, Hari; Ohad Ben-Cohen; Hiremath, Vaibhav; 
> Shilimkar, Santosh;
> > Sin, David; Molnar, Lajos
> > Subject: [RFC 1/8] TILER-DMM: DMM-PAT driver for TI TILER
> > 
> > This patch adds support for DMM-PAT initialization and programming.
> > 
> [Hiremath, Vaibhav] Sorry for delayed response, always better 
> late than never.

[dhs] Thanks for your comments, Vaibhav.  I'll pull them in for RFC v2.
> 
> 
> > Signed-off-by: David Sin <davidsin@ti.com>
> > Signed-off-by: Lajos Molnar <molnar@ti.com>
> > ---
> >  arch/arm/mach-omap2/include/mach/dmm.h |  128 ++++++++++++++++++++
> >  drivers/media/video/tiler/dmm.c        |  200
> > ++++++++++++++++++++++++++++++++
> >  2 files changed, 328 insertions(+), 0 deletions(-)
> >  create mode 100644 arch/arm/mach-omap2/include/mach/dmm.h
> >  create mode 100644 drivers/media/video/tiler/dmm.c
> > 
> [Hiremath, Vaibhav] If I understand correctly, DMM stands for 
> dynamic memory manager. Is it something which can only be 
> used with Video devices? Any specific reason why this is part 
> of drivers/media/video/ directory,
[dhs] Any device can use TILER memory, but there is a big advantage, performance-wise, for 2-Dimensional macro block based buffers.  This HW is intended for image/video hardware accelerators (e.g. OMAP4 IVA-HD).  Plus there's the added advantage of doing zero-copy flips and rotations for the OMAP display and image sub-systems. 
> 
> 
> > diff --git a/arch/arm/mach-omap2/include/mach/dmm.h b/arch/arm/mach-
> > omap2/include/mach/dmm.h
> > new file mode 100644
> > index 0000000..68b798a
> > --- /dev/null
> > +++ b/arch/arm/mach-omap2/include/mach/dmm.h
> > @@ -0,0 +1,128 @@
> > +/*
> > + * dmm.h
> > + *
> > + * DMM driver support functions for TI DMM-TILER hardware block.
> > + *
> > + * Author: David Sin <davidsin@ti.com>
> > + *
> > + * Copyright (C) 2009-2010 Texas Instruments, Inc.
> > + *
> > + * This package is free software; you can redistribute it 
> and/or modify
> > + * it under the terms of the GNU General Public License 
> version 2 as
> > + * published by the Free Software Foundation.
> > + *
> > + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
> > + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
> > + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A 
> PARTICULAR PURPOSE.
> > + */
> > +
> > +#ifndef DMM_H
> > +#define DMM_H
> > +
> > +#define DMM_BASE 0x4E000000
> > +#define DMM_SIZE 0x800
> [Hiremath, Vaibhav] Unused definition (DMM_SIZE), do we required it?
[dhs] It's currently being used in dmm.c to indicate how much to ioremap.
> 
> > +
> > +#define DMM_REVISION          0x000
> > +#define DMM_HWINFO            0x004
> > +#define DMM_LISA_HWINFO       0x008
> > +#define DMM_DMM_SYSCONFIG     0x010
> > +#define DMM_LISA_LOCK         0x01C
> > +#define DMM_LISA_MAP__0       0x040
> > +#define DMM_LISA_MAP__1       0x044
> > +#define DMM_TILER_HWINFO      0x208
> > +#define DMM_TILER_OR__0       0x220
> > +#define DMM_TILER_OR__1       0x224
> > +#define DMM_PAT_HWINFO        0x408
> > +#define DMM_PAT_GEOMETRY      0x40C
> > +#define DMM_PAT_CONFIG        0x410
> > +#define DMM_PAT_VIEW__0       0x420
> > +#define DMM_PAT_VIEW__1       0x424
> > +#define DMM_PAT_VIEW_MAP__0   0x440
> > +#define DMM_PAT_VIEW_MAP_BASE 0x460
> > +#define DMM_PAT_IRQ_EOI       0x478
> > +#define DMM_PAT_IRQSTATUS_RAW 0x480
> > +#define DMM_PAT_IRQSTATUS     0x490
> > +#define DMM_PAT_IRQENABLE_SET 0x4A0
> > +#define DMM_PAT_IRQENABLE_CLR 0x4B0
> > +#define DMM_PAT_STATUS__0     0x4C0
> > +#define DMM_PAT_STATUS__1     0x4C4
> > +#define DMM_PAT_STATUS__2     0x4C8
> > +#define DMM_PAT_STATUS__3     0x4CC
> > +#define DMM_PAT_DESCR__0      0x500
> > +#define DMM_PAT_AREA__0       0x504
> > +#define DMM_PAT_CTRL__0       0x508
> > +#define DMM_PAT_DATA__0       0x50C
> [Hiremath, Vaibhav] Not sure whether somebody has given same 
> comment or not, any specific reason behind double _ here?
[dhs] Yes -- this comment has been made already.  I'm using the same names defined in the TRM.  However, it can be changed.
> 
> > +#define DMM_PEG_HWINFO        0x608
> > +#define DMM_PEG_PRIO          0x620
> > +#define DMM_PEG_PRIO_PAT      0x640
> > +
> > +/**
> > + * PAT refill programming mode.
> > + */
> > +enum pat_mode {
> > +	MANUAL,
> > +	AUTO
> > +};
> > +
> > +/**
> > + * Area definition for DMM physical address translator.
> > + */
> > +struct pat_area {
> > +	s32 x0:8;
> > +	s32 y0:8;
> > +	s32 x1:8;
> > +	s32 y1:8;
> > +};
> > +
> > +/**
> > + * DMM physical address translator control.
> > + */
> > +struct pat_ctrl {
> > +	s32 start:4;
> > +	s32 dir:4;
> > +	s32 lut_id:8;
> > +	s32 sync:12;
> > +	s32 ini:4;
> > +};
> > +
> > +/**
> > + * PAT descriptor.
> > + */
> > +struct pat {
> > +	struct pat *next;
> > +	struct pat_area area;
> > +	struct pat_ctrl ctrl;
> > +	u32 data;
> > +};
> > +
> > +/**
> > + * DMM device data
> > + */
> > +struct dmm {
> > +	void __iomem *base;
> > +};
> > +
> > +/**
> > + * Create and initialize the physical address translator.
> > + * @param id    PAT id
> > + * @return pointer to device data
> > + */
> > +struct dmm *dmm_pat_init(u32 id);
> > +
> > +/**
> > + * Program the physical address translator.
> > + * @param dmm   Device data
> > + * @param desc  PAT descriptor
> > + * @param mode  programming mode
> > + * @return an error status.
> > + */
> > +s32 dmm_pat_refill(struct dmm *dmm, struct pat *desc, enum 
> pat_mode mode);
> > +
> > +/**
> > + * Clean up the physical address translator.
> > + * @param dmm    Device data
> > + * @return an error status.
> > + */
> > +void dmm_pat_release(struct dmm *dmm);
> > +
> > +#endif
> > diff --git a/drivers/media/video/tiler/dmm.c
> > b/drivers/media/video/tiler/dmm.c
> > new file mode 100644
> > index 0000000..e715936
> > --- /dev/null
> > +++ b/drivers/media/video/tiler/dmm.c
> > @@ -0,0 +1,200 @@
> > +/*
> > + * dmm.c
> > + *
> > + * DMM driver support functions for TI OMAP processors.
> > + *
> > + * Authors: David Sin <davidsin@ti.com>
> > + *          Lajos Molnar <molnar@ti.com>
> > + *
> > + * Copyright (C) 2009-2010 Texas Instruments, Inc.
> > + *
> > + * This package is free software; you can redistribute it 
> and/or modify
> > + * it under the terms of the GNU General Public License 
> version 2 as
> > + * published by the Free Software Foundation.
> > + *
> > + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
> > + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
> > + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A 
> PARTICULAR PURPOSE.
> > + */
> > +
> > +#include <linux/init.h>
> > +#include <linux/module.h>
> > +#include <linux/platform_device.h> /* platform_device() */
> > +#include <linux/io.h>              /* ioremap() */
> [Hiremath, Vaibhav] No need to specify comments here actually?
[dhs] This can be removed -- thanks.
> 
> > +#include <linux/errno.h>
> > +#include <linux/slab.h>
> > +
> > +#include <mach/dmm.h>
> > +
> > +#define MASK(msb, lsb) (((1 << ((msb) + 1 - (lsb))) - 1) << (lsb))
> > +#define SET_FLD(reg, msb, lsb, val) \
> > +(((reg) & ~MASK((msb), (lsb))) | (((val) << (lsb)) & 
> MASK((msb), (lsb))))
> > +
> > +static struct platform_driver dmm_driver_ldm = {
> > +	.driver = {
> > +		.owner = THIS_MODULE,
> > +		.name = "dmm",
> > +	},
> > +	.probe = NULL,
> > +	.shutdown = NULL,
> > +	.remove = NULL,
> > +};
> > +
> > +s32 dmm_pat_refill(struct dmm *dmm, struct pat *pd, enum 
> pat_mode mode)
> > +{
> > +	void __iomem *r;
> > +	u32 v;
> > +
> > +	/* Only manual refill supported */
> > +	if (mode != MANUAL)
> > +		return -EFAULT;
> > +
> > +	/* Check that the DMM_PAT_STATUS register has not 
> reported an error */
> > +	r = dmm->base + DMM_PAT_STATUS__0;
> > +	v = __raw_readl(r);
> > +	if (WARN(v & 0xFC00, KERN_ERR "dmm_pat_refill() error.\n"))
> > +		return -EIO;
> > +
> > +	/* Set "next" register to NULL */
> > +	r = dmm->base + DMM_PAT_DESCR__0;
> > +	v = __raw_readl(r);
> > +	v = SET_FLD(v, 31, 4, (u32) NULL);
> > +	__raw_writel(v, r);
> > +
> > +	/* Set area to be refilled */
> > +	r = dmm->base + DMM_PAT_AREA__0;
> > +	v = __raw_readl(r);
> > +	v = SET_FLD(v, 30, 24, pd->area.y1);
> > +	v = SET_FLD(v, 23, 16, pd->area.x1);
> > +	v = SET_FLD(v, 14, 8, pd->area.y0);
> > +	v = SET_FLD(v, 7, 0, pd->area.x0);
> > +	__raw_writel(v, r);
> > +	wmb();
> > +
> > +	/* First, clear the DMM_PAT_IRQSTATUS register */
> > +	r = dmm->base + DMM_PAT_IRQSTATUS;
> > +	__raw_writel(0xFFFFFFFF, r);
> > +	wmb();
> > +
> > +	r = dmm->base + DMM_PAT_IRQSTATUS_RAW;
> > +	while (__raw_readl(r) != 0)
> > +		;
> > +
> [Hiremath, Vaibhav] Get rid of infinite loop??
[dhs] Yes -- this comment has already been posted, thanks.
> 
> > +	/* Fill data register */
> > +	r = dmm->base + DMM_PAT_DATA__0;
> > +	v = __raw_readl(r);
> > +
> > +	v = SET_FLD(v, 31, 4, pd->data >> 4);
> > +	__raw_writel(v, r);
> > +	wmb();
> > +
> > +	/* Read back PAT_DATA__0 to see if write was successful */
> > +	while (__raw_readl(r) != pd->data)
> > +		;
> > +
> > +	r = dmm->base + DMM_PAT_CTRL__0;
> > +	v = __raw_readl(r);
> > +	v = SET_FLD(v, 31, 28, pd->ctrl.ini);
> > +	v = SET_FLD(v, 16, 16, pd->ctrl.sync);
> > +	v = SET_FLD(v, 9, 8, pd->ctrl.lut_id);
> > +	v = SET_FLD(v, 6, 4, pd->ctrl.dir);
> > +	v = SET_FLD(v, 0, 0, pd->ctrl.start);
> > +	__raw_writel(v, r);
> > +	wmb();
> > +
> > +	/* Check if PAT_IRQSTATUS_RAW is set after the PAT has 
> been refilled
> > */
> > +	r = dmm->base + DMM_PAT_IRQSTATUS_RAW;
> > +	while ((__raw_readl(r) & 0x3) != 0x3)
> > +		;
> > +
> > +	/* Again, clear the DMM_PAT_IRQSTATUS register */
> > +	r = dmm->base + DMM_PAT_IRQSTATUS;
> > +	__raw_writel(0xFFFFFFFF, r);
> > +	wmb();
> > +
> > +	r = dmm->base + DMM_PAT_IRQSTATUS_RAW;
> > +	while (__raw_readl(r) != 0)
> > +		;
> [Hiremath, Vaibhav] Do you want to wait on whole register 
> value or one specific bit here?
[dhs] Not whole register, but not one bit either.  I'll revisit this. 
> 
> > +
> > +	/* Again, set "next" register to NULL to clear any PAT 
> STATUS errors
> > */
> > +	r = dmm->base + DMM_PAT_DESCR__0;
> > +	v = __raw_readl(r);
> > +	v = SET_FLD(v, 31, 4, (u32) NULL);
> [Hiremath, Vaibhav] Why NULL, can't pass directly 0 here?
[dhs] This value should be the pointer to the next PAT descriptor.  In this case, it's NULL, but '0' should work too.
> 
> Thanks,
> Vaibhav
> 
> > +	__raw_writel(v, r);
> > +
> > +	/*
> > +	 * Now, check that the DMM_PAT_STATUS register
> > +	 * has not reported an error before exiting.
> > +	*/
> > +	r = dmm->base + DMM_PAT_STATUS__0;
> > +	v = __raw_readl(r);
> > +	if (WARN(v & 0xFC00, KERN_ERR "dmm_pat_refill() error.\n"))
> > +		return -EIO;
> > +
> > +	return 0;
> > +}
> > +EXPORT_SYMBOL(dmm_pat_refill);
> > +
> > +struct dmm *dmm_pat_init(u32 id)
> > +{
> > +	u32 base;
> > +	struct dmm *dmm;
> > +	switch (id) {
> > +	case 0:
> > +		/* only support id 0 for now */
> > +		base = DMM_BASE;
> > +		break;
> > +	default:
> > +		return NULL;
> > +	}
> > +
> > +	dmm = kzalloc(sizeof(*dmm), GFP_KERNEL);
> > +	if (!dmm)
> > +		return NULL;
> > +
> > +	dmm->base = ioremap(base, DMM_SIZE);
> > +	if (!dmm->base) {
> > +		kfree(dmm);
> > +		return NULL;
> > +	}
> > +
> > +	__raw_writel(0x88888888, dmm->base + DMM_PAT_VIEW__0);
> > +	__raw_writel(0x88888888, dmm->base + DMM_PAT_VIEW__1);
> > +	__raw_writel(0x80808080, dmm->base + DMM_PAT_VIEW_MAP__0);
> > +	__raw_writel(0x80000000, dmm->base + DMM_PAT_VIEW_MAP_BASE);
> > +	__raw_writel(0x88888888, dmm->base + DMM_TILER_OR__0);
> > +	__raw_writel(0x88888888, dmm->base + DMM_TILER_OR__1);
> > +
> > +	return dmm;
> > +}
> > +EXPORT_SYMBOL(dmm_pat_init);
> > +
> > +/**
> > + * Clean up the physical address translator.
> > + * @param dmm    Device data
> > + * @return an error status.
> > + */
> > +void dmm_pat_release(struct dmm *dmm)
> > +{
> > +	if (dmm) {
> > +		iounmap(dmm->base);
> > +		kfree(dmm);
> > +	}
> > +}
> > +EXPORT_SYMBOL(dmm_pat_release);
> > +
> > +static s32 __init dmm_init(void)
> > +{
> > +	return platform_driver_register(&dmm_driver_ldm);
> > +}
> > +
> > +static void __exit dmm_exit(void)
> > +{
> > +	platform_driver_unregister(&dmm_driver_ldm);
> > +}
> > +
> > +MODULE_LICENSE("GPL v2");
> > +MODULE_AUTHOR("davidsin@ti.com");
> > +MODULE_AUTHOR("molnar@ti.com");
> > +module_init(dmm_init);
> > +module_exit(dmm_exit);
> > --
> > 1.6.3.3
> 
> 

^ permalink raw reply	[flat|nested] 46+ messages in thread

* RE: [RFC 1/8] TILER-DMM: DMM-PAT driver for TI TILER
  2010-07-27 19:05     ` Sin, David
@ 2010-07-27 19:53       ` Hiremath, Vaibhav
  2010-07-28 10:00         ` Laurent Pinchart
  2010-07-28  9:45       ` Laurent Pinchart
  1 sibling, 1 reply; 46+ messages in thread
From: Hiremath, Vaibhav @ 2010-07-27 19:53 UTC (permalink / raw)
  To: Sin, David, linux-arm-kernel@lists.infradead.org,
	linux-omap@vger.kernel.org, Tony
  Cc: Kanigeri, Hari, Ohad Ben-Cohen, Shilimkar, Santosh, Molnar, Lajos


> -----Original Message-----
> From: Sin, David
> Sent: Wednesday, July 28, 2010 12:35 AM
> To: Hiremath, Vaibhav; linux-arm-kernel@lists.infradead.org; linux-
> omap@vger.kernel.org; Tony Lindgren; Russell King
> Cc: Kanigeri, Hari; Ohad Ben-Cohen; Shilimkar, Santosh; Molnar, Lajos
> Subject: RE: [RFC 1/8] TILER-DMM: DMM-PAT driver for TI TILER
>
> > -----Original Message-----
> > From: Hiremath, Vaibhav
> > Sent: Tuesday, July 27, 2010 1:38 PM
> > To: Sin, David; linux-arm-kernel@lists.arm.linux.org.uk;
> > linux-omap@vger.kernel.org; Tony Lindgren; Russell King
> > Cc: Kanigeri, Hari; Ohad Ben-Cohen; Shilimkar, Santosh; Molnar, Lajos
> > Subject: RE: [RFC 1/8] TILER-DMM: DMM-PAT driver for TI TILER
> >
> > > -----Original Message-----
> > > From: Sin, David
> > > Sent: Saturday, July 24, 2010 4:52 AM
> > > To: linux-arm-kernel@lists.arm.linux.org.uk;
> > linux-omap@vger.kernel.org;
> > > Tony Lindgren; Russell King
> > > Cc: Kanigeri, Hari; Ohad Ben-Cohen; Hiremath, Vaibhav;
> > Shilimkar, Santosh;
> > > Sin, David; Molnar, Lajos
> > > Subject: [RFC 1/8] TILER-DMM: DMM-PAT driver for TI TILER
> > >
> > > This patch adds support for DMM-PAT initialization and programming.
> > >
> > [Hiremath, Vaibhav] Sorry for delayed response, always better
> > late than never.
>
> [dhs] Thanks for your comments, Vaibhav.  I'll pull them in for RFC v2.
> >
> >
> > > Signed-off-by: David Sin <davidsin@ti.com>
> > > Signed-off-by: Lajos Molnar <molnar@ti.com>
> > > ---
> > >  arch/arm/mach-omap2/include/mach/dmm.h |  128 ++++++++++++++++++++
> > >  drivers/media/video/tiler/dmm.c        |  200
> > > ++++++++++++++++++++++++++++++++
> > >  2 files changed, 328 insertions(+), 0 deletions(-)
> > >  create mode 100644 arch/arm/mach-omap2/include/mach/dmm.h
> > >  create mode 100644 drivers/media/video/tiler/dmm.c
> > >
> > [Hiremath, Vaibhav] If I understand correctly, DMM stands for
> > dynamic memory manager. Is it something which can only be
> > used with Video devices? Any specific reason why this is part
> > of drivers/media/video/ directory,
> [dhs] Any device can use TILER memory, but there is a big advantage,
> performance-wise, for 2-Dimensional macro block based buffers.  This HW is
> intended for image/video hardware accelerators (e.g. OMAP4 IVA-HD).  Plus
> there's the added advantage of doing zero-copy flips and rotations for the
> OMAP display and image sub-systems.
> >
[Hiremath, Vaibhav] When you mention Tiler memory, you meant Tiler Virtual memory which is independent of physical memory. Driver requesting/using Tiler is responsible for allocating physical memory. Is that understanding correct?

If yes, then feature wise it is same as VRFB in OMAP3, where it provides virtual address space and driver requesting VRFB is responsible for physical memory allocation. There could be additional features, enhancement and stuff but zero-copy rotation for DSS, then its same as VRFB.

Don't you think is would be very difficult to use for drivers with such proposals, I can comment from DSS point of view,

In case of OMAP4 80% of code is being re-used from OMAP3 (located under drivers/video/omap2/), which is currently supported hardware rotation/mirroring and hardly tied to VRFB API's.

Now with this driver we have to do something,

cpu_is_omap34xx()
        VRFB
else if cpu_is_omap44xx()
        Tiler

I am not sure about further OMAP series of devices, where we might have something else with DSS IP reuse (along with software). And I believe Tiler is not part of DSS at all.
Again if some other devices are using Tiler API's it would become more difficult to re-use the code when same IP is being used in multiple SoC's.

Does it make sense to you to have registration based mechanism (function pointer) where you register your hardware capabilities/API's, driver don't have to dependent on underneath hardware block. Ofcource if driver intend to use some specific/custom feature supported by some hardware block then he has to call that API under cpu_is_xxxx

> >
> > > diff --git a/arch/arm/mach-omap2/include/mach/dmm.h b/arch/arm/mach-
> > > omap2/include/mach/dmm.h
> > > new file mode 100644
> > > index 0000000..68b798a
> > > --- /dev/null
> > > +++ b/arch/arm/mach-omap2/include/mach/dmm.h
> > > @@ -0,0 +1,128 @@
> > > +/*
> > > + * dmm.h
> > > + *
> > > + * DMM driver support functions for TI DMM-TILER hardware block.
> > > + *
> > > + * Author: David Sin <davidsin@ti.com>
> > > + *
> > > + * Copyright (C) 2009-2010 Texas Instruments, Inc.
> > > + *
> > > + * This package is free software; you can redistribute it
> > and/or modify
> > > + * it under the terms of the GNU General Public License
> > version 2 as
> > > + * published by the Free Software Foundation.
> > > + *
> > > + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
> > > + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
> > > + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A
> > PARTICULAR PURPOSE.
> > > + */
> > > +
> > > +#ifndef DMM_H
> > > +#define DMM_H
> > > +
> > > +#define DMM_BASE 0x4E000000
> > > +#define DMM_SIZE 0x800
> > [Hiremath, Vaibhav] Unused definition (DMM_SIZE), do we required it?
> [dhs] It's currently being used in dmm.c to indicate how much to ioremap.
[Hiremath, Vaibhav] Opps. Missed it. You can use SZ_2K here.

> >
> > > +
> > > +#define DMM_REVISION          0x000
> > > +#define DMM_HWINFO            0x004
> > > +#define DMM_LISA_HWINFO       0x008
> > > +#define DMM_DMM_SYSCONFIG     0x010
> > > +#define DMM_LISA_LOCK         0x01C
> > > +#define DMM_LISA_MAP__0       0x040
> > > +#define DMM_LISA_MAP__1       0x044
> > > +#define DMM_TILER_HWINFO      0x208
> > > +#define DMM_TILER_OR__0       0x220
> > > +#define DMM_TILER_OR__1       0x224
> > > +#define DMM_PAT_HWINFO        0x408
> > > +#define DMM_PAT_GEOMETRY      0x40C
> > > +#define DMM_PAT_CONFIG        0x410
> > > +#define DMM_PAT_VIEW__0       0x420
> > > +#define DMM_PAT_VIEW__1       0x424
> > > +#define DMM_PAT_VIEW_MAP__0   0x440
> > > +#define DMM_PAT_VIEW_MAP_BASE 0x460
> > > +#define DMM_PAT_IRQ_EOI       0x478
> > > +#define DMM_PAT_IRQSTATUS_RAW 0x480
> > > +#define DMM_PAT_IRQSTATUS     0x490
> > > +#define DMM_PAT_IRQENABLE_SET 0x4A0
> > > +#define DMM_PAT_IRQENABLE_CLR 0x4B0
> > > +#define DMM_PAT_STATUS__0     0x4C0
> > > +#define DMM_PAT_STATUS__1     0x4C4
> > > +#define DMM_PAT_STATUS__2     0x4C8
> > > +#define DMM_PAT_STATUS__3     0x4CC
> > > +#define DMM_PAT_DESCR__0      0x500
> > > +#define DMM_PAT_AREA__0       0x504
> > > +#define DMM_PAT_CTRL__0       0x508
> > > +#define DMM_PAT_DATA__0       0x50C
> > [Hiremath, Vaibhav] Not sure whether somebody has given same
> > comment or not, any specific reason behind double _ here?
> [dhs] Yes -- this comment has been made already.  I'm using the same names
> defined in the TRM.  However, it can be changed.
[Hiremath, Vaibhav] Any specific reason why TRM documents like this?

I am still reviewing the patches, so expect some comments.

Thanks,
Vaibhav
> >
> > > +#define DMM_PEG_HWINFO        0x608
> > > +#define DMM_PEG_PRIO          0x620
> > > +#define DMM_PEG_PRIO_PAT      0x640
> > > +
> > > +/**
> > > + * PAT refill programming mode.
> > > + */
> > > +enum pat_mode {
> > > + MANUAL,
> > > + AUTO
> > > +};
> > > +
> > > +/**
> > > + * Area definition for DMM physical address translator.
> > > + */
> > > +struct pat_area {
> > > + s32 x0:8;
> > > + s32 y0:8;
> > > + s32 x1:8;
> > > + s32 y1:8;
> > > +};
> > > +
> > > +/**
> > > + * DMM physical address translator control.
> > > + */
> > > +struct pat_ctrl {
> > > + s32 start:4;
> > > + s32 dir:4;
> > > + s32 lut_id:8;
> > > + s32 sync:12;
> > > + s32 ini:4;
> > > +};
> > > +
> > > +/**
> > > + * PAT descriptor.
> > > + */
> > > +struct pat {
> > > + struct pat *next;
> > > + struct pat_area area;
> > > + struct pat_ctrl ctrl;
> > > + u32 data;
> > > +};
> > > +
> > > +/**
> > > + * DMM device data
> > > + */
> > > +struct dmm {
> > > + void __iomem *base;
> > > +};
> > > +
> > > +/**
> > > + * Create and initialize the physical address translator.
> > > + * @param id    PAT id
> > > + * @return pointer to device data
> > > + */
> > > +struct dmm *dmm_pat_init(u32 id);
> > > +
> > > +/**
> > > + * Program the physical address translator.
> > > + * @param dmm   Device data
> > > + * @param desc  PAT descriptor
> > > + * @param mode  programming mode
> > > + * @return an error status.
> > > + */
> > > +s32 dmm_pat_refill(struct dmm *dmm, struct pat *desc, enum
> > pat_mode mode);
> > > +
> > > +/**
> > > + * Clean up the physical address translator.
> > > + * @param dmm    Device data
> > > + * @return an error status.
> > > + */
> > > +void dmm_pat_release(struct dmm *dmm);
> > > +
> > > +#endif
> > > diff --git a/drivers/media/video/tiler/dmm.c
> > > b/drivers/media/video/tiler/dmm.c
> > > new file mode 100644
> > > index 0000000..e715936
> > > --- /dev/null
> > > +++ b/drivers/media/video/tiler/dmm.c
> > > @@ -0,0 +1,200 @@
> > > +/*
> > > + * dmm.c
> > > + *
> > > + * DMM driver support functions for TI OMAP processors.
> > > + *
> > > + * Authors: David Sin <davidsin@ti.com>
> > > + *          Lajos Molnar <molnar@ti.com>
> > > + *
> > > + * Copyright (C) 2009-2010 Texas Instruments, Inc.
> > > + *
> > > + * This package is free software; you can redistribute it
> > and/or modify
> > > + * it under the terms of the GNU General Public License
> > version 2 as
> > > + * published by the Free Software Foundation.
> > > + *
> > > + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
> > > + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
> > > + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A
> > PARTICULAR PURPOSE.
> > > + */
> > > +
> > > +#include <linux/init.h>
> > > +#include <linux/module.h>
> > > +#include <linux/platform_device.h> /* platform_device() */
> > > +#include <linux/io.h>              /* ioremap() */
> > [Hiremath, Vaibhav] No need to specify comments here actually?
> [dhs] This can be removed -- thanks.
> >
> > > +#include <linux/errno.h>
> > > +#include <linux/slab.h>
> > > +
> > > +#include <mach/dmm.h>
> > > +
> > > +#define MASK(msb, lsb) (((1 << ((msb) + 1 - (lsb))) - 1) << (lsb))
> > > +#define SET_FLD(reg, msb, lsb, val) \
> > > +(((reg) & ~MASK((msb), (lsb))) | (((val) << (lsb)) &
> > MASK((msb), (lsb))))
> > > +
> > > +static struct platform_driver dmm_driver_ldm = {
> > > + .driver = {
> > > +         .owner = THIS_MODULE,
> > > +         .name = "dmm",
> > > + },
> > > + .probe = NULL,
> > > + .shutdown = NULL,
> > > + .remove = NULL,
> > > +};
> > > +
> > > +s32 dmm_pat_refill(struct dmm *dmm, struct pat *pd, enum
> > pat_mode mode)
> > > +{
> > > + void __iomem *r;
> > > + u32 v;
> > > +
> > > + /* Only manual refill supported */
> > > + if (mode != MANUAL)
> > > +         return -EFAULT;
> > > +
> > > + /* Check that the DMM_PAT_STATUS register has not
> > reported an error */
> > > + r = dmm->base + DMM_PAT_STATUS__0;
> > > + v = __raw_readl(r);
> > > + if (WARN(v & 0xFC00, KERN_ERR "dmm_pat_refill() error.\n"))
> > > +         return -EIO;
> > > +
> > > + /* Set "next" register to NULL */
> > > + r = dmm->base + DMM_PAT_DESCR__0;
> > > + v = __raw_readl(r);
> > > + v = SET_FLD(v, 31, 4, (u32) NULL);
> > > + __raw_writel(v, r);
> > > +
> > > + /* Set area to be refilled */
> > > + r = dmm->base + DMM_PAT_AREA__0;
> > > + v = __raw_readl(r);
> > > + v = SET_FLD(v, 30, 24, pd->area.y1);
> > > + v = SET_FLD(v, 23, 16, pd->area.x1);
> > > + v = SET_FLD(v, 14, 8, pd->area.y0);
> > > + v = SET_FLD(v, 7, 0, pd->area.x0);
> > > + __raw_writel(v, r);
> > > + wmb();
> > > +
> > > + /* First, clear the DMM_PAT_IRQSTATUS register */
> > > + r = dmm->base + DMM_PAT_IRQSTATUS;
> > > + __raw_writel(0xFFFFFFFF, r);
> > > + wmb();
> > > +
> > > + r = dmm->base + DMM_PAT_IRQSTATUS_RAW;
> > > + while (__raw_readl(r) != 0)
> > > +         ;
> > > +
> > [Hiremath, Vaibhav] Get rid of infinite loop??
> [dhs] Yes -- this comment has already been posted, thanks.
> >
> > > + /* Fill data register */
> > > + r = dmm->base + DMM_PAT_DATA__0;
> > > + v = __raw_readl(r);
> > > +
> > > + v = SET_FLD(v, 31, 4, pd->data >> 4);
> > > + __raw_writel(v, r);
> > > + wmb();
> > > +
> > > + /* Read back PAT_DATA__0 to see if write was successful */
> > > + while (__raw_readl(r) != pd->data)
> > > +         ;
> > > +
> > > + r = dmm->base + DMM_PAT_CTRL__0;
> > > + v = __raw_readl(r);
> > > + v = SET_FLD(v, 31, 28, pd->ctrl.ini);
> > > + v = SET_FLD(v, 16, 16, pd->ctrl.sync);
> > > + v = SET_FLD(v, 9, 8, pd->ctrl.lut_id);
> > > + v = SET_FLD(v, 6, 4, pd->ctrl.dir);
> > > + v = SET_FLD(v, 0, 0, pd->ctrl.start);
> > > + __raw_writel(v, r);
> > > + wmb();
> > > +
> > > + /* Check if PAT_IRQSTATUS_RAW is set after the PAT has
> > been refilled
> > > */
> > > + r = dmm->base + DMM_PAT_IRQSTATUS_RAW;
> > > + while ((__raw_readl(r) & 0x3) != 0x3)
> > > +         ;
> > > +
> > > + /* Again, clear the DMM_PAT_IRQSTATUS register */
> > > + r = dmm->base + DMM_PAT_IRQSTATUS;
> > > + __raw_writel(0xFFFFFFFF, r);
> > > + wmb();
> > > +
> > > + r = dmm->base + DMM_PAT_IRQSTATUS_RAW;
> > > + while (__raw_readl(r) != 0)
> > > +         ;
> > [Hiremath, Vaibhav] Do you want to wait on whole register
> > value or one specific bit here?
> [dhs] Not whole register, but not one bit either.  I'll revisit this.
> >
> > > +
> > > + /* Again, set "next" register to NULL to clear any PAT
> > STATUS errors
> > > */
> > > + r = dmm->base + DMM_PAT_DESCR__0;
> > > + v = __raw_readl(r);
> > > + v = SET_FLD(v, 31, 4, (u32) NULL);
> > [Hiremath, Vaibhav] Why NULL, can't pass directly 0 here?
> [dhs] This value should be the pointer to the next PAT descriptor.  In this
> case, it's NULL, but '0' should work too.
> >
> > Thanks,
> > Vaibhav
> >
> > > + __raw_writel(v, r);
> > > +
> > > + /*
> > > +  * Now, check that the DMM_PAT_STATUS register
> > > +  * has not reported an error before exiting.
> > > + */
> > > + r = dmm->base + DMM_PAT_STATUS__0;
> > > + v = __raw_readl(r);
> > > + if (WARN(v & 0xFC00, KERN_ERR "dmm_pat_refill() error.\n"))
> > > +         return -EIO;
> > > +
> > > + return 0;
> > > +}
> > > +EXPORT_SYMBOL(dmm_pat_refill);
> > > +
> > > +struct dmm *dmm_pat_init(u32 id)
> > > +{
> > > + u32 base;
> > > + struct dmm *dmm;
> > > + switch (id) {
> > > + case 0:
> > > +         /* only support id 0 for now */
> > > +         base = DMM_BASE;
> > > +         break;
> > > + default:
> > > +         return NULL;
> > > + }
> > > +
> > > + dmm = kzalloc(sizeof(*dmm), GFP_KERNEL);
> > > + if (!dmm)
> > > +         return NULL;
> > > +
> > > + dmm->base = ioremap(base, DMM_SIZE);
> > > + if (!dmm->base) {
> > > +         kfree(dmm);
> > > +         return NULL;
> > > + }
> > > +
> > > + __raw_writel(0x88888888, dmm->base + DMM_PAT_VIEW__0);
> > > + __raw_writel(0x88888888, dmm->base + DMM_PAT_VIEW__1);
> > > + __raw_writel(0x80808080, dmm->base + DMM_PAT_VIEW_MAP__0);
> > > + __raw_writel(0x80000000, dmm->base + DMM_PAT_VIEW_MAP_BASE);
> > > + __raw_writel(0x88888888, dmm->base + DMM_TILER_OR__0);
> > > + __raw_writel(0x88888888, dmm->base + DMM_TILER_OR__1);
> > > +
> > > + return dmm;
> > > +}
> > > +EXPORT_SYMBOL(dmm_pat_init);
> > > +
> > > +/**
> > > + * Clean up the physical address translator.
> > > + * @param dmm    Device data
> > > + * @return an error status.
> > > + */
> > > +void dmm_pat_release(struct dmm *dmm)
> > > +{
> > > + if (dmm) {
> > > +         iounmap(dmm->base);
> > > +         kfree(dmm);
> > > + }
> > > +}
> > > +EXPORT_SYMBOL(dmm_pat_release);
> > > +
> > > +static s32 __init dmm_init(void)
> > > +{
> > > + return platform_driver_register(&dmm_driver_ldm);
> > > +}
> > > +
> > > +static void __exit dmm_exit(void)
> > > +{
> > > + platform_driver_unregister(&dmm_driver_ldm);
> > > +}
> > > +
> > > +MODULE_LICENSE("GPL v2");
> > > +MODULE_AUTHOR("davidsin@ti.com");
> > > +MODULE_AUTHOR("molnar@ti.com");
> > > +module_init(dmm_init);
> > > +module_exit(dmm_exit);
> > > --
> > > 1.6.3.3
> >
> >

^ permalink raw reply	[flat|nested] 46+ messages in thread

* RE: [RFC 2/8] TILER-DMM: Container manager interface and utility definitons
  2010-07-23 23:22   ` [RFC 2/8] TILER-DMM: Container manager interface and utility definitons David Sin
  2010-07-23 23:22     ` [RFC 3/8] TILER-DMM: Sample TCM implementation: Simple TILER Allocator David Sin
  2010-07-24  6:56     ` [RFC 2/8] TILER-DMM: Container manager interface and utility definitons Shilimkar, Santosh
@ 2010-07-27 20:21     ` Hiremath, Vaibhav
  2 siblings, 0 replies; 46+ messages in thread
From: Hiremath, Vaibhav @ 2010-07-27 20:21 UTC (permalink / raw)
  To: Sin, David, linux-arm-kernel@lists.arm.linux.org.uk,
	linux-omap@vger.kernel.org, Tony
  Cc: Kanigeri, Hari, Ohad Ben-Cohen, Shilimkar, Santosh, Molnar, Lajos,
	Ramachandra, Ravikiran


> -----Original Message-----
> From: Sin, David
> Sent: Saturday, July 24, 2010 4:52 AM
> To: linux-arm-kernel@lists.arm.linux.org.uk; linux-omap@vger.kernel.org;
> Tony Lindgren; Russell King
> Cc: Kanigeri, Hari; Ohad Ben-Cohen; Hiremath, Vaibhav; Shilimkar, Santosh;
> Molnar, Lajos; Sin, David; Ramachandra, Ravikiran
> Subject: [RFC 2/8] TILER-DMM: Container manager interface and utility
> definitons
> 
> From: Lajos Molnar <molnar@ti.com>
> 
> This patch defined the TILER Container Manager (TCM) interface and
> provides utility methods for implementing a TCM.
> 
> Signed-off-by: Lajos Molnar <molnar@ti.com>
> Signed-off-by: David Sin <davidsin@ti.com>
> Signed-off-by: Ravi Ramachandra <r.ramachandra@ti.com>
> ---
>  drivers/media/video/tiler/tcm.h           |  209
> +++++++++++++++++++++++++++++
>  drivers/media/video/tiler/tcm/tcm-utils.h |   54 ++++++++
>  2 files changed, 263 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/media/video/tiler/tcm.h
>  create mode 100644 drivers/media/video/tiler/tcm/tcm-utils.h
> 
> diff --git a/drivers/media/video/tiler/tcm.h
> b/drivers/media/video/tiler/tcm.h
> new file mode 100644
> index 0000000..52a022a
> --- /dev/null
> +++ b/drivers/media/video/tiler/tcm.h
> @@ -0,0 +1,209 @@
> +/*
> + * tcm.h
> + *
> + * TILER container manager specification and support functions for TI
> + * TILER driver.
> + *
> + * Author: Lajos Molnar <molnar@ti.com>
> + *
> + * Copyright (C) 2009-2010 Texas Instruments, Inc.
> + *
> + * This package is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
> + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
> + */
> +
> +#ifndef TCM_H
> +#define TCM_H
> +
> +struct tcm;
> +
> +/* point */
> +struct tcm_pt {
> +	u16 x;
> +	u16 y;
> +};
> +
> +/* 2d area */
> +struct tcm_area {
> +	struct tcm    *tcm;	/* parent */
> +	struct tcm_pt  p0;
> +	struct tcm_pt  p1;
> +};
> +
> +struct tcm {
> +	u16 width, height;	/* container dimensions */
> +
> +	/* '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
> +	any changes to the publicly available width and height fields. */
> +	void *pvt;
> +
> +	/* function table */
> +	s32 (*reserve_2d)(struct tcm *tcm, u16 height, u16 width, u8 align,
> +			  struct tcm_area *area);
> +	s32 (*free)      (struct tcm *tcm, struct tcm_area *area);
> +	void (*deinit)   (struct tcm *tcm);
> +};
> +
> +/*=========================================================================
> ====
> +    BASIC TILER CONTAINER MANAGER INTERFACE
> +===========================================================================
> ==*/
> +
> +/*
> + * NOTE:
> + *
> + * Since some basic parameter checking is done outside the TCM algorithms,
> + * TCM implementation do NOT have to check the following:
> + *
> + *   area pointer is NULL
> + *   width and height fits within container
> + *   number of pages is more than the size of the container
> + *
> + */
> +
> +/**
> + * Template for <ALGO_NAME>_tcm_init method.  Define as:
> + * TCM_INIT(<ALGO_NAME>_tcm_init)
> + *
> + * Allocates and initializes a tiler container manager.
> + *
> + * @param width		Width of container
> + * @param height	Height of container
> + * @param attr		Container manager specific configuration
> + *			arguments.  Please describe these in
> + *			your header file.
> + *
> + * @return Pointer to the allocated and initialized container
> + *	   manager.  NULL on failure.  DO NOT leak any memory on
> + *	   failure!
> + */
> +#define TCM_INIT(name, attr_t) \
> +struct tcm *name(u16 width, u16 height, typeof(attr_t) *attr);
> +
> +/**
> + * Deinitialize tiler container manager.
> + *
> + * @param tcm	Pointer to container manager.
> + *
> + * @return 0 on success, non-0 error value on error.  The call
> + *	   should free as much memory as possible and meaningful
> + *	   even on failure.  Some error codes: -ENODEV: invalid
> + *	   manager.
> + */
> +static inline void tcm_deinit(struct tcm *tcm)
> +{
> +	if (tcm)
> +		tcm->deinit(tcm);
[Hiremath, Vaibhav] you may want to check for tcm->deinit also before calling.

> +}
> +
> +/**
> + * Reserves a 2D area in the container.
> + *
> + * @param tcm		Pointer to container manager.
> + * @param height	Height(in pages) of area to be reserved.
> + * @param width		Width(in pages) of area to be reserved.
> + * @param align		Alignment requirement for top-left corner of area.
> Not
> + *			all values may be supported by the container manager,
> + *			but it must support 0 (1), 32 and 64.
> + *			0 value is equivalent to 1.
> + * @param area		Pointer to where the reserved area should be stored.
> + *
> + * @return 0 on success.  Non-0 error code on failure.  Also,
> + *	   the tcm field of the area will be set to NULL on
> + *	   failure.  Some error codes: -ENODEV: invalid manager,
> + *	   -EINVAL: invalid area, -ENOMEM: not enough space for
> + *	    allocation.
> + */
> +static inline s32 tcm_reserve_2d(struct tcm *tcm, u16 width, u16 height,
> +				 u16 align, struct tcm_area *area)
> +{
> +	/* perform rudimentary error checking */
> +	s32 res = (tcm  == NULL ? -ENODEV :
> +		(area == NULL || width == 0 || height == 0 ||
> +		 /* align must be a 2 power */
> +		 align & (align - 1)) ? -EINVAL :
> +		(height > tcm->height || width > tcm->width) ? -ENOMEM :
> +		tcm->reserve_2d(tcm, height, width, align, area));
> +
> +	if (area)
> +		area->tcm = res ? NULL : tcm;
> +
> +	return res;
> +}
> +
> +/**
> + * Free a previously reserved area from the container.
> + *
> + * @param area	Pointer to area reserved by a prior call to tcm_reserve_2d
> call,
> + *		whether it was successful or not. (Note: all fields of
> + *		the structure must match.)
> + *
> + * @return 0 on success.  Non-0 error code on failure.  Also, the tcm
> + *	   field of the area is set to NULL on success to avoid subsequent
> + *	   freeing.  This call will succeed even if supplying
> + *	   the area from a failed reserved call.
> + */
> +static inline s32 tcm_free(struct tcm_area *area)
> +{
> +	s32 res = 0; /* free succeeds by default */
> +
> +	if (area && area->tcm) {
> +		res = area->tcm->free(area->tcm, area);
> +		if (res == 0)
> +			area->tcm = NULL;
> +	}
> +
> +	return res;
> +}
> +
> +/*=========================================================================
> ====
> +    HELPER FUNCTION FOR ANY TILER CONTAINER MANAGER
> +===========================================================================
> ==*/
> +
> +/* Verify if a tcm area is logically valid */
> +static inline bool tcm_area_is_valid(struct tcm_area *area)
> +{
> +	return area && area->tcm &&
> +		/* coordinate bounds */
> +		area->p1.x < area->tcm->width &&
> +		area->p1.y < area->tcm->height &&
> +		area->p0.y <= area->p1.y &&
> +		area->p0.x <= area->p1.x;
> +}
> +
> +/* see if a coordinate is within an area */
> +static inline bool __tcm_is_in(struct tcm_pt *p, struct tcm_area *a)
> +{
> +	return p->x >= a->p0.x && p->x <= a->p1.x &&
> +		p->y >= a->p0.y && p->y <= a->p1.y;
> +}
> +
> +/* calculate area width */
> +static inline u16 __tcm_area_width(struct tcm_area *area)
> +{
> +	return area->p1.x - area->p0.x + 1;
> +}
> +
> +/* calculate area height */
> +static inline u16 __tcm_area_height(struct tcm_area *area)
> +{
> +	return area->p1.y - area->p0.y + 1;
> +}
> +
> +/* calculate number of slots in an area */
> +static inline u16 __tcm_sizeof(struct tcm_area *area)
> +{
> +	return __tcm_area_width(area) * __tcm_area_height(area);
> +}
> +#define tcm_sizeof(area) __tcm_sizeof(&(area))
> +#define tcm_awidth(area) __tcm_area_width(&(area))
> +#define tcm_aheight(area) __tcm_area_height(&(area))
> +#define tcm_is_in(pt, area) __tcm_is_in(&(pt), &(area))
> +
> +#endif
> diff --git a/drivers/media/video/tiler/tcm/tcm-utils.h
> b/drivers/media/video/tiler/tcm/tcm-utils.h
> new file mode 100644
> index 0000000..0d1260a
> --- /dev/null
> +++ b/drivers/media/video/tiler/tcm/tcm-utils.h
> @@ -0,0 +1,54 @@
> +/*
> + * tcm_utils.h
> + *
> + * Utility functions for implementing TILER container managers.
> + *
> + * Author: Lajos Molnar <molnar@ti.com>
> + *
> + * Copyright (C) 2009-2010 Texas Instruments, Inc.
> + *
> + * This package is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
> + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
> + */
> +
> +#ifndef TCM_UTILS_H
> +#define TCM_UTILS_H
> +
> +#include "../tcm.h"
> +
> +/* TCM_ALG_NAME must be defined to use the debug methods */
> +
> +#ifdef DEBUG
> +#define IFDEBUG(x) x
> +#else
> +/* compile-check debug statements even if not DEBUG */
> +#define IFDEBUG(x) do { if (0) x; } while (0)
> +#endif
[Hiremath, Vaibhav] Why do you need this IFDEBUG, its like nesting, you can do directly something

#ifdef DEBUG
#define TCM_DBG(x) printk(KERN_DEBUG TCM_ALG_NAME ":%d:%s()" fmt "\n", \
			__LINE__, __func__, ##__VA_ARGS__))
#else
#define TCM_DBG(x) do{}while(0)
#endif

Infact I would suggest you to define levels for debug messages where you can set level through bootargs, sometime proves to be very helpful for debugging.

> +
> +#define P(level, fmt, ...) \
> +	IFDEBUG(printk(level TCM_ALG_NAME ":%d:%s()" fmt "\n", \
> +			__LINE__, __func__, ##__VA_ARGS__))
> +
> +#define P1(fmt, ...) P(KERN_NOTICE, fmt, ##__VA_ARGS__)
> +#define P2(fmt, ...) P(KERN_INFO, fmt, ##__VA_ARGS__)
> +#define P3(fmt, ...) P(KERN_DEBUG, fmt, ##__VA_ARGS__)
> +
[Hiremath, Vaibhav] Consider changing naming convention of P1/P2/P3 to some informative, like

TCM_DBG
TCM_INFO

Thanks,
Vaibhav

> +#define PA(level, msg, p_area) P##level(msg " (%03d %03d)-(%03d %03d)\n", \
> +	(p_area)->p0.x, (p_area)->p0.y, (p_area)->p1.x, (p_area)->p1.y)
> +
> +/* assign coordinates to area */
> +static inline
> +void assign(struct tcm_area *a, u16 x0, u16 y0, u16 x1, u16 y1)
> +{
> +	a->p0.x = x0;
> +	a->p0.y = y0;
> +	a->p1.x = x1;
> +	a->p1.y = y1;
> +}
> +
> +#endif
> --
> 1.6.3.3


^ permalink raw reply	[flat|nested] 46+ messages in thread

* RE: [RFC 3/8] TILER-DMM: Sample TCM implementation: Simple TILER Allocator
  2010-07-23 23:22     ` [RFC 3/8] TILER-DMM: Sample TCM implementation: Simple TILER Allocator David Sin
  2010-07-23 23:22       ` [RFC 4/8] TILER-DMM: TILER Memory Manager interface and implementation David Sin
  2010-07-24  7:13       ` [RFC 3/8] TILER-DMM: Sample TCM implementation: Simple TILER Allocator Shilimkar, Santosh
@ 2010-07-27 20:41       ` Hiremath, Vaibhav
  2 siblings, 0 replies; 46+ messages in thread
From: Hiremath, Vaibhav @ 2010-07-27 20:41 UTC (permalink / raw)
  To: Sin, David, linux-arm-kernel@lists.arm.linux.org.uk,
	linux-omap@vger.kernel.org, Tony
  Cc: Kanigeri, Hari, Ohad Ben-Cohen, Shilimkar, Santosh,
	Ramachandra, Ravikiran, Molnar, Lajos

> -----Original Message-----
> From: Sin, David
> Sent: Saturday, July 24, 2010 4:52 AM
> To: linux-arm-kernel@lists.arm.linux.org.uk; linux-omap@vger.kernel.org;
> Tony Lindgren; Russell King
> Cc: Kanigeri, Hari; Ohad Ben-Cohen; Hiremath, Vaibhav; Shilimkar, Santosh;
> Ramachandra, Ravikiran; Molnar, Lajos; Sin, David
> Subject: [RFC 3/8] TILER-DMM: Sample TCM implementation: Simple TILER
> Allocator
>
> From: Ravi Ramachandra <r.ramachandra@ti.com>
>
> This patch implements a simple TILER Container Manager.
>
> Signed-off-by: Ravi Ramachandra <r.ramachandra@ti.com>
> Signed-off-by: Lajos Molnar <molnar@ti.com>
> Signed-off-by: David Sin <davidsin@ti.com>
> ---
>  drivers/media/video/tiler/tcm/Makefile    |    1 +
>  drivers/media/video/tiler/tcm/_tcm-sita.h |   64 ++++
>  drivers/media/video/tiler/tcm/tcm-sita.c  |  459
> +++++++++++++++++++++++++++++
>  drivers/media/video/tiler/tcm/tcm-sita.h  |   37 +++
>  4 files changed, 561 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/media/video/tiler/tcm/Makefile
>  create mode 100644 drivers/media/video/tiler/tcm/_tcm-sita.h
>  create mode 100644 drivers/media/video/tiler/tcm/tcm-sita.c
>  create mode 100644 drivers/media/video/tiler/tcm/tcm-sita.h
>
> diff --git a/drivers/media/video/tiler/tcm/Makefile
> b/drivers/media/video/tiler/tcm/Makefile
> new file mode 100644
> index 0000000..8434607
> --- /dev/null
> +++ b/drivers/media/video/tiler/tcm/Makefile
> @@ -0,0 +1 @@
> +obj-$(CONFIG_TI_TILER) += tcm-sita.o
> diff --git a/drivers/media/video/tiler/tcm/_tcm-sita.h
> b/drivers/media/video/tiler/tcm/_tcm-sita.h
> new file mode 100644
> index 0000000..4ede1ab
> --- /dev/null
> +++ b/drivers/media/video/tiler/tcm/_tcm-sita.h
> @@ -0,0 +1,64 @@
> +/*
> + * _tcm_sita.h
> + *
> + * SImple Tiler Allocator (SiTA) private structures.
> + *
> + * Author: Ravi Ramachandra <r.ramachandra@ti.com>
> + *
> + * Copyright (C) 2009-2010 Texas Instruments, Inc.
> + *
> + * This package is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
> + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
> + */
> +
> +#ifndef _TCM_SITA_H
> +#define _TCM_SITA_H
> +
> +#include "../tcm.h"
> +
> +/* length between two coordinates */
> +#define LEN(a, b) ((a) > (b) ? (a) - (b) + 1 : (b) - (a) + 1)
> +
> +enum criteria {
> +     CR_MAX_NEIGHS           = 0x01,
> +     CR_FIRST_FOUND          = 0x10,
> +     CR_BIAS_HORIZONTAL      = 0x20,
> +     CR_BIAS_VERTICAL        = 0x40,
> +     CR_DIAGONAL_BALANCE     = 0x80
> +};
> +
> +/* nearness to the beginning of the search field from 0 to 1000 */
> +struct nearness_factor {
> +     s32 x;
> +     s32 y;
> +};
> +
> +/*
> + * Statistics on immediately neighboring slots.  Edge is the number of
> + * border segments that are also border segments of the scan field.  Busy
> + * refers to the number of neighbors that are occupied.
> + */
> +struct neighbor_stats {
> +     u16 edge;
> +     u16 busy;
> +};
> +
> +/* structure to keep the score of a potential allocation */
> +struct score {
> +     struct nearness_factor  f;
> +     struct neighbor_stats   n;
> +     struct tcm_area         a;
> +     u16    neighs;          /* number of busy neighbors */
> +};
> +
> +struct sita_pvt {
> +     struct mutex mtx;
> +     struct tcm_area ***map; /* pointers to the parent area for each slot
> */
> +};
> +
> +#endif
> diff --git a/drivers/media/video/tiler/tcm/tcm-sita.c
> b/drivers/media/video/tiler/tcm/tcm-sita.c
> new file mode 100644
> index 0000000..93be3e6
> --- /dev/null
> +++ b/drivers/media/video/tiler/tcm/tcm-sita.c
> @@ -0,0 +1,459 @@
> +/*
> + * tcm-sita.c
> + *
> + * SImple Tiler Allocator (SiTA): 2D and 1D allocation(reservation)
> algorithm
> + *
> + * Authors: Ravi Ramachandra <r.ramachandra@ti.com>,
> + *          Lajos Molnar <molnar@ti.com>
> + *
> + * Copyright (C) 2009-2010 Texas Instruments, Inc.
> + *
> + * This package is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
> + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
> + *
> + */
> +#include <linux/slab.h>
> +
> +#include "_tcm-sita.h"
> +#include "tcm-sita.h"
> +
> +#define TCM_ALG_NAME "tcm_sita"
[Hiremath, Vaibhav] Move this after include statement.

> +#include "tcm-utils.h"
> +
> +#define ALIGN_DOWN(value, align) ((value) & ~((align) - 1))
> +
> +/* Individual selection criteria for different scan areas */
> +static s32 CR_L2R_T2B = CR_BIAS_HORIZONTAL;
> +
[Hiremath, Vaibhav] Not good practice to define variable in caps.
Also why do we need this variable which is not getting modified and used as constant only?

> +/*********************************************
> + *   TCM API - Sita Implementation
> + *********************************************/
> +static s32 sita_reserve_2d(struct tcm *tcm, u16 h, u16 w, u8 align,
> +                        struct tcm_area *area);
> +static s32 sita_free(struct tcm *tcm, struct tcm_area *area);
> +static void sita_deinit(struct tcm *tcm);
> +
> +/*********************************************
> + *   Main Scanner functions
> + *********************************************/
> +static s32 scan_areas_and_find_fit(struct tcm *tcm, u16 w, u16 h, u16 align,
> +                                struct tcm_area *area);
> +
> +static s32 scan_l2r_t2b(struct tcm *tcm, u16 w, u16 h, u16 align,
> +                     struct tcm_area *field, struct tcm_area *area);
> +
> +/*********************************************
> + *   Support Infrastructure Methods
> + *********************************************/
> +static s32 is_area_free(struct tcm_area ***map, u16 x0, u16 y0, u16 w, u16
> h);
> +
> +static s32 update_candidate(struct tcm *tcm, u16 x0, u16 y0, u16 w, u16 h,
> +                         struct tcm_area *field, s32 criteria,
> +                         struct score *best);
> +
> +static void get_nearness_factor(struct tcm_area *field,
> +                             struct tcm_area *candidate,
> +                             struct nearness_factor *nf);
> +
> +static void get_neighbor_stats(struct tcm *tcm, struct tcm_area *area,
> +                            struct neighbor_stats *stat);
> +
> +static void fill_area(struct tcm *tcm,
> +                             struct tcm_area *area, struct tcm_area *parent);
> +
> +/*********************************************/
> +
> +/*********************************************
> + *   Utility Methods
> + *********************************************/
> +struct tcm *sita_init(u16 width, u16 height, void *attr)
> +{
> +     struct tcm *tcm;
> +     struct sita_pvt *pvt;
> +     struct tcm_area area = {0};
> +     s32 i;
> +
> +     if (width == 0 || height == 0)
> +             return NULL;
> +
> +     tcm = kzalloc(sizeof(*tcm), GFP_KERNEL);
> +     pvt = kzalloc(sizeof(*pvt), GFP_KERNEL);
> +     if (!tcm || !pvt)
> +             goto error;
> +
> +     /* Updating the pointers to SiTA implementation APIs */
> +     tcm->height = height;
> +     tcm->width = width;
> +     tcm->reserve_2d = sita_reserve_2d;
> +     tcm->free = sita_free;
> +     tcm->deinit = sita_deinit;
> +     tcm->pvt = (void *)pvt;
> +
> +     mutex_init(&(pvt->mtx));
> +
> +     /* Creating tam map */
> +     pvt->map = kzalloc(sizeof(*pvt->map) * tcm->width, GFP_KERNEL);
> +     if (!pvt->map)
> +             goto error;
> +
> +     for (i = 0; i < tcm->width; i++) {
> +             pvt->map[i] =
> +                     kzalloc(sizeof(**pvt->map) * tcm->height,
> +                                                             GFP_KERNEL);
> +             if (pvt->map[i] == NULL) {
> +                     while (i--)
> +                             kfree(pvt->map[i]);
> +                     kfree(pvt->map);
> +                     goto error;
> +             }
> +     }
> +
> +     mutex_lock(&(pvt->mtx));
> +     assign(&area, 0, 0, width - 1, height - 1);
> +     fill_area(tcm, &area, NULL);
> +     mutex_unlock(&(pvt->mtx));
> +     return tcm;
> +
> +error:
> +     kfree(tcm);
> +     kfree(pvt);
> +     return NULL;
> +}
> +
> +static void sita_deinit(struct tcm *tcm)
> +{
> +     struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
> +     struct tcm_area area = {0};
> +     s32 i;
> +
> +     area.p1.x = tcm->width - 1;
> +     area.p1.y = tcm->height - 1;
> +
> +     mutex_lock(&(pvt->mtx));
> +     fill_area(tcm, &area, NULL);
> +     mutex_unlock(&(pvt->mtx));
> +
> +     mutex_destroy(&(pvt->mtx));
> +
> +     for (i = 0; i < tcm->height; i++)
> +             kfree(pvt->map[i]);
> +     kfree(pvt->map);
> +     kfree(pvt);
[Hiremath, Vaibhav] Why are we not freeing tcm memory here?

Thanks,
Vaibhav
> +}
> +
> +/**
> + * Reserve a 2D area in the container
> + *
> + * @param w  width
> + * @param h  height
> + * @param area       pointer to the area that will be populated with the
> reesrved
> + *           area
> + *
> + * @return 0 on success, non-0 error value on failure.
> + */
> +static s32 sita_reserve_2d(struct tcm *tcm, u16 h, u16 w, u8 align,
> +                        struct tcm_area *area)
> +{
> +     s32 ret;
> +     struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
> +
> +     /* not supporting more than 64 as alignment */
> +     if (align > 64)
> +             return -EINVAL;
> +
> +     /* we prefer 1, 32 and 64 as alignment */
> +     align = align <= 1 ? 1 : align <= 32 ? 32 : 64;
> +
> +     mutex_lock(&(pvt->mtx));
> +     ret = scan_areas_and_find_fit(tcm, w, h, align, area);
> +     if (!ret)
> +             /* update map */
> +             fill_area(tcm, area, area);
> +
> +     mutex_unlock(&(pvt->mtx));
> +     return ret;
> +}
> +
> +/**
> + * Unreserve a previously allocated 2D or 1D area
> + * @param area       area to be freed
> + * @return 0 - success
> + */
> +static s32 sita_free(struct tcm *tcm, struct tcm_area *area)
> +{
> +     struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
> +
> +     mutex_lock(&(pvt->mtx));
> +
> +     /* Clear the contents of the associated tiles in the map */
> +     fill_area(tcm, area, NULL);
> +
> +     mutex_unlock(&(pvt->mtx));
> +
> +     return 0;
> +}
> +
> +/**
> + * Note: In general the cordinates in the scan field area relevant to the
> can
> + * sweep directions. The scan origin (e.g. top-left corner) will always be
> + * the p0 member of the field.  Therfore, for a scan from top-left p0.x <=
> p1.x
> + * and p0.y <= p1.y; whereas, for a scan from bottom-right p1.x <= p0.x and
> p1.y
> + * <= p0.y
> + */
> +
> +/**
> + * Raster scan horizontally left to right from top to bottom to find a
> place for
> + * a 2D area of given size inside a scan field.
> + *
> + * @param w  width of desired area
> + * @param h  height of desired area
> + * @param align      desired area alignment
> + * @param area       pointer to the area that will be set to the best position
> + * @param field      area to scan (inclusive)
> + *
> + * @return 0 on success, non-0 error value on failure.
> + */
> +static s32 scan_l2r_t2b(struct tcm *tcm, u16 w, u16 h, u16 align,
> +                     struct tcm_area *field, struct tcm_area *area)
> +{
> +     s32 x, y;
> +     s16 start_x, end_x, start_y, end_y;
> +     struct tcm_area ***map = ((struct sita_pvt *)tcm->pvt)->map;
> +     struct score best = {{0}, {0}, {0}, 0};
> +
> +     PA(2, "scan_l2r_t2b:", field);
> +
> +     start_x = field->p0.x;
> +     end_x = field->p1.x;
> +     start_y = field->p0.y;
> +     end_y = field->p1.y;
> +
> +     /* check scan area co-ordinates */
> +     if (field->p1.x < field->p0.x ||
> +         field->p1.y < field->p0.y)
> +             return -EINVAL;
> +
> +     /* check if allocation would fit in scan area */
> +     if (w > LEN(end_x, start_x) || h > LEN(end_y, start_y))
> +             return -ENOSPC;
> +
> +     start_x = ALIGN(start_x, align);
> +
> +     /* check if allocation would still fit in scan area */
> +     if (w > LEN(end_x, start_x))
> +             return -ENOSPC;
> +
> +     /* adjust end_x and end_y, as allocation would not fit beyond */
> +     end_x = end_x - w + 1; /* + 1 to be inclusive */
> +     end_y = end_y - h + 1;
> +
> +     P2("ali=%d x=%d..%d y=%d..%d", align, start_x, end_x, start_y, end_y);
> +
> +     /* scan field top-to-bottom, left-to-right */
> +     for (y = start_y; y <= end_y; y++) {
> +             for (x = start_x; x <= end_x; x += align) {
> +                     if (is_area_free(map, x, y, w, h)) {
> +                             P3("found shoulder: %d,%d", x, y);
> +
> +                             /* update best candidate */
> +                             if (update_candidate(tcm, x, y, w, h, field,
> +                                                     CR_L2R_T2B, &best))
> +                                     goto done;
> +                             break;
> +                     } else if (map[x][y]) {
> +                             /* step over 2D areas */
> +                             x = ALIGN_DOWN(map[x][y]->p1.x, align);
> +                             P3("moving to: %d,%d", x, y);
> +                     }
> +             }
> +     }
> +
> +     if (!best.a.tcm)
> +             return -ENOSPC;
> +done:
> +     assign(area, best.a.p0.x, best.a.p0.y, best.a.p1.x, best.a.p1.y);
> +     return 0;
> +}
> +
> +/**
> + * Find a place for a 2D area of given size inside a scan field based on
> its
> + * alignment needs.
> + *
> + * @param w  width of desired area
> + * @param h  height of desired area
> + * @param align      desired area alignment
> + * @param area       pointer to the area that will be set to the best position
> + *
> + * @return 0 on success, non-0 error value on failure.
> + */
> +static s32 scan_areas_and_find_fit(struct tcm *tcm, u16 w, u16 h, u16 align,
> +                                struct tcm_area *area)
> +{
> +     struct tcm_area field = {0};
> +
> +     /* scan whole container left to right, top to bottom */
> +     assign(&field, 0, 0, tcm->width - 1, tcm->height - 1);
> +     return scan_l2r_t2b(tcm, w, h, align, &field, area);
> +}
> +
> +/* check if an entire area is free */
> +static s32 is_area_free(struct tcm_area ***map, u16 x0, u16 y0, u16 w, u16
> h)
> +{
> +     u16 x = 0, y = 0;
> +     for (y = y0; y < y0 + h; y++) {
> +             for (x = x0; x < x0 + w; x++) {
> +                     if (map[x][y])
> +                             return false;
> +             }
> +     }
> +     return true;
> +}
> +
> +/* fills an area with a parent tcm_area */
> +static void fill_area(struct tcm *tcm, struct tcm_area *area,
> +                     struct tcm_area *parent)
> +{
> +     s32 x, y;
> +     struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
> +
> +     PA(2, "fill 2d area", area);
> +     for (x = area->p0.x; x <= area->p1.x; ++x)
> +             for (y = area->p0.y; y <= area->p1.y; ++y)
> +                     pvt->map[x][y] = parent;
> +}
> +
> +/**
> + * Compares a candidate area to the current best area, and if it is a
> better
> + * fit, it updates the best to this one.
> + *
> + * @param x0, y0, w, h               top, left, width, height of candidate area
> + * @param field                      scan field
> + * @param criteria           scan criteria
> + * @param best                       best candidate and its scores
> + *
> + * @return 1 (true) if the candidate area is known to be the final best, so
> no
> + * more searching should be performed
> + */
> +static s32 update_candidate(struct tcm *tcm, u16 x0, u16 y0, u16 w, u16 h,
> +                         struct tcm_area *field, s32 criteria,
> +                         struct score *best)
> +{
> +     struct score me;        /* score for area */
> +
> +     /*
> +      * If first found is enabled then we stop looking
> +      * NOTE: For horizontal bias we always give the first found, because
> our
> +      * scan is horizontal-raster-based and the first candidate will always
> +      * have the horizontal bias.
> +      */
> +     bool first = criteria & (CR_FIRST_FOUND | CR_BIAS_HORIZONTAL);
> +
> +     assign(&me.a, x0, y0, x0 + w - 1, y0 + h - 1);
> +
> +     /* calculate score for current candidate */
> +     if (!first) {
> +             get_neighbor_stats(tcm, &me.a, &me.n);
> +             me.neighs = me.n.edge + me.n.busy;
> +             get_nearness_factor(field, &me.a, &me.f);
> +     }
> +
> +     /* the 1st candidate is always the best */
> +     if (!best->a.tcm)
> +             goto better;
> +
> +     /* see if this are is better than the best so far */
> +
> +     /* neighbor check */
> +     if ((criteria & CR_MAX_NEIGHS) &&
> +             me.neighs > best->neighs)
> +             goto better;
> +
> +     /* vertical bias check */
> +     if ((criteria & CR_BIAS_VERTICAL) &&
> +     /*
> +      * NOTE: not checking if lengths are same, because that does not
> +      * find new shoulders on the same row after a fit
> +      */
> +             LEN(me.a.p0.y, field->p0.y) >
> +             LEN(best->a.p0.y, field->p0.y))
> +             goto better;
> +
> +     /* diagonal balance check */
> +     if ((criteria & CR_DIAGONAL_BALANCE) &&
> +             best->neighs <= me.neighs &&
> +             (best->neighs < me.neighs ||
> +              /* this implies that neighs and occupied match */
> +              best->n.busy < me.n.busy ||
> +              (best->n.busy == me.n.busy &&
> +               /* check the nearness factor */
> +               best->f.x + best->f.y > me.f.x + me.f.y)))
> +             goto better;
> +
> +     /* not better, keep going */
> +     return 0;
> +
> +better:
> +     /* save current area as best */
> +     memcpy(best, &me, sizeof(me));
> +     best->a.tcm = tcm;
> +     return first;
> +}
> +
> +/**
> + * Calculate the nearness factor of an area in a search field.  The
> nearness
> + * factor is smaller if the area is closer to the search origin.
> + */
> +static void get_nearness_factor(struct tcm_area *field, struct tcm_area
> *area,
> +                             struct nearness_factor *nf)
> +{
> +     /**
> +      * Using signed math as field coordinates may be reversed if
> +      * search direction is right-to-left or bottom-to-top.
> +      */
> +     nf->x = (s32)(area->p0.x - field->p0.x) * 1000 /
> +             (field->p1.x - field->p0.x);
> +     nf->y = (s32)(area->p0.y - field->p0.y) * 1000 /
> +             (field->p1.y - field->p0.y);
> +}
> +
> +/* get neighbor statistics */
> +static void get_neighbor_stats(struct tcm *tcm, struct tcm_area *area,
> +                      struct neighbor_stats *stat)
> +{
> +     s16 x = 0, y = 0;
> +     struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
> +
> +     /* Clearing any exisiting values */
> +     memset(stat, 0, sizeof(*stat));
> +
> +     /* process top & bottom edges */
> +     for (x = area->p0.x; x <= area->p1.x; x++) {
> +             if (area->p0.y == 0)
> +                     stat->edge++;
> +             else if (pvt->map[x][area->p0.y - 1])
> +                     stat->busy++;
> +
> +             if (area->p1.y == tcm->height - 1)
> +                     stat->edge++;
> +             else if (pvt->map[x][area->p1.y + 1])
> +                     stat->busy++;
> +     }
> +
> +     /* process left & right edges */
> +     for (y = area->p0.y; y <= area->p1.y; ++y) {
> +             if (area->p0.x == 0)
> +                     stat->edge++;
> +             else if (pvt->map[area->p0.x - 1][y])
> +                     stat->busy++;
> +
> +             if (area->p1.x == tcm->width - 1)
> +                     stat->edge++;
> +             else if (pvt->map[area->p1.x + 1][y])
> +                     stat->busy++;
> +     }
> +}
> diff --git a/drivers/media/video/tiler/tcm/tcm-sita.h
> b/drivers/media/video/tiler/tcm/tcm-sita.h
> new file mode 100644
> index 0000000..ab2d05b
> --- /dev/null
> +++ b/drivers/media/video/tiler/tcm/tcm-sita.h
> @@ -0,0 +1,37 @@
> +/*
> + * tcm_sita.h
> + *
> + * SImple Tiler Allocator (SiTA) interface.
> + *
> + * Author: Ravi Ramachandra <r.ramachandra@ti.com>
> + *
> + * Copyright (C) 2009-2010 Texas Instruments, Inc.
> + *
> + * This package is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
> + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
> + */
> +
> +#ifndef TCM_SITA_H
> +#define TCM_SITA_H
> +
> +#include "../tcm.h"
> +
> +/**
> + * Create a SiTA tiler container manager.
> + *
> + * @param width  Container width
> + * @param height Container height
> + * @param attr   unused
> + *
> + * @return TCM instance
> + */
> +struct tcm *sita_init(u16 width, u16 height, void *attr);
> +
> +TCM_INIT(sita_init, void);
> +
> +#endif /* TCM_SITA_H_ */
> --
> 1.6.3.3


^ permalink raw reply	[flat|nested] 46+ messages in thread

* RE: [RFC 4/8] TILER-DMM: TILER Memory Manager interface and implementation
  2010-07-23 23:22       ` [RFC 4/8] TILER-DMM: TILER Memory Manager interface and implementation David Sin
  2010-07-23 23:22         ` [RFC 5/8] TILER-DMM: TILER interface file and documentation David Sin
  2010-07-24  8:01         ` [RFC 4/8] TILER-DMM: TILER Memory Manager interface and implementation Russell King - ARM Linux
@ 2010-07-28  5:53         ` Hiremath, Vaibhav
  2 siblings, 0 replies; 46+ messages in thread
From: Hiremath, Vaibhav @ 2010-07-28  5:53 UTC (permalink / raw)
  To: Sin, David, linux-arm-kernel@lists.arm.linux.org.uk,
	linux-omap@vger.kernel.org, Tony
  Cc: Kanigeri, Hari, Ohad Ben-Cohen, Shilimkar, Santosh, Molnar, Lajos

> -----Original Message-----
> From: Sin, David
> Sent: Saturday, July 24, 2010 4:52 AM
> To: linux-arm-kernel@lists.arm.linux.org.uk; linux-omap@vger.kernel.org;
> Tony Lindgren; Russell King
> Cc: Kanigeri, Hari; Ohad Ben-Cohen; Hiremath, Vaibhav; Shilimkar, Santosh;
> Molnar, Lajos; Sin, David
> Subject: [RFC 4/8] TILER-DMM: TILER Memory Manager interface and
> implementation
> 
> From: Lajos Molnar <molnar@ti.com>
> 
> This patch defines the TILER Memory Manager (TMM) interface and
> provides implementation for a PAT-supporting TMM.
> 
> Signed-off-by: Lajos Molnar <molnar@ti.com>
> Signed-off-by: David Sin <davidsin@ti.com>
> ---
>  drivers/media/video/tiler/tmm-pat.c |  274
> +++++++++++++++++++++++++++++++++++
>  drivers/media/video/tiler/tmm.h     |  109 ++++++++++++++
>  2 files changed, 383 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/media/video/tiler/tmm-pat.c
>  create mode 100644 drivers/media/video/tiler/tmm.h
> 
> diff --git a/drivers/media/video/tiler/tmm-pat.c
> b/drivers/media/video/tiler/tmm-pat.c
> new file mode 100644
> index 0000000..ccd32b4
> --- /dev/null
> +++ b/drivers/media/video/tiler/tmm-pat.c
> @@ -0,0 +1,274 @@
> +/*
> + * tmm-pat.c
> + *
> + * DMM driver support functions for TI TILER hardware block.
> + *
> + * Authors: Lajos Molnar <molnar@ti.com>
> + *          David Sin <davidsin@ti.com>
> + *
> + * Copyright (C) 2009-2010 Texas Instruments, Inc.
> + *
> + * This package is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
> + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
> + */
> +#include <linux/init.h>
> +#include <linux/module.h>
> +#include <linux/mm.h>
> +#include <linux/mmzone.h>
> +#include <asm/cacheflush.h>
> +#include <linux/mutex.h>
> +#include <linux/list.h>
> +#include <linux/slab.h>
> +
> +#include "tmm.h"
> +
> +/* Page size granularity can be 4k, 16k, or 64k */
> +#define DMM_PAGE 0x1000
> +
[Hiremath, Vaibhav] You can use SZ_4K, SZ_16K macros here.

> +/* Memory limit to cache free pages. TILER will eventually use this much */
> +static u32 cache_limit = CONFIG_TILER_CACHE_LIMIT << 20;
> +module_param_named(cache, cache_limit, uint, 0644);
> +MODULE_PARM_DESC(cache, "Cache free pages if total memory is under this
> limit");
> +
> +/* global state - statically initialized */
> +static LIST_HEAD(free_list);	/* page cache: list of free pages */
> +static u32 total_mem;		/* total memory allocated (free & used) */
> +static u32 refs;		/* number of tmm_pat instances */
> +static DEFINE_MUTEX(mtx);	/* global mutex */
> +
> +/* The page struct pointer and physical address of each page.*/
> +struct mem {
> +	struct list_head list;
> +	struct page *pg;	/* page struct */
> +	u32 pa;			/* physical address */
> +};
> +
> +/* Used to keep track of mem per tmm_pat_get_pages call */
> +struct fast {
[Hiremath, Vaibhav] Can you think of some better naming convention here, "fast" is bit confusing here?
Does following convention make sense to you here,

struct mem	=> struct tmm_page
struct fast	=> struct tmm_pages


> +	struct list_head list;
> +	struct mem **mem;	/* array of page info */
> +	u32 *pa;		/* array of physical addresses */
> +	u32 num;		/* number of pages */
> +};
> +
> +/* TMM PAT private structure */
> +struct dmm_mem {
> +	struct list_head fast_list;
> +	struct dmm *dmm;
> +};
> +
> +/**
> + *  Frees pages in a fast structure.  Moves pages to the free list if there
> + *  are	less pages used	than max_to_keep.  Otherwise, it frees the
> pages
> + */
> +static void free_fast(struct fast *f)
[Hiremath, Vaibhav] Same here, free_pages. Applicable to all places.

> +{
> +	s32 i = 0;
> +
> +	/* mutex is locked */
> +	for (i = 0; i < f->num; i++) {
> +		if (total_mem < cache_limit) {
> +			/* cache free page if under the limit */
> +			list_add(&f->mem[i]->list, &free_list);
> +		} else {
> +			/* otherwise, free */
> +			total_mem -= PAGE_SIZE;
[Hiremath, Vaibhav] I have one Q here,

What if DMM/Tiler page size is different than Linux PAGE_SIZE? Does this driver will still work? Have you tested it?

Thanks,
Vaibhav

> +			__free_page(f->mem[i]->pg);
> +		}
> +	}
> +	kfree(f->pa);
> +	kfree(f->mem);
> +	/* remove only if element was added */
> +	if (f->list.next)
> +		list_del(&f->list);
> +	kfree(f);
> +}
> +
> +/* allocate and flush a page */
> +static struct mem *alloc_mem(void)
> +{
> +	struct mem *m = kzalloc(sizeof(*m), GFP_KERNEL);
> +	if (!m)
> +		return NULL;
> +
> +	m->pg = alloc_page(GFP_KERNEL | GFP_DMA);
> +	if (!m->pg) {
> +		kfree(m);
> +		return NULL;
> +	}
> +
> +	m->pa = page_to_phys(m->pg);
> +
> +	/* flush the cache entry for each page we allocate. */
> +	dmac_flush_range(page_address(m->pg),
> +				page_address(m->pg) + PAGE_SIZE);
> +	outer_flush_range(m->pa, m->pa + PAGE_SIZE);
> +
> +	return m;
> +}
> +
> +static void free_page_cache(void)
> +{
> +	struct mem *m, *m_;
> +
> +	/* mutex is locked */
> +	list_for_each_entry_safe(m, m_, &free_list, list) {
> +		__free_page(m->pg);
> +		total_mem -= PAGE_SIZE;
> +		list_del(&m->list);
> +		kfree(m);
> +	}
> +}
> +
> +static void tmm_pat_deinit(struct tmm *tmm)
> +{
> +	struct fast *f, *f_;
> +	struct dmm_mem *pvt = (struct dmm_mem *) tmm->pvt;
> +
> +	mutex_lock(&mtx);
> +
> +	/* free all outstanding used memory */
> +	list_for_each_entry_safe(f, f_, &pvt->fast_list, list)
> +		free_fast(f);
> +
> +	/* if this is the last tmm_pat, free all memory */
> +	if (--refs == 0)
> +		free_page_cache();
> +
> +	mutex_unlock(&mtx);
> +}
> +
> +static u32 *tmm_pat_get_pages(struct tmm *tmm, u32 n)
> +{
> +	struct mem *m;
> +	struct fast *f;
> +	struct dmm_mem *pvt = (struct dmm_mem *) tmm->pvt;
> +
> +	f = kzalloc(sizeof(*f), GFP_KERNEL);
> +	if (!f)
> +		return NULL;
> +
> +	/* array of mem struct pointers */
> +	f->mem = kzalloc(n * sizeof(*f->mem), GFP_KERNEL);
> +
> +	/* array of physical addresses */
> +	f->pa = kzalloc(n * sizeof(*f->pa), GFP_KERNEL);
> +
> +	/* no pages have been allocated yet (needed for cleanup) */
> +	f->num = 0;
> +
> +	if (!f->mem || !f->pa)
> +		goto cleanup;
> +
> +	/* fill out fast struct mem array with free pages */
> +	mutex_lock(&mtx);
> +	while (f->num < n) {
> +		/* if there is a free cached page use it */
> +		if (!list_empty(&free_list)) {
> +			/* unbind first element from list */
> +			m = list_first_entry(&free_list, typeof(*m), list);
> +			list_del(&m->list);
> +		} else {
> +			mutex_unlock(&mtx);
> +
> +			/**
> +			 * Unlock mutex during allocation and cache flushing.
> +			 */
> +			m = alloc_mem();
> +			if (!m)
> +				goto cleanup;
> +
> +			mutex_lock(&mtx);
> +			total_mem += PAGE_SIZE;
> +		}
> +
> +		f->mem[f->num] = m;
> +		f->pa[f->num++] = m->pa;
> +	}
> +
> +	list_add(&f->list, &pvt->fast_list);
> +	mutex_unlock(&mtx);
> +	return f->pa;
> +
> +cleanup:
> +	free_fast(f);
> +	return NULL;
> +}
> +
> +static void tmm_pat_free_pages(struct tmm *tmm, u32 *page_list)
> +{
> +	struct dmm_mem *pvt = (struct dmm_mem *) tmm->pvt;
> +	struct fast *f, *f_;
> +
> +	mutex_lock(&mtx);
> +	/* find fast struct based on 1st page */
> +	list_for_each_entry_safe(f, f_, &pvt->fast_list, list) {
> +		if (f->pa[0] == page_list[0]) {
> +			free_fast(f);
> +			break;
> +		}
> +	}
> +	mutex_unlock(&mtx);
> +}
> +
> +static s32 tmm_pat_map(struct tmm *tmm, struct pat_area area, u32 page_pa)
> +{
> +	struct dmm_mem *pvt = (struct dmm_mem *) tmm->pvt;
> +	struct pat pat_desc = {0};
> +
> +	/* send pat descriptor to dmm driver */
> +	pat_desc.ctrl.dir = 0;
> +	pat_desc.ctrl.ini = 0;
> +	pat_desc.ctrl.lut_id = 0;
> +	pat_desc.ctrl.start = 1;
> +	pat_desc.ctrl.sync = 0;
> +	pat_desc.area = area;
> +	pat_desc.next = NULL;
> +
> +	/* must be a 16-byte aligned physical address */
> +	pat_desc.data = page_pa;
> +	return dmm_pat_refill(pvt->dmm, &pat_desc, MANUAL);
> +}
> +
> +struct tmm *tmm_pat_init(u32 pat_id)
> +{
> +	struct tmm *tmm = NULL;
> +	struct dmm_mem *pvt = NULL;
> +
> +	struct dmm *dmm = dmm_pat_init(pat_id);
> +	if (dmm)
> +		tmm = kzalloc(sizeof(*tmm), GFP_KERNEL);
> +	if (tmm)
> +		pvt = kzalloc(sizeof(*pvt), GFP_KERNEL);
> +	if (pvt) {
> +		/* private data */
> +		pvt->dmm = dmm;
> +		INIT_LIST_HEAD(&pvt->fast_list);
> +
> +		/* increate tmm_pat references */
> +		mutex_lock(&mtx);
> +		refs++;
> +		mutex_unlock(&mtx);
> +
> +		/* public data */
> +		tmm->pvt = pvt;
> +		tmm->deinit = tmm_pat_deinit;
> +		tmm->get = tmm_pat_get_pages;
> +		tmm->free = tmm_pat_free_pages;
> +		tmm->map = tmm_pat_map;
> +		tmm->clear = NULL;   /* not yet supported */
> +
> +		return tmm;
> +	}
> +
> +	kfree(pvt);
> +	kfree(tmm);
> +	dmm_pat_release(dmm);
> +	return NULL;
> +}
> +EXPORT_SYMBOL(tmm_pat_init);
> diff --git a/drivers/media/video/tiler/tmm.h
> b/drivers/media/video/tiler/tmm.h
> new file mode 100644
> index 0000000..fbdc1e2
> --- /dev/null
> +++ b/drivers/media/video/tiler/tmm.h
> @@ -0,0 +1,109 @@
> +/*
> + * tmm.h
> + *
> + * TMM interface definition for TI TILER driver.
> + *
> + * Author: Lajos Molnar <molnar@ti.com>
> + *
> + * Copyright (C) 2009-2010 Texas Instruments, Inc.
> + *
> + * This package is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
> + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
> + */
> +#ifndef TMM_H
> +#define TMM_H
> +
> +#include <mach/dmm.h>
> +/**
> + * TMM interface
> + */
> +struct tmm {
> +	void *pvt;
> +
> +	/* function table */
> +	u32 *(*get)	(struct tmm *tmm, u32 num_pages);
> +	void (*free)	(struct tmm *tmm, u32 *pages);
> +	s32  (*map)	(struct tmm *tmm, struct pat_area area, u32 page_pa);
> +	void (*clear)	(struct tmm *tmm, struct pat_area area);
> +	void (*deinit)	(struct tmm *tmm);
> +};
> +
> +/**
> + * Request a set of pages from the DMM free page stack.
> + * @return a pointer to a list of physical page addresses.
> + */
> +static inline
> +u32 *tmm_get(struct tmm *tmm, u32 num_pages)
> +{
> +	if (tmm && tmm->pvt)
> +		return tmm->get(tmm, num_pages);
> +	return NULL;
> +}
> +
> +/**
> + * Return a set of used pages to the DMM free page stack.
> + * @param list a pointer to a list of physical page addresses.
> + */
> +static inline
> +void tmm_free(struct tmm *tmm, u32 *pages)
> +{
> +	if (tmm && tmm->pvt)
> +		tmm->free(tmm, pages);
> +}
> +
> +/**
> + * Program the physical address translator.
> + * @param area PAT area
> + * @param list of pages
> + */
> +static inline
> +s32 tmm_map(struct tmm *tmm, struct pat_area area, u32 page_pa)
> +{
> +	if (tmm && tmm->map && tmm->pvt)
> +		return tmm->map(tmm, area, page_pa);
> +	return -ENODEV;
> +}
> +
> +/**
> + * Clears the physical address translator.
> + * @param area PAT area
> + */
> +static inline
> +void tmm_clear(struct tmm *tmm, struct pat_area area)
> +{
> +	if (tmm && tmm->clear && tmm->pvt)
> +		tmm->clear(tmm, area);
> +}
> +
> +/**
> + * Checks whether tiler memory manager supports mapping
> + */
> +static inline
> +bool tmm_can_map(struct tmm *tmm)
> +{
> +	return tmm && tmm->map;
> +}
> +
> +/**
> + * Deinitialize tiler memory manager
> + */
> +static inline
> +void tmm_deinit(struct tmm *tmm)
> +{
> +	if (tmm && tmm->pvt)
> +		tmm->deinit(tmm);
> +}
> +
> +/**
> + * TMM implementation for PAT support.
> + *
> + * Initialize TMM for PAT with given id.
> + */
> +struct tmm *tmm_pat_init(u32 pat_id);
> +
> +#endif
> --
> 1.6.3.3


^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [RFC 1/8] TILER-DMM: DMM-PAT driver for TI TILER
  2010-07-27 19:05     ` Sin, David
  2010-07-27 19:53       ` Hiremath, Vaibhav
@ 2010-07-28  9:45       ` Laurent Pinchart
  1 sibling, 0 replies; 46+ messages in thread
From: Laurent Pinchart @ 2010-07-28  9:45 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Sin, David, Hiremath, Vaibhav, linux-omap@vger.kernel.org,
	Tony Lindgren, Russell King, Ohad Ben-Cohen, Kanigeri, Hari,
	Shilimkar, Santosh, Molnar, Lajos

Hi,

On Tuesday 27 July 2010 21:05:11 Sin, David wrote:
> On Tuesday 27 July 2010 13:38:00 Hiremath, Vaibhav wrote:
> > On Saturday 24 July 2010 04:52:00 Sin, David wrote:
> > > 
> > > This patch adds support for DMM-PAT initialization and programming.
[snip]

> > > diff --git a/arch/arm/mach-omap2/include/mach/dmm.h b/arch/arm/mach-
> > > omap2/include/mach/dmm.h
> > > new file mode 100644
> > > index 0000000..68b798a
> > > --- /dev/null
> > > +++ b/arch/arm/mach-omap2/include/mach/dmm.h
> > > @@ -0,0 +1,128 @@

[snip]

> > > +#define DMM_PAT_STATUS__0     0x4C0
> > > +#define DMM_PAT_STATUS__1     0x4C4
> > > +#define DMM_PAT_STATUS__2     0x4C8
> > > +#define DMM_PAT_STATUS__3     0x4CC
> > > +#define DMM_PAT_DESCR__0      0x500
> > > +#define DMM_PAT_AREA__0       0x504
> > > +#define DMM_PAT_CTRL__0       0x508
> > > +#define DMM_PAT_DATA__0       0x50C
> > 
> > [Hiremath, Vaibhav] Not sure whether somebody has given same comment or
> > not, any specific reason behind double _ here?
> 
> [dhs] Yes -- this comment has been made already.  I'm using the same names
> defined in the TRM.  However, it can be changed.

If the TRM uses two underscores I'm fine with it.

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [RFC 1/8] TILER-DMM: DMM-PAT driver for TI TILER
  2010-07-27 19:53       ` Hiremath, Vaibhav
@ 2010-07-28 10:00         ` Laurent Pinchart
  2010-07-28 14:39           ` Sin, David
  0 siblings, 1 reply; 46+ messages in thread
From: Laurent Pinchart @ 2010-07-28 10:00 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Hiremath, Vaibhav, Sin, David, linux-omap@vger.kernel.org,
	Tony Lindgren, Russell King, Ohad Ben-Cohen, Kanigeri, Hari,
	Shilimkar, Santosh, Molnar, Lajos


On Tuesday 27 July 2010 21:53:28 Hiremath, Vaibhav wrote:
> On Wednesday 28 July 2010 00:35:00 Sin, David wrote:
> > On Tuesday 27 July 2010 01:38:00 Hiremath, Vaibhav wrote:
> > > On Saturday 24 July 2010 04:52:00 Sin, David wrote:

[snip]

> > > [Hiremath, Vaibhav] If I understand correctly, DMM stands for
> > > dynamic memory manager. Is it something which can only be
> > > used with Video devices? Any specific reason why this is part
> > > of drivers/media/video/ directory,
> >
> > [dhs] Any device can use TILER memory, but there is a big advantage,
> > performance-wise, for 2-Dimensional macro block based buffers.  This HW
> > is intended for image/video hardware accelerators (e.g. OMAP4 IVA-HD). 
> > Plus there's the added advantage of doing zero-copy flips and rotations
> > for the OMAP display and image sub-systems.
> 
> [Hiremath, Vaibhav] When you mention Tiler memory, you meant Tiler Virtual
> memory which is independent of physical memory. Driver requesting/using
> Tiler is responsible for allocating physical memory. Is that understanding
> correct?
> 
> If yes, then feature wise it is same as VRFB in OMAP3, where it provides
> virtual address space and driver requesting VRFB is responsible for
> physical memory allocation. There could be additional features,
> enhancement and stuff but zero-copy rotation for DSS, then its same as
> VRFB.
> 
> Don't you think is would be very difficult to use for drivers with such
> proposals, I can comment from DSS point of view,
> 
> In case of OMAP4 80% of code is being re-used from OMAP3 (located under
> drivers/video/omap2/), which is currently supported hardware
> rotation/mirroring and hardly tied to VRFB API's.
> 
> Now with this driver we have to do something,
> 
> cpu_is_omap34xx()
>         VRFB
> else if cpu_is_omap44xx()
>         Tiler
> 
> I am not sure about further OMAP series of devices, where we might have
> something else with DSS IP reuse (along with software). And I believe
> Tiler is not part of DSS at all. Again if some other devices are using
> Tiler API's it would become more difficult to re-use the code when same IP
> is being used in multiple SoC's.
> 
> Does it make sense to you to have registration based mechanism (function
> pointer) where you register your hardware capabilities/API's, driver don't
> have to dependent on underneath hardware block. Ofcource if driver intend
> to use some specific/custom feature supported by some hardware block then
> he has to call that API under cpu_is_xxxx

I think I agree with it. The tiler provides dynamic views on arbitrary 
physical memory. Ideally it shouldn't be tied to the media/video subsystem 
(obviously it should still provide an interface for V4L drivers).

It's getting a bit hard to comment on the proposal, as there's no public 
documentation I'm aware of beside the Documentation/arm/TILER file in the 
patch set, and that information is far too concise and vague.

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 46+ messages in thread

* RE: [RFC 1/8] TILER-DMM: DMM-PAT driver for TI TILER
  2010-07-28 10:00         ` Laurent Pinchart
@ 2010-07-28 14:39           ` Sin, David
  2010-07-28 15:46             ` Hiremath, Vaibhav
  0 siblings, 1 reply; 46+ messages in thread
From: Sin, David @ 2010-07-28 14:39 UTC (permalink / raw)
  To: Laurent Pinchart, linux-arm-kernel@lists.infradead.org
  Cc: Hiremath, Vaibhav, linux-omap@vger.kernel.org, Tony Lindgren,
	Russell King, Ohad Ben-Cohen, Kanigeri, Hari, Shilimkar, Santosh,
	Molnar, Lajos

> -----Original Message-----
> From: Laurent Pinchart [mailto:laurent.pinchart@ideasonboard.com] 
> Sent: Wednesday, July 28, 2010 5:00 AM
> To: linux-arm-kernel@lists.infradead.org
> Cc: Hiremath, Vaibhav; Sin, David; 
> linux-omap@vger.kernel.org; Tony Lindgren; Russell King; Ohad 
> Ben-Cohen; Kanigeri, Hari; Shilimkar, Santosh; Molnar, Lajos
> Subject: Re: [RFC 1/8] TILER-DMM: DMM-PAT driver for TI TILER
> 
> 
> On Tuesday 27 July 2010 21:53:28 Hiremath, Vaibhav wrote:
> > On Wednesday 28 July 2010 00:35:00 Sin, David wrote:
> > > On Tuesday 27 July 2010 01:38:00 Hiremath, Vaibhav wrote:
> > > > On Saturday 24 July 2010 04:52:00 Sin, David wrote:
> 
> [snip]
> 
> > > > [Hiremath, Vaibhav] If I understand correctly, DMM stands for
> > > > dynamic memory manager. Is it something which can only be
> > > > used with Video devices? Any specific reason why this is part
> > > > of drivers/media/video/ directory,
> > >
> > > [dhs] Any device can use TILER memory, but there is a big 
> advantage,
> > > performance-wise, for 2-Dimensional macro block based 
> buffers.  This HW
> > > is intended for image/video hardware accelerators (e.g. 
> OMAP4 IVA-HD). 
> > > Plus there's the added advantage of doing zero-copy flips 
> and rotations
> > > for the OMAP display and image sub-systems.
> > 
> > [Hiremath, Vaibhav] When you mention Tiler memory, you 
> meant Tiler Virtual
> > memory which is independent of physical memory. Driver 
> requesting/using
> > Tiler is responsible for allocating physical memory. Is 
> that understanding
> > correct?

[dhs] Yes this is correct.  I'm referring to the 33 bit 4 GB TILER virtual memory.

> > 
> > If yes, then feature wise it is same as VRFB in OMAP3, 
> where it provides
> > virtual address space and driver requesting VRFB is responsible for
> > physical memory allocation. There could be additional features,
> > enhancement and stuff but zero-copy rotation for DSS, then 
> its same as
> > VRFB.
> > 
> > Don't you think is would be very difficult to use for 
> drivers with such
> > proposals, I can comment from DSS point of view,
> > 
> > In case of OMAP4 80% of code is being re-used from OMAP3 
> (located under
> > drivers/video/omap2/), which is currently supported hardware
> > rotation/mirroring and hardly tied to VRFB API's.
> > 
> > Now with this driver we have to do something,
> > 
> > cpu_is_omap34xx()
> >         VRFB
> > else if cpu_is_omap44xx()
> >         Tiler
> > 
> > I am not sure about further OMAP series of devices, where 
> we might have
> > something else with DSS IP reuse (along with software). And 
> I believe
> > Tiler is not part of DSS at all. Again if some other 
> devices are using
> > Tiler API's it would become more difficult to re-use the 
> code when same IP
> > is being used in multiple SoC's.
> > 
> > Does it make sense to you to have registration based 
> mechanism (function
> > pointer) where you register your hardware 
> capabilities/API's, driver don't
> > have to dependent on underneath hardware block. Ofcource if 
> driver intend
> > to use some specific/custom feature supported by some 
> hardware block then
> > he has to call that API under cpu_is_xxxx
> 
> I think I agree with it. The tiler provides dynamic views on 
> arbitrary 
> physical memory. Ideally it shouldn't be tied to the 
> media/video subsystem 
> (obviously it should still provide an interface for V4L drivers).
> 
> It's getting a bit hard to comment on the proposal, as 
> there's no public 
> documentation I'm aware of beside the Documentation/arm/TILER 
> file in the 
> patch set, and that information is far too concise and vague.
> 
> -- 
> Regards,
> 
> Laurent Pinchart
> 

[dhs] I understand what you're stating here, conceptually, but I'm missing some details.  Do you mean that there needs to be a generic layer between a given video memory allocator and V4L? and that set of APIs should point to specific functions based on availability (e.g. VRFB, TILER, future TILER, other IP, etc)?

Laurent:  The TRM for DMM-TILER should be publicly available already, but for some reason, I'm not able to see the link.  I will work on this...  

^ permalink raw reply	[flat|nested] 46+ messages in thread

* RE: [RFC 0/8] TI TILER-DMM driver
  2010-07-24 11:12 ` Hans Verkuil
@ 2010-07-28 15:23   ` Sin, David
  2010-07-28 17:30     ` Hiremath, Vaibhav
  0 siblings, 1 reply; 46+ messages in thread
From: Sin, David @ 2010-07-28 15:23 UTC (permalink / raw)
  To: Hans Verkuil
  Cc: linux-omap@vger.kernel.org, Tony Lindgren, Russell King,
	Kanigeri, Hari, Ohad Ben-Cohen, Hiremath, Vaibhav,
	Shilimkar, Santosh, linux-arm-kernel@lists.infradead.org

> -----Original Message-----
> From: Hans Verkuil [mailto:hverkuil@xs4all.nl] 
> Sent: Saturday, July 24, 2010 6:13 AM
> To: Sin, David
> Cc: linux-arm-kernel@lists.arm.linux.org.uk; 
> linux-omap@vger.kernel.org; Tony Lindgren; Russell King; 
> Kanigeri, Hari; Ohad Ben-Cohen; Hiremath, Vaibhav; Shilimkar, Santosh
> Subject: Re: [RFC 0/8] TI TILER-DMM driver
> 
> Hi David,
> 
> On Saturday 24 July 2010 01:22:20 David Sin wrote:
> > TILER is a hardware block made by Texas Instruments.  Its 
> purpose is to 
> > organize video/image memory in a 2-dimensional fashion to 
> limit memory 
> > bandwidth and facilitate 0 effort rotation and mirroring.  
> The TILER 
> > driver facilitates allocating, freeing, as well as mapping 
> 2D blocks (areas) 
> > in the TILER container(s).  It also facilitates rotating 
> and mirroring 
> > the allocated blocks or its rectangular subsections.
> 
> Since this driver is part of the media/video subsystem you 
> should cross-post
> it to the linux-media mailinglist as well.
> 
> The main question that I have is how this driver is to be 
> used in practice.
> How does it fit into the bigger video4linux picture? Is this 
> something that
> is mainly used from other v4l or fb drivers? Or is it 
> controlled by userspace?

[dhs] I missed this one -- my apologies.  As I stated to Vaibhav, any device can use TILER memory, but there is a big advantage, performance-wise, for 2-Dimensional macro block based buffers.  This HW is intended for image/video hardware accelerators (e.g. OMAP4 IVA-HD).  Plus there's the added advantage of doing zero-copy flips and rotations for the OMAP display and image sub-systems.

In this RFC, there are only kernel APIs to allocate TILER memory.  Eventually, we would like to provide a way to obtain TILER memory to the user space.

> 
> Regards,
> 
> 	Hans
> 
> > 
> > List of pending items in proposed order:
> > 
> > * Add area packing support (multiple blocks can reside in 
> the same band/area)
> >   to optimize area use
> > * Add group-ID support (to specify which blocks can reside 
> together in the
> >   same area)
> > * Add multiple search directions to TCM-SiTA
> > * Add 1D block support (including adding 1D search algo to TCM-SiTA)
> > * Optimize mutex handling (don.t hold mutex during memory
> >   allocation/mapping/cache flushing)
> > * Add block reference counting, support for sharing blocks
> > * Move all kernel-API-s to tiler-iface.c
> > * Support orphaned block support (in preparation for 
> process cleanup support)
> > * Change block identification from physical address to key-ID pair
> >   (in preparation for user space support, and process security)
> > * Add support for process security (blocks from separate 
> processes never
> >   reside in the same band)
> > * Support file interface (ioctl and mmap)
> > * Support for buffers (ordered list of blocks that are 
> mapped to userspace
> >   together, such as YUV420sp)
> > * Support 1D user buffer mapping into TILER container
> > * Support for block pre-reservation (to further optimize area use)
> > 
> > David Sin (1):
> >   TILER-DMM: DMM-PAT driver for TI TILER
> > 
> > Lajos Molnar (6):
> >   TILER-DMM: Container manager interface and utility definitons
> >   TILER-DMM: TILER Memory Manager interface and implementation
> >   TILER-DMM: TILER interface file and documentation
> >   TILER-DMM: Geometry and view manipulation functions.
> >   TILER-DMM: Main TILER driver implementation.
> >   TILER-DMM: Linking TILER driver into the Linux kernel build
> > 
> > Ravi Ramachandra (1):
> >   TILER-DMM: Sample TCM implementation: Simple TILER Allocator
> > 
> >  Documentation/arm/TILER                   |  144 +++++++++
> >  arch/arm/mach-omap2/include/mach/dmm.h    |  128 ++++++++
> >  arch/arm/mach-omap2/include/mach/tiler.h  |  201 +++++++++++++
> >  drivers/media/Kconfig                     |    6 +
> >  drivers/media/Makefile                    |    2 +
> >  drivers/media/video/tiler/Kconfig         |   65 ++++
> >  drivers/media/video/tiler/Makefile        |    7 +
> >  drivers/media/video/tiler/_tiler.h        |   51 ++++
> >  drivers/media/video/tiler/dmm.c           |  200 +++++++++++++
> >  drivers/media/video/tiler/tcm.h           |  209 +++++++++++++
> >  drivers/media/video/tiler/tcm/Makefile    |    1 +
> >  drivers/media/video/tiler/tcm/_tcm-sita.h |   64 ++++
> >  drivers/media/video/tiler/tcm/tcm-sita.c  |  459 
> +++++++++++++++++++++++++++++
> >  drivers/media/video/tiler/tcm/tcm-sita.h  |   37 +++
> >  drivers/media/video/tiler/tcm/tcm-utils.h |   54 ++++
> >  drivers/media/video/tiler/tiler-geom.c    |  360 
> ++++++++++++++++++++++
> >  drivers/media/video/tiler/tiler-iface.c   |  106 +++++++
> >  drivers/media/video/tiler/tiler-main.c    |  426 
> ++++++++++++++++++++++++++
> >  drivers/media/video/tiler/tmm-pat.c       |  274 +++++++++++++++++
> >  drivers/media/video/tiler/tmm.h           |  109 +++++++
> >  20 files changed, 2903 insertions(+), 0 deletions(-)
> >  create mode 100644 Documentation/arm/TILER
> >  create mode 100644 arch/arm/mach-omap2/include/mach/dmm.h
> >  create mode 100644 arch/arm/mach-omap2/include/mach/tiler.h
> >  create mode 100644 drivers/media/video/tiler/Kconfig
> >  create mode 100644 drivers/media/video/tiler/Makefile
> >  create mode 100644 drivers/media/video/tiler/_tiler.h
> >  create mode 100644 drivers/media/video/tiler/dmm.c
> >  create mode 100644 drivers/media/video/tiler/tcm.h
> >  create mode 100644 drivers/media/video/tiler/tcm/Makefile
> >  create mode 100644 drivers/media/video/tiler/tcm/_tcm-sita.h
> >  create mode 100644 drivers/media/video/tiler/tcm/tcm-sita.c
> >  create mode 100644 drivers/media/video/tiler/tcm/tcm-sita.h
> >  create mode 100644 drivers/media/video/tiler/tcm/tcm-utils.h
> >  create mode 100644 drivers/media/video/tiler/tiler-geom.c
> >  create mode 100644 drivers/media/video/tiler/tiler-iface.c
> >  create mode 100644 drivers/media/video/tiler/tiler-main.c
> >  create mode 100644 drivers/media/video/tiler/tmm-pat.c
> >  create mode 100644 drivers/media/video/tiler/tmm.h
> > 
> > --
> > To unsubscribe from this list: send the line "unsubscribe 
> linux-omap" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > 
> > 
> 
> -- 
> Hans Verkuil - video4linux developer - sponsored by TANDBERG, 
> part of Cisco
> 

^ permalink raw reply	[flat|nested] 46+ messages in thread

* RE: [RFC 1/8] TILER-DMM: DMM-PAT driver for TI TILER
  2010-07-28 14:39           ` Sin, David
@ 2010-07-28 15:46             ` Hiremath, Vaibhav
  0 siblings, 0 replies; 46+ messages in thread
From: Hiremath, Vaibhav @ 2010-07-28 15:46 UTC (permalink / raw)
  To: Sin, David, Laurent Pinchart,
	linux-arm-kernel@lists.infradead.org
  Cc: linux-omap@vger.kernel.org, Tony Lindgren, Russell King,
	Ohad Ben-Cohen, Kanigeri, Hari, Shilimkar, Santosh, Molnar, Lajos

> -----Original Message-----
> From: Sin, David
> Sent: Wednesday, July 28, 2010 8:09 PM
> To: Laurent Pinchart; linux-arm-kernel@lists.infradead.org
> Cc: Hiremath, Vaibhav; linux-omap@vger.kernel.org; Tony Lindgren; Russell
> King; Ohad Ben-Cohen; Kanigeri, Hari; Shilimkar, Santosh; Molnar, Lajos
> Subject: RE: [RFC 1/8] TILER-DMM: DMM-PAT driver for TI TILER
> 
> > -----Original Message-----
> > From: Laurent Pinchart [mailto:laurent.pinchart@ideasonboard.com]
> > Sent: Wednesday, July 28, 2010 5:00 AM
> > To: linux-arm-kernel@lists.infradead.org
> > Cc: Hiremath, Vaibhav; Sin, David;
> > linux-omap@vger.kernel.org; Tony Lindgren; Russell King; Ohad
> > Ben-Cohen; Kanigeri, Hari; Shilimkar, Santosh; Molnar, Lajos
> > Subject: Re: [RFC 1/8] TILER-DMM: DMM-PAT driver for TI TILER
<snip>

> > I think I agree with it. The tiler provides dynamic views on
> > arbitrary
> > physical memory. Ideally it shouldn't be tied to the
> > media/video subsystem
> > (obviously it should still provide an interface for V4L drivers).
> >
> > It's getting a bit hard to comment on the proposal, as
> > there's no public
> > documentation I'm aware of beside the Documentation/arm/TILER
> > file in the
> > patch set, and that information is far too concise and vague.
> >
> > --
> > Regards,
> >
> > Laurent Pinchart
> >
> 
> [dhs] I understand what you're stating here, conceptually, but I'm missing
> some details.  Do you mean that there needs to be a generic layer between a
> given video memory allocator and V4L? 
> and that set of APIs should point to
> specific functions based on availability (e.g. VRFB, TILER, future TILER,
> other IP, etc)?
> 
[Hiremath, Vaibhav] David,
As far as Memory allocator is concerned I think it is more generic term and should not really tie to underneath hardware/feature (Tiler, VRFB or could be anything). This is long time issue with every Embedded devices dealing with Video, due to their dynamic requirement of memory/buffers.

Have you looked at Samsung (CMA) and Qualcomm (IOMMU) patches for memory allocation/management? I think it is worth to look at their approach. 

Thanks,
Vaibhav

> Laurent:  The TRM for DMM-TILER should be publicly available already, but
> for some reason, I'm not able to see the link.  I will work on this...

^ permalink raw reply	[flat|nested] 46+ messages in thread

* RE: [RFC 0/8] TI TILER-DMM driver
  2010-07-28 15:23   ` Sin, David
@ 2010-07-28 17:30     ` Hiremath, Vaibhav
  2010-07-28 19:15       ` Sin, David
  0 siblings, 1 reply; 46+ messages in thread
From: Hiremath, Vaibhav @ 2010-07-28 17:30 UTC (permalink / raw)
  To: Sin, David, Hans Verkuil
  Cc: linux-omap@vger.kernel.org, Tony Lindgren, Russell King,
	Kanigeri, Hari, Ohad Ben-Cohen, Shilimkar, Santosh,
	linux-arm-kernel@lists.infradead.org

> -----Original Message-----
> From: Sin, David
> Sent: Wednesday, July 28, 2010 8:53 PM
> To: Hans Verkuil
> Cc: linux-omap@vger.kernel.org; Tony Lindgren; Russell King; Kanigeri, Hari;
> Ohad Ben-Cohen; Hiremath, Vaibhav; Shilimkar, Santosh; linux-arm-
> kernel@lists.infradead.org
> Subject: RE: [RFC 0/8] TI TILER-DMM driver
> 
> > -----Original Message-----
> > From: Hans Verkuil [mailto:hverkuil@xs4all.nl]
> > Sent: Saturday, July 24, 2010 6:13 AM
> > To: Sin, David
> > Cc: linux-arm-kernel@lists.arm.linux.org.uk;
> > linux-omap@vger.kernel.org; Tony Lindgren; Russell King;
> > Kanigeri, Hari; Ohad Ben-Cohen; Hiremath, Vaibhav; Shilimkar, Santosh
> > Subject: Re: [RFC 0/8] TI TILER-DMM driver
> >
> > Hi David,
> >
<snip>

> > The main question that I have is how this driver is to be
> > used in practice.
> > How does it fit into the bigger video4linux picture? Is this
> > something that
> > is mainly used from other v4l or fb drivers? Or is it
> > controlled by userspace?
> 
> [dhs] I missed this one -- my apologies.  As I stated to Vaibhav, any device
> can use TILER memory, but there is a big advantage, performance-wise, for 2-
> Dimensional macro block based buffers.  This HW is intended for image/video
> hardware accelerators (e.g. OMAP4 IVA-HD).  Plus there's the added advantage
> of doing zero-copy flips and rotations for the OMAP display and image sub-
> systems.
> 
> In this RFC, there are only kernel APIs to allocate TILER memory.
> Eventually, we would like to provide a way to obtain TILER memory to the
> user space.
> 
[Hiremath, Vaibhav] Don't you think, user has to mmap memory (irrespective of whether it is tiles view or not) to userland in both the cases, Fbdev and V4L2 (MMAP mode)?

Am I missing something here?

Thanks,
Vaibhav

> >
> > Regards,
> >
> > 	Hans
> >
> > >
> > > List of pending items in proposed order:
> > >
> > > * Add area packing support (multiple blocks can reside in
> > the same band/area)
> > >   to optimize area use
> > > * Add group-ID support (to specify which blocks can reside
> > together in the
> > >   same area)
> > > * Add multiple search directions to TCM-SiTA
> > > * Add 1D block support (including adding 1D search algo to TCM-SiTA)
> > > * Optimize mutex handling (don.t hold mutex during memory
> > >   allocation/mapping/cache flushing)
> > > * Add block reference counting, support for sharing blocks
> > > * Move all kernel-API-s to tiler-iface.c
> > > * Support orphaned block support (in preparation for
> > process cleanup support)
> > > * Change block identification from physical address to key-ID pair
> > >   (in preparation for user space support, and process security)
> > > * Add support for process security (blocks from separate
> > processes never
> > >   reside in the same band)
> > > * Support file interface (ioctl and mmap)
> > > * Support for buffers (ordered list of blocks that are
> > mapped to userspace
> > >   together, such as YUV420sp)
> > > * Support 1D user buffer mapping into TILER container
> > > * Support for block pre-reservation (to further optimize area use)
> > >
> > > David Sin (1):
> > >   TILER-DMM: DMM-PAT driver for TI TILER
> > >
> > > Lajos Molnar (6):
> > >   TILER-DMM: Container manager interface and utility definitons
> > >   TILER-DMM: TILER Memory Manager interface and implementation
> > >   TILER-DMM: TILER interface file and documentation
> > >   TILER-DMM: Geometry and view manipulation functions.
> > >   TILER-DMM: Main TILER driver implementation.
> > >   TILER-DMM: Linking TILER driver into the Linux kernel build
> > >
> > > Ravi Ramachandra (1):
> > >   TILER-DMM: Sample TCM implementation: Simple TILER Allocator
> > >
> > >  Documentation/arm/TILER                   |  144 +++++++++
> > >  arch/arm/mach-omap2/include/mach/dmm.h    |  128 ++++++++
> > >  arch/arm/mach-omap2/include/mach/tiler.h  |  201 +++++++++++++
> > >  drivers/media/Kconfig                     |    6 +
> > >  drivers/media/Makefile                    |    2 +
> > >  drivers/media/video/tiler/Kconfig         |   65 ++++
> > >  drivers/media/video/tiler/Makefile        |    7 +
> > >  drivers/media/video/tiler/_tiler.h        |   51 ++++
> > >  drivers/media/video/tiler/dmm.c           |  200 +++++++++++++
> > >  drivers/media/video/tiler/tcm.h           |  209 +++++++++++++
> > >  drivers/media/video/tiler/tcm/Makefile    |    1 +
> > >  drivers/media/video/tiler/tcm/_tcm-sita.h |   64 ++++
> > >  drivers/media/video/tiler/tcm/tcm-sita.c  |  459
> > +++++++++++++++++++++++++++++
> > >  drivers/media/video/tiler/tcm/tcm-sita.h  |   37 +++
> > >  drivers/media/video/tiler/tcm/tcm-utils.h |   54 ++++
> > >  drivers/media/video/tiler/tiler-geom.c    |  360
> > ++++++++++++++++++++++
> > >  drivers/media/video/tiler/tiler-iface.c   |  106 +++++++
> > >  drivers/media/video/tiler/tiler-main.c    |  426
> > ++++++++++++++++++++++++++
> > >  drivers/media/video/tiler/tmm-pat.c       |  274 +++++++++++++++++
> > >  drivers/media/video/tiler/tmm.h           |  109 +++++++
> > >  20 files changed, 2903 insertions(+), 0 deletions(-)
> > >  create mode 100644 Documentation/arm/TILER
> > >  create mode 100644 arch/arm/mach-omap2/include/mach/dmm.h
> > >  create mode 100644 arch/arm/mach-omap2/include/mach/tiler.h
> > >  create mode 100644 drivers/media/video/tiler/Kconfig
> > >  create mode 100644 drivers/media/video/tiler/Makefile
> > >  create mode 100644 drivers/media/video/tiler/_tiler.h
> > >  create mode 100644 drivers/media/video/tiler/dmm.c
> > >  create mode 100644 drivers/media/video/tiler/tcm.h
> > >  create mode 100644 drivers/media/video/tiler/tcm/Makefile
> > >  create mode 100644 drivers/media/video/tiler/tcm/_tcm-sita.h
> > >  create mode 100644 drivers/media/video/tiler/tcm/tcm-sita.c
> > >  create mode 100644 drivers/media/video/tiler/tcm/tcm-sita.h
> > >  create mode 100644 drivers/media/video/tiler/tcm/tcm-utils.h
> > >  create mode 100644 drivers/media/video/tiler/tiler-geom.c
> > >  create mode 100644 drivers/media/video/tiler/tiler-iface.c
> > >  create mode 100644 drivers/media/video/tiler/tiler-main.c
> > >  create mode 100644 drivers/media/video/tiler/tmm-pat.c
> > >  create mode 100644 drivers/media/video/tiler/tmm.h
> > >
> > > --
> > > To unsubscribe from this list: send the line "unsubscribe
> > linux-omap" in
> > > the body of a message to majordomo@vger.kernel.org
> > > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > >
> > >
> >
> > --
> > Hans Verkuil - video4linux developer - sponsored by TANDBERG,
> > part of Cisco
> >

^ permalink raw reply	[flat|nested] 46+ messages in thread

* RE: [RFC 0/8] TI TILER-DMM driver
  2010-07-28 17:30     ` Hiremath, Vaibhav
@ 2010-07-28 19:15       ` Sin, David
  0 siblings, 0 replies; 46+ messages in thread
From: Sin, David @ 2010-07-28 19:15 UTC (permalink / raw)
  To: Hiremath, Vaibhav, Hans Verkuil
  Cc: linux-omap@vger.kernel.org, Tony Lindgren, Russell King,
	Kanigeri, Hari, Ohad Ben-Cohen, Shilimkar, Santosh,
	linux-arm-kernel@lists.infradead.org

> -----Original Message-----
> From: Hiremath, Vaibhav 
> Sent: Wednesday, July 28, 2010 12:31 PM
> To: Sin, David; Hans Verkuil
> Cc: linux-omap@vger.kernel.org; Tony Lindgren; Russell King; 
> Kanigeri, Hari; Ohad Ben-Cohen; Shilimkar, Santosh; 
> linux-arm-kernel@lists.infradead.org
> Subject: RE: [RFC 0/8] TI TILER-DMM driver
> 
> > -----Original Message-----
> > From: Sin, David
> > Sent: Wednesday, July 28, 2010 8:53 PM
> > To: Hans Verkuil
> > Cc: linux-omap@vger.kernel.org; Tony Lindgren; Russell 
> King; Kanigeri, Hari;
> > Ohad Ben-Cohen; Hiremath, Vaibhav; Shilimkar, Santosh; linux-arm-
> > kernel@lists.infradead.org
> > Subject: RE: [RFC 0/8] TI TILER-DMM driver
> > 
> > > -----Original Message-----
> > > From: Hans Verkuil [mailto:hverkuil@xs4all.nl]
> > > Sent: Saturday, July 24, 2010 6:13 AM
> > > To: Sin, David
> > > Cc: linux-arm-kernel@lists.arm.linux.org.uk;
> > > linux-omap@vger.kernel.org; Tony Lindgren; Russell King;
> > > Kanigeri, Hari; Ohad Ben-Cohen; Hiremath, Vaibhav; 
> Shilimkar, Santosh
> > > Subject: Re: [RFC 0/8] TI TILER-DMM driver
> > >
> > > Hi David,
> > >
> <snip>
> 
> > > The main question that I have is how this driver is to be
> > > used in practice.
> > > How does it fit into the bigger video4linux picture? Is this
> > > something that
> > > is mainly used from other v4l or fb drivers? Or is it
> > > controlled by userspace?
> > 
> > [dhs] I missed this one -- my apologies.  As I stated to 
> Vaibhav, any device
> > can use TILER memory, but there is a big advantage, 
> performance-wise, for 2-
> > Dimensional macro block based buffers.  This HW is intended 
> for image/video
> > hardware accelerators (e.g. OMAP4 IVA-HD).  Plus there's 
> the added advantage
> > of doing zero-copy flips and rotations for the OMAP display 
> and image sub-
> > systems.
> > 
> > In this RFC, there are only kernel APIs to allocate TILER memory.
> > Eventually, we would like to provide a way to obtain TILER 
> memory to the
> > user space.
> > 
> [Hiremath, Vaibhav] Don't you think, user has to mmap memory 
> (irrespective of whether it is tiles view or not) to userland 
> in both the cases, Fbdev and V4L2 (MMAP mode)?
> 
> Am I missing something here?
> 
> Thanks,
> Vaibhav
> 

[dhs] You're right; this is needed.  However, I first wanted to get some feedback for allocating 2-D memory just from kernel space.  

> > >
> > > Regards,
> > >
> > > 	Hans
> > >
> > > >
> > > > List of pending items in proposed order:
> > > >
> > > > * Add area packing support (multiple blocks can reside in
> > > the same band/area)
> > > >   to optimize area use
> > > > * Add group-ID support (to specify which blocks can reside
> > > together in the
> > > >   same area)
> > > > * Add multiple search directions to TCM-SiTA
> > > > * Add 1D block support (including adding 1D search algo 
> to TCM-SiTA)
> > > > * Optimize mutex handling (don.t hold mutex during memory
> > > >   allocation/mapping/cache flushing)
> > > > * Add block reference counting, support for sharing blocks
> > > > * Move all kernel-API-s to tiler-iface.c
> > > > * Support orphaned block support (in preparation for
> > > process cleanup support)
> > > > * Change block identification from physical address to 
> key-ID pair
> > > >   (in preparation for user space support, and process security)
> > > > * Add support for process security (blocks from separate
> > > processes never
> > > >   reside in the same band)
> > > > * Support file interface (ioctl and mmap)
> > > > * Support for buffers (ordered list of blocks that are
> > > mapped to userspace
> > > >   together, such as YUV420sp)
> > > > * Support 1D user buffer mapping into TILER container
> > > > * Support for block pre-reservation (to further 
> optimize area use)
> > > >
> > > > David Sin (1):
> > > >   TILER-DMM: DMM-PAT driver for TI TILER
> > > >
> > > > Lajos Molnar (6):
> > > >   TILER-DMM: Container manager interface and utility definitons
> > > >   TILER-DMM: TILER Memory Manager interface and implementation
> > > >   TILER-DMM: TILER interface file and documentation
> > > >   TILER-DMM: Geometry and view manipulation functions.
> > > >   TILER-DMM: Main TILER driver implementation.
> > > >   TILER-DMM: Linking TILER driver into the Linux kernel build
> > > >
> > > > Ravi Ramachandra (1):
> > > >   TILER-DMM: Sample TCM implementation: Simple TILER Allocator
> > > >
> > > >  Documentation/arm/TILER                   |  144 +++++++++
> > > >  arch/arm/mach-omap2/include/mach/dmm.h    |  128 ++++++++
> > > >  arch/arm/mach-omap2/include/mach/tiler.h  |  201 +++++++++++++
> > > >  drivers/media/Kconfig                     |    6 +
> > > >  drivers/media/Makefile                    |    2 +
> > > >  drivers/media/video/tiler/Kconfig         |   65 ++++
> > > >  drivers/media/video/tiler/Makefile        |    7 +
> > > >  drivers/media/video/tiler/_tiler.h        |   51 ++++
> > > >  drivers/media/video/tiler/dmm.c           |  200 +++++++++++++
> > > >  drivers/media/video/tiler/tcm.h           |  209 +++++++++++++
> > > >  drivers/media/video/tiler/tcm/Makefile    |    1 +
> > > >  drivers/media/video/tiler/tcm/_tcm-sita.h |   64 ++++
> > > >  drivers/media/video/tiler/tcm/tcm-sita.c  |  459
> > > +++++++++++++++++++++++++++++
> > > >  drivers/media/video/tiler/tcm/tcm-sita.h  |   37 +++
> > > >  drivers/media/video/tiler/tcm/tcm-utils.h |   54 ++++
> > > >  drivers/media/video/tiler/tiler-geom.c    |  360
> > > ++++++++++++++++++++++
> > > >  drivers/media/video/tiler/tiler-iface.c   |  106 +++++++
> > > >  drivers/media/video/tiler/tiler-main.c    |  426
> > > ++++++++++++++++++++++++++
> > > >  drivers/media/video/tiler/tmm-pat.c       |  274 
> +++++++++++++++++
> > > >  drivers/media/video/tiler/tmm.h           |  109 +++++++
> > > >  20 files changed, 2903 insertions(+), 0 deletions(-)
> > > >  create mode 100644 Documentation/arm/TILER
> > > >  create mode 100644 arch/arm/mach-omap2/include/mach/dmm.h
> > > >  create mode 100644 arch/arm/mach-omap2/include/mach/tiler.h
> > > >  create mode 100644 drivers/media/video/tiler/Kconfig
> > > >  create mode 100644 drivers/media/video/tiler/Makefile
> > > >  create mode 100644 drivers/media/video/tiler/_tiler.h
> > > >  create mode 100644 drivers/media/video/tiler/dmm.c
> > > >  create mode 100644 drivers/media/video/tiler/tcm.h
> > > >  create mode 100644 drivers/media/video/tiler/tcm/Makefile
> > > >  create mode 100644 drivers/media/video/tiler/tcm/_tcm-sita.h
> > > >  create mode 100644 drivers/media/video/tiler/tcm/tcm-sita.c
> > > >  create mode 100644 drivers/media/video/tiler/tcm/tcm-sita.h
> > > >  create mode 100644 drivers/media/video/tiler/tcm/tcm-utils.h
> > > >  create mode 100644 drivers/media/video/tiler/tiler-geom.c
> > > >  create mode 100644 drivers/media/video/tiler/tiler-iface.c
> > > >  create mode 100644 drivers/media/video/tiler/tiler-main.c
> > > >  create mode 100644 drivers/media/video/tiler/tmm-pat.c
> > > >  create mode 100644 drivers/media/video/tiler/tmm.h
> > > >
> > > > --
> > > > To unsubscribe from this list: send the line "unsubscribe
> > > linux-omap" in
> > > > the body of a message to majordomo@vger.kernel.org
> > > > More majordomo info at  
> http://vger.kernel.org/majordomo-info.html
> > > >
> > > >
> > >
> > > --
> > > Hans Verkuil - video4linux developer - sponsored by TANDBERG,
> > > part of Cisco
> > >
> 

^ permalink raw reply	[flat|nested] 46+ messages in thread

* RE: [RFC 4/8] TILER-DMM: TILER Memory Manager interface and implementation
  2010-07-24  8:01         ` [RFC 4/8] TILER-DMM: TILER Memory Manager interface and implementation Russell King - ARM Linux
  2010-07-26 19:34           ` Sin, David
@ 2010-08-02 14:40           ` Sin, David
  2010-08-02 14:44             ` Shilimkar, Santosh
  1 sibling, 1 reply; 46+ messages in thread
From: Sin, David @ 2010-08-02 14:40 UTC (permalink / raw)
  To: Russell King - ARM Linux, Woodruff, Richard
  Cc: linux-omap@vger.kernel.org, Tony Lindgren, Kanigeri, Hari,
	Ohad Ben-Cohen, Hiremath, Vaibhav, Shilimkar, Santosh,
	Molnar, Lajos, Voultoury, Pierre,
	linux-arm-kernel@lists.infradead.org

-----Original Message-----
From: Russell King - ARM Linux [mailto:linux@arm.linux.org.uk] 
Sent: Saturday, July 24, 2010 3:01 AM
To: Sin, David
Cc: linux-arm-kernel@lists.arm.linux.org.uk; linux-omap@vger.kernel.org; Tony Lindgren; Kanigeri, Hari; Ohad Ben-Cohen; Hiremath, Vaibhav; Shilimkar, Santosh; Molnar, Lajos
Subject: Re: [RFC 4/8] TILER-DMM: TILER Memory Manager interface and implementation

On Fri, Jul 23, 2010 at 06:22:24PM -0500, David Sin wrote:
> +/* allocate and flush a page */
> +static struct mem *alloc_mem(void)
> +{
> +	struct mem *m = kzalloc(sizeof(*m), GFP_KERNEL);
> +	if (!m)
> +		return NULL;
> +
> +	m->pg = alloc_page(GFP_KERNEL | GFP_DMA);
> +	if (!m->pg) {
> +		kfree(m);
> +		return NULL;
> +	}
> +
> +	m->pa = page_to_phys(m->pg);
> +
> +	/* flush the cache entry for each page we allocate. */
> +	dmac_flush_range(page_address(m->pg),
> +				page_address(m->pg) + PAGE_SIZE);
> +	outer_flush_range(m->pa, m->pa + PAGE_SIZE);

NAK.  This is an abuse of these interfaces, and is buggy in any case.

ARMv6 and ARMv7 CPUs speculatively prefetch memory, which means that
there's no guarantee that if you flush the caches for a particular
range of virtual space, that it will stay flushed until you decide
to read it.  So flushing the caches in some memory allocator can't
guarantee that when you eventually get around to using the page that
there won't be cache lines associated with it.

[dhs] Russell, thanks for reviewing this code.  Do you have any interface suggestions that you can share that would make this proper?  Ideally, I would like to get physical pages without associated virtual address, or ones that are non-cached/non-bufferable.    

^ permalink raw reply	[flat|nested] 46+ messages in thread

* RE: [RFC 4/8] TILER-DMM: TILER Memory Manager interface and implementation
  2010-08-02 14:40           ` Sin, David
@ 2010-08-02 14:44             ` Shilimkar, Santosh
  2010-08-02 14:49               ` Sin, David
  0 siblings, 1 reply; 46+ messages in thread
From: Shilimkar, Santosh @ 2010-08-02 14:44 UTC (permalink / raw)
  To: Sin, David, Russell King - ARM Linux, Woodruff, Richard
  Cc: linux-omap@vger.kernel.org, Tony Lindgren, Kanigeri, Hari,
	Ohad Ben-Cohen, Hiremath, Vaibhav, Molnar, Lajos,
	Voultoury, Pierre, linux-arm-kernel@lists.infradead.org

> -----Original Message-----
> From: Sin, David
> Sent: Monday, August 02, 2010 8:11 PM
> To: Russell King - ARM Linux; Woodruff, Richard
> Cc: linux-omap@vger.kernel.org; Tony Lindgren; Kanigeri, Hari; Ohad Ben-
> Cohen; Hiremath, Vaibhav; Shilimkar, Santosh; Molnar, Lajos; Voultoury,
> Pierre; linux-arm-kernel@lists.infradead.org
> Subject: RE: [RFC 4/8] TILER-DMM: TILER Memory Manager interface and
> implementation
> 
> -----Original Message-----
> From: Russell King - ARM Linux [mailto:linux@arm.linux.org.uk]
> Sent: Saturday, July 24, 2010 3:01 AM
> To: Sin, David
> Cc: linux-arm-kernel@lists.arm.linux.org.uk; linux-omap@vger.kernel.org;
> Tony Lindgren; Kanigeri, Hari; Ohad Ben-Cohen; Hiremath, Vaibhav;
> Shilimkar, Santosh; Molnar, Lajos
> Subject: Re: [RFC 4/8] TILER-DMM: TILER Memory Manager interface and
> implementation
> 
> On Fri, Jul 23, 2010 at 06:22:24PM -0500, David Sin wrote:
> > +/* allocate and flush a page */
> > +static struct mem *alloc_mem(void)
> > +{
> > +	struct mem *m = kzalloc(sizeof(*m), GFP_KERNEL);
> > +	if (!m)
> > +		return NULL;
> > +
> > +	m->pg = alloc_page(GFP_KERNEL | GFP_DMA);
> > +	if (!m->pg) {
> > +		kfree(m);
> > +		return NULL;
> > +	}
> > +
> > +	m->pa = page_to_phys(m->pg);
> > +
> > +	/* flush the cache entry for each page we allocate. */
> > +	dmac_flush_range(page_address(m->pg),
> > +				page_address(m->pg) + PAGE_SIZE);
> > +	outer_flush_range(m->pa, m->pa + PAGE_SIZE);
> 
> NAK.  This is an abuse of these interfaces, and is buggy in any case.
> 
> ARMv6 and ARMv7 CPUs speculatively prefetch memory, which means that
> there's no guarantee that if you flush the caches for a particular
> range of virtual space, that it will stay flushed until you decide
> to read it.  So flushing the caches in some memory allocator can't
> guarantee that when you eventually get around to using the page that
> there won't be cache lines associated with it.
> 
> [dhs] Russell, thanks for reviewing this code.  Do you have any interface
> suggestions that you can share that would make this proper?  Ideally, I
> would like to get physical pages without associated virtual address, or
> ones that are non-cached/non-bufferable.

There is nothing called 'non-bufferable' any more David on ARMv6 and ARMv7. 
You can get non-cached memory using "dma_alloc_coherent"

Regards,
Santosh

^ permalink raw reply	[flat|nested] 46+ messages in thread

* RE: [RFC 4/8] TILER-DMM: TILER Memory Manager interface and implementation
  2010-08-02 14:44             ` Shilimkar, Santosh
@ 2010-08-02 14:49               ` Sin, David
  2010-08-02 14:52                 ` Shilimkar, Santosh
  0 siblings, 1 reply; 46+ messages in thread
From: Sin, David @ 2010-08-02 14:49 UTC (permalink / raw)
  To: Shilimkar, Santosh, Russell King - ARM Linux, Woodruff, Richard
  Cc: linux-omap@vger.kernel.org, Tony Lindgren, Kanigeri, Hari,
	Ohad Ben-Cohen, Hiremath, Vaibhav, Molnar, Lajos,
	Voultoury, Pierre, linux-arm-kernel@lists.infradead.org

-----Original Message-----
From: Shilimkar, Santosh 
Sent: Monday, August 02, 2010 9:45 AM
To: Sin, David; Russell King - ARM Linux; Woodruff, Richard
Cc: linux-omap@vger.kernel.org; Tony Lindgren; Kanigeri, Hari; Ohad Ben-Cohen; Hiremath, Vaibhav; Molnar, Lajos; Voultoury, Pierre; linux-arm-kernel@lists.infradead.org
Subject: RE: [RFC 4/8] TILER-DMM: TILER Memory Manager interface and implementation

> -----Original Message-----
> From: Sin, David
> Sent: Monday, August 02, 2010 8:11 PM
> To: Russell King - ARM Linux; Woodruff, Richard
> Cc: linux-omap@vger.kernel.org; Tony Lindgren; Kanigeri, Hari; Ohad Ben-
> Cohen; Hiremath, Vaibhav; Shilimkar, Santosh; Molnar, Lajos; Voultoury,
> Pierre; linux-arm-kernel@lists.infradead.org
> Subject: RE: [RFC 4/8] TILER-DMM: TILER Memory Manager interface and
> implementation
> 
> -----Original Message-----
> From: Russell King - ARM Linux [mailto:linux@arm.linux.org.uk]
> Sent: Saturday, July 24, 2010 3:01 AM
> To: Sin, David
> Cc: linux-arm-kernel@lists.arm.linux.org.uk; linux-omap@vger.kernel.org;
> Tony Lindgren; Kanigeri, Hari; Ohad Ben-Cohen; Hiremath, Vaibhav;
> Shilimkar, Santosh; Molnar, Lajos
> Subject: Re: [RFC 4/8] TILER-DMM: TILER Memory Manager interface and
> implementation
> 
> On Fri, Jul 23, 2010 at 06:22:24PM -0500, David Sin wrote:
> > +/* allocate and flush a page */
> > +static struct mem *alloc_mem(void)
> > +{
> > +	struct mem *m = kzalloc(sizeof(*m), GFP_KERNEL);
> > +	if (!m)
> > +		return NULL;
> > +
> > +	m->pg = alloc_page(GFP_KERNEL | GFP_DMA);
> > +	if (!m->pg) {
> > +		kfree(m);
> > +		return NULL;
> > +	}
> > +
> > +	m->pa = page_to_phys(m->pg);
> > +
> > +	/* flush the cache entry for each page we allocate. */
> > +	dmac_flush_range(page_address(m->pg),
> > +				page_address(m->pg) + PAGE_SIZE);
> > +	outer_flush_range(m->pa, m->pa + PAGE_SIZE);
> 
> NAK.  This is an abuse of these interfaces, and is buggy in any case.
> 
> ARMv6 and ARMv7 CPUs speculatively prefetch memory, which means that
> there's no guarantee that if you flush the caches for a particular
> range of virtual space, that it will stay flushed until you decide
> to read it.  So flushing the caches in some memory allocator can't
> guarantee that when you eventually get around to using the page that
> there won't be cache lines associated with it.
> 
> [dhs] Russell, thanks for reviewing this code.  Do you have any interface
> suggestions that you can share that would make this proper?  Ideally, I
> would like to get physical pages without associated virtual address, or
> ones that are non-cached/non-bufferable.

There is nothing called 'non-bufferable' any more David on ARMv6 and ARMv7. 
You can get non-cached memory using "dma_alloc_coherent"

[dhs] Thanks, Santosh, for the clarification.  I believe dma_alloc_coherent is quite limited, right?  We need to be able to cover potentially 128MB of physical memory for the TILER.  BTW, does GFP_DMA indicate that I don't want cached memory?

Regards,
Santosh

^ permalink raw reply	[flat|nested] 46+ messages in thread

* RE: [RFC 4/8] TILER-DMM: TILER Memory Manager interface and implementation
  2010-08-02 14:49               ` Sin, David
@ 2010-08-02 14:52                 ` Shilimkar, Santosh
  2010-08-02 14:55                   ` Sin, David
       [not found]                   ` <9DCA1E44C5805D4EB7C1626D5FD1739E048EDA223B@dlee02.ent.ti.com>
  0 siblings, 2 replies; 46+ messages in thread
From: Shilimkar, Santosh @ 2010-08-02 14:52 UTC (permalink / raw)
  To: Sin, David, Russell King - ARM Linux, Woodruff, Richard
  Cc: linux-omap@vger.kernel.org, Tony Lindgren, Kanigeri, Hari,
	Ohad Ben-Cohen, Hiremath, Vaibhav, Molnar, Lajos,
	Voultoury, Pierre, linux-arm-kernel@lists.infradead.org



> -----Original Message-----
> From: Sin, David
> Sent: Monday, August 02, 2010 8:20 PM
> To: Shilimkar, Santosh; Russell King - ARM Linux; Woodruff, Richard
> Cc: linux-omap@vger.kernel.org; Tony Lindgren; Kanigeri, Hari; Ohad Ben-
> Cohen; Hiremath, Vaibhav; Molnar, Lajos; Voultoury, Pierre; linux-arm-
> kernel@lists.infradead.org
> Subject: RE: [RFC 4/8] TILER-DMM: TILER Memory Manager interface and
> implementation
> 
> -----Original Message-----
> From: Shilimkar, Santosh
> Sent: Monday, August 02, 2010 9:45 AM
> To: Sin, David; Russell King - ARM Linux; Woodruff, Richard
> Cc: linux-omap@vger.kernel.org; Tony Lindgren; Kanigeri, Hari; Ohad Ben-
> Cohen; Hiremath, Vaibhav; Molnar, Lajos; Voultoury, Pierre; linux-arm-
> kernel@lists.infradead.org
> Subject: RE: [RFC 4/8] TILER-DMM: TILER Memory Manager interface and
> implementation
> 
< snip>

> > > +	m->pa = page_to_phys(m->pg);
> > > +
> > > +	/* flush the cache entry for each page we allocate. */
> > > +	dmac_flush_range(page_address(m->pg),
> > > +				page_address(m->pg) + PAGE_SIZE);
> > > +	outer_flush_range(m->pa, m->pa + PAGE_SIZE);
> >
> > NAK.  This is an abuse of these interfaces, and is buggy in any case.
> >
> > ARMv6 and ARMv7 CPUs speculatively prefetch memory, which means that
> > there's no guarantee that if you flush the caches for a particular
> > range of virtual space, that it will stay flushed until you decide
> > to read it.  So flushing the caches in some memory allocator can't
> > guarantee that when you eventually get around to using the page that
> > there won't be cache lines associated with it.
> >
> > [dhs] Russell, thanks for reviewing this code.  Do you have any
> interface
> > suggestions that you can share that would make this proper?  Ideally, I
> > would like to get physical pages without associated virtual address, or
> > ones that are non-cached/non-bufferable.
> 
> There is nothing called 'non-bufferable' any more David on ARMv6 and
> ARMv7.
> You can get non-cached memory using "dma_alloc_coherent"
> 
> [dhs] Thanks, Santosh, for the clarification.  I believe
> dma_alloc_coherent is quite limited, right?  We need to be able to cover
> potentially 128MB of physical memory for the TILER.  BTW, does GFP_DMA
> indicate that I don't want cached memory?
> 
It's configurable. By default it's 2 MB pool. GFP_DMA doesn't give you
un-cacheable memory.


^ permalink raw reply	[flat|nested] 46+ messages in thread

* RE: [RFC 4/8] TILER-DMM: TILER Memory Manager interface and implementation
  2010-08-02 14:52                 ` Shilimkar, Santosh
@ 2010-08-02 14:55                   ` Sin, David
       [not found]                   ` <9DCA1E44C5805D4EB7C1626D5FD1739E048EDA223B@dlee02.ent.ti.com>
  1 sibling, 0 replies; 46+ messages in thread
From: Sin, David @ 2010-08-02 14:55 UTC (permalink / raw)
  To: Shilimkar, Santosh, Russell King - ARM Linux, Woodruff, Richard
  Cc: linux-omap@vger.kernel.org, Tony Lindgren, Kanigeri, Hari,
	Ohad Ben-Cohen, Hiremath, Vaibhav, Molnar, Lajos,
	Voultoury, Pierre, linux-arm-kernel@lists.infradead.org

-----Original Message-----
From: Shilimkar, Santosh 
Sent: Monday, August 02, 2010 9:53 AM
To: Sin, David; Russell King - ARM Linux; Woodruff, Richard
Cc: linux-omap@vger.kernel.org; Tony Lindgren; Kanigeri, Hari; Ohad Ben-Cohen; Hiremath, Vaibhav; Molnar, Lajos; Voultoury, Pierre; linux-arm-kernel@lists.infradead.org
Subject: RE: [RFC 4/8] TILER-DMM: TILER Memory Manager interface and implementation



> -----Original Message-----
> From: Sin, David
> Sent: Monday, August 02, 2010 8:20 PM
> To: Shilimkar, Santosh; Russell King - ARM Linux; Woodruff, Richard
> Cc: linux-omap@vger.kernel.org; Tony Lindgren; Kanigeri, Hari; Ohad Ben-
> Cohen; Hiremath, Vaibhav; Molnar, Lajos; Voultoury, Pierre; linux-arm-
> kernel@lists.infradead.org
> Subject: RE: [RFC 4/8] TILER-DMM: TILER Memory Manager interface and
> implementation
> 
> -----Original Message-----
> From: Shilimkar, Santosh
> Sent: Monday, August 02, 2010 9:45 AM
> To: Sin, David; Russell King - ARM Linux; Woodruff, Richard
> Cc: linux-omap@vger.kernel.org; Tony Lindgren; Kanigeri, Hari; Ohad Ben-
> Cohen; Hiremath, Vaibhav; Molnar, Lajos; Voultoury, Pierre; linux-arm-
> kernel@lists.infradead.org
> Subject: RE: [RFC 4/8] TILER-DMM: TILER Memory Manager interface and
> implementation
> 
< snip>

> > > +	m->pa = page_to_phys(m->pg);
> > > +
> > > +	/* flush the cache entry for each page we allocate. */
> > > +	dmac_flush_range(page_address(m->pg),
> > > +				page_address(m->pg) + PAGE_SIZE);
> > > +	outer_flush_range(m->pa, m->pa + PAGE_SIZE);
> >
> > NAK.  This is an abuse of these interfaces, and is buggy in any case.
> >
> > ARMv6 and ARMv7 CPUs speculatively prefetch memory, which means that
> > there's no guarantee that if you flush the caches for a particular
> > range of virtual space, that it will stay flushed until you decide
> > to read it.  So flushing the caches in some memory allocator can't
> > guarantee that when you eventually get around to using the page that
> > there won't be cache lines associated with it.
> >
> > [dhs] Russell, thanks for reviewing this code.  Do you have any
> interface
> > suggestions that you can share that would make this proper?  Ideally, I
> > would like to get physical pages without associated virtual address, or
> > ones that are non-cached/non-bufferable.
> 
> There is nothing called 'non-bufferable' any more David on ARMv6 and
> ARMv7.
> You can get non-cached memory using "dma_alloc_coherent"
> 
> [dhs] Thanks, Santosh, for the clarification.  I believe
> dma_alloc_coherent is quite limited, right?  We need to be able to cover
> potentially 128MB of physical memory for the TILER.  BTW, does GFP_DMA
> indicate that I don't want cached memory?
> 
It's configurable. By default it's 2 MB pool. GFP_DMA doesn't give you
un-cacheable memory.

[dhs] OK -- I will increase this and try to allocate this way.  Thank you.


^ permalink raw reply	[flat|nested] 46+ messages in thread

* RE: [RFC 4/8] TILER-DMM: TILER Memory Manager interface and implementation
       [not found]                   ` <9DCA1E44C5805D4EB7C1626D5FD1739E048EDA223B@dlee02.ent.ti.com>
@ 2010-08-03 19:49                     ` Sin, David
  0 siblings, 0 replies; 46+ messages in thread
From: Sin, David @ 2010-08-03 19:49 UTC (permalink / raw)
  To: Sin, David, Shilimkar, Santosh,
	'Russell King - ARM Linux', Woodruff, Richard
  Cc: 'linux-omap@vger.kernel.org', 'Tony Lindgren',
	Kanigeri, Hari, 'Ohad Ben-Cohen', Hiremath, Vaibhav,
	Molnar, Lajos, Voultoury, Pierre,
	'linux-arm-kernel@lists.infradead.org'

Russell, 

> -----Original Message-----
> From: Sin, David 
> Sent: Monday, August 02, 2010 9:55 AM
> To: Shilimkar, Santosh; Russell King - ARM Linux; Woodruff, Richard
> Cc: linux-omap@vger.kernel.org; Tony Lindgren; Kanigeri, 
> Hari; Ohad Ben-Cohen; Hiremath, Vaibhav; Molnar, Lajos; 
> Voultoury, Pierre; linux-arm-kernel@lists.infradead.org
> Subject: RE: [RFC 4/8] TILER-DMM: TILER Memory Manager 
> interface and implementation
> 
> -----Original Message-----
> From: Shilimkar, Santosh 
> Sent: Monday, August 02, 2010 9:53 AM
> To: Sin, David; Russell King - ARM Linux; Woodruff, Richard
> Cc: linux-omap@vger.kernel.org; Tony Lindgren; Kanigeri, 
> Hari; Ohad Ben-Cohen; Hiremath, Vaibhav; Molnar, Lajos; 
> Voultoury, Pierre; linux-arm-kernel@lists.infradead.org
> Subject: RE: [RFC 4/8] TILER-DMM: TILER Memory Manager 
> interface and implementation
> 
> 
> 
> > -----Original Message-----
> > From: Sin, David
> > Sent: Monday, August 02, 2010 8:20 PM
> > To: Shilimkar, Santosh; Russell King - ARM Linux; Woodruff, Richard
> > Cc: linux-omap@vger.kernel.org; Tony Lindgren; Kanigeri, 
> Hari; Ohad Ben-
> > Cohen; Hiremath, Vaibhav; Molnar, Lajos; Voultoury, Pierre; 
> linux-arm-
> > kernel@lists.infradead.org
> > Subject: RE: [RFC 4/8] TILER-DMM: TILER Memory Manager interface and
> > implementation
> > 
> > -----Original Message-----
> > From: Shilimkar, Santosh
> > Sent: Monday, August 02, 2010 9:45 AM
> > To: Sin, David; Russell King - ARM Linux; Woodruff, Richard
> > Cc: linux-omap@vger.kernel.org; Tony Lindgren; Kanigeri, 
> Hari; Ohad Ben-
> > Cohen; Hiremath, Vaibhav; Molnar, Lajos; Voultoury, Pierre; 
> linux-arm-
> > kernel@lists.infradead.org
> > Subject: RE: [RFC 4/8] TILER-DMM: TILER Memory Manager interface and
> > implementation
> > 
> < snip>
> 
> > > > +	m->pa = page_to_phys(m->pg);
> > > > +
> > > > +	/* flush the cache entry for each page we allocate. */
> > > > +	dmac_flush_range(page_address(m->pg),
> > > > +				page_address(m->pg) + 
> PAGE_SIZE);
> > > > +	outer_flush_range(m->pa, m->pa + PAGE_SIZE);
> > >
> > > NAK.  This is an abuse of these interfaces, and is buggy 
> in any case.
> > >
> > > ARMv6 and ARMv7 CPUs speculatively prefetch memory, which 
> means that
> > > there's no guarantee that if you flush the caches for a particular
> > > range of virtual space, that it will stay flushed until you decide
> > > to read it.  So flushing the caches in some memory allocator can't
> > > guarantee that when you eventually get around to using 
> the page that
> > > there won't be cache lines associated with it.
> > >
> > > [dhs] Russell, thanks for reviewing this code.  Do you have any
> > interface
> > > suggestions that you can share that would make this 
> proper?  Ideally, I
> > > would like to get physical pages without associated 
> virtual address, or
> > > ones that are non-cached/non-bufferable.
> > 
> > There is nothing called 'non-bufferable' any more David on ARMv6 and
> > ARMv7.
> > You can get non-cached memory using "dma_alloc_coherent"
> > 
> > [dhs] Thanks, Santosh, for the clarification.  I believe
> > dma_alloc_coherent is quite limited, right?  We need to be 
> able to cover
> > potentially 128MB of physical memory for the TILER.  BTW, 
> does GFP_DMA
> > indicate that I don't want cached memory?
> > 
> It's configurable. By default it's 2 MB pool. GFP_DMA doesn't give you
> un-cacheable memory.
> 
> [dhs] OK -- I will increase this and try to allocate this 
> way.  Thank you.
> 
> 

As Santosh suggests, I will increase the dma_alloc_coherent pool size to something that will accomdate TILER requirements.  I believe this will work, as I'm only making 4k allocations per call, as opposed to one large contiguous allocation.  However, I'd like to be able to use an API similar to alloc_page() that gives back device or strongly ordered memory so that we don't have to pre-allocate such a large amount at boot-up.  Is this something that you're considering on your end for the near future?  Thanks for working through this with us.

Regards,
-David

^ permalink raw reply	[flat|nested] 46+ messages in thread

end of thread, other threads:[~2010-08-03 19:50 UTC | newest]

Thread overview: 46+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-07-23 23:22 [RFC 0/8] TI TILER-DMM driver David Sin
2010-07-23 23:22 ` [RFC 1/8] TILER-DMM: DMM-PAT driver for TI TILER David Sin
2010-07-23 23:22   ` [RFC 2/8] TILER-DMM: Container manager interface and utility definitons David Sin
2010-07-23 23:22     ` [RFC 3/8] TILER-DMM: Sample TCM implementation: Simple TILER Allocator David Sin
2010-07-23 23:22       ` [RFC 4/8] TILER-DMM: TILER Memory Manager interface and implementation David Sin
2010-07-23 23:22         ` [RFC 5/8] TILER-DMM: TILER interface file and documentation David Sin
2010-07-23 23:22           ` [RFC 6/8] TILER-DMM: Geometry and view manipulation functions David Sin
2010-07-23 23:22             ` [RFC 7/8] TILER-DMM: Main TILER driver implementation David Sin
2010-07-23 23:22               ` [RFC 8/8] TILER-DMM: Linking TILER driver into the Linux kernel build David Sin
2010-07-24  7:32               ` [RFC 7/8] TILER-DMM: Main TILER driver implementation Shilimkar, Santosh
2010-07-24 13:41                 ` Hari Kanigeri
2010-07-24 13:53                   ` Shilimkar, Santosh
2010-07-24  7:55               ` Russell King - ARM Linux
2010-07-24  7:21           ` [RFC 5/8] TILER-DMM: TILER interface file and documentation Shilimkar, Santosh
2010-07-24  8:01         ` [RFC 4/8] TILER-DMM: TILER Memory Manager interface and implementation Russell King - ARM Linux
2010-07-26 19:34           ` Sin, David
2010-08-02 14:40           ` Sin, David
2010-08-02 14:44             ` Shilimkar, Santosh
2010-08-02 14:49               ` Sin, David
2010-08-02 14:52                 ` Shilimkar, Santosh
2010-08-02 14:55                   ` Sin, David
     [not found]                   ` <9DCA1E44C5805D4EB7C1626D5FD1739E048EDA223B@dlee02.ent.ti.com>
2010-08-03 19:49                     ` Sin, David
2010-07-28  5:53         ` Hiremath, Vaibhav
2010-07-24  7:13       ` [RFC 3/8] TILER-DMM: Sample TCM implementation: Simple TILER Allocator Shilimkar, Santosh
2010-07-25 15:45         ` Molnar, Lajos
2010-07-26 19:33         ` Sin, David
2010-07-27 20:41       ` Hiremath, Vaibhav
2010-07-24  6:56     ` [RFC 2/8] TILER-DMM: Container manager interface and utility definitons Shilimkar, Santosh
2010-07-27 20:21     ` Hiremath, Vaibhav
2010-07-24  6:51   ` [RFC 1/8] TILER-DMM: DMM-PAT driver for TI TILER Shilimkar, Santosh
2010-07-24  8:09   ` Russell King - ARM Linux
2010-07-24 10:15     ` Russell King - ARM Linux
2010-07-26 19:28     ` Sin, David
2010-07-27 18:37   ` Hiremath, Vaibhav
2010-07-27 19:05     ` Sin, David
2010-07-27 19:53       ` Hiremath, Vaibhav
2010-07-28 10:00         ` Laurent Pinchart
2010-07-28 14:39           ` Sin, David
2010-07-28 15:46             ` Hiremath, Vaibhav
2010-07-28  9:45       ` Laurent Pinchart
2010-07-24  7:44 ` [RFC 0/8] TI TILER-DMM driver Shilimkar, Santosh
2010-07-26 19:20   ` Sin, David
2010-07-24 11:12 ` Hans Verkuil
2010-07-28 15:23   ` Sin, David
2010-07-28 17:30     ` Hiremath, Vaibhav
2010-07-28 19:15       ` Sin, David

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).