diff options
Diffstat (limited to 'drivers/media/video/tiler/dmm.c')
| -rw-r--r-- | drivers/media/video/tiler/dmm.c | 211 |
1 files changed, 54 insertions, 157 deletions
diff --git a/drivers/media/video/tiler/dmm.c b/drivers/media/video/tiler/dmm.c index 8663b36a5e7..685a1935a7f 100644 --- a/drivers/media/video/tiler/dmm.c +++ b/drivers/media/video/tiler/dmm.c | |||
| @@ -3,6 +3,9 @@ | |||
| 3 | * | 3 | * |
| 4 | * DMM driver support functions for TI OMAP processors. | 4 | * DMM driver support functions for TI OMAP processors. |
| 5 | * | 5 | * |
| 6 | * Authors: David Sin <davidsin@ti.com> | ||
| 7 | * Lajos Molnar <molnar@ti.com> | ||
| 8 | * | ||
| 6 | * Copyright (C) 2009-2010 Texas Instruments, Inc. | 9 | * Copyright (C) 2009-2010 Texas Instruments, Inc. |
| 7 | * | 10 | * |
| 8 | * This package is free software; you can redistribute it and/or modify | 11 | * This package is free software; you can redistribute it and/or modify |
| @@ -16,10 +19,6 @@ | |||
| 16 | 19 | ||
| 17 | #include <linux/init.h> | 20 | #include <linux/init.h> |
| 18 | #include <linux/module.h> | 21 | #include <linux/module.h> |
| 19 | #include <linux/cdev.h> /* struct cdev */ | ||
| 20 | #include <linux/kdev_t.h> /* MKDEV() */ | ||
| 21 | #include <linux/fs.h> /* register_chrdev_region() */ | ||
| 22 | #include <linux/device.h> /* struct class */ | ||
| 23 | #include <linux/platform_device.h> /* platform_device() */ | 22 | #include <linux/platform_device.h> /* platform_device() */ |
| 24 | #include <linux/err.h> /* IS_ERR() */ | 23 | #include <linux/err.h> /* IS_ERR() */ |
| 25 | #include <linux/io.h> /* ioremap() */ | 24 | #include <linux/io.h> /* ioremap() */ |
| @@ -29,10 +28,10 @@ | |||
| 29 | #include <mach/dmm.h> | 28 | #include <mach/dmm.h> |
| 30 | 29 | ||
| 31 | #undef __DEBUG__ | 30 | #undef __DEBUG__ |
| 32 | #define BITS_32(in_NbBits) ((((u32)1 << in_NbBits) - 1) | ((u32)1 << in_NbBits)) | 31 | |
| 33 | #define BITFIELD_32(in_UpBit, in_LowBit)\ | 32 | #define MASK(msb, lsb) (((1 << ((msb) + 1 - (lsb))) - 1) << (lsb)) |
| 34 | (BITS_32(in_UpBit) & ~((BITS_32(in_LowBit)) >> 1)) | 33 | #define SET_FLD(reg, msb, lsb, val) \ |
| 35 | #define BF BITFIELD_32 | 34 | (((reg) & ~MASK((msb), (lsb))) | (((val) << (lsb)) & MASK((msb), (lsb)))) |
| 36 | 35 | ||
| 37 | #ifdef __DEBUG__ | 36 | #ifdef __DEBUG__ |
| 38 | #define DEBUG(x, y) printk(KERN_NOTICE "%s()::%d:%s=(0x%08x)\n", \ | 37 | #define DEBUG(x, y) printk(KERN_NOTICE "%s()::%d:%s=(0x%08x)\n", \ |
| @@ -41,16 +40,6 @@ | |||
| 41 | #define DEBUG(x, y) | 40 | #define DEBUG(x, y) |
| 42 | #endif | 41 | #endif |
| 43 | 42 | ||
| 44 | static s32 dmm_major; | ||
| 45 | static s32 dmm_minor; | ||
| 46 | |||
| 47 | struct dmm_dev { | ||
| 48 | struct cdev cdev; | ||
| 49 | }; | ||
| 50 | |||
| 51 | static struct dmm_dev *dmm_device; | ||
| 52 | static struct class *dmmdev_class; | ||
| 53 | |||
| 54 | static struct platform_driver dmm_driver_ldm = { | 43 | static struct platform_driver dmm_driver_ldm = { |
| 55 | .driver = { | 44 | .driver = { |
| 56 | .owner = THIS_MODULE, | 45 | .owner = THIS_MODULE, |
| @@ -63,18 +52,15 @@ static struct platform_driver dmm_driver_ldm = { | |||
| 63 | 52 | ||
| 64 | s32 dmm_pat_refill(struct dmm *dmm, struct pat *pd, enum pat_mode mode) | 53 | s32 dmm_pat_refill(struct dmm *dmm, struct pat *pd, enum pat_mode mode) |
| 65 | { | 54 | { |
| 66 | void __iomem *r = NULL; | 55 | void __iomem *r; |
| 67 | u32 v = -1, w = -1; | 56 | u32 v; |
| 68 | 57 | ||
| 69 | /* Only manual refill supported */ | 58 | /* Only manual refill supported */ |
| 70 | if (mode != MANUAL) | 59 | if (mode != MANUAL) |
| 71 | return -EFAULT; | 60 | return -EFAULT; |
| 72 | 61 | ||
| 73 | /* | 62 | /* Check that the DMM_PAT_STATUS register has not reported an error */ |
| 74 | * Check that the DMM_PAT_STATUS register | 63 | r = dmm->base + DMM_PAT_STATUS__0; |
| 75 | * has not reported an error. | ||
| 76 | */ | ||
| 77 | r = (void __iomem *)((u32)dmm->base | DMM_PAT_STATUS__0); | ||
| 78 | v = __raw_readl(r); | 64 | v = __raw_readl(r); |
| 79 | if ((v & 0xFC00) != 0) { | 65 | if ((v & 0xFC00) != 0) { |
| 80 | while (1) | 66 | while (1) |
| @@ -82,28 +68,19 @@ s32 dmm_pat_refill(struct dmm *dmm, struct pat *pd, enum pat_mode mode) | |||
| 82 | } | 68 | } |
| 83 | 69 | ||
| 84 | /* Set "next" register to NULL */ | 70 | /* Set "next" register to NULL */ |
| 85 | r = (void __iomem *)((u32)dmm->base | DMM_PAT_DESCR__0); | 71 | r = dmm->base + DMM_PAT_DESCR__0; |
| 86 | v = __raw_readl(r); | 72 | v = __raw_readl(r); |
| 87 | w = (v & (~(BF(31, 4)))) | ((((u32)NULL) << 4) & BF(31, 4)); | 73 | v = SET_FLD(v, 31, 4, (u32) NULL); |
| 88 | __raw_writel(w, r); | 74 | __raw_writel(v, r); |
| 89 | 75 | ||
| 90 | /* Set area to be refilled */ | 76 | /* Set area to be refilled */ |
| 91 | r = (void __iomem *)((u32)dmm->base | DMM_PAT_AREA__0); | 77 | r = dmm->base + DMM_PAT_AREA__0; |
| 92 | v = __raw_readl(r); | ||
| 93 | w = (v & (~(BF(30, 24)))) | ((((s8)pd->area.y1) << 24) & BF(30, 24)); | ||
| 94 | __raw_writel(w, r); | ||
| 95 | |||
| 96 | v = __raw_readl(r); | ||
| 97 | w = (v & (~(BF(23, 16)))) | ((((s8)pd->area.x1) << 16) & BF(23, 16)); | ||
| 98 | __raw_writel(w, r); | ||
| 99 | |||
| 100 | v = __raw_readl(r); | ||
| 101 | w = (v & (~(BF(14, 8)))) | ((((s8)pd->area.y0) << 8) & BF(14, 8)); | ||
| 102 | __raw_writel(w, r); | ||
| 103 | |||
| 104 | v = __raw_readl(r); | 78 | v = __raw_readl(r); |
| 105 | w = (v & (~(BF(7, 0)))) | ((((s8)pd->area.x0) << 0) & BF(7, 0)); | 79 | v = SET_FLD(v, 30, 24, pd->area.y1); |
| 106 | __raw_writel(w, r); | 80 | v = SET_FLD(v, 23, 16, pd->area.x1); |
| 81 | v = SET_FLD(v, 14, 8, pd->area.y0); | ||
| 82 | v = SET_FLD(v, 7, 0, pd->area.x0); | ||
| 83 | __raw_writel(v, r); | ||
| 107 | wmb(); | 84 | wmb(); |
| 108 | 85 | ||
| 109 | #ifdef __DEBUG__ | 86 | #ifdef __DEBUG__ |
| @@ -115,92 +92,71 @@ s32 dmm_pat_refill(struct dmm *dmm, struct pat *pd, enum pat_mode mode) | |||
| 115 | #endif | 92 | #endif |
| 116 | 93 | ||
| 117 | /* First, clear the DMM_PAT_IRQSTATUS register */ | 94 | /* First, clear the DMM_PAT_IRQSTATUS register */ |
| 118 | r = (void __iomem *)((u32)dmm->base | (u32)DMM_PAT_IRQSTATUS); | 95 | r = dmm->base + DMM_PAT_IRQSTATUS; |
| 119 | __raw_writel(0xFFFFFFFF, r); | 96 | __raw_writel(0xFFFFFFFF, r); |
| 120 | wmb(); | 97 | wmb(); |
| 121 | 98 | ||
| 122 | r = (void __iomem *)((u32)dmm->base | (u32)DMM_PAT_IRQSTATUS_RAW); | 99 | r = dmm->base + DMM_PAT_IRQSTATUS_RAW; |
| 123 | v = 0xFFFFFFFF; | 100 | do { |
| 124 | |||
| 125 | while (v != 0x0) { | ||
| 126 | v = __raw_readl(r); | 101 | v = __raw_readl(r); |
| 127 | DEBUG("DMM_PAT_IRQSTATUS_RAW", v); | 102 | DEBUG("DMM_PAT_IRQSTATUS_RAW", v); |
| 128 | } | 103 | } while (v != 0x0); |
| 129 | 104 | ||
| 130 | /* Fill data register */ | 105 | /* Fill data register */ |
| 131 | r = (void __iomem *)((u32)dmm->base | DMM_PAT_DATA__0); | 106 | r = dmm->base + DMM_PAT_DATA__0; |
| 132 | v = __raw_readl(r); | 107 | v = __raw_readl(r); |
| 133 | 108 | ||
| 134 | /* Apply 4 bit left shft to counter the 4 bit right shift */ | 109 | /* pd->data must be 16 aligned */ |
| 135 | w = (v & (~(BF(31, 4)))) | ((((u32)(pd->data >> 4)) << 4) & BF(31, 4)); | 110 | BUG_ON(pd->data & 15); |
| 136 | __raw_writel(w, r); | 111 | v = SET_FLD(v, 31, 4, pd->data >> 4); |
| 112 | __raw_writel(v, r); | ||
| 137 | wmb(); | 113 | wmb(); |
| 138 | 114 | ||
| 139 | /* Read back PAT_DATA__0 to see if write was successful */ | 115 | /* Read back PAT_DATA__0 to see if write was successful */ |
| 140 | v = 0x0; | 116 | do { |
| 141 | while (v != pd->data) { | ||
| 142 | v = __raw_readl(r); | 117 | v = __raw_readl(r); |
| 143 | DEBUG("DMM_PAT_DATA__0", v); | 118 | DEBUG("DMM_PAT_DATA__0", v); |
| 144 | } | 119 | } while (v != pd->data); |
| 145 | |||
| 146 | r = (void __iomem *)((u32)dmm->base | (u32)DMM_PAT_CTRL__0); | ||
| 147 | v = __raw_readl(r); | ||
| 148 | |||
| 149 | w = (v & (~(BF(31, 28)))) | ((((u32)pd->ctrl.ini) << 28) & BF(31, 28)); | ||
| 150 | __raw_writel(w, r); | ||
| 151 | |||
| 152 | v = __raw_readl(r); | ||
| 153 | w = (v & (~(BF(16, 16)))) | ((((u32)pd->ctrl.sync) << 16) & BF(16, 16)); | ||
| 154 | __raw_writel(w, r); | ||
| 155 | |||
| 156 | v = __raw_readl(r); | ||
| 157 | w = (v & (~(BF(9, 8)))) | ((((u32)pd->ctrl.lut_id) << 8) & BF(9, 8)); | ||
| 158 | __raw_writel(w, r); | ||
| 159 | |||
| 160 | v = __raw_readl(r); | ||
| 161 | w = (v & (~(BF(6, 4)))) | ((((u32)pd->ctrl.dir) << 4) & BF(6, 4)); | ||
| 162 | __raw_writel(w, r); | ||
| 163 | 120 | ||
| 121 | r = dmm->base + DMM_PAT_CTRL__0; | ||
| 164 | v = __raw_readl(r); | 122 | v = __raw_readl(r); |
| 165 | w = (v & (~(BF(0, 0)))) | ((((u32)pd->ctrl.start) << 0) & BF(0, 0)); | 123 | v = SET_FLD(v, 31, 28, pd->ctrl.ini); |
| 166 | __raw_writel(w, r); | 124 | v = SET_FLD(v, 16, 16, pd->ctrl.sync); |
| 125 | v = SET_FLD(v, 9, 8, pd->ctrl.lut_id); | ||
| 126 | v = SET_FLD(v, 6, 4, pd->ctrl.dir); | ||
| 127 | v = SET_FLD(v, 0, 0, pd->ctrl.start); | ||
| 128 | __raw_writel(v, r); | ||
| 167 | wmb(); | 129 | wmb(); |
| 168 | 130 | ||
| 169 | /* | 131 | /* Check if PAT_IRQSTATUS_RAW is set after the PAT has been refilled */ |
| 170 | * Now, check if PAT_IRQSTATUS_RAW has been | 132 | r = dmm->base + DMM_PAT_IRQSTATUS_RAW; |
| 171 | * set after the PAT has been refilled | 133 | do { |
| 172 | */ | ||
| 173 | r = (void __iomem *)((u32)dmm->base | (u32)DMM_PAT_IRQSTATUS_RAW); | ||
| 174 | v = 0x0; | ||
| 175 | while ((v & 0x3) != 0x3) { | ||
| 176 | v = __raw_readl(r); | 134 | v = __raw_readl(r); |
| 177 | DEBUG("DMM_PAT_IRQSTATUS_RAW", v); | 135 | DEBUG("DMM_PAT_IRQSTATUS_RAW", v); |
| 178 | } | 136 | } while ((v & 0x3) != 0x3); |
| 179 | 137 | ||
| 180 | /* Again, clear the DMM_PAT_IRQSTATUS register */ | 138 | /* Again, clear the DMM_PAT_IRQSTATUS register */ |
| 181 | r = (void __iomem *)((u32)dmm->base | (u32)DMM_PAT_IRQSTATUS); | 139 | r = dmm->base + DMM_PAT_IRQSTATUS; |
| 182 | __raw_writel(0xFFFFFFFF, r); | 140 | __raw_writel(0xFFFFFFFF, r); |
| 183 | wmb(); | 141 | wmb(); |
| 184 | 142 | ||
| 185 | r = (void __iomem *)((u32)dmm->base | (u32)DMM_PAT_IRQSTATUS_RAW); | 143 | r = dmm->base + DMM_PAT_IRQSTATUS_RAW; |
| 186 | v = 0xFFFFFFFF; | 144 | do { |
| 187 | |||
| 188 | while (v != 0x0) { | ||
| 189 | v = __raw_readl(r); | 145 | v = __raw_readl(r); |
| 190 | DEBUG("DMM_PAT_IRQSTATUS_RAW", v); | 146 | DEBUG("DMM_PAT_IRQSTATUS_RAW", v); |
| 191 | } | 147 | } while (v != 0x0); |
| 192 | 148 | ||
| 193 | /* Again, set "next" register to NULL to clear any PAT STATUS errors */ | 149 | /* Again, set "next" register to NULL to clear any PAT STATUS errors */ |
| 194 | r = (void __iomem *)((u32)dmm->base | DMM_PAT_DESCR__0); | 150 | r = dmm->base + DMM_PAT_DESCR__0; |
| 195 | v = __raw_readl(r); | 151 | v = __raw_readl(r); |
| 196 | w = (v & (~(BF(31, 4)))) | ((((u32)NULL) << 4) & BF(31, 4)); | 152 | v = SET_FLD(v, 31, 4, (u32) NULL); |
| 197 | __raw_writel(w, r); | 153 | __raw_writel(v, r); |
| 198 | 154 | ||
| 199 | /* | 155 | /* |
| 200 | * Now, check that the DMM_PAT_STATUS register | 156 | * Now, check that the DMM_PAT_STATUS register |
| 201 | * has not reported an error before exiting. | 157 | * has not reported an error before exiting. |
| 202 | */ | 158 | */ |
| 203 | r = (void __iomem *)((u32)dmm->base | DMM_PAT_STATUS__0); | 159 | r = dmm->base + DMM_PAT_STATUS__0; |
| 204 | v = __raw_readl(r); | 160 | v = __raw_readl(r); |
| 205 | if ((v & 0xFC00) != 0) { | 161 | if ((v & 0xFC00) != 0) { |
| 206 | while (1) | 162 | while (1) |
| @@ -211,25 +167,10 @@ s32 dmm_pat_refill(struct dmm *dmm, struct pat *pd, enum pat_mode mode) | |||
| 211 | } | 167 | } |
| 212 | EXPORT_SYMBOL(dmm_pat_refill); | 168 | EXPORT_SYMBOL(dmm_pat_refill); |
| 213 | 169 | ||
| 214 | static s32 dmm_open(struct inode *ip, struct file *filp) | ||
| 215 | { | ||
| 216 | return 0; | ||
| 217 | } | ||
| 218 | |||
| 219 | static s32 dmm_release(struct inode *ip, struct file *filp) | ||
| 220 | { | ||
| 221 | return 0; | ||
| 222 | } | ||
| 223 | |||
| 224 | static const struct file_operations dmm_fops = { | ||
| 225 | .open = dmm_open, | ||
| 226 | .release = dmm_release, | ||
| 227 | }; | ||
| 228 | |||
| 229 | struct dmm *dmm_pat_init(u32 id) | 170 | struct dmm *dmm_pat_init(u32 id) |
| 230 | { | 171 | { |
| 231 | u32 base = 0; | 172 | u32 base; |
| 232 | struct dmm *dmm = NULL; | 173 | struct dmm *dmm; |
| 233 | switch (id) { | 174 | switch (id) { |
| 234 | case 0: | 175 | case 0: |
| 235 | /* only support id 0 for now */ | 176 | /* only support id 0 for now */ |
| @@ -276,60 +217,16 @@ EXPORT_SYMBOL(dmm_pat_release); | |||
| 276 | 217 | ||
| 277 | static s32 __init dmm_init(void) | 218 | static s32 __init dmm_init(void) |
| 278 | { | 219 | { |
| 279 | dev_t dev = 0; | 220 | return platform_driver_register(&dmm_driver_ldm); |
| 280 | s32 r = -1; | ||
| 281 | struct device *device = NULL; | ||
| 282 | |||
| 283 | if (dmm_major) { | ||
| 284 | dev = MKDEV(dmm_major, dmm_minor); | ||
| 285 | r = register_chrdev_region(dev, 1, "dmm"); | ||
| 286 | } else { | ||
| 287 | r = alloc_chrdev_region(&dev, dmm_minor, 1, "dmm"); | ||
| 288 | dmm_major = MAJOR(dev); | ||
| 289 | } | ||
| 290 | |||
| 291 | dmm_device = kmalloc(sizeof(*dmm_device), GFP_KERNEL); | ||
| 292 | if (!dmm_device) { | ||
| 293 | unregister_chrdev_region(dev, 1); | ||
| 294 | return -ENOMEM; | ||
| 295 | } | ||
| 296 | memset(dmm_device, 0x0, sizeof(struct dmm_dev)); | ||
| 297 | |||
| 298 | cdev_init(&dmm_device->cdev, &dmm_fops); | ||
| 299 | dmm_device->cdev.owner = THIS_MODULE; | ||
| 300 | dmm_device->cdev.ops = &dmm_fops; | ||
| 301 | |||
| 302 | r = cdev_add(&dmm_device->cdev, dev, 1); | ||
| 303 | if (r) | ||
| 304 | printk(KERN_ERR "cdev_add():failed\n"); | ||
| 305 | |||
| 306 | dmmdev_class = class_create(THIS_MODULE, "dmm"); | ||
| 307 | |||
| 308 | if (IS_ERR(dmmdev_class)) { | ||
| 309 | printk(KERN_ERR "class_create():failed\n"); | ||
| 310 | goto EXIT; | ||
| 311 | } | ||
| 312 | |||
| 313 | device = device_create(dmmdev_class, NULL, dev, NULL, "dmm"); | ||
| 314 | if (device == NULL) | ||
| 315 | printk(KERN_ERR "device_create() fail\n"); | ||
| 316 | |||
| 317 | r = platform_driver_register(&dmm_driver_ldm); | ||
| 318 | |||
| 319 | EXIT: | ||
| 320 | return r; | ||
| 321 | } | 221 | } |
| 322 | 222 | ||
| 323 | static void __exit dmm_exit(void) | 223 | static void __exit dmm_exit(void) |
| 324 | { | 224 | { |
| 325 | platform_driver_unregister(&dmm_driver_ldm); | 225 | platform_driver_unregister(&dmm_driver_ldm); |
| 326 | cdev_del(&dmm_device->cdev); | ||
| 327 | kfree(dmm_device); | ||
| 328 | device_destroy(dmmdev_class, MKDEV(dmm_major, dmm_minor)); | ||
| 329 | class_destroy(dmmdev_class); | ||
| 330 | } | 226 | } |
| 331 | 227 | ||
| 332 | MODULE_LICENSE("GPL v2"); | 228 | MODULE_LICENSE("GPL v2"); |
| 333 | MODULE_AUTHOR("davidsin@ti.com"); | 229 | MODULE_AUTHOR("davidsin@ti.com"); |
| 230 | MODULE_AUTHOR("molnar@ti.com"); | ||
| 334 | module_init(dmm_init); | 231 | module_init(dmm_init); |
| 335 | module_exit(dmm_exit); | 232 | module_exit(dmm_exit); |
