Commit 5c137797 authored by Andy Gross's avatar Andy Gross Committed by Greg Kroah-Hartman

staging: drm/omap: Get DMM resources from hwmod

This patch splits the DMM off into a separate sub-device, in order to
utilize the platform device information that was created as part of
the OMAP hwmod entry for the DMM.

The driver probe function queries the iomem resource and IRQ using
standard platform_get functions.

The OMAP DRM driver now calls the platform_driver_register() function
for the subordinate DMM driver inside its probe function.  This
guarantees the required order for the DMM and ensures the DMM resources
are available for use by the DRM driver.
Signed-off-by: default avatarAndy Gross <andy.gross@ti.com>
Signed-off-by: default avatarRob Clark <rob@ti.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 02646fb8
...@@ -34,6 +34,8 @@ ...@@ -34,6 +34,8 @@
#include "omap_dmm_tiler.h" #include "omap_dmm_tiler.h"
#include "omap_dmm_priv.h" #include "omap_dmm_priv.h"
#define DMM_DRIVER_NAME "dmm"
/* mappings for associating views to luts */ /* mappings for associating views to luts */
static struct tcm *containers[TILFMT_NFORMATS]; static struct tcm *containers[TILFMT_NFORMATS];
static struct dmm *omap_dmm; static struct dmm *omap_dmm;
...@@ -465,7 +467,12 @@ size_t tiler_vsize(enum tiler_fmt fmt, uint16_t w, uint16_t h) ...@@ -465,7 +467,12 @@ size_t tiler_vsize(enum tiler_fmt fmt, uint16_t w, uint16_t h)
return round_up(geom[fmt].cpp * w, PAGE_SIZE) * h; return round_up(geom[fmt].cpp * w, PAGE_SIZE) * h;
} }
int omap_dmm_remove(void) bool dmm_is_initialized(void)
{
return omap_dmm ? true : false;
}
static int omap_dmm_remove(struct platform_device *dev)
{ {
struct tiler_block *block, *_block; struct tiler_block *block, *_block;
int i; int i;
...@@ -499,40 +506,49 @@ int omap_dmm_remove(void) ...@@ -499,40 +506,49 @@ int omap_dmm_remove(void)
if (omap_dmm->irq != -1) if (omap_dmm->irq != -1)
free_irq(omap_dmm->irq, omap_dmm); free_irq(omap_dmm->irq, omap_dmm);
iounmap(omap_dmm->base);
kfree(omap_dmm); kfree(omap_dmm);
omap_dmm = NULL;
} }
return 0; return 0;
} }
int omap_dmm_init(struct drm_device *dev) static int omap_dmm_probe(struct platform_device *dev)
{ {
int ret = -EFAULT, i; int ret = -EFAULT, i;
struct tcm_area area = {0}; struct tcm_area area = {0};
u32 hwinfo, pat_geom, lut_table_size; u32 hwinfo, pat_geom, lut_table_size;
struct omap_drm_platform_data *pdata = dev->dev->platform_data; struct resource *mem;
if (!pdata || !pdata->dmm_pdata) {
dev_err(dev->dev, "dmm platform data not present, skipping\n");
return ret;
}
omap_dmm = kzalloc(sizeof(*omap_dmm), GFP_KERNEL); omap_dmm = kzalloc(sizeof(*omap_dmm), GFP_KERNEL);
if (!omap_dmm) { if (!omap_dmm) {
dev_err(dev->dev, "failed to allocate driver data section\n"); dev_err(&dev->dev, "failed to allocate driver data section\n");
goto fail; goto fail;
} }
/* lookup hwmod data - base address and irq */ /* lookup hwmod data - base address and irq */
omap_dmm->base = pdata->dmm_pdata->base; mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
omap_dmm->irq = pdata->dmm_pdata->irq; if (!mem) {
omap_dmm->dev = dev->dev; dev_err(&dev->dev, "failed to get base address resource\n");
goto fail;
}
omap_dmm->base = ioremap(mem->start, SZ_2K);
if (!omap_dmm->base) { if (!omap_dmm->base) {
dev_err(dev->dev, "failed to get dmm base address\n"); dev_err(&dev->dev, "failed to get dmm base address\n");
goto fail; goto fail;
} }
omap_dmm->irq = platform_get_irq(dev, 0);
if (omap_dmm->irq < 0) {
dev_err(&dev->dev, "failed to get IRQ resource\n");
goto fail;
}
omap_dmm->dev = &dev->dev;
hwinfo = readl(omap_dmm->base + DMM_PAT_HWINFO); hwinfo = readl(omap_dmm->base + DMM_PAT_HWINFO);
omap_dmm->num_engines = (hwinfo >> 24) & 0x1F; omap_dmm->num_engines = (hwinfo >> 24) & 0x1F;
omap_dmm->num_lut = (hwinfo >> 16) & 0x1F; omap_dmm->num_lut = (hwinfo >> 16) & 0x1F;
...@@ -556,7 +572,7 @@ int omap_dmm_init(struct drm_device *dev) ...@@ -556,7 +572,7 @@ int omap_dmm_init(struct drm_device *dev)
"omap_dmm_irq_handler", omap_dmm); "omap_dmm_irq_handler", omap_dmm);
if (ret) { if (ret) {
dev_err(dev->dev, "couldn't register IRQ %d, error %d\n", dev_err(&dev->dev, "couldn't register IRQ %d, error %d\n",
omap_dmm->irq, ret); omap_dmm->irq, ret);
omap_dmm->irq = -1; omap_dmm->irq = -1;
goto fail; goto fail;
...@@ -575,25 +591,30 @@ int omap_dmm_init(struct drm_device *dev) ...@@ -575,25 +591,30 @@ int omap_dmm_init(struct drm_device *dev)
omap_dmm->lut = vmalloc(lut_table_size * sizeof(*omap_dmm->lut)); omap_dmm->lut = vmalloc(lut_table_size * sizeof(*omap_dmm->lut));
if (!omap_dmm->lut) { if (!omap_dmm->lut) {
dev_err(dev->dev, "could not allocate lut table\n"); dev_err(&dev->dev, "could not allocate lut table\n");
ret = -ENOMEM; ret = -ENOMEM;
goto fail; goto fail;
} }
omap_dmm->dummy_page = alloc_page(GFP_KERNEL | __GFP_DMA32); omap_dmm->dummy_page = alloc_page(GFP_KERNEL | __GFP_DMA32);
if (!omap_dmm->dummy_page) { if (!omap_dmm->dummy_page) {
dev_err(dev->dev, "could not allocate dummy page\n"); dev_err(&dev->dev, "could not allocate dummy page\n");
ret = -ENOMEM; ret = -ENOMEM;
goto fail; goto fail;
} }
/* set dma mask for device */
/* NOTE: this is a workaround for the hwmod not initializing properly */
dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
omap_dmm->dummy_pa = page_to_phys(omap_dmm->dummy_page); omap_dmm->dummy_pa = page_to_phys(omap_dmm->dummy_page);
/* alloc refill memory */ /* alloc refill memory */
omap_dmm->refill_va = dma_alloc_coherent(dev->dev, omap_dmm->refill_va = dma_alloc_coherent(&dev->dev,
REFILL_BUFFER_SIZE * omap_dmm->num_engines, REFILL_BUFFER_SIZE * omap_dmm->num_engines,
&omap_dmm->refill_pa, GFP_KERNEL); &omap_dmm->refill_pa, GFP_KERNEL);
if (!omap_dmm->refill_va) { if (!omap_dmm->refill_va) {
dev_err(dev->dev, "could not allocate refill memory\n"); dev_err(&dev->dev, "could not allocate refill memory\n");
goto fail; goto fail;
} }
...@@ -602,7 +623,7 @@ int omap_dmm_init(struct drm_device *dev) ...@@ -602,7 +623,7 @@ int omap_dmm_init(struct drm_device *dev)
omap_dmm->num_engines * sizeof(struct refill_engine), omap_dmm->num_engines * sizeof(struct refill_engine),
GFP_KERNEL); GFP_KERNEL);
if (!omap_dmm->engines) { if (!omap_dmm->engines) {
dev_err(dev->dev, "could not allocate engines\n"); dev_err(&dev->dev, "could not allocate engines\n");
ret = -ENOMEM; ret = -ENOMEM;
goto fail; goto fail;
} }
...@@ -624,7 +645,7 @@ int omap_dmm_init(struct drm_device *dev) ...@@ -624,7 +645,7 @@ int omap_dmm_init(struct drm_device *dev)
omap_dmm->tcm = kzalloc(omap_dmm->num_lut * sizeof(*omap_dmm->tcm), omap_dmm->tcm = kzalloc(omap_dmm->num_lut * sizeof(*omap_dmm->tcm),
GFP_KERNEL); GFP_KERNEL);
if (!omap_dmm->tcm) { if (!omap_dmm->tcm) {
dev_err(dev->dev, "failed to allocate lut ptrs\n"); dev_err(&dev->dev, "failed to allocate lut ptrs\n");
ret = -ENOMEM; ret = -ENOMEM;
goto fail; goto fail;
} }
...@@ -636,7 +657,7 @@ int omap_dmm_init(struct drm_device *dev) ...@@ -636,7 +657,7 @@ int omap_dmm_init(struct drm_device *dev)
NULL); NULL);
if (!omap_dmm->tcm[i]) { if (!omap_dmm->tcm[i]) {
dev_err(dev->dev, "failed to allocate container\n"); dev_err(&dev->dev, "failed to allocate container\n");
ret = -ENOMEM; ret = -ENOMEM;
goto fail; goto fail;
} }
...@@ -676,7 +697,7 @@ int omap_dmm_init(struct drm_device *dev) ...@@ -676,7 +697,7 @@ int omap_dmm_init(struct drm_device *dev)
return 0; return 0;
fail: fail:
omap_dmm_remove(); omap_dmm_remove(dev);
return ret; return ret;
} }
...@@ -836,3 +857,17 @@ int tiler_map_show(struct seq_file *s, void *arg) ...@@ -836,3 +857,17 @@ int tiler_map_show(struct seq_file *s, void *arg)
return 0; return 0;
} }
#endif #endif
struct platform_driver omap_dmm_driver = {
.probe = omap_dmm_probe,
.remove = omap_dmm_remove,
.driver = {
.owner = THIS_MODULE,
.name = DMM_DRIVER_NAME,
},
};
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Andy Gross <andy.gross@ti.com>");
MODULE_DESCRIPTION("OMAP DMM/Tiler Driver");
MODULE_ALIAS("platform:" DMM_DRIVER_NAME);
...@@ -73,10 +73,6 @@ struct tiler_block { ...@@ -73,10 +73,6 @@ struct tiler_block {
#define TIL_ADDR(x, orient, a)\ #define TIL_ADDR(x, orient, a)\
((u32) (x) | (orient) | ((a) << SHIFT_ACC_MODE)) ((u32) (x) | (orient) | ((a) << SHIFT_ACC_MODE))
/* externally accessible functions */
int omap_dmm_init(struct drm_device *dev);
int omap_dmm_remove(void);
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
int tiler_map_show(struct seq_file *s, void *arg); int tiler_map_show(struct seq_file *s, void *arg);
#endif #endif
...@@ -98,7 +94,9 @@ uint32_t tiler_stride(enum tiler_fmt fmt); ...@@ -98,7 +94,9 @@ uint32_t tiler_stride(enum tiler_fmt fmt);
size_t tiler_size(enum tiler_fmt fmt, uint16_t w, uint16_t h); size_t tiler_size(enum tiler_fmt fmt, uint16_t w, uint16_t h);
size_t tiler_vsize(enum tiler_fmt fmt, uint16_t w, uint16_t h); size_t tiler_vsize(enum tiler_fmt fmt, uint16_t w, uint16_t h);
void tiler_align(enum tiler_fmt fmt, uint16_t *w, uint16_t *h); void tiler_align(enum tiler_fmt fmt, uint16_t *w, uint16_t *h);
bool dmm_is_initialized(void);
extern struct platform_driver omap_dmm_driver;
/* GEM bo flags -> tiler fmt */ /* GEM bo flags -> tiler fmt */
static inline enum tiler_fmt gem2fmt(uint32_t flags) static inline enum tiler_fmt gem2fmt(uint32_t flags)
...@@ -128,11 +126,6 @@ static inline bool validfmt(enum tiler_fmt fmt) ...@@ -128,11 +126,6 @@ static inline bool validfmt(enum tiler_fmt fmt)
} }
} }
struct omap_dmm_platform_data {
void __iomem *base;
int irq;
};
static inline int dmm_is_available(void) static inline int dmm_is_available(void)
{ {
return cpu_is_omap44xx(); return cpu_is_omap44xx();
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "drm_crtc_helper.h" #include "drm_crtc_helper.h"
#include "drm_fb_helper.h" #include "drm_fb_helper.h"
#include "omap_dmm_tiler.h"
#define DRIVER_NAME MODULE_NAME #define DRIVER_NAME MODULE_NAME
#define DRIVER_DESC "OMAP DRM" #define DRIVER_DESC "OMAP DRM"
...@@ -802,6 +803,9 @@ static void pdev_shutdown(struct platform_device *device) ...@@ -802,6 +803,9 @@ static void pdev_shutdown(struct platform_device *device)
static int pdev_probe(struct platform_device *device) static int pdev_probe(struct platform_device *device)
{ {
DBG("%s", device->name); DBG("%s", device->name);
if (platform_driver_register(&omap_dmm_driver))
dev_err(&device->dev, "DMM registration failed\n");
return drm_platform_init(&omap_drm_driver, device); return drm_platform_init(&omap_drm_driver, device);
} }
...@@ -809,6 +813,8 @@ static int pdev_remove(struct platform_device *device) ...@@ -809,6 +813,8 @@ static int pdev_remove(struct platform_device *device)
{ {
DBG(""); DBG("");
drm_platform_exit(&omap_drm_driver, device); drm_platform_exit(&omap_drm_driver, device);
platform_driver_unregister(&omap_dmm_driver);
return 0; return 0;
} }
......
...@@ -1238,12 +1238,11 @@ void omap_gem_init(struct drm_device *dev) ...@@ -1238,12 +1238,11 @@ void omap_gem_init(struct drm_device *dev)
const enum tiler_fmt fmts[] = { const enum tiler_fmt fmts[] = {
TILFMT_8BIT, TILFMT_16BIT, TILFMT_32BIT TILFMT_8BIT, TILFMT_16BIT, TILFMT_32BIT
}; };
int i, j, ret; int i, j;
ret = omap_dmm_init(dev); if (!dmm_is_initialized()) {
if (ret) {
/* DMM only supported on OMAP4 and later, so this isn't fatal */ /* DMM only supported on OMAP4 and later, so this isn't fatal */
dev_warn(dev->dev, "omap_dmm_init failed, disabling DMM\n"); dev_warn(dev->dev, "DMM not available, disable DMM support\n");
return; return;
} }
...@@ -1293,6 +1292,5 @@ void omap_gem_deinit(struct drm_device *dev) ...@@ -1293,6 +1292,5 @@ void omap_gem_deinit(struct drm_device *dev)
/* I believe we can rely on there being no more outstanding GEM /* I believe we can rely on there being no more outstanding GEM
* objects which could depend on usergart/dmm at this point. * objects which could depend on usergart/dmm at this point.
*/ */
omap_dmm_remove();
kfree(usergart); kfree(usergart);
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment