aboutsummaryrefslogtreecommitdiff
path: root/drivers/mfd
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/glamo/Kconfig22
-rw-r--r--drivers/mfd/glamo/glamo-cmdq.c145
-rw-r--r--drivers/mfd/glamo/glamo-cmdq.h3
-rw-r--r--drivers/mfd/glamo/glamo-drm-drv.c4
-rw-r--r--drivers/mfd/glamo/glamo-drm-private.h5
5 files changed, 113 insertions, 66 deletions
diff --git a/drivers/mfd/glamo/Kconfig b/drivers/mfd/glamo/Kconfig
index 3b942ab0a6d..7db45288c38 100644
--- a/drivers/mfd/glamo/Kconfig
+++ b/drivers/mfd/glamo/Kconfig
@@ -35,18 +35,20 @@ config MFD_GLAMO_FB_XGLAMO_WORKAROUND
If unsure, say N.
config MFD_GLAMO_SPI_GPIO
- tristate "Glamo GPIO SPI bitbang support"
- depends on MFD_GLAMO
- help
- Enable a bitbanging SPI adapter driver for the Smedia Glamo.
+ tristate "Glamo GPIO SPI bitbang support"
+ depends on MFD_GLAMO
+ select SPI_BITBANG
+
+ help
+ Enable a bitbanging SPI adapter driver for the Smedia Glamo.
config MFD_GLAMO_SPI_FB
- tristate "Glamo LCM control channel SPI support"
- depends on MFD_GLAMO_FB
- help
- Enable a bitbanging SPI adapter driver for the Smedia Glamo LCM
- control channel. This SPI interface is frequently used to
- interconnect the LCM control interface.
+ tristate "Glamo LCM control channel SPI support"
+ depends on MFD_GLAMO_FB
+ help
+ Enable a bitbanging SPI adapter driver for the Smedia Glamo LCM
+ control channel. This SPI interface is frequently used to
+ interconnect the LCM control interface.
config MFD_GLAMO_MCI
tristate "Glamo S3C SD/MMC Card Interface support"
diff --git a/drivers/mfd/glamo/glamo-cmdq.c b/drivers/mfd/glamo/glamo-cmdq.c
index bdae9859854..f2a124a6e18 100644
--- a/drivers/mfd/glamo/glamo-cmdq.c
+++ b/drivers/mfd/glamo/glamo-cmdq.c
@@ -2,6 +2,7 @@
* SMedia Glamo 336x/337x command queue handling
*
* Copyright (C) 2008-2009 Thomas White <taw@bitwiz.org.uk>
+ * Copyright (C) 2009 Andreas Pokorny <andreas.pokorny@gmail.com>
* Based on xf86-video-glamo (see below for details)
*
* All rights reserved.
@@ -49,7 +50,6 @@
* OF THIS SOFTWARE.
*/
-
#include <drm/drmP.h>
#include <drm/glamo_drm.h>
@@ -58,18 +58,40 @@
#include "glamo-regs.h"
-static void reg_write(struct glamodrm_handle *gdrm,
+static inline void reg_write(struct glamodrm_handle *gdrm,
u_int16_t reg, u_int16_t val)
{
iowrite16(val, gdrm->reg_base + reg);
}
-static u16 reg_read(struct glamodrm_handle *gdrm, u_int16_t reg)
+static inline u16 reg_read(struct glamodrm_handle *gdrm, u_int16_t reg)
{
return ioread16(gdrm->reg_base + reg);
}
+static u32 glamo_get_read(struct glamodrm_handle *gdrm)
+{
+ /* we could turn off clock here */
+ u32 ring_read = reg_read(gdrm, GLAMO_REG_CMDQ_READ_ADDRL);
+ ring_read |= ((reg_read(gdrm, GLAMO_REG_CMDQ_READ_ADDRH)
+ & 0x7) << 16);
+
+ return ring_read;
+}
+
+static u32 glamo_get_write(struct glamodrm_handle *gdrm)
+{
+ u32 ring_write = reg_read(gdrm, GLAMO_REG_CMDQ_WRITE_ADDRL);
+ ring_write |= ((reg_read(gdrm, GLAMO_REG_CMDQ_WRITE_ADDRH)
+ & 0x7) << 16);
+
+ return ring_write;
+}
+
+#if 0
+
+/* hopefully we will never need that again */
static void
glamo_cmdq_wait(struct glamodrm_handle *gdrm, enum glamo_engine engine)
@@ -118,6 +140,7 @@ glamo_cmdq_wait(struct glamodrm_handle *gdrm, enum glamo_engine engine)
ring_read);
}
}
+#endif
/* Add commands to the ring buffer */
@@ -127,8 +150,11 @@ static int glamo_add_to_ring(struct glamodrm_handle *gdrm, u16 *addr,
size_t ring_write, ring_read;
size_t new_ring_write;
- ring_write = reg_read(gdrm, GLAMO_REG_CMDQ_WRITE_ADDRL);
- ring_write |= (reg_read(gdrm, GLAMO_REG_CMDQ_WRITE_ADDRH) << 16);
+ printk( KERN_INFO "[glamo-drm] glamo add to ring %d bytes, ring_read: %d\n", count, glamo_get_read(gdrm));
+
+ up(&gdrm->add_to_ring);
+
+ ring_write = glamo_get_write(gdrm);
/* Calculate where we'll end up */
new_ring_write = (ring_write + count) % GLAMO_CMDQ_SIZE;
@@ -138,37 +164,28 @@ static int glamo_add_to_ring(struct glamodrm_handle *gdrm, u16 *addr,
/* Loop while the read pointer is between the old and new
* positions */
do {
- ring_read = reg_read(gdrm, GLAMO_REG_CMDQ_READ_ADDRL);
- ring_read |= ((reg_read(gdrm, GLAMO_REG_CMDQ_READ_ADDRH)
- & 0x7) << 16);
+ ring_read = glamo_get_read(gdrm);
} while (ring_read > ring_write && ring_read < new_ring_write);
- } else {
+ } else {
/* Same, but kind of inside-out */
do {
- ring_read = reg_read(gdrm, GLAMO_REG_CMDQ_READ_ADDRL);
- ring_read |= ((reg_read(gdrm, GLAMO_REG_CMDQ_READ_ADDRH)
- & 0x7) << 16);
+ ring_read = glamo_get_read(gdrm);
} while (ring_read > ring_write || ring_read < new_ring_write);
}
/* Are we about to wrap around? */
if (ring_write >= new_ring_write) {
- size_t rest_size;
- int i;
+ u32 rest_size;
printk(KERN_INFO "[glamo-drm] CmdQ wrap-around...\n");
/* Wrap around */
rest_size = GLAMO_CMDQ_SIZE - ring_write; /* Space left */
/* Write from current position to end */
- for ( i=0; i<rest_size; i++ ) {
- iowrite16(*(addr+i), gdrm->cmdq_base+ring_write+(i*2));
- }
+ memcpy_toio(gdrm->cmdq_base+ring_write, addr, rest_size);
/* Write from start */
- for ( i=0; i<(count-rest_size); i++ ) {
- iowrite16(*(addr+rest_size+i), gdrm->cmdq_base+(i*2));
- }
+ memcpy_toio(gdrm->cmdq_base, addr+(rest_size>>1), count - rest_size);
/* ring_write being 0 will result in a deadlock because the
* cmdq read will never stop. To avoid such an behaviour insert
@@ -181,7 +198,7 @@ static int glamo_add_to_ring(struct glamodrm_handle *gdrm, u16 *addr,
/* Suppose we just filled the WHOLE ring buffer, and so the
* write position ends up in the same place as it started.
- * No change in pointer means no activity from the command
+ * No change in poginter means no activity from the command
* queue engine. So, insert a no-op */
if (ring_write == new_ring_write) {
iowrite16(0x0000, gdrm->cmdq_base + new_ring_write);
@@ -191,32 +208,26 @@ static int glamo_add_to_ring(struct glamodrm_handle *gdrm, u16 *addr,
} else {
- int i;
- /* The easy case */
- for ( i=0; i<count/2; i++ ) { /* Number of words */
- iowrite16(*(addr+i), gdrm->cmdq_base+ring_write+(i*2));
- }
+ memcpy_toio(gdrm->cmdq_base+ring_write, addr,count);
}
- /* Before changing write position, read has to stop
- * (Brought across from xf86-video-glamo)
- * TAW: Really? Is pausing the clock not enough? */
- glamo_cmdq_wait(gdrm, GLAMO_ENGINE_CMDQ);
- /* Note that CLOCK_2D_EN_M6CLK has nothing to do with the 2D engine */
- glamo_engine_clkreg_set(gdrm->glamo_core, GLAMO_ENGINE_2D,
- GLAMO_CLOCK_2D_EN_M6CLK, 0x0000);
reg_write(gdrm, GLAMO_REG_CMDQ_WRITE_ADDRH,
- (new_ring_write >> 16) & 0x7f);
+ (new_ring_write >> 16) & 0x7f);
reg_write(gdrm, GLAMO_REG_CMDQ_WRITE_ADDRL,
- new_ring_write & 0xffff);
- glamo_engine_clkreg_set(gdrm->glamo_core, GLAMO_ENGINE_2D,
- GLAMO_CLOCK_2D_EN_M6CLK, 0xffff);
+ new_ring_write & 0xffff);
+
+ down(&gdrm->add_to_ring);
+
+ printk( KERN_INFO "[glamo-drm] IOCTL2 CMDQ at: %d-%d, CMDQ CTRL: %d, CMDQ STATUS: %d\n",
+ glamo_get_read(gdrm), glamo_get_write(gdrm),
+ reg_read(gdrm, GLAMO_REG_CMDQ_CONTROL),
+ reg_read(gdrm, GLAMO_REG_CMDQ_STATUS) );
+
return 0;
}
-
/* Return true for a legal sequence of commands, otherwise false */
static int glamo_sanitize_buffer(u16 *cmds, unsigned int count)
{
@@ -231,16 +242,16 @@ static int glamo_do_relocation(struct glamodrm_handle *gdrm,
struct drm_device *dev,
struct drm_file *file_priv)
{
- uint32_t *handles;
+ u32 *handles;
int *offsets;
int nobjs = cbuf->nobjs;
int i;
if ( nobjs > 32 ) return -EINVAL; /* Get real... */
- handles = drm_alloc(nobjs*sizeof(uint32_t), DRM_MEM_DRIVER);
+ handles = drm_alloc(nobjs*sizeof(u32), DRM_MEM_DRIVER);
if ( handles == NULL ) return -1;
- if ( copy_from_user(handles, cbuf->objs, nobjs*sizeof(uint32_t)) )
+ if ( copy_from_user(handles, cbuf->objs, nobjs*sizeof(u32)) )
return -1;
offsets = drm_alloc(nobjs*sizeof(int), DRM_MEM_DRIVER);
@@ -250,7 +261,7 @@ static int glamo_do_relocation(struct glamodrm_handle *gdrm,
for ( i=0; i<nobjs; i++ ) {
- uint32_t handle = handles[i];
+ u32 handle = handles[i];
int offset = offsets[i];
struct drm_gem_object *obj;
struct drm_glamo_gem_object *gobj;
@@ -310,6 +321,7 @@ fail:
int glamo_ioctl_cmdbuf(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
+ int ret = 0;
struct glamodrm_handle *gdrm;
unsigned int count;
drm_glamo_cmd_buffer_t *cbuf = data;
@@ -317,33 +329,48 @@ int glamo_ioctl_cmdbuf(struct drm_device *dev, void *data,
gdrm = dev->dev_private;
+ printk( KERN_INFO "[glamo-drm] IOCTL CMDQ at: %d-%d, CMDQ CTRL: %d, CMDQ STATUS: %d\n",
+ glamo_get_read(gdrm), glamo_get_write(gdrm),
+ reg_read(gdrm, GLAMO_REG_CMDQ_CONTROL),
+ reg_read(gdrm, GLAMO_REG_CMDQ_STATUS) );
+
+
count = cbuf->bufsz;
if ( count > PAGE_SIZE ) return -EINVAL;
cmds = drm_alloc(count, DRM_MEM_DRIVER);
if ( cmds == NULL ) return -ENOMEM;
- if ( copy_from_user(cmds, cbuf->buf, count) ) return -EINVAL;
+ if ( copy_from_user(cmds, cbuf->buf, count) ) {
+ printk( KERN_WARNING "[glamo-drm] copy from user failed\n");
+ ret = -EINVAL;
+ goto cleanup;
+ }
/* Check the buffer isn't going to tell Glamo to enact naughtiness */
- if ( !glamo_sanitize_buffer(cmds, count) ) return -EINVAL;
+ if ( !glamo_sanitize_buffer(cmds, count) ) {
+ printk( KERN_WARNING "[glamo-drm] sanitize buffer failed\n");
+ ret = -EINVAL;
+ goto cleanup;
+ }
/* Perform relocation, if necessary */
if ( cbuf->nobjs ) {
if ( glamo_do_relocation(gdrm, cbuf, cmds, dev, file_priv) )
- return -EINVAL; /* Relocation failed */
+ {
+ printk( KERN_WARNING "[glamo-drm] Relocation failed\n");
+ ret = -EINVAL;
+ goto cleanup;
+ }
}
glamo_add_to_ring(gdrm, cmds, count);
- /* Having the CPU wait for the CPU is, to put it mildly,
- * less than optimal.
- * TODO: Avoid doing this, by some suitable means */
- glamo_cmdq_wait(gdrm, GLAMO_ENGINE_ALL);
+cleanup:
drm_free(cmds, 1, DRM_MEM_DRIVER);
- return 0;
+ return ret;
}
@@ -351,6 +378,8 @@ int glamo_cmdq_init(struct glamodrm_handle *gdrm)
{
unsigned int i;
+ init_MUTEX(&gdrm->add_to_ring);
+
/* Enable 2D and 3D */
glamo_engine_enable(gdrm->glamo_core, GLAMO_ENGINE_2D);
glamo_engine_reset(gdrm->glamo_core, GLAMO_ENGINE_2D);
@@ -373,16 +402,22 @@ int glamo_cmdq_init(struct glamodrm_handle *gdrm)
reg_write(gdrm, GLAMO_REG_CMDQ_LEN, (GLAMO_CMDQ_SIZE >> 10)-1);
reg_write(gdrm, GLAMO_REG_CMDQ_WRITE_ADDRH, 0);
reg_write(gdrm, GLAMO_REG_CMDQ_WRITE_ADDRL, 0);
- reg_write(gdrm, GLAMO_REG_CMDQ_READ_ADDRH, 0);
- reg_write(gdrm, GLAMO_REG_CMDQ_READ_ADDRL, 0);
reg_write(gdrm, GLAMO_REG_CMDQ_CONTROL,
1 << 12 | /* Turbo flip (?) */
- 5 << 8 | /* No interrupt */
+ 5 << 8 | /* no interrupt */
8 << 4); /* HQ threshold */
- /* Wait for things to settle down */
- glamo_cmdq_wait(gdrm, GLAMO_ENGINE_ALL);
+ printk( KERN_INFO "[glamo-drm] INIT CMDQ at: %d-%d, CMDQ CTRL: %d, CMDQ STATUS: %d\n",
+ glamo_get_read(gdrm), glamo_get_write(gdrm),
+ reg_read(gdrm, GLAMO_REG_CMDQ_CONTROL),
+ reg_read(gdrm, GLAMO_REG_CMDQ_STATUS) );
+
+ return 0;
+}
+
+int glamo_cmdq_shutdown(struct glamodrm_handle *gdrm)
+{
return 0;
}
diff --git a/drivers/mfd/glamo/glamo-cmdq.h b/drivers/mfd/glamo/glamo-cmdq.h
index 4bc6b717115..35c8bea1dcb 100644
--- a/drivers/mfd/glamo/glamo-cmdq.h
+++ b/drivers/mfd/glamo/glamo-cmdq.h
@@ -1,6 +1,7 @@
/* Smedia Glamo 336x/337x command queue handling
*
* Copyright (c) 2008-2009 Thomas White <taw@bitwiz.org.uk>
+ * Copyright (c) 2009 Andreas Pokorny <andreas.pokorny@gmail.com>
* Based on xf86-video-glamo
* Copyright 2007 OpenMoko, Inc.
* Copyright © 2009 Lars-Peter Clausen <lars@metafoo.de>
@@ -34,8 +35,8 @@ extern int glamo_ioctl_cmdbuf(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern int glamo_cmdq_init(struct glamodrm_handle *gdrm);
+extern int glamo_cmdq_shutdown(struct glamodrm_handle *gdrm);
extern void glamo_cmdq_suspend(struct glamodrm_handle *gdrm);
extern void glamo_cmdq_resume(struct glamodrm_handle *gdrm);
-
#endif /* __GLAMO_CMDQ_H */
diff --git a/drivers/mfd/glamo/glamo-drm-drv.c b/drivers/mfd/glamo/glamo-drm-drv.c
index d71da8850ac..9725968a196 100644
--- a/drivers/mfd/glamo/glamo-drm-drv.c
+++ b/drivers/mfd/glamo/glamo-drm-drv.c
@@ -2,6 +2,7 @@
*
* Copyright (C) 2009 Openmoko, Inc. Jorge Luis Zapata <turran@openmoko.com>
* Copyright (C) 2008-2009 Thomas White <taw@bitwiz.org.uk>
+ * Copyright (C) 2009 Andreas Pokorny <andreas.pokorny@gmail.com>
*
* All rights reserved.
*
@@ -331,6 +332,9 @@ static int glamodrm_remove(struct platform_device *pdev)
{
struct glamodrm_handle *gdrm = platform_get_drvdata(pdev);
+ glamo_buffer_final(gdrm);
+ glamo_cmdq_shutdown(gdrm);
+
drm_exit(&glamodrm_drm_driver);
platform_set_drvdata(pdev, NULL);
diff --git a/drivers/mfd/glamo/glamo-drm-private.h b/drivers/mfd/glamo/glamo-drm-private.h
index 59030cb2313..3f01f1fd6a1 100644
--- a/drivers/mfd/glamo/glamo-drm-private.h
+++ b/drivers/mfd/glamo/glamo-drm-private.h
@@ -1,6 +1,7 @@
/* Smedia Glamo 336x/337x DRM private bits
*
* Copyright (C) 2008-2009 Thomas White <taw@bitwiz.org.uk>
+ * Copyright (C) 2009 Andreas Pokorny <andreas.pokorny@gmail.com>
* Based on xf86-video-glamo
* Copyright 2007 OpenMoko, Inc.
* Copyright © 2009 Lars-Peter Clausen <lars@metafoo.de>
@@ -29,6 +30,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/semaphore.h>
#include "glamo-core.h"
@@ -70,6 +72,9 @@ struct glamodrm_handle {
/* Memory management */
struct drm_mm *mmgr;
+ /* semaphore against concurrent ioctl */
+ struct semaphore add_to_ring;
+
/* Saved state */
u_int16_t saved_clock;
u_int16_t saved_width;