* [RFC v2 1/8] TILER-DMM: DMM-PAT driver for TI TILER
2010-11-30 19:58 [RFC v2 0/8] TI DMM-TILER driver David Sin
@ 2010-11-30 19:58 ` David Sin
2010-12-01 6:04 ` Varadarajan, Charulatha
2010-11-30 19:58 ` [RFC v2 2/8] TILER-DMM: Container manager interface and utility definitons David Sin
` (7 subsequent siblings)
8 siblings, 1 reply; 22+ messages in thread
From: David Sin @ 2010-11-30 19:58 UTC (permalink / raw)
To: linux-arm-kernel
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/dmm-omap44xx.c | 81 ++++++++++++++
arch/arm/mach-omap2/include/mach/dmm.h | 92 ++++++++++++++++
drivers/misc/tiler/dmm-main.c | 187 ++++++++++++++++++++++++++++++++
3 files changed, 360 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/mach-omap2/dmm-omap44xx.c
create mode 100644 arch/arm/mach-omap2/include/mach/dmm.h
create mode 100644 drivers/misc/tiler/dmm-main.c
diff --git a/arch/arm/mach-omap2/dmm-omap44xx.c b/arch/arm/mach-omap2/dmm-omap44xx.c
new file mode 100644
index 0000000..2919d8e
--- /dev/null
+++ b/arch/arm/mach-omap2/dmm-omap44xx.c
@@ -0,0 +1,81 @@
+/*
+ * DMM driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <mach/dmm.h>
+#include <plat/omap_device.h>
+#include <plat/omap_hwmod.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+
+static struct dmm *plat_data;
+static int pdata;
+
+#ifdef CONFIG_ARCH_OMAP4
+static struct dmm omap4_plat_data[] = {
+ {
+ .oh_name = "dmm",
+ },
+};
+#define NUM_PDATA ARRAY_SIZE(omap4_plat_data)
+#else
+#define omap4_plat_data NULL
+#define NUM_PDATA 0
+#endif
+
+static struct omap_device_pm_latency omap_dmm_latency[] = {
+ [0] = {
+ .deactivate_func = omap_device_idle_hwmods,
+ .activate_func = omap_device_enable_hwmods,
+ .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+ },
+};
+
+static s32 __init dmm_omap_init(void)
+{
+ struct omap_hwmod *oh = NULL;
+ struct omap_device *od = NULL;
+ struct omap_device_pm_latency *ohl = NULL;
+ int ohlc = 0, i = 0;
+
+ plat_data = omap4_plat_data;
+ pdata = NUM_PDATA;
+
+ for (i = 0; i < pdata; i++) {
+ struct dmm *data = &plat_data[i];
+
+ oh = omap_hwmod_lookup(data->oh_name);
+ if (!oh)
+ goto error;
+
+ data->base = oh->_mpu_rt_va;
+ ohl = omap_dmm_latency;
+ ohlc = ARRAY_SIZE(omap_dmm_latency);
+
+ od = omap_device_build(data->oh_name, i, oh, data,
+ sizeof(*data), ohl, ohlc, false);
+ if (IS_ERR(od))
+ goto error;
+ }
+ return 0;
+error:
+ return -ENODEV;
+}
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("David Sin <davidsin@ti.com>");
+MODULE_AUTHOR("Lajos Molnar <molnar@ti.com>");
+device_initcall(dmm_omap_init);
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..33a1215
--- /dev/null
+++ b/arch/arm/mach-omap2/include/mach/dmm.h
@@ -0,0 +1,92 @@
+/*
+ * Dynamic Memory Manager (DMM) driver support functions for
+ * TI DMM-TILER hardware block.
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef DMM_H
+#define DMM_H
+
+#define DMM_TILER_OR__0 0x220
+#define DMM_TILER_OR__1 0x224
+#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_IRQSTATUS_RAW 0x480
+#define DMM_PAT_IRQSTATUS 0x490
+#define DMM_PAT_STATUS__0 0x4C0
+#define DMM_PAT_DESCR__0 0x500
+#define DMM_PAT_AREA__0 0x504
+#define DMM_PAT_CTRL__0 0x508
+#define DMM_PAT_DATA__0 0x50C
+
+/*
+ * Physical Address Translator (PAT) refill programming mode
+ */
+enum pat_mode {
+ MANUAL,
+ AUTO
+};
+
+/*
+ * Area definition for DMM physical address translator
+ */
+struct pat_area {
+ s8 x0:8;
+ s8 y0:8;
+ s8 x1:8;
+ s8 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;
+};
+
+/*
+ * Physical Address Translator (PAT) descriptor
+ */
+struct pat {
+ struct pat *next;
+ struct pat_area area;
+ struct pat_ctrl ctrl;
+ u32 data;
+};
+
+/*
+ * DMM device data
+ */
+struct dmm {
+ const char *oh_name;
+ void __iomem *base;
+ int irq;
+};
+
+/*
+ * Create and initialize the physical address translator
+ */
+struct dmm *dmm_pat_init(u32 id);
+
+/*
+ * Program the physical address translator
+ */
+int dmm_pat_refill(struct dmm *dmm, struct pat *desc, enum pat_mode mode);
+
+#endif
diff --git a/drivers/misc/tiler/dmm-main.c b/drivers/misc/tiler/dmm-main.c
new file mode 100644
index 0000000..412f592
--- /dev/null
+++ b/drivers/misc/tiler/dmm-main.c
@@ -0,0 +1,187 @@
+/*
+ * DMM driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/delay.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))))
+#define MAX_RETRY_MS 1000
+
+static struct dmm *dmm;
+
+static int dmm_probe(struct platform_device *dev)
+{
+ if (dev)
+ dmm = dev->dev.platform_data;
+
+ if (dmm && dmm->base) {
+ writel(0x88888888, dmm->base + DMM_TILER_OR__0);
+ writel(0x88888888, dmm->base + DMM_TILER_OR__1);
+ return 0;
+ }
+ return -EFAULT;
+}
+
+static int dmm_remove(struct platform_device *dev)
+{
+ return 0;
+}
+
+static struct platform_driver dmm_driver = {
+ .probe = dmm_probe,
+ .remove = dmm_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "dmm",
+ },
+};
+
+int dmm_pat_refill(struct dmm *dmm, struct pat *pd, enum pat_mode mode)
+{
+ void __iomem *r;
+ u32 v, i;
+
+ if (!dmm || !dmm->base || !pd)
+ return -EFAULT;
+
+ /* 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 = 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 = readl(r);
+ v = SET_FLD(v, 31, 4, (u32) NULL);
+ writel(v, r);
+
+ /* Set area to be refilled */
+ r = dmm->base + DMM_PAT_AREA__0;
+ v = 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);
+ writel(v, r);
+
+ /* First, clear the DMM_PAT_IRQSTATUS register */
+ writel(0xFFFFFFFF, dmm->base + DMM_PAT_IRQSTATUS);
+
+ i = 1000;
+ while (readl(dmm->base + DMM_PAT_IRQSTATUS_RAW) != 0) {
+ if (--i == 0)
+ return -EFAULT;
+ udelay(1);
+ }
+
+ /* Fill data register */
+ v = readl(dmm->base + DMM_PAT_DATA__0);
+
+ v = SET_FLD(v, 31, 4, pd->data >> 4);
+ writel(v, r);
+
+ /* Read back PAT_DATA__0 to see if write was successful */
+ i = 1000;
+ while (readl(r) != pd->data) {
+ if (--i == 0)
+ return -EFAULT;
+ udelay(1);
+ }
+
+ v = readl(dmm->base + DMM_PAT_CTRL__0);
+ 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);
+ writel(v, r);
+
+ /* Check if PAT_IRQSTATUS_RAW is set after the PAT has been refilled */
+ i = 1000;
+ while ((readl(dmm->base + DMM_PAT_IRQSTATUS_RAW) & 0x3) != 0x3) {
+ if (--i == 0)
+ return -EFAULT;
+ udelay(1);
+ }
+
+ /* Again, clear the DMM_PAT_IRQSTATUS register */
+ writel(0xFFFFFFFF, dmm->base + DMM_PAT_IRQSTATUS);
+
+ i = 1000;
+ while (readl(dmm->base + DMM_PAT_IRQSTATUS_RAW) != 0) {
+ if (--i == 0)
+ return -EFAULT;
+ udelay(1);
+ }
+
+ /* Again, set "next" register to NULL to clear any PAT STATUS errors */
+ v = readl(dmm->base + DMM_PAT_DESCR__0);
+ v = SET_FLD(v, 31, 4, (u32) NULL);
+ writel(v, r);
+
+ /*
+ * Now, check that the DMM_PAT_STATUS register
+ * has not reported an error before exiting.
+ */
+ v = readl(dmm->base + DMM_PAT_STATUS__0);
+ 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)
+{
+ if (dmm && dmm->base) {
+ writel(0x88888888, dmm->base + DMM_PAT_VIEW__0);
+ writel(0x88888888, dmm->base + DMM_PAT_VIEW__1);
+ writel(0x80808080, dmm->base + DMM_PAT_VIEW_MAP__0);
+ writel(0x80000000, dmm->base + DMM_PAT_VIEW_MAP_BASE);
+ }
+
+ return dmm;
+}
+EXPORT_SYMBOL(dmm_pat_init);
+
+static s32 __init dmm_init(void)
+{
+ return platform_driver_register(&dmm_driver);
+}
+
+static void __exit dmm_exit(void)
+{
+ platform_driver_unregister(&dmm_driver);
+}
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("David Sin <davidsin@ti.com>");
+MODULE_AUTHOR("Lajos Molnar <molnar@ti.com>");
+module_init(dmm_init);
+module_exit(dmm_exit);
--
1.7.0.4
^ permalink raw reply related [flat|nested] 22+ messages in thread* [RFC v2 1/8] TILER-DMM: DMM-PAT driver for TI TILER
2010-11-30 19:58 ` [RFC v2 1/8] TILER-DMM: DMM-PAT driver for TI TILER David Sin
@ 2010-12-01 6:04 ` Varadarajan, Charulatha
2010-12-02 2:10 ` Kanigeri, Hari
0 siblings, 1 reply; 22+ messages in thread
From: Varadarajan, Charulatha @ 2010-12-01 6:04 UTC (permalink / raw)
To: linux-arm-kernel
David,
On Wed, Dec 1, 2010 at 01:28, David Sin <davidsin@ti.com> wrote:
> 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/dmm-omap44xx.c ? ? | ? 81 ++++++++++++++
> ?arch/arm/mach-omap2/include/mach/dmm.h | ? 92 ++++++++++++++++
> ?drivers/misc/tiler/dmm-main.c ? ? ? ? ?| ?187 ++++++++++++++++++++++++++++++++
> ?3 files changed, 360 insertions(+), 0 deletions(-)
> ?create mode 100644 arch/arm/mach-omap2/dmm-omap44xx.c
> ?create mode 100644 arch/arm/mach-omap2/include/mach/dmm.h
> ?create mode 100644 drivers/misc/tiler/dmm-main.c
>
> diff --git a/arch/arm/mach-omap2/dmm-omap44xx.c b/arch/arm/mach-omap2/dmm-omap44xx.c
> new file mode 100644
> index 0000000..2919d8e
> --- /dev/null
> +++ b/arch/arm/mach-omap2/dmm-omap44xx.c
> @@ -0,0 +1,81 @@
> +/*
> + * DMM driver support functions for TI OMAP processors.
> + *
> + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation version 2.
> + *
> + * This program is distributed "as is" WITHOUT ANY WARRANTY of any
> + * kind, whether express or implied; without even the implied warranty
> + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ?See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/module.h>
> +#include <mach/dmm.h>
> +#include <plat/omap_device.h>
> +#include <plat/omap_hwmod.h>
> +#include <linux/errno.h>
> +#include <linux/err.h>
> +
> +static struct dmm *plat_data;
> +static int pdata;
> +
> +#ifdef CONFIG_ARCH_OMAP4
Do not use these #ifdefs as it would not work as intended in multi-omap build.
This driver is making use of omap_hwmod fw. Try to take advantage of hwmod_fw
and avoid these checks.
> +static struct dmm omap4_plat_data[] = {
> + ? ? ? {
> + ? ? ? ? ? ? ? .oh_name = "dmm",
Do not use "oh_name" as it is confusing.
> + ? ? ? },
> +};
> +#define NUM_PDATA ARRAY_SIZE(omap4_plat_data)
> +#else
> +#define omap4_plat_data NULL
> +#define NUM_PDATA 0
> +#endif
> +
> +static struct omap_device_pm_latency omap_dmm_latency[] = {
> + ? ? ? [0] = {
> + ? ? ? ? ? ? ? .deactivate_func = omap_device_idle_hwmods,
> + ? ? ? ? ? ? ? .activate_func = omap_device_enable_hwmods,
> + ? ? ? ? ? ? ? .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
> + ? ? ? },
> +};
> +
> +static s32 __init dmm_omap_init(void)
> +{
> + ? ? ? struct omap_hwmod *oh = NULL;
> + ? ? ? struct omap_device *od = NULL;
> + ? ? ? struct omap_device_pm_latency *ohl = NULL;
Any specific reson for not assigning it directly to omap_dmm_latency?
I think this is redundant and omap_dmm_latency can be directly passed
to omap_device_build()
> + ? ? ? int ohlc = 0, i = 0;
> +
> + ? ? ? plat_data = omap4_plat_data;
> + ? ? ? pdata = NUM_PDATA;
name "pdata" is confusing. Also no need to iterate over the list of
devices using
NUM_PDATA. If you have multiple devices, make use of hwmod class.
> +
> + ? ? ? for (i = 0; i < pdata; i++) {
> + ? ? ? ? ? ? ? struct dmm *data = &plat_data[i];
> +
> + ? ? ? ? ? ? ? oh = omap_hwmod_lookup(data->oh_name)
I do not find any other devices sharing same name for the device name
and oh->name.
Normally the device's name is preferred to be "omap_devname.id" to be
consistent across all drivers
and the oh->name is given as "devname(id)"
example: McSPI's device name could be "omap_mcspi" and it's hwmod name
could be "mcspi"
> + ? ? ? ? ? ? ? if (!oh)
> + ? ? ? ? ? ? ? ? ? ? ? goto error;
> +
> + ? ? ? ? ? ? ? data->base = oh->_mpu_rt_va;
not required. Make use of platform_get APIs in probe to extract the
base, dma and irq info using pdev.
> + ? ? ? ? ? ? ? ohl = omap_dmm_latency;
> + ? ? ? ? ? ? ? ohlc = ARRAY_SIZE(omap_dmm_latency);
> +
> + ? ? ? ? ? ? ? od = omap_device_build(data->oh_name, i, oh, data,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?sizeof(*data), ohl, ohlc, false);
> + ? ? ? ? ? ? ? if (IS_ERR(od))
> + ? ? ? ? ? ? ? ? ? ? ? goto error;
> + ? ? ? }
> + ? ? ? return 0;
> +error:
> + ? ? ? return -ENODEV;
print the error message.
> +}
> +
> +MODULE_LICENSE("GPL v2");
> +MODULE_AUTHOR("David Sin <davidsin@ti.com>");
> +MODULE_AUTHOR("Lajos Molnar <molnar@ti.com>");
> +device_initcall(dmm_omap_init);
<<snip>>
^ permalink raw reply [flat|nested] 22+ messages in thread* [RFC v2 1/8] TILER-DMM: DMM-PAT driver for TI TILER
2010-12-01 6:04 ` Varadarajan, Charulatha
@ 2010-12-02 2:10 ` Kanigeri, Hari
2010-12-02 2:27 ` Kanigeri, Hari
0 siblings, 1 reply; 22+ messages in thread
From: Kanigeri, Hari @ 2010-12-02 2:10 UTC (permalink / raw)
To: linux-arm-kernel
On Wed, Dec 1, 2010 at 12:04 AM, Varadarajan, Charulatha <charu@ti.com> wrote:
> David,
>
>> + ? ? ? ? ? ? ? if (!oh)
>> + ? ? ? ? ? ? ? ? ? ? ? goto error;
>> +
>> + ? ? ? ? ? ? ? data->base = oh->_mpu_rt_va;
>
> not required. Make use of platform_get APIs in probe to extract the
> base, dma and irq info using pdev.
Not sure about using platform_get APIs. I think one has to use
omap_hwmod_get_mpu_rt_va to get the address, which internally returns
oh-<_mpu_rt_va.
omap_hwmod_get_mpu_rt_va was added so that the individual drivers can
avoid doing the ioremap.
check the discussion regarding this.
http://www.spinics.net/lists/linux-omap/msg33048.html
Thank you,
Best regards,
Hari Kanigeri
^ permalink raw reply [flat|nested] 22+ messages in thread
* [RFC v2 1/8] TILER-DMM: DMM-PAT driver for TI TILER
2010-12-02 2:10 ` Kanigeri, Hari
@ 2010-12-02 2:27 ` Kanigeri, Hari
2010-12-02 5:16 ` Varadarajan, Charulatha
0 siblings, 1 reply; 22+ messages in thread
From: Kanigeri, Hari @ 2010-12-02 2:27 UTC (permalink / raw)
To: linux-arm-kernel
On Wed, Dec 1, 2010 at 8:10 PM, Kanigeri, Hari <h-kanigeri2@ti.com> wrote:
> On Wed, Dec 1, 2010 at 12:04 AM, Varadarajan, Charulatha <charu@ti.com> wrote:
>> David,
>
>>
>>> + ? ? ? ? ? ? ? if (!oh)
>>> + ? ? ? ? ? ? ? ? ? ? ? goto error;
>>> +
>>> + ? ? ? ? ? ? ? data->base = oh->_mpu_rt_va;
>>
>> not required. Make use of platform_get APIs in probe to extract the
>> base, dma and irq info using pdev.
>
> Not sure about using platform_get APIs. I think one has to use
> omap_hwmod_get_mpu_rt_va to get the address, which internally returns
> oh-<_mpu_rt_va.
small correction... omap_device_get_rt_va and not omap_hwmod_get_mpu_rt_va.
Thank you,
Best regards,
Hari Kanigeri
^ permalink raw reply [flat|nested] 22+ messages in thread
* [RFC v2 1/8] TILER-DMM: DMM-PAT driver for TI TILER
2010-12-02 2:27 ` Kanigeri, Hari
@ 2010-12-02 5:16 ` Varadarajan, Charulatha
2010-12-02 10:23 ` Hari Kanigeri
0 siblings, 1 reply; 22+ messages in thread
From: Varadarajan, Charulatha @ 2010-12-02 5:16 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, Dec 2, 2010 at 07:57, Kanigeri, Hari <h-kanigeri2@ti.com> wrote:
> On Wed, Dec 1, 2010 at 8:10 PM, Kanigeri, Hari <h-kanigeri2@ti.com> wrote:
>> On Wed, Dec 1, 2010 at 12:04 AM, Varadarajan, Charulatha <charu@ti.com> wrote:
>>> David,
>>
>>>
>>>> + ? ? ? ? ? ? ? if (!oh)
>>>> + ? ? ? ? ? ? ? ? ? ? ? goto error;
>>>> +
>>>> + ? ? ? ? ? ? ? data->base = oh->_mpu_rt_va;
>>>
>>> not required. Make use of platform_get APIs in probe to extract the
>>> base, dma and irq info using pdev.
>>
>> Not sure about using platform_get APIs. I think one has to use
>> omap_hwmod_get_mpu_rt_va to get the address, which internally returns
>> oh-<_mpu_rt_va.
> small correction... omap_device_get_rt_va and not omap_hwmod_get_mpu_rt_va.
To get the base address & irq, you need not have to use
omap_device_get_rt_va and pass it as
pdata and then use it during probe. Instead in probe, you may do
something like the following:
static int __devinit dev_probe (*pdev) {
struct resource *res;
void __iomem *base;
u16 irq;
....
....
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (unlikely(!res)) {
....
return -ENODEV;
}
base = ioremap(res->start, resource_size(res));
if (base) {
....
return -ENOMEM;
}
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (unlikely(!res)) {
....
return -ENODEV;
}
irq = res->start;
....
....
}
-V Charulatha
^ permalink raw reply [flat|nested] 22+ messages in thread* [RFC v2 1/8] TILER-DMM: DMM-PAT driver for TI TILER
2010-12-02 5:16 ` Varadarajan, Charulatha
@ 2010-12-02 10:23 ` Hari Kanigeri
2010-12-02 10:31 ` Varadarajan, Charulatha
0 siblings, 1 reply; 22+ messages in thread
From: Hari Kanigeri @ 2010-12-02 10:23 UTC (permalink / raw)
To: linux-arm-kernel
On Wed, Dec 1, 2010 at 11:16 PM, Varadarajan, Charulatha <charu@ti.com> wrote:
> On Thu, Dec 2, 2010 at 07:57, Kanigeri, Hari <h-kanigeri2@ti.com> wrote:
>> On Wed, Dec 1, 2010 at 8:10 PM, Kanigeri, Hari <h-kanigeri2@ti.com> wrote:
>>> On Wed, Dec 1, 2010 at 12:04 AM, Varadarajan, Charulatha <charu@ti.com> wrote:
>>>> David,
>>>
>>>>
>>>>> + ? ? ? ? ? ? ? if (!oh)
>>>>> + ? ? ? ? ? ? ? ? ? ? ? goto error;
>>>>> +
>>>>> + ? ? ? ? ? ? ? data->base = oh->_mpu_rt_va;
>>>>
>>>> not required. Make use of platform_get APIs in probe to extract the
>>>> base, dma and irq info using pdev.
>>>
>>> Not sure about using platform_get APIs. I think one has to use
>>> omap_hwmod_get_mpu_rt_va to get the address, which internally returns
>>> oh-<_mpu_rt_va.
>> small correction... omap_device_get_rt_va and not omap_hwmod_get_mpu_rt_va.
>
> To get the base address & irq, you need not have to use
> omap_device_get_rt_va and pass it as
> pdata and then use it during probe. Instead in probe, you may do
> something like the following:
If hwmod framework is already doing the ioremap on device address,
then it is better to use it rather than duplicating the ioremap part
again in probe function.
^ permalink raw reply [flat|nested] 22+ messages in thread
* [RFC v2 1/8] TILER-DMM: DMM-PAT driver for TI TILER
2010-12-02 10:23 ` Hari Kanigeri
@ 2010-12-02 10:31 ` Varadarajan, Charulatha
0 siblings, 0 replies; 22+ messages in thread
From: Varadarajan, Charulatha @ 2010-12-02 10:31 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, Dec 2, 2010 at 15:53, Hari Kanigeri <hari.kanigeri@gmail.com> wrote:
> On Wed, Dec 1, 2010 at 11:16 PM, Varadarajan, Charulatha <charu@ti.com> wrote:
>> On Thu, Dec 2, 2010 at 07:57, Kanigeri, Hari <h-kanigeri2@ti.com> wrote:
>>> On Wed, Dec 1, 2010 at 8:10 PM, Kanigeri, Hari <h-kanigeri2@ti.com> wrote:
>>>> On Wed, Dec 1, 2010 at 12:04 AM, Varadarajan, Charulatha <charu@ti.com> wrote:
>>>>> David,
>>>>
>>>>>
>>>>>> + ? ? ? ? ? ? ? if (!oh)
>>>>>> + ? ? ? ? ? ? ? ? ? ? ? goto error;
>>>>>> +
>>>>>> + ? ? ? ? ? ? ? data->base = oh->_mpu_rt_va;
>>>>>
>>>>> not required. Make use of platform_get APIs in probe to extract the
>>>>> base, dma and irq info using pdev.
>>>>
>>>> Not sure about using platform_get APIs. I think one has to use
>>>> omap_hwmod_get_mpu_rt_va to get the address, which internally returns
>>>> oh-<_mpu_rt_va.
>>> small correction... omap_device_get_rt_va and not omap_hwmod_get_mpu_rt_va.
>>
>> To get the base address & irq, you need not have to use
>> omap_device_get_rt_va and pass it as
>> pdata and then use it during probe. Instead in probe, you may do
>> something like the following:
>
> If hwmod framework is already doing the ioremap on device address,
> then it is better to use it rather than duplicating the ioremap part
> again in probe function.
> From what I understand regarding omap_device_get_rt_va() function, it
> is added so that Driver's can avoid doing ioremap.
> check Santosh's comment on this API
> http://www.spinics.net/lists/arm-kernel/msg92260.html
Okay. For base address, I agree, as it avoids redoing ioremap in drivers.
For "irq" & "DMA", it is still required to use platform_get*() APIs.
>
>>
>> static int __devinit ?dev_probe (*pdev) {
>> ? struct resource *res;
>> ? void __iomem *base;
>> ? u16 irq;
>> ? ....
>> ? ....
>> ? res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> ? if (unlikely(!res)) {
>> ? ? ? ? ? ? ?....
>> ? ? ? ? ? ? ?return -ENODEV;
>> ? }
>>
>> ? base = ioremap(res->start, resource_size(res));
>> ? if (base) {
>> ? ? ? ? ? ? ? ....
>> ? ? ? ? ? ? ? return -ENOMEM;
>> ? }
>>
>> ? res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
>> ? if (unlikely(!res)) {
>> ? ? ? ? ? ? ? ....
>> ? ? ? ? ? ? ? return -ENODEV;
>> ? }
>> ? irq = res->start;
>> ? ....
>> ? ....
>> }
>>
>> -V Charulatha
^ permalink raw reply [flat|nested] 22+ messages in thread
* [RFC v2 2/8] TILER-DMM: Container manager interface and utility definitons
2010-11-30 19:58 [RFC v2 0/8] TI DMM-TILER driver David Sin
2010-11-30 19:58 ` [RFC v2 1/8] TILER-DMM: DMM-PAT driver for TI TILER David Sin
@ 2010-11-30 19:58 ` David Sin
2010-11-30 19:58 ` [RFC v2 3/8] TILER-DMM: Sample TCM implementation: Simple TILER Allocator (SiTA) David Sin
` (6 subsequent siblings)
8 siblings, 0 replies; 22+ messages in thread
From: David Sin @ 2010-11-30 19:58 UTC (permalink / raw)
To: linux-arm-kernel
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/misc/tiler/tcm.h | 171 ++++++++++++++++++++++++++++++++++++
drivers/misc/tiler/tcm/tcm-utils.h | 51 +++++++++++
2 files changed, 222 insertions(+), 0 deletions(-)
create mode 100644 drivers/misc/tiler/tcm.h
create mode 100644 drivers/misc/tiler/tcm/tcm-utils.h
diff --git a/drivers/misc/tiler/tcm.h b/drivers/misc/tiler/tcm.h
new file mode 100644
index 0000000..8968108
--- /dev/null
+++ b/drivers/misc/tiler/tcm.h
@@ -0,0 +1,171 @@
+/*
+ * TILER container manager specification and support functions for TI
+ * TILER driver.
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#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);
+};
+
+/*
+ * 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.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * 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;
+}
+
+/* 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/misc/tiler/tcm/tcm-utils.h b/drivers/misc/tiler/tcm/tcm-utils.h
new file mode 100644
index 0000000..400c2fe
--- /dev/null
+++ b/drivers/misc/tiler/tcm/tcm-utils.h
@@ -0,0 +1,51 @@
+/*
+ * Utility functions for implementing TILER container managers.
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#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.7.0.4
^ permalink raw reply related [flat|nested] 22+ messages in thread* [RFC v2 3/8] TILER-DMM: Sample TCM implementation: Simple TILER Allocator (SiTA)
2010-11-30 19:58 [RFC v2 0/8] TI DMM-TILER driver David Sin
2010-11-30 19:58 ` [RFC v2 1/8] TILER-DMM: DMM-PAT driver for TI TILER David Sin
2010-11-30 19:58 ` [RFC v2 2/8] TILER-DMM: Container manager interface and utility definitons David Sin
@ 2010-11-30 19:58 ` David Sin
2010-11-30 19:58 ` [RFC v2 4/8] TILER-DMM: TILER Memory Manager interface and implementation David Sin
` (5 subsequent siblings)
8 siblings, 0 replies; 22+ messages in thread
From: David Sin @ 2010-11-30 19:58 UTC (permalink / raw)
To: linux-arm-kernel
From: Ravi Ramachandra <r.ramachandra@ti.com>
This patch implements a simple TILER Container Manager (TCM).
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/misc/tiler/tcm/Makefile | 1 +
drivers/misc/tiler/tcm/_tcm-sita.h | 61 +++++
drivers/misc/tiler/tcm/tcm-sita.c | 422 ++++++++++++++++++++++++++++++++++++
drivers/misc/tiler/tcm/tcm-sita.h | 28 +++
4 files changed, 512 insertions(+), 0 deletions(-)
create mode 100644 drivers/misc/tiler/tcm/Makefile
create mode 100644 drivers/misc/tiler/tcm/_tcm-sita.h
create mode 100644 drivers/misc/tiler/tcm/tcm-sita.c
create mode 100644 drivers/misc/tiler/tcm/tcm-sita.h
diff --git a/drivers/misc/tiler/tcm/Makefile b/drivers/misc/tiler/tcm/Makefile
new file mode 100644
index 0000000..8434607
--- /dev/null
+++ b/drivers/misc/tiler/tcm/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_TI_TILER) += tcm-sita.o
diff --git a/drivers/misc/tiler/tcm/_tcm-sita.h b/drivers/misc/tiler/tcm/_tcm-sita.h
new file mode 100644
index 0000000..6e4d292
--- /dev/null
+++ b/drivers/misc/tiler/tcm/_tcm-sita.h
@@ -0,0 +1,61 @@
+/*
+ * SImple Tiler Allocator (SiTA) private structures.
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#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/misc/tiler/tcm/tcm-sita.c b/drivers/misc/tiler/tcm/tcm-sita.c
new file mode 100644
index 0000000..a7ceac4
--- /dev/null
+++ b/drivers/misc/tiler/tcm/tcm-sita.c
@@ -0,0 +1,422 @@
+/*
+ * SImple Tiler Allocator (SiTA): 2D and 1D allocation(reservation) algorithm
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#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 = {NULL};
+ 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 = {NULL};
+ 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
+ */
+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
+ */
+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.
+ */
+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}, {NULL}, 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.
+ */
+static s32 scan_areas_and_find_fit(struct tcm *tcm, u16 w, u16 h, u16 align,
+ struct tcm_area *area)
+{
+ struct tcm_area field = {NULL};
+
+ /* 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. 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/misc/tiler/tcm/tcm-sita.h b/drivers/misc/tiler/tcm/tcm-sita.h
new file mode 100644
index 0000000..a435bce
--- /dev/null
+++ b/drivers/misc/tiler/tcm/tcm-sita.h
@@ -0,0 +1,28 @@
+/*
+ * SImple Tiler Allocator (SiTA) interface.
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef TCM_SITA_H
+#define TCM_SITA_H
+
+#include "../tcm.h"
+
+/*
+ * Create a SiTA tiler container manager.
+ */
+struct tcm *sita_init(u16 width, u16 height, void *attr);
+
+TCM_INIT(sita_init, void);
+
+#endif
--
1.7.0.4
^ permalink raw reply related [flat|nested] 22+ messages in thread* [RFC v2 4/8] TILER-DMM: TILER Memory Manager interface and implementation
2010-11-30 19:58 [RFC v2 0/8] TI DMM-TILER driver David Sin
` (2 preceding siblings ...)
2010-11-30 19:58 ` [RFC v2 3/8] TILER-DMM: Sample TCM implementation: Simple TILER Allocator (SiTA) David Sin
@ 2010-11-30 19:58 ` David Sin
2010-11-30 19:58 ` [RFC v2 5/8] TILER-DMM: TILER interface file and documentation David Sin
` (4 subsequent siblings)
8 siblings, 0 replies; 22+ messages in thread
From: David Sin @ 2010-11-30 19:58 UTC (permalink / raw)
To: linux-arm-kernel
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/misc/tiler/tmm-pat.c | 266 ++++++++++++++++++++++++++++++++++++++++++
drivers/misc/tiler/tmm.h | 103 ++++++++++++++++
2 files changed, 369 insertions(+), 0 deletions(-)
create mode 100644 drivers/misc/tiler/tmm-pat.c
create mode 100644 drivers/misc/tiler/tmm.h
diff --git a/drivers/misc/tiler/tmm-pat.c b/drivers/misc/tiler/tmm-pat.c
new file mode 100644
index 0000000..26b4da3
--- /dev/null
+++ b/drivers/misc/tiler/tmm-pat.c
@@ -0,0 +1,266 @@
+/*
+ * DMM driver support functions for TI TILER hardware block.
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#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 <linux/dma-mapping.h>
+
+#include "tmm.h"
+
+/* Page size granularity can be 4k, 16k, or 64k */
+#define DMM_PAGE SZ_4K
+
+/* 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;
+ u32 *pg; /* page struct */
+ dma_addr_t 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;
+ dma_free_coherent(NULL, DMM_PAGE, f->mem[i]->pg,
+ f->mem[i]->pa);
+ }
+ }
+ 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 = dma_alloc_coherent(NULL, DMM_PAGE, &m->pa, GFP_KERNEL);
+ if (!m->pg) {
+ kfree(m);
+ return NULL;
+ }
+ wmb();
+
+ 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) {
+ dma_free_coherent(NULL, DMM_PAGE, m->pg, m->pa);
+ 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 = {NULL};
+
+ /* 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);
+ return NULL;
+}
+EXPORT_SYMBOL(tmm_pat_init);
diff --git a/drivers/misc/tiler/tmm.h b/drivers/misc/tiler/tmm.h
new file mode 100644
index 0000000..cb90664
--- /dev/null
+++ b/drivers/misc/tiler/tmm.h
@@ -0,0 +1,103 @@
+/*
+ * TMM interface definition for TI TILER driver.
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#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.
+ */
+static inline
+void tmm_free(struct tmm *tmm, u32 *pages)
+{
+ if (tmm && tmm->pvt)
+ tmm->free(tmm, pages);
+}
+
+/*
+ * Program the physical address translator.
+ */
+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.
+ */
+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.7.0.4
^ permalink raw reply related [flat|nested] 22+ messages in thread* [RFC v2 5/8] TILER-DMM: TILER interface file and documentation
2010-11-30 19:58 [RFC v2 0/8] TI DMM-TILER driver David Sin
` (3 preceding siblings ...)
2010-11-30 19:58 ` [RFC v2 4/8] TILER-DMM: TILER Memory Manager interface and implementation David Sin
@ 2010-11-30 19:58 ` David Sin
2010-12-01 0:53 ` Greg KH
2010-11-30 19:58 ` [RFC v2 6/8] TILER-DMM: Geometry and view manipulation functions David Sin
` (3 subsequent siblings)
8 siblings, 1 reply; 22+ messages in thread
From: David Sin @ 2010-11-30 19:58 UTC (permalink / raw)
To: linux-arm-kernel
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/OMAP/TILER | 126 ++++++++++++++++++++++
arch/arm/mach-omap2/include/mach/tiler.h | 173 ++++++++++++++++++++++++++++++
2 files changed, 299 insertions(+), 0 deletions(-)
create mode 100644 Documentation/arm/OMAP/TILER
create mode 100644 arch/arm/mach-omap2/include/mach/tiler.h
diff --git a/Documentation/arm/OMAP/TILER b/Documentation/arm/OMAP/TILER
new file mode 100644
index 0000000..2e94ad7
--- /dev/null
+++ b/Documentation/arm/OMAP/TILER
@@ -0,0 +1,126 @@
+Tiling and Isometric Lightweight Engine for Rotation (TILER) driver
+
+Dynamic Memory Manager (DMM) is a hardware block made by Texas Instruments.
+Within the DMM exists at least one TILER hardware component. 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 component 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).
+
+Using TILER driver KERNEL APIs:
+
+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));
+ }
+
+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 Physical Address Translator 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..280f7bb
--- /dev/null
+++ b/arch/arm/mach-omap2/include/mach/tiler.h
@@ -0,0 +1,173 @@
+/*
+ * TILER driver support functions for TI TILER hardware block.
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#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.
+ *
+ * @blk: pointer to tiler block data. This must be set up ('phys' member must
+ * be 0) with the tiler block information.
+ * @fmt: TILER block format
+ * @align: block alignment (default: normally PAGE_SIZE)
+ * @offs: block offset
+ *
+ */
+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.
+ *
+ * @blk: pointer to tiler block data
+ * @offs: offset from where to map (must be page aligned)
+ * @size: size of area to map (must be page aligned)
+ * @vma: VMM memory area to map to
+ * @voffs: offset (from vm_start) in the VMM memory area to start mapping at
+ *
+ */
+s32 tiler_mmap_blk(struct tiler_block_t *blk, u32 offs, u32 size,
+ struct vm_area_struct *vma, u32 voffs);
+
+/*
+ * 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.
+ *
+ * @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.
+ *
+ * @view: Pointer to a view where the information will be stored
+ * @ssptr: MUST BE a tiler address
+ * @width: view width
+ * @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
+ *
+ * @view: Pointer to a view where the information will be stored
+ * @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.
+ *
+ * @view: Pointer to tiler view to be cropped
+ * @left: x of top-left corner
+ * @top: y of top-left corner
+ * @width: crop width
+ * @height: crop height
+ *
+ * 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.
+ *
+ * @view: Pointer to tiler view to be cropped
+ * @rotate: Degree of rotation (clockwise). Must be a multiple of 90.
+ *
+ * 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.
+ *
+ * @view: Pointer to tiler view to be cropped
+ * @flip_x: Mirror horizontally (left-to-right)
+ * @flip_y: Mirror vertically (top-to-bottom)
+ *
+ * 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.7.0.4
^ permalink raw reply related [flat|nested] 22+ messages in thread* [RFC v2 6/8] TILER-DMM: Geometry and view manipulation functions
2010-11-30 19:58 [RFC v2 0/8] TI DMM-TILER driver David Sin
` (4 preceding siblings ...)
2010-11-30 19:58 ` [RFC v2 5/8] TILER-DMM: TILER interface file and documentation David Sin
@ 2010-11-30 19:58 ` David Sin
2010-12-01 0:55 ` Greg KH
2010-11-30 19:58 ` [RFC v2 7/8] TILER-DMM: Main TILER driver implementation David Sin
` (2 subsequent siblings)
8 siblings, 1 reply; 22+ messages in thread
From: David Sin @ 2010-11-30 19:58 UTC (permalink / raw)
To: linux-arm-kernel
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/misc/tiler/_tiler.h | 48 +++++
drivers/misc/tiler/tiler-geom.c | 362 +++++++++++++++++++++++++++++++++++++++
2 files changed, 410 insertions(+), 0 deletions(-)
create mode 100644 drivers/misc/tiler/_tiler.h
create mode 100644 drivers/misc/tiler/tiler-geom.c
diff --git a/drivers/misc/tiler/_tiler.h b/drivers/misc/tiler/_tiler.h
new file mode 100644
index 0000000..0f00330
--- /dev/null
+++ b/drivers/misc/tiler/_tiler.h
@@ -0,0 +1,48 @@
+/*
+ * TI TILER driver internal shared definitions.
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#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/misc/tiler/tiler-geom.c b/drivers/misc/tiler/tiler-geom.c
new file mode 100644
index 0000000..df5fe2c
--- /dev/null
+++ b/drivers/misc/tiler/tiler-geom.c
@@ -0,0 +1,362 @@
+/*
+ * TILER geometry functions for TI TILER hardware block.
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#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)
+ view->tsptr += (view->width - 1) * view->h_inc;
+ if (flip_y)
+ view->tsptr += (view->height - 1) * view->v_inc;
+
+ /* flip view orientation */
+ if (orient & MASK_XY_FLIP)
+ swap(flip_x, flip_y);
+
+ if (flip_x)
+ orient ^= MASK_X_INVERT;
+ if (flip_y)
+ orient ^= MASK_Y_INVERT;
+
+ /* 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.7.0.4
^ permalink raw reply related [flat|nested] 22+ messages in thread* [RFC v2 6/8] TILER-DMM: Geometry and view manipulation functions
2010-11-30 19:58 ` [RFC v2 6/8] TILER-DMM: Geometry and view manipulation functions David Sin
@ 2010-12-01 0:55 ` Greg KH
0 siblings, 0 replies; 22+ messages in thread
From: Greg KH @ 2010-12-01 0:55 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, Nov 30, 2010 at 01:58:57PM -0600, David Sin wrote:
> 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/misc/tiler/_tiler.h | 48 +++++
Ick, no, just name it "tiler.h" please. There should not be any need to
put _ in front of a .h file.
> +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);
Don't cause the kernel to crash within a driver for no good reason like
this. Please fix these to WARN_ON if it's really something that can
happen.
If not, then just remove it.
> +
> + return geom[fmt].bpp;
> +}
> +EXPORT_SYMBOL(tiler_bpp);
EXPORT_SYMBOL_GPL() perhaps for all of these?
thanks,
greg k-h
^ permalink raw reply [flat|nested] 22+ messages in thread
* [RFC v2 7/8] TILER-DMM: Main TILER driver implementation
2010-11-30 19:58 [RFC v2 0/8] TI DMM-TILER driver David Sin
` (5 preceding siblings ...)
2010-11-30 19:58 ` [RFC v2 6/8] TILER-DMM: Geometry and view manipulation functions David Sin
@ 2010-11-30 19:58 ` David Sin
2010-11-30 19:57 ` Randy Dunlap
2010-11-30 19:58 ` [RFC v2 8/8] TILER-DMM: Linking TILER driver into the Linux kernel build David Sin
2010-12-01 6:47 ` [RFC v2 0/8] TI DMM-TILER driver Varadarajan, Charulatha
8 siblings, 1 reply; 22+ messages in thread
From: David Sin @ 2010-11-30 19:58 UTC (permalink / raw)
To: linux-arm-kernel
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>
---
arch/arm/mach-omap2/Makefile | 1 +
drivers/misc/tiler/Kconfig | 72 +++++++
drivers/misc/tiler/Makefile | 7 +
drivers/misc/tiler/tiler-iface.c | 66 ++++++
drivers/misc/tiler/tiler-main.c | 405 ++++++++++++++++++++++++++++++++++++++
5 files changed, 551 insertions(+), 0 deletions(-)
create mode 100644 drivers/misc/tiler/Kconfig
create mode 100644 drivers/misc/tiler/Makefile
create mode 100644 drivers/misc/tiler/tiler-iface.c
create mode 100644 drivers/misc/tiler/tiler-main.c
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index ebd2589..d55e29c 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -183,3 +183,4 @@ obj-y += $(nand-m) $(nand-y)
smc91x-$(CONFIG_SMC91X) := gpmc-smc91x.o
obj-y += $(smc91x-m) $(smc91x-y)
obj-$(CONFIG_ARCH_OMAP4) += hwspinlocks.o
+obj-$(CONFIG_ARCH_OMAP4) += dmm-omap44xx.o
diff --git a/drivers/misc/tiler/Kconfig b/drivers/misc/tiler/Kconfig
new file mode 100644
index 0000000..9b8bfed
--- /dev/null
+++ b/drivers/misc/tiler/Kconfig
@@ -0,0 +1,72 @@
+config HAVE_TI_DMM
+ bool
+ default y
+ depends on ARCH_OMAP4
+
+menuconfig TI_DMM
+ tristate "TI DMM support"
+ default y
+ depends on HAVE_TI_DMM
+ help
+ DMM driver for TI chips.
+
+menuconfig TI_TILER
+ tristate "TI TILER support"
+ default y
+ depends on TI_DMM
+ help
+ TILER driver for TI chips. The TI TILER device
+ enables video rotation on certain TI chips such as OMAP4 or
+ TI816x. 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/misc/tiler/Makefile b/drivers/misc/tiler/Makefile
new file mode 100644
index 0000000..7dbc828
--- /dev/null
+++ b/drivers/misc/tiler/Makefile
@@ -0,0 +1,7 @@
+obj-$(CONFIG_TI_DMM) += dmm.o
+dmm-objs = dmm-main.o
+
+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
diff --git a/drivers/misc/tiler/tiler-iface.c b/drivers/misc/tiler/tiler-iface.c
new file mode 100644
index 0000000..3c64c00
--- /dev/null
+++ b/drivers/misc/tiler/tiler-iface.c
@@ -0,0 +1,66 @@
+/*
+ * TILER driver interace functions for TI TILER hardware block.
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/mm_types.h>
+#include <asm/mach/map.h>
+
+#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);
+
diff --git a/drivers/misc/tiler/tiler-main.c b/drivers/misc/tiler/tiler-main.c
new file mode 100644
index 0000000..64bcdd0
--- /dev/null
+++ b/drivers/misc/tiler/tiler-main.c
@@ -0,0 +1,405 @@
+/*
+ * TILER driver main support functions for TI TILER hardware block.
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/errno.h>
+#include <linux/mutex.h>
+#include <linux/dma-mapping.h>
+#include <linux/pagemap.h>
+#include <linux/slab.h>
+
+#include <mach/dmm.h>
+#include "tmm.h"
+#include "_tiler.h"
+#include "tcm/tcm-sita.h"
+
+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)");
+
+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 */
+};
+
+/*
+ * TILER Memory Manager (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 __analyze_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 (__analyze_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;
+
+ /* 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 = 0;
+ 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_KERNEL);
+ 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;
+ }
+
+ 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. TILER Memory Manager (TMM)
+ * is unique per TILER Container Manager (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);
+}
+
+/*
+ * 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.7.0.4
^ permalink raw reply related [flat|nested] 22+ messages in thread* [RFC v2 7/8] TILER-DMM: Main TILER driver implementation
2010-11-30 19:58 ` [RFC v2 7/8] TILER-DMM: Main TILER driver implementation David Sin
@ 2010-11-30 19:57 ` Randy Dunlap
0 siblings, 0 replies; 22+ messages in thread
From: Randy Dunlap @ 2010-11-30 19:57 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, 30 Nov 2010 13:58:58 -0600 David Sin wrote:
> 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>
> ---
> arch/arm/mach-omap2/Makefile | 1 +
> drivers/misc/tiler/Kconfig | 72 +++++++
> drivers/misc/tiler/Makefile | 7 +
> drivers/misc/tiler/tiler-iface.c | 66 ++++++
> drivers/misc/tiler/tiler-main.c | 405 ++++++++++++++++++++++++++++++++++++++
> 5 files changed, 551 insertions(+), 0 deletions(-)
> create mode 100644 drivers/misc/tiler/Kconfig
> create mode 100644 drivers/misc/tiler/Makefile
> create mode 100644 drivers/misc/tiler/tiler-iface.c
> create mode 100644 drivers/misc/tiler/tiler-main.c
> diff --git a/drivers/misc/tiler/Kconfig b/drivers/misc/tiler/Kconfig
> new file mode 100644
> index 0000000..9b8bfed
> --- /dev/null
> +++ b/drivers/misc/tiler/Kconfig
> @@ -0,0 +1,72 @@
> +config HAVE_TI_DMM
> + bool
> + default y
> + depends on ARCH_OMAP4
> +
> +menuconfig TI_DMM
> + tristate "TI DMM support"
> + default y
> + depends on HAVE_TI_DMM
> + help
> + DMM driver for TI chips.
> +
> +menuconfig TI_TILER
> + tristate "TI TILER support"
> + default y
> + depends on TI_DMM
> + help
> + TILER driver for TI chips. The TI TILER device
> + enables video rotation on certain TI chips such as OMAP4 or
> + TI816x. Video rotation will be limited without TILER support.
> +
> +config TILER_GRANULARITY
> + int "Allocation granularity (2^n)"
Having (2^n) in the prompt makes me think that the value set here is "n",
but that's not the case. I suggest removing (2^n) here...
> + 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
and changing 2^n here to just say:
Must be a power of 2 in the range of 1 to 4096; however, ...
and then same 2 comments again repeated below.
> + 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.
---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***
^ permalink raw reply [flat|nested] 22+ messages in thread
* [RFC v2 8/8] TILER-DMM: Linking TILER driver into the Linux kernel build
2010-11-30 19:58 [RFC v2 0/8] TI DMM-TILER driver David Sin
` (6 preceding siblings ...)
2010-11-30 19:58 ` [RFC v2 7/8] TILER-DMM: Main TILER driver implementation David Sin
@ 2010-11-30 19:58 ` David Sin
2010-12-01 0:56 ` Greg KH
2010-12-01 6:47 ` [RFC v2 0/8] TI DMM-TILER driver Varadarajan, Charulatha
8 siblings, 1 reply; 22+ messages in thread
From: David Sin @ 2010-11-30 19:58 UTC (permalink / raw)
To: linux-arm-kernel
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/misc/Kconfig | 5 +++++
drivers/misc/Makefile | 1 +
2 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index ac6d6ac..fff7927 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -378,4 +378,9 @@ source "drivers/misc/eeprom/Kconfig"
source "drivers/misc/cb710/Kconfig"
source "drivers/misc/iwmc3200top/Kconfig"
+#
+# TI TILER driver support
+#
+source "drivers/misc/tiler/Kconfig"
+
endif # MISC_DEVICES
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index bf6f0e0..9985a6f 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -33,3 +33,4 @@ obj-y += eeprom/
obj-y += cb710/
obj-$(CONFIG_VMWARE_BALLOON) += vmware_balloon.o
obj-$(CONFIG_SENSORS_BH1780) += bh1780gli.o
+obj-$(CONFIG_TI_TILER) += tiler/
--
1.7.0.4
^ permalink raw reply related [flat|nested] 22+ messages in thread* [RFC v2 8/8] TILER-DMM: Linking TILER driver into the Linux kernel build
2010-11-30 19:58 ` [RFC v2 8/8] TILER-DMM: Linking TILER driver into the Linux kernel build David Sin
@ 2010-12-01 0:56 ` Greg KH
2010-12-02 13:46 ` David Sin
0 siblings, 1 reply; 22+ messages in thread
From: Greg KH @ 2010-12-01 0:56 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, Nov 30, 2010 at 01:58:59PM -0600, David Sin wrote:
> 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/misc/Kconfig | 5 +++++
> drivers/misc/Makefile | 1 +
> 2 files changed, 6 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
> index ac6d6ac..fff7927 100644
> --- a/drivers/misc/Kconfig
> +++ b/drivers/misc/Kconfig
> @@ -378,4 +378,9 @@ source "drivers/misc/eeprom/Kconfig"
> source "drivers/misc/cb710/Kconfig"
> source "drivers/misc/iwmc3200top/Kconfig"
>
> +#
> +# TI TILER driver support
> +#
Comments not needed.
thanks,
greg k-h
^ permalink raw reply [flat|nested] 22+ messages in thread
* [RFC v2 8/8] TILER-DMM: Linking TILER driver into the Linux kernel build
2010-12-01 0:56 ` Greg KH
@ 2010-12-02 13:46 ` David Sin
0 siblings, 0 replies; 22+ messages in thread
From: David Sin @ 2010-12-02 13:46 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, Nov 30, 2010 at 04:56:47PM -0800, Greg KH wrote:
> On Tue, Nov 30, 2010 at 01:58:59PM -0600, David Sin wrote:
> > 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/misc/Kconfig | 5 +++++
> > drivers/misc/Makefile | 1 +
> > 2 files changed, 6 insertions(+), 0 deletions(-)
> >
> > diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
> > index ac6d6ac..fff7927 100644
> > --- a/drivers/misc/Kconfig
> > +++ b/drivers/misc/Kconfig
> > @@ -378,4 +378,9 @@ source "drivers/misc/eeprom/Kconfig"
> > source "drivers/misc/cb710/Kconfig"
> > source "drivers/misc/iwmc3200top/Kconfig"
> >
> > +#
> > +# TI TILER driver support
> > +#
>
> Comments not needed.
>
> thanks,
>
> greg k-h
thanks, Greg, for the comments. I will make all of these changes
in the next revision.
--
David Sin
^ permalink raw reply [flat|nested] 22+ messages in thread
* [RFC v2 0/8] TI DMM-TILER driver
2010-11-30 19:58 [RFC v2 0/8] TI DMM-TILER driver David Sin
` (7 preceding siblings ...)
2010-11-30 19:58 ` [RFC v2 8/8] TILER-DMM: Linking TILER driver into the Linux kernel build David Sin
@ 2010-12-01 6:47 ` Varadarajan, Charulatha
2010-12-02 13:52 ` David Sin
8 siblings, 1 reply; 22+ messages in thread
From: Varadarajan, Charulatha @ 2010-12-01 6:47 UTC (permalink / raw)
To: linux-arm-kernel
On Wed, Dec 1, 2010 at 01:28, David Sin <davidsin@ti.com> wrote:
> Tiling and Isometric Lightweight Engine for Rotation (TILER) driver
>
> Dynamic Memory Manager (DMM) is a hardware block made by Texas Instruments.
> Within the DMM exists at least one TILER hardware component. ?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 component 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).
>
> Changes made from RFC v1: http://www.spinics.net/lists/linux-omap/msg33867.html
>
> Santosh Shilimkar:
> 1) Correct documentation location
> 2) Remove ioremap of RAM
> 3) Implement probe function and hwmod
> 4) Correct commenting style
> 5) Reduce use of barrier instances
>
> Linus Walleij:
> 1) Define TCM acryonym
>
> Russell King:
> 1) Implement probe function
> 2) Fix spelling mistake
> 3) Remove GFP_ATOMIC flag when calling dma_alloc_coherent for PAT array mem
> 4) Replace alloc_page and flush range calls with dma_alloc_coherent
>
> Nishanth Menon:
> 1) Address infinite while loop when reading dmm register
>
> Benoit Cousson:
> 1) Fix source file headers
> 2) Correct logical errors in device file
>
> Kevin Hilman:
> 1) Move DMM/TILER source code into driver/misc/tiler until a recommendation
> is made as to where it should go
>
> List of pending items in proposed order:
>
> * Determine driver source code location
> ?(Currently, resides in drivers/misc/tiler)
> * 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 (SiTA)
>
> ?Documentation/arm/OMAP/TILER ? ? ? ? ? ? | ?126 +++++++++
> ?arch/arm/mach-omap2/Makefile ? ? ? ? ? ? | ? ?1 +
> ?arch/arm/mach-omap2/dmm-omap44xx.c ? ? ? | ? 81 ++++++
> ?arch/arm/mach-omap2/include/mach/dmm.h ? | ? 92 +++++++
> ?arch/arm/mach-omap2/include/mach/tiler.h | ?173 ++++++++++++
> ?drivers/misc/Kconfig ? ? ? ? ? ? ? ? ? ? | ? ?5 +
> ?drivers/misc/Makefile ? ? ? ? ? ? ? ? ? ?| ? ?1 +
> ?drivers/misc/tiler/Kconfig ? ? ? ? ? ? ? | ? 72 +++++
> ?drivers/misc/tiler/Makefile ? ? ? ? ? ? ?| ? ?7 +
> ?drivers/misc/tiler/_tiler.h ? ? ? ? ? ? ?| ? 48 ++++
> ?drivers/misc/tiler/dmm-main.c ? ? ? ? ? ?| ?187 +++++++++++++
> ?drivers/misc/tiler/tcm.h ? ? ? ? ? ? ? ? | ?171 ++++++++++++
> ?drivers/misc/tiler/tcm/Makefile ? ? ? ? ?| ? ?1 +
> ?drivers/misc/tiler/tcm/_tcm-sita.h ? ? ? | ? 61 +++++
> ?drivers/misc/tiler/tcm/tcm-sita.c ? ? ? ?| ?422 ++++++++++++++++++++++++++++++
> ?drivers/misc/tiler/tcm/tcm-sita.h ? ? ? ?| ? 28 ++
> ?drivers/misc/tiler/tcm/tcm-utils.h ? ? ? | ? 51 ++++
> ?drivers/misc/tiler/tiler-geom.c ? ? ? ? ?| ?362 +++++++++++++++++++++++++
> ?drivers/misc/tiler/tiler-iface.c ? ? ? ? | ? 66 +++++
> ?drivers/misc/tiler/tiler-main.c ? ? ? ? ?| ?405 ++++++++++++++++++++++++++++
> ?drivers/misc/tiler/tmm-pat.c ? ? ? ? ? ? | ?266 +++++++++++++++++++
> ?drivers/misc/tiler/tmm.h ? ? ? ? ? ? ? ? | ?103 ++++++++
> ?22 files changed, 2729 insertions(+), 0 deletions(-)
> ?create mode 100644 Documentation/arm/OMAP/TILER
> ?create mode 100644 arch/arm/mach-omap2/dmm-omap44xx.c
> ?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/misc/tiler/Kconfig
> ?create mode 100644 drivers/misc/tiler/Makefile
> ?create mode 100644 drivers/misc/tiler/_tiler.h
> ?create mode 100644 drivers/misc/tiler/dmm-main.c
> ?create mode 100644 drivers/misc/tiler/tcm.h
> ?create mode 100644 drivers/misc/tiler/tcm/Makefile
> ?create mode 100644 drivers/misc/tiler/tcm/_tcm-sita.h
> ?create mode 100644 drivers/misc/tiler/tcm/tcm-sita.c
> ?create mode 100644 drivers/misc/tiler/tcm/tcm-sita.h
> ?create mode 100644 drivers/misc/tiler/tcm/tcm-utils.h
> ?create mode 100644 drivers/misc/tiler/tiler-geom.c
> ?create mode 100644 drivers/misc/tiler/tiler-iface.c
> ?create mode 100644 drivers/misc/tiler/tiler-main.c
> ?create mode 100644 drivers/misc/tiler/tmm-pat.c
> ?create mode 100644 drivers/misc/tiler/tmm.h
The dmm driver is making use of omap_hwmod fw. But I could not see a patch
to add dmm hwmod data to omap4 hwmod base in this series. Is this patch series
tested?
^ permalink raw reply [flat|nested] 22+ messages in thread