Messing About with Glamo's 3D Engine

Wolfgang Spraul wolfgang at openmoko.com
Tue Dec 9 18:14:23 CET 2008


Thomas,
oh wow - his looks like a great start, and hopefully we can sync it  
with what Graeme is doing, maybe Juan also...
Just a reminder - anyone who wants access to the glamo docs can email  
me to sign the NDA and get access to Openmoko's complete internal  
document storage, within 24 hours.
Best Regards,
Wolfgang

On Dec 9, 2008, at 5:10 AM, Thomas White wrote:

> I thought I'd follow up Graeme's Xorg report with a snippet about my
> experiences messing about with Glamo's 3D engine so far.
>
> Since I've had the NDA's documentation, I've been hacking around in  
> the
> kernel to try to write something which makes the 3D engine do  
> something
> sensible.  Even with the docs, this is hard work: they aren't very
> specific on what the expected sequence of operations is, or what the
> exact meanings of a few registers are.
>
> Anyway, this patch is what I've been messing around with.  It's made
> against the current 'stable' branch, but rebases quite easily against
> andy-tracking.  It's a combination of some sensible parts:
>
> * Extension to glamo_engine_enable() to allow it to manipulate the 3D
> engine clocks and status.
>
> * As above for glamo_engine_disable() and glamo_engine_reset().
>
> * Make the Glamo memory allocations a little easier to read in
> glamo-core.h.  Give all the memory left over after FB and MMC to the
> (new) 3D platform device, but making it easily to change that if
> necessary.
>
> * Add sysfs entries in /sys/devices/platform/glamo3362.0/glamo-3d.0:
> 	status: contains the status of the bits of the 3D engine
> 	regs: contains the contents of the first bit of 3D MMIO space.
>
> ... and some parts which are purely me messing around:
>
> * When "init" is written to the 'status' sysfs entry, it'll try to set
> up an identity projection matrix, clipping and scaling, colour buffer
> and Z-buffer and draw a triangle across.  Then it checks to see if
> anything's been written to the colour buffer, and puts a line in dmesg
> if so.  The current challenge is to get this to happen.
>
> A practical DRM module will look very different indeed, but I thought
> I'd publish this early to hopefully inspire some of the people who  
> were
> initially keen on this project to join in, and to get some extra pairs
> of eyes on the way I'm manipulating the hardware.
>
> Signed-off-by: Thomas White <taw27 at cam.ac.uk>
> ---
> arch/arm/mach-s3c2440/mach-gta02.c |    2 +-
> drivers/mfd/glamo/Kconfig          |   12 +-
> drivers/mfd/glamo/Makefile         |    1 +
> drivers/mfd/glamo/glamo-3d-regs.h  |  180 +++++++++++
> drivers/mfd/glamo/glamo-3d.c       |  574 +++++++++++++++++++++++++++ 
> +++++++++
> drivers/mfd/glamo/glamo-core.c     |   48 +++-
> drivers/mfd/glamo/glamo-core.h     |   28 +-
> 7 files changed, 827 insertions(+), 18 deletions(-)
> create mode 100644 drivers/mfd/glamo/glamo-3d-regs.h
> create mode 100644 drivers/mfd/glamo/glamo-3d.c
>
> diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach- 
> s3c2440/mach-gta02.c
> index b1aa95b..64fc8e8 100644
> --- a/arch/arm/mach-s3c2440/mach-gta02.c
> +++ b/arch/arm/mach-s3c2440/mach-gta02.c
> @@ -1414,7 +1414,7 @@ static struct glamofb_platform_data  
> gta02_glamo_pdata = {
> 	.lower_margin	= 16,
> 	.hsync_len	= 8,
> 	.vsync_len	= 2,
> -	.fb_mem_size	= 0x400000, /* glamo has 8 megs of SRAM. we use 4 */
> +	.fb_mem_size	= 0x12c000, /* 640 x 480 x 4 = 1200 kiB */
> 	.xres		= {
> 		.min	= 240,
> 		.max	= 640,
> diff --git a/drivers/mfd/glamo/Kconfig b/drivers/mfd/glamo/Kconfig
> index 86a7c40..2b617a3 100644
> --- a/drivers/mfd/glamo/Kconfig
> +++ b/drivers/mfd/glamo/Kconfig
> @@ -41,4 +41,14 @@ config MFD_GLAMO_MCI
> 	  the S-Media GLAMO chip, as used in Openmoko
> 	  neo1973 GTA-02.
>
> -	  If unsure, say N.
> \ No newline at end of file
> +	  If unsure, say N.
> +
> +config MFD_GLAMO_3D
> +	tristate "3D Support for SMedia Glamo 336x/337x"
> +	depends on MFD_GLAMO && MFD_GLAMO_FB
> +	help
> +	  This enables a driver for the 3D engine of the SMedia
> +	  Glamo 336x/337x.
> +
> +	  If unsure, say N.
> +
> diff --git a/drivers/mfd/glamo/Makefile b/drivers/mfd/glamo/Makefile
> index dc64d50..8423351 100644
> --- a/drivers/mfd/glamo/Makefile
> +++ b/drivers/mfd/glamo/Makefile
> @@ -9,4 +9,5 @@ obj-$(CONFIG_MFD_GLAMO_SPI_GPIO) 	+= glamo-spi-gpio.o
> obj-$(CONFIG_MFD_GLAMO_FB)		+= glamo-fb.o
> obj-$(CONFIG_MFD_GLAMO_SPI_FB)		+= glamo-lcm-spi.o
> obj-$(CONFIG_MFD_GLAMO_MCI)		+= glamo-mci.o
> +obj-$(CONFIG_MFD_GLAMO_3D)		+= glamo-3d.o
>
> diff --git a/drivers/mfd/glamo/glamo-3d-regs.h b/drivers/mfd/glamo/ 
> glamo-3d-regs.h
> new file mode 100644
> index 0000000..c6a73ac
> --- /dev/null
> +++ b/drivers/mfd/glamo/glamo-3d-regs.h
> @@ -0,0 +1,180 @@
> +#ifndef _GLAMO_3D_REGS_H
> +#define _GLAMO_3D_REGS_H
> +
> +/*
> + * 3D Support for SMedia Glamo 336x/337x
> + *
> + * (c) 2008 Thomas White <taw27 at srcf.ucam.org>
> + *
> + * 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; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> + * MA 02111-1307 USA
> + */
> +
> +/* Preserve sanity by making the addresses below match
> + * with those in the data sheet */
> +#define reg(a) (a-0x1b00)
> +
> +enum {
> +
> +	/* Vertex information	1b00 -> 1bff */
> +
> +	/* Vertex information	1c00 -> 1cff */
> +	GLAMO3DREG_VERT_AX			= reg(0x1c00),	/* s[8].23 */
> +	GLAMO3DREG_VERT_AY			= reg(0x1c04),	/* s[8].23 */
> +	GLAMO3DREG_VERT_AZ			= reg(0x1c08),	/* s[8].23 */
> +	GLAMO3DREG_VERT_AW			= reg(0x1c0c),	/* s[8].23 */
> +	GLAMO3DREG_NORM_AX			= reg(0x1c10),	/* s[8].23 */
> +	GLAMO3DREG_NORM_AY			= reg(0x1c14),	/* s[8].23 */
> +	GLAMO3DREG_NORM_AZ			= reg(0x1c18),	/* s[8].23 */
> +	GLAMO3DREG_COLOR_A			= reg(0x1c20),	/* depends */
> +	GLAMO3DREG_VERT_BX			= reg(0x1c30),	/* s[8].23 */
> +	GLAMO3DREG_VERT_BY			= reg(0x1c34),	/* s[8].23 */
> +	GLAMO3DREG_VERT_BZ			= reg(0x1c38),	/* s[8].23 */
> +	GLAMO3DREG_VERT_BW			= reg(0x1c3c),	/* s[8].23 */
> +	GLAMO3DREG_NORM_BX			= reg(0x1c40),	/* s[8].23 */
> +	GLAMO3DREG_NORM_BY			= reg(0x1c44),	/* s[8].23 */
> +	GLAMO3DREG_NORM_BZ			= reg(0x1c48),	/* s[8].23 */
> +	GLAMO3DREG_COLOR_B			= reg(0x1c40),	/* depends */
> +	GLAMO3DREG_VERT_CX			= reg(0x1c60),	/* s[8].23 */
> +	GLAMO3DREG_VERT_CY			= reg(0x1c64),	/* s[8].23 */
> +	GLAMO3DREG_VERT_CZ			= reg(0x1c68),	/* s[8].23 */
> +	GLAMO3DREG_VERT_CW			= reg(0x1c6c),	/* s[8].23 */
> +	GLAMO3DREG_NORM_CX			= reg(0x1c70),	/* s[8].23 */
> +	GLAMO3DREG_NORM_CY			= reg(0x1c74),	/* s[8].23 */
> +	GLAMO3DREG_NORM_CZ			= reg(0x1c78),	/* s[8].23 */
> +	GLAMO3DREG_COLOR_C			= reg(0x1c70),	/* depends */
> +
> +	/* Paletted texture	1c00 -> 1dff */
> +	/* Vertex defaults	1e00 -> 1e4f */
> +
> +	/* Stream table		1f00 -> 1f4f */
> +	GLAMO3DREG_STREAMCFG			= reg(0x1f0c),	/* D32 */
> +
> +	/* Command buffer	2030 -> 203f */
> +	/* Parser		2040 -> 204f */
> +	/* Primitives		2050 -> 2053 */
> +
> +	/* Status / Firing	2054 -> 205b */
> +	GLAMO3DREG_STATUS_A			= reg(0x2054),	/* read */
> +	GLAMO3DREG_SETUPFIRE			= reg(0x2054),	/* write */
> +	GLAMO3DREG_STATUS_B			= reg(0x2056),
> +	GLAMO3DREG_STATUS_C			= reg(0x2058),	/* read */
> +	GLAMO3DREG_FIRE				= reg(0x2058),	/* write */
> +	GLAMO3DREG_STATUS_D			= reg(0x205a),
> +
> +	/* Depth buffer stuff */
> +	GLAMO3DREG_ZCFG				= reg(0x2108),	/* D32 */
> +	GLAMO3DREG_ZWRITEMASK			= reg(0x210C),	/* D16 */
> +	GLAMO3DREG_ZINITVAL			= reg(0x210E),	/* D16 */
> +	GLAMO3DREG_ZBASE			= reg(0x2110),	/* D32 */
> +
> +	/* Colour buffer stuff */
> +	GLAMO3DREG_COLCFG			= reg(0x2120),	/* D32 */
> +	GLAMO3DREG_COLMASK			= reg(0x2124),	/* D32 */
> +	GLAMO3DREG_COLBASE			= reg(0x2128),	/* D32 */
> +
> +	/* Clipping */
> +	GLAMO3DREG_CLIP_TOPBOT			= reg(0x2164),	/*  0-9 top */
> +								/* 16-25 bot */
> +	GLAMO3DREG_CLIP_LEFTRIGHT		= reg(0x2168),	/*  0-9 right */
> +								/* 16-25 left */
> +
> +	/* Viewport */
> +	GLAMO3DREG_SCALE_X			= reg(0x2678),	/* s[7].16 */
> +	GLAMO3DREG_OFFS_X			= reg(0x267c),	/* s[7].16 */
> +	GLAMO3DREG_SCALE_Y			= reg(0x2680),	/* s[7].16 */
> +	GLAMO3DREG_OFFS_Y			= reg(0x2684),	/* s[7].16 */
> +	GLAMO3DREG_SCALE_Z			= reg(0x2688),	/* s[7].16 */
> +	GLAMO3DREG_OFFS_Z			= reg(0x268c),	/* s[7].16 */
> +
> +	/* Transformation matrix */
> +	GLAMO3DREG_T_00				= reg(0x26a0),	/* s[7].16 */
> +	GLAMO3DREG_T_01				= reg(0x26a4),	/* s[7].16 */
> +	GLAMO3DREG_T_02				= reg(0x26a8),	/* s[7].16 */
> +	GLAMO3DREG_T_03				= reg(0x26ac),	/* s[7].16 */
> +	GLAMO3DREG_T_10				= reg(0x26b0),	/* s[7].16 */
> +	GLAMO3DREG_T_11				= reg(0x26b4),	/* s[7].16 */
> +	GLAMO3DREG_T_12				= reg(0x26b8),	/* s[7].16 */
> +	GLAMO3DREG_T_13				= reg(0x26bc),	/* s[7].16 */
> +	GLAMO3DREG_T_20				= reg(0x26c0),	/* s[7].16 */
> +	GLAMO3DREG_T_21				= reg(0x26c4),	/* s[7].16 */
> +	GLAMO3DREG_T_22				= reg(0x26c8),	/* s[7].16 */
> +	GLAMO3DREG_T_23				= reg(0x26cc),	/* s[7].16 */
> +	GLAMO3DREG_T_30				= reg(0x26d0),	/* s[7].16 */
> +	GLAMO3DREG_T_31				= reg(0x26d4),	/* s[7].16 */
> +	GLAMO3DREG_T_32				= reg(0x26d8),	/* s[7].16 */
> +	GLAMO3DREG_T_33				= reg(0x26dc),	/* s[7].16 */
> +
> +	/* Transformation matrix */
> +	GLAMO3DREG_W_00				= reg(0x26e0),	/* s[7].16 */
> +	GLAMO3DREG_W_01				= reg(0x26e4),	/* s[7].16 */
> +	GLAMO3DREG_W_02				= reg(0x26e8),	/* s[7].16 */
> +	GLAMO3DREG_W_10				= reg(0x26ec),	/* s[7].16 */
> +	GLAMO3DREG_W_11				= reg(0x26f0),	/* s[7].16 */
> +	GLAMO3DREG_W_12				= reg(0x26f4),	/* s[7].16 */
> +	GLAMO3DREG_W_20				= reg(0x26f8),	/* s[7].16 */
> +	GLAMO3DREG_W_21				= reg(0x26fc),	/* s[7].16 */
> +	GLAMO3DREG_W_22				= reg(0x2700),	/* s[7].16 */
> +	GLAMO3DREG_W_30				= reg(0x2708),	/* s[7].16 */
> +	GLAMO3DREG_W_31				= reg(0x270c),	/* s[7].16 */
> +	GLAMO3DREG_W_32				= reg(0x2700),	/* s[7].16 */
> +
> +	/* Normal matrix */
> +	GLAMO3DREG_N_00				= reg(0x2710),	/* s[7].16 */
> +	GLAMO3DREG_N_01				= reg(0x2714),	/* s[7].16 */
> +	GLAMO3DREG_N_02				= reg(0x2718),	/* s[7].16 */
> +	GLAMO3DREG_N_10				= reg(0x271c),	/* s[7].16 */
> +	GLAMO3DREG_N_11				= reg(0x2720),	/* s[7].16 */
> +	GLAMO3DREG_N_12				= reg(0x2724),	/* s[7].16 */
> +	GLAMO3DREG_N_20				= reg(0x2728),	/* s[7].16 */
> +	GLAMO3DREG_N_21				= reg(0x272c),	/* s[7].16 */
> +	GLAMO3DREG_N_22				= reg(0x2730),	/* s[7].16 */
> +
> +	/* Normal factor */
> +	GLAMO3DREG_NFACT			= reg(0x2734),	/* s[7].16 */
> +
> +	/* Clip plane */
> +	GLAMO3DREG_CLIPa			= reg(0x2738),	/* s[7].16 */
> +	GLAMO3DREG_CLIPb			= reg(0x273c),	/* s[7].16 */
> +	GLAMO3DREG_CLIPc			= reg(0x2740),	/* s[7].16 */
> +	GLAMO3DREG_CLIPd			= reg(0x2744),	/* s[7].16 */
> +
> +};
> +
> +/* Bits in STATUS_A */
> +enum {
> +	GLAMO3DBIT_STATUS_AGP			= 1<<9,
> +	GLAMO3DBIT_STATUS_DRAWDIR		= 1<<8,
> +	GLAMO3DBIT_STATUS_POST			= 1<<7,
> +	GLAMO3DBIT_STATUS_BLEND			= 1<<6,
> +	GLAMO3DBIT_STATUS_Z			= 1<<5,
> +	GLAMO3DBIT_STATUS_TEX			= 1<<4,
> +	GLAMO3DBIT_STATUS_SHADE			= 1<<3,
> +	GLAMO3DBIT_STATUS_SETUP			= 1<<2,
> +	GLAMO3DBIT_STATUS_QUEUE			= 1<<1,
> +	GLAMO3DBIT_STATUS_3D			= 1<<0,
> +};
> +
> +/* Bits in STREAMCFG */
> +enum {
> +	GLAMO3DBIT_VCOLFMT			= 1<<0,
> +};
> +
> +/* Bits in COLCFG */
> +enum {
> +	GLAMO3DBIT_COLVRAM			= 1<<23,
> +};
> +
> +#endif /* _GLAMO_3D_REGS_H */
> diff --git a/drivers/mfd/glamo/glamo-3d.c b/drivers/mfd/glamo/ 
> glamo-3d.c
> new file mode 100644
> index 0000000..0b3250a
> --- /dev/null
> +++ b/drivers/mfd/glamo/glamo-3d.c
> @@ -0,0 +1,574 @@
> +/*
> + * 3D Support for SMedia Glamo 336x/337x
> + *
> + * (c) 2008 Thomas White <taw27 at srcf.ucam.org>
> + * Loosely based on glamo-fb.c by Harald Welte
> + *
> + * 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; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> + * MA 02111-1307 USA
> + */
> +
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <asm/io.h>
> +#include <linux/delay.h>
> +
> +#include "glamo-core.h"
> +#include "glamo-3d-regs.h"
> +
> +#define RESSIZE(resource) (((resource)->end - (resource)->start)+1)
> +
> +struct glamo3d_handle {
> +
> +	/* This device */
> +	struct device *dev;
> +	/* The parent device handle */
> +	struct glamo_core *glamo_core;
> +
> +	/* MMIO region */
> +	struct resource *reg;
> +	char __iomem *base;
> +
> +	/* VRAM */
> +	struct resource *vram;
> +	char __iomem *vram_base;
> +	ssize_t vram_size;
> +	ssize_t cb_size;
> +
> +};
> +
> +static inline void glamo3d_access_delay(void)
> +{
> +	int n;
> +
> +	for (n = 0; n != 2; n++)
> +		nop();
> +}
> +
> +static u_int16_t reg_read(struct glamo3d_handle *glamo3d, u_int16_t  
> reg)
> +{
> +	glamo3d_access_delay();
> +	return readw(glamo3d->base + reg);
> +}
> +
> +static u_int32_t reg_read_32(struct glamo3d_handle *glamo3d,  
> u_int16_t reg)
> +{
> +	int lower, upper;
> +	glamo3d_access_delay();
> +	lower = readw(glamo3d->base + reg);
> +	upper = readw(glamo3d->base + reg + 2);
> +	return lower + (upper << 16);
> +}
> +
> +static void reg_write(struct glamo3d_handle *glamo3d,
> +			     u_int16_t reg, u_int16_t val)
> +{
> +	glamo3d_access_delay();
> +	writew(val, glamo3d->base + reg);
> +}
> +
> +static void reg_write_32(struct glamo3d_handle *glamo3d,
> +			     u_int16_t reg, u_int32_t val)
> +{
> +	int lower, upper;
> +	glamo3d_access_delay();
> +	lower = val & 0x0000ffff;
> +	upper = (val & 0xffff0000) >> 16;
> +	writew(lower, glamo3d->base + reg);
> +	writew(upper, glamo3d->base + reg + 2);
> +}
> +
> +static void reg_set_bit_mask(struct glamo3d_handle *glamo3d,
> +				u_int16_t reg, u_int32_t mask,
> +				u_int32_t val)
> +{
> +	u_int32_t tmp;
> +
> +	val &= mask;
> +
> +	tmp = reg_read_32(glamo3d, reg);
> +	tmp &= ~mask;
> +	tmp |= val;
> +	reg_write_32(glamo3d, reg, tmp);
> +}
> +
> +static void reg_set_bit_mask_32(struct glamo3d_handle *glamo3d,
> +				u_int16_t reg, u_int32_t mask,
> +				u_int32_t val)
> +{
> +	u_int16_t tmp;
> +
> +	val &= mask;
> +
> +	tmp = reg_read(glamo3d, reg);
> +	tmp &= ~mask;
> +	tmp |= val;
> +	reg_write(glamo3d, reg, tmp);
> +}
> +
> +/* Write a block of data to the memory allocated for Glamo 3D.
> + * addr: address relative to the base of the 3D memory block
> + *  src: pointer to data to be written
> + *  len: length of data */
> +static void glamo_3dvram_write(struct glamo3d_handle *glamo3d,
> +					u_int32_t addr, void *src, int len)
> +{
> +	int i;
> +	u_int16_t *src16 = src;
> +
> +	if (addr & 0x0001 || (unsigned long)src & 0x0001 || len & 0x0001) {
> +		dev_err(glamo3d->dev, "unaligned write(0x%08x, 0x%p, "
> +			"0x%x)!!\n", addr, src, len);
> +	}
> +
> +	for ( i=0; i<len/2; i++ ) {
> +		glamo3d_access_delay();
> +		writew(src16[i], glamo3d->vram_base + addr + 2*i);
> +	}
> +}
> +
> +/* Read a block of data from the memory allocated for Glamo 3D.
> + *  buf: pointer to buffer to recieve the data
> + * addr: address relative to the base of the 3D memory block
> + *  len: length of data */
> +static void glamo_3dvram_read(struct glamo3d_handle *glamo3d,
> +					u_int32_t addr, void *buf, int len)
> +{
> +	int i;
> +	u_int16_t *buf16 = buf;
> +
> +	if (addr & 0x0001 || (unsigned long) buf & 0x0001 || len & 0x0001) {
> +		dev_err(glamo3d->dev, "unaligned read(0x%p, 0x08%x, "
> +			"0x%x)!!\n", buf, addr, len);
> +	}
> +
> +	for ( i=0; i<len/2; i++ ) {
> +		glamo3d_access_delay();
> +		buf16[i] = readw(glamo3d->vram_base + addr + 2*i);
> +	}
> +}
> +
> +static ssize_t dummy_store(struct device *dev, struct  
> device_attribute *attr,
> +			   const char *buf, size_t count)
> +{
> +	return 0;
> +}
> +
> +static int glamo3d_check_buffer(struct glamo3d_handle *glamo3d)
> +{
> +	u_int8_t *buf;
> +	int i;
> +
> +	buf = kmalloc(glamo3d->cb_size, GFP_KERNEL);
> +	if ( !buf ) {
> +		printk(KERN_INFO "Couldn't allocate memory.\n");
> +		return 0;
> +	}
> +
> +	glamo_3dvram_read(glamo3d, 0x0, buf, glamo3d->cb_size);
> +
> +	for ( i=0; i<glamo3d->cb_size; i++ ) {
> +		if ( buf[i] != 0x00 ) {
> +			return 1;
> +		}
> +	}
> +
> +	kfree(buf);
> +
> +	return 0;
> +}
> +
> +static void glamo3d_setup_fire(struct glamo3d_handle *glamo3d)
> +{
> +	reg_write(glamo3d, GLAMO3DREG_SETUPFIRE, 0xffff);
> +}
> +
> +static void glamo3d_fire(struct glamo3d_handle *glamo3d)
> +{
> +	reg_write(glamo3d, GLAMO3DREG_FIRE, 0xffff);
> +}
> +
> +/* Initialise colour and Z buffers */
> +static void glamo3d_init_status(struct glamo3d_handle *glamo3d)
> +{
> +	u_int8_t *buf;
> +	int i;
> +	u_int32_t cbdetails;
> +	int cb_size;
> +	u_int32_t zconf;
> +
> +	/* Enable colour buffer writes */
> +	reg_write_32(glamo3d, GLAMO3DREG_COLMASK, 0x0001);
> +
> +	/* Colour buffer base address */
> +	reg_write_32(glamo3d, GLAMO3DREG_COLBASE, GLAMO_OFFSET_3DVRAM);
> +
> +	/* Colour buffer pitch and format */
> +	cbdetails = 0x0f000000;			/* Raster operation: white */
> +	cbdetails |= GLAMO3DBIT_COLVRAM;	/* Buffer in (Glamo) VRAM */
> +	cbdetails |= (0x13)<<16;		/* Format: A4R4G4B4 */
> +	cbdetails |= 320 / 2;			/* Pitch = 320 */
> +	printk(KERN_INFO "Colour buffer settings: %08X\n", cbdetails);
> +	reg_write_32(glamo3d, GLAMO3DREG_COLCFG, cbdetails);
> +
> +	/* 320x320px, 8 bytes per pixel: AAAA RRRR GGGG BBBB */
> +	cb_size = 320*320*8;
> +	glamo3d->cb_size = cb_size;
> +
> +	/* Blank out the colour buffer */
> +	buf = kmalloc(cb_size, GFP_KERNEL);
> +	if ( !buf ) {
> +		printk(KERN_INFO "Couldn't allocate test memory.\n");
> +		return;
> +	}
> +	for ( i=0; i<cb_size; i++ ) {
> +		buf[i] = 0x00;
> +	}
> +	glamo_3dvram_write(glamo3d, 0x0, buf, cb_size);
> +	if ( glamo3d_check_buffer(glamo3d) != 0 ) {
> +		printk(KERN_WARNING "Couldn't zero colour buffer!\n");
> +	}
> +	kfree(buf);
> +
> +	/* Set up the depth buffer */
> +	zconf  = 320*2;		/* Pitch in bytes */
> +	zconf |= 0x01070000;	/* [5].11 floating point, always pass */
> +	reg_write_32(glamo3d, GLAMO3DREG_ZCFG, zconf);
> +	reg_write(glamo3d, GLAMO3DREG_ZWRITEMASK, 1);
> +	reg_write(glamo3d, GLAMO3DREG_ZINITVAL, 0);
> +	reg_write_32(glamo3d, GLAMO3DREG_ZBASE, GLAMO_OFFSET_3DVRAM 
> +cb_size);
> +	msleep(10);
> +
> +	/* Set up the viewing transformation */
> +	reg_write_32(glamo3d, GLAMO3DREG_T_00, 0x003f0000);
> +	reg_write_32(glamo3d, GLAMO3DREG_T_01, 0x00000000);
> +	reg_write_32(glamo3d, GLAMO3DREG_T_02, 0x00000000);
> +	reg_write_32(glamo3d, GLAMO3DREG_T_03, 0x00000000);
> +	reg_write_32(glamo3d, GLAMO3DREG_T_10, 0x00000000);
> +	reg_write_32(glamo3d, GLAMO3DREG_T_11, 0x003f0000);
> +	reg_write_32(glamo3d, GLAMO3DREG_T_12, 0x00000000);
> +	reg_write_32(glamo3d, GLAMO3DREG_T_13, 0x00000000);
> +	reg_write_32(glamo3d, GLAMO3DREG_T_20, 0x00000000);
> +	reg_write_32(glamo3d, GLAMO3DREG_T_21, 0x00000000);
> +	reg_write_32(glamo3d, GLAMO3DREG_T_22, 0x003f0000);
> +	reg_write_32(glamo3d, GLAMO3DREG_T_23, 0x00000000);
> +	reg_write_32(glamo3d, GLAMO3DREG_T_30, 0x00000000);
> +	reg_write_32(glamo3d, GLAMO3DREG_T_31, 0x00000000);
> +	reg_write_32(glamo3d, GLAMO3DREG_T_32, 0x00000000);
> +	reg_write_32(glamo3d, GLAMO3DREG_T_33, 0x003f0000);
> +
> +	/* Set up the (other?) viewing transformation */
> +	reg_write_32(glamo3d, GLAMO3DREG_W_00, 0x003f0000);
> +	reg_write_32(glamo3d, GLAMO3DREG_W_01, 0x00000000);
> +	reg_write_32(glamo3d, GLAMO3DREG_W_02, 0x00000000);
> +	reg_write_32(glamo3d, GLAMO3DREG_W_10, 0x00000000);
> +	reg_write_32(glamo3d, GLAMO3DREG_W_11, 0x003f0000);
> +	reg_write_32(glamo3d, GLAMO3DREG_W_12, 0x00000000);
> +	reg_write_32(glamo3d, GLAMO3DREG_W_20, 0x00000000);
> +	reg_write_32(glamo3d, GLAMO3DREG_W_21, 0x00000000);
> +	reg_write_32(glamo3d, GLAMO3DREG_W_22, 0x003f0000);
> +	reg_write_32(glamo3d, GLAMO3DREG_W_30, 0x00000000);
> +	reg_write_32(glamo3d, GLAMO3DREG_W_31, 0x00000000);
> +	reg_write_32(glamo3d, GLAMO3DREG_W_32, 0x00000000);
> +
> +	/* Normal factor */
> +	reg_write_32(glamo3d, GLAMO3DREG_NFACT, 0x003f0000);
> +
> +	/* Viewport transformation */
> +	reg_write_32(glamo3d, GLAMO3DREG_SCALE_X, 0x003f0000);
> +	reg_write_32(glamo3d, GLAMO3DREG_OFFS_X, 0x003f0000);
> +	reg_write_32(glamo3d, GLAMO3DREG_SCALE_Y, 0x003f0000);
> +	reg_write_32(glamo3d, GLAMO3DREG_OFFS_Y, 0x003f0000);
> +	reg_write_32(glamo3d, GLAMO3DREG_SCALE_Z, 0x003f0000);
> +	reg_write_32(glamo3d, GLAMO3DREG_OFFS_Z, 0x003f0000);
> +
> +	/* Clipping */
> +	reg_write_32(glamo3d, GLAMO3DREG_CLIP_TOPBOT, 0x03ff0000);
> +	reg_write_32(glamo3d, GLAMO3DREG_CLIP_LEFTRIGHT, 0x03ff0000);
> +
> +	/* Try to draw something */
> +	msleep(10);
> +	reg_set_bit_mask_32(glamo3d, GLAMO3DREG_STREAMCFG,
> +				GLAMO3DBIT_VCOLFMT, 0x00000001);
> +	reg_write_32(glamo3d, GLAMO3DREG_VERT_AX, 0);
> +	reg_write_32(glamo3d, GLAMO3DREG_VERT_AY, 0);
> +	reg_write_32(glamo3d, GLAMO3DREG_VERT_AZ, 0);
> +	reg_write_32(glamo3d, GLAMO3DREG_VERT_AW, 0x3f800000);
> +	reg_write_32(glamo3d, GLAMO3DREG_COLOR_A, 0xffffffff);
> +	reg_write_32(glamo3d, GLAMO3DREG_VERT_BX, 0x3f800000);
> +	reg_write_32(glamo3d, GLAMO3DREG_VERT_BY, 0);
> +	reg_write_32(glamo3d, GLAMO3DREG_VERT_BZ, 0);
> +	reg_write_32(glamo3d, GLAMO3DREG_VERT_BW, 0x3f800000);
> +	reg_write_32(glamo3d, GLAMO3DREG_COLOR_B, 0xffffffff);
> +	reg_write_32(glamo3d, GLAMO3DREG_VERT_CX, 0x3f800000);
> +	reg_write_32(glamo3d, GLAMO3DREG_VERT_CY, 0x3f800000);
> +	reg_write_32(glamo3d, GLAMO3DREG_VERT_CZ, 0);
> +	reg_write_32(glamo3d, GLAMO3DREG_VERT_CW, 0x3f800000);
> +	reg_write_32(glamo3d, GLAMO3DREG_COLOR_C, 0xffffffff);
> +	msleep(10);
> +	glamo3d_setup_fire(glamo3d);
> +	msleep(10);
> +	if ( glamo3d_check_buffer(glamo3d) != 0 ) {
> +		printk(KERN_WARNING "Found something in the colour buffer!\n");
> +	}
> +}
> +
> +static void glamo3d_reset(struct glamo3d_handle *glamo3d)
> +{
> +	printk(KERN_INFO "Resetting 3D engine...\n");
> +	glamo_engine_reset(glamo3d->glamo_core, GLAMO_ENGINE_3D);
> +}
> +
> +static ssize_t status_store(struct device *dev, struct  
> device_attribute *attr,
> +			   const char *buf, size_t count)
> +{
> +	struct glamo3d_handle *glamo3d = dev_get_drvdata(dev);
> +
> +	if ( (count == 5) && (strncmp(buf, "init", 4)==0) ) {
> +		glamo3d_init_status(glamo3d);
> +	} else if ( (count == 6) && (strncmp(buf, "reset", 5)==0) ) {
> +		glamo3d_reset(glamo3d);
> +	}
> +
> +	return count;
> +}
> +
> +static ssize_t regs_show(struct device *dev, struct  
> device_attribute *attr,
> +			char *buf)
> +{
> +	u_int16_t i;
> +	char *end = buf;
> +	struct glamo3d_handle *glamo3d = dev_get_drvdata(dev);
> +
> +	end += snprintf(end, PAGE_SIZE-(end-buf)-1, "Glamo 3D register  
> dump:");
> +	for ( i=0x0; i<0x100; i+=2 ) {
> +		if ( (i & 0xf) == 0 ) {
> +			end += snprintf(end, PAGE_SIZE-(end-buf)-1,
> +					"\n%04X: ", i+0x1b00);
> +		}
> +		end += snprintf(end, PAGE_SIZE-(end-buf)-1,
> +				"%04x ", reg_read(glamo3d, i));
> +		msleep(2);
> +	}
> +	end += snprintf(end, PAGE_SIZE-(end-buf)-1, "\n");
> +
> +	return end - buf;
> +}
> +
> +#define IDLE_BUSY(a) \
> +	if ( status_a & (a) ) {			\
> +		end += snprintf(end, PAGE_SIZE-(end-buf)-1, "idle\n");	\
> +	} else {							\
> +		end += snprintf(end, PAGE_SIZE-(end-buf)-1, "busy\n");	\
> +	}
> +
> +
> +static ssize_t status_show(struct device *dev, struct  
> device_attribute *attr,
> +			char *buf)
> +{
> +	char *end = buf;
> +	u_int16_t status_a;
> +	struct glamo3d_handle *glamo3d = dev_get_drvdata(dev);
> +
> +	status_a = reg_read(glamo3d, GLAMO3DREG_STATUS_A);
> +
> +	end += snprintf(end, PAGE_SIZE-(end-buf)-1, "     Draw direction:  
> ");
> +	if ( status_a & GLAMO3DBIT_STATUS_DRAWDIR ) {
> +		end += snprintf(end, PAGE_SIZE-(end-buf)-1,
> +				"vertical, right-to-left\n");
> +	} else {
> +		end += snprintf(end, PAGE_SIZE-(end-buf)-1,
> +				"horizontal, left-to-right\n");
> +	}
> +
> +	end += snprintf(end, PAGE_SIZE-(end-buf)-1, "          3D engine:  
> ");
> +	IDLE_BUSY(GLAMO3DBIT_STATUS_3D)
> +	end += snprintf(end, PAGE_SIZE-(end-buf)-1, "AGP fetching engine:  
> ");
> +	IDLE_BUSY(GLAMO3DBIT_STATUS_AGP)
> +	end += snprintf(end, PAGE_SIZE-(end-buf)-1, "        Post engine:  
> ");
> +	IDLE_BUSY(GLAMO3DBIT_STATUS_POST)
> +	end += snprintf(end, PAGE_SIZE-(end-buf)-1, "    Blending engine:  
> ");
> +	IDLE_BUSY(GLAMO3DBIT_STATUS_BLEND)
> +	end += snprintf(end, PAGE_SIZE-(end-buf)-1, "           Z engine:  
> ");
> +	IDLE_BUSY(GLAMO3DBIT_STATUS_Z)
> +	end += snprintf(end, PAGE_SIZE-(end-buf)-1, "     Texture engine:  
> ");
> +	IDLE_BUSY(GLAMO3DBIT_STATUS_TEX)
> +	end += snprintf(end, PAGE_SIZE-(end-buf)-1, "     Shading engine:  
> ");
> +	IDLE_BUSY(GLAMO3DBIT_STATUS_SHADE)
> +	end += snprintf(end, PAGE_SIZE-(end-buf)-1, "       Setup engine:  
> ");
> +	IDLE_BUSY(GLAMO3DBIT_STATUS_SETUP)
> +
> +	end += snprintf(end, PAGE_SIZE-(end-buf)-1, "           3D queue:  
> ");
> +	if ( status_a & GLAMO3DBIT_STATUS_QUEUE ) {
> +		end += snprintf(end, PAGE_SIZE-(end-buf)-1, "empty\n");
> +	} else {
> +		end += snprintf(end, PAGE_SIZE-(end-buf)-1, "not empty\n");
> +	}
> +
> +
> +	return end - buf;
> +}
> +
> +static DEVICE_ATTR(regs, 0444, regs_show, dummy_store);
> +static DEVICE_ATTR(status, 0644, status_show, status_store);
> +static struct attribute *glamo3d_sysfs_entries[] = {
> +	&dev_attr_regs.attr,
> +	&dev_attr_status.attr,
> +	NULL
> +};
> +static struct attribute_group glamo3d_attr_group = {
> +	.name	= NULL,
> +	.attrs	= glamo3d_sysfs_entries,
> +};
> +
> +static int __init glamo3d_probe(struct platform_device *pdev)
> +{
> +	int rc;
> +	struct glamo3d_handle *glamo3d;
> +
> +	printk(KERN_INFO "SMedia Glamo 3D driver (c) 2008 "
> +		"Thomas White <taw27 at srcf.ucam.org>\n");
> +
> +	glamo3d = kmalloc(sizeof(*glamo3d), GFP_KERNEL);
> +	if ( !glamo3d )
> +		return -ENOMEM;
> +	platform_set_drvdata(pdev, glamo3d);
> +	glamo3d->glamo_core = pdev->dev.platform_data;
> +
> +	glamo3d->reg = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if ( !glamo3d->reg ) {
> +		dev_err(&pdev->dev, "Unable to find 3D registers.\n");
> +		rc = -ENOENT;
> +		goto out_free;
> +	}
> +
> +	/* Look for the 3D registers */
> +	glamo3d->reg = request_mem_region(glamo3d->reg->start,
> +					  RESSIZE(glamo3d->reg), pdev->name);
> +	if ( !glamo3d->reg ) {
> +		dev_err(&pdev->dev, "failed to request MMIO region\n");
> +		rc = -ENOENT;
> +		goto out_free;
> +	}
> +
> +	/* Remap the 3D registers */
> +	glamo3d->base = ioremap(glamo3d->reg->start, RESSIZE(glamo3d->reg));
> +	if ( !glamo3d->base ) {
> +		dev_err(&pdev->dev, "failed to ioremap() MMIO memory\n");
> +		rc = -ENOENT;
> +		goto out_release_regs;
> +	}
> +
> +	/* Look for the VRAM we're going to use for 3D */
> +	glamo3d->vram = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> +	if ( !glamo3d->vram ) {
> +		dev_err(&pdev->dev, "Unable to find VRAM for 3D.\n");
> +		rc = -ENOENT;
> +		goto out_unmap_regs;
> +	}
> +
> +	glamo3d->vram = request_mem_region(glamo3d->vram->start,
> +					  RESSIZE(glamo3d->vram), pdev->name);
> +	if ( !glamo3d->vram ) {
> +		dev_err(&pdev->dev, "failed to request VRAM region\n");
> +		rc = -ENOENT;
> +		goto out_unmap_regs;
> +	}
> +
> +	/* Remap the 3D VRAM */
> +	glamo3d->vram_base = ioremap(glamo3d->vram->start,
> +							RESSIZE(glamo3d->vram));
> +	if ( !glamo3d->vram_base ) {
> +		dev_err(&pdev->dev, "failed to ioremap() MMIO memory\n");
> +		rc = -ENOENT;
> +		goto out_release_vram;
> +	}
> +
> +	glamo3d->vram_size = RESSIZE(glamo3d->vram);
> +	printk(KERN_INFO "%lli bytes of Glamo RAM for 3D\n",
> +					(long long int)glamo3d->vram_size);
> +
> +	/* Ok, here goes nothing... */
> +	glamo_engine_enable(glamo3d->glamo_core, GLAMO_ENGINE_3D);
> +	glamo_engine_reset(glamo3d->glamo_core, GLAMO_ENGINE_3D);
> +	msleep(5);
> +
> +	rc = sysfs_create_group(&pdev->dev.kobj, &glamo3d_attr_group);
> +	if ( rc < 0 ) {
> +		dev_err(&pdev->dev, "cannot create sysfs group\n");
> +		goto out_disable_engine;
> +	}
> +
> +	printk(KERN_INFO "Glamo 3D engine enabled.\n");
> +
> +	return 0;
> +
> +out_disable_engine:
> +	glamo_engine_disable(glamo3d->glamo_core, GLAMO_ENGINE_3D);
> +out_release_vram:
> +	release_mem_region(glamo3d->vram->start, RESSIZE(glamo3d->vram));
> +out_unmap_regs:
> +	iounmap(glamo3d->base);
> +out_release_regs:
> +	release_mem_region(glamo3d->reg->start, RESSIZE(glamo3d->reg));
> +out_free:
> +	kfree(glamo3d);
> +	pdev->dev.driver_data = NULL;
> +	return rc;
> +}
> +
> +static int glamo3d_remove(struct platform_device *pdev)
> +{
> +	struct glamo3d_handle *glamo3d = platform_get_drvdata(pdev);
> +	struct glamo_core *glamocore = pdev->dev.platform_data;
> +
> +	glamo_engine_disable(glamocore, GLAMO_ENGINE_3D);
> +
> +	sysfs_remove_group(&pdev->dev.kobj, &glamo3d_attr_group);
> +	platform_set_drvdata(pdev, NULL);
> +	iounmap(glamo3d->base);
> +	release_mem_region(glamo3d->reg->start, RESSIZE(glamo3d->reg));
> +	iounmap(glamo3d->vram_base);
> +	release_mem_region(glamo3d->vram->start, RESSIZE(glamo3d->vram));
> +	kfree(glamo3d);
> +
> +	return 0;
> +}
> +
> +static struct platform_driver glamo3d_driver = {
> +	.probe		= glamo3d_probe,
> +	.remove		= glamo3d_remove,
> +	.driver		= {
> +		.name	= "glamo-3d",
> +		.owner	= THIS_MODULE,
> +	},
> +};
> +
> +static int __devinit glamo3d_init(void)
> +{
> +	return platform_driver_register(&glamo3d_driver);
> +}
> +
> +static void __exit glamo3d_exit(void)
> +{
> +	platform_driver_unregister(&glamo3d_driver);
> +}
> +
> +module_init(glamo3d_init);
> +module_exit(glamo3d_exit);
> +
> +MODULE_AUTHOR("Thomas White <taw27 at srcf.ucam.org>");
> +MODULE_DESCRIPTION("3D Support for SMedia Glamo 336x/337x");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/mfd/glamo/glamo-core.c b/drivers/mfd/glamo/ 
> glamo-core.c
> index 58ee3e2..6f43896 100644
> --- a/drivers/mfd/glamo/glamo-core.c
> +++ b/drivers/mfd/glamo/glamo-core.c
> @@ -209,7 +209,12 @@ static struct resource glamo_3d_resources[] = {
> 		.start	= GLAMO_REGOFS_3D,
> 		.end	= GLAMO_REGOFS_END - 1,
> 		.flags	= IORESOURCE_MEM,
> +	}, {
> +		.start	= GLAMO_OFFSET_3DVRAM,
> +		.end	= GLAMO_OFFSET_3DVRAM + GLAMO_3DVRAM_SIZE - 1,
> +		.flags	= IORESOURCE_MEM,
> 	},
> +
> };
>
> static struct platform_device glamo_3d_dev = {
> @@ -254,9 +259,8 @@ static struct resource glamo_mmc_resources[] = {
> 		.end	= IRQ_GLAMO_MMC,
> 		.flags	= IORESOURCE_IRQ,
> 	}, { /* our data buffer for MMC transfers */
> -		.start	= GLAMO_OFFSET_FB + GLAMO_FB_SIZE,
> -		.end	= GLAMO_OFFSET_FB + GLAMO_FB_SIZE +
> -				  GLAMO_MMC_BUFFER_SIZE - 1,
> +		.start	= GLAMO_OFFSET_MMC,
> +		.end	= GLAMO_OFFSET_MMC + GLAMO_MMC_BUFFER_SIZE - 1,
> 		.flags	= IORESOURCE_MEM
> 	},
> };
> @@ -433,6 +437,19 @@ int __glamo_engine_enable(struct glamo_core  
> *glamo, enum glamo_engine engine)
> 				   GLAMO_HOSTBUS2_MMIO_EN_2D,
> 				   GLAMO_HOSTBUS2_MMIO_EN_2D);
> 		break;
> +	case GLAMO_ENGINE_3D:
> +		__reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_3D,
> +				   GLAMO_CLOCK_3D_EN_M8CLK |
> +				   GLAMO_CLOCK_3D_EN_ECLK |
> +				   GLAMO_CLOCK_3D_EN_RCLK |
> +				   GLAMO_CLOCK_3D_DG_M8CLK |
> +				   GLAMO_CLOCK_3D_DG_RCLK |
> +				   GLAMO_CLOCK_3D_DG_ECLK, 0xffff);
> +		/* Enable 3D MMIO */
> +		__reg_set_bit_mask(glamo, GLAMO_REG_HOSTBUS(2),
> +				   GLAMO_HOSTBUS2_MMIO_EN_3D,
> +				   GLAMO_HOSTBUS2_MMIO_EN_3D);
> +		break;
> 	case GLAMO_ENGINE_CMDQ:
> 		__reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_2D,
> 				   GLAMO_CLOCK_2D_EN_M6CLK, 0xffff);
> @@ -502,6 +519,22 @@ int __glamo_engine_disable(struct glamo_core  
> *glamo, enum glamo_engine engine)
> 		      GLAMO_CLOCK_MMC_RESET, glamo->base + GLAMO_REG_CLOCK_MMC);
> */
> 		break;
> +	case GLAMO_ENGINE_3D:
> +		/* Leave the 3D state the way it was to start:
> +		 *  Engine clocks disabled, MMIO disabled,
> +		 *  front and back reset set. */
> +		__reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_3D,
> +				   GLAMO_CLOCK_3D_FRONT_RESET |
> +				   GLAMO_CLOCK_3D_BACK_RESET |
> +				   GLAMO_CLOCK_3D_EN_M8CLK |
> +				   GLAMO_CLOCK_3D_EN_ECLK |
> +				   GLAMO_CLOCK_3D_EN_RCLK |
> +				   GLAMO_CLOCK_3D_DG_M8CLK |
> +				   GLAMO_CLOCK_3D_DG_RCLK |
> +				   GLAMO_CLOCK_3D_DG_ECLK, 0x3000);
> +		__reg_set_bit_mask(glamo, GLAMO_REG_HOSTBUS(2),
> +				   GLAMO_HOSTBUS2_MMIO_EN_3D, 0);
> +		break;
> 	default:
> 		break;
> 	}
> @@ -574,6 +607,10 @@ struct glamo_script reset_regs[] = {
> 	[GLAMO_ENGINE_2D] = {
> 		GLAMO_REG_CLOCK_2D, GLAMO_CLOCK_2D_RESET
> 	},
> +	[GLAMO_ENGINE_3D] = {
> +		GLAMO_REG_CLOCK_3D, GLAMO_CLOCK_3D_FRONT_RESET |
> +				    GLAMO_CLOCK_3D_BACK_RESET
> +	},
> 	[GLAMO_ENGINE_JPEG] = {
> 		GLAMO_REG_CLOCK_JPEG, GLAMO_CLOCK_JPEG_RESET
> 	},
> @@ -734,8 +771,8 @@ static struct glamo_script glamo_init_script[] = {
> 	{ GLAMO_REG_CLOCK_ISP,		0x1000 },
> 	{ GLAMO_REG_CLOCK_ISP,		0x3000 },
> 	{ GLAMO_REG_CLOCK_JPEG,		0x1000 },
> -	{ GLAMO_REG_CLOCK_3D,		0x1000 },
> -	{ GLAMO_REG_CLOCK_3D,		0x3000 },
> +	{ GLAMO_REG_CLOCK_3D,		0x1000 }, /* Reset back */
> +	{ GLAMO_REG_CLOCK_3D,		0x3000 }, /* Reset front+back */
> 	{ GLAMO_REG_CLOCK_2D,		0x1000 },
> 	{ GLAMO_REG_CLOCK_2D,		0x3000 },
> 	{ GLAMO_REG_CLOCK_RISC1,	0x1000 },
> @@ -1164,6 +1201,7 @@ static int __init glamo_probe(struct  
> platform_device *pdev)
> 	platform_device_register(&glamo_2d_dev);
>
> 	glamo_3d_dev.dev.parent = &pdev->dev;
> +	glamo_3d_dev.dev.platform_data = glamo;
> 	mangle_mem_resources(glamo_3d_dev.resource,
> 			     glamo_3d_dev.num_resources, glamo->mem);
> 	platform_device_register(&glamo_3d_dev);
> diff --git a/drivers/mfd/glamo/glamo-core.h b/drivers/mfd/glamo/ 
> glamo-core.h
> index fb5f0f6..281fde8 100644
> --- a/drivers/mfd/glamo/glamo-core.h
> +++ b/drivers/mfd/glamo/glamo-core.h
> @@ -4,19 +4,25 @@
> #include <asm/system.h>
> #include <linux/resume-dependency.h>
>
> -/* for the time being, we put the on-screen framebuffer into the  
> lowest
> - * VRAM space.  This should make the code easily compatible with  
> the various
> - * 2MB/4MB/8MB variants of the Smedia chips */
> -#define GLAMO_OFFSET_VRAM	0x800000
> -#define GLAMO_OFFSET_FB	(GLAMO_OFFSET_VRAM)
> -
> -/* we only allocate the minimum possible size for the framebuffer  
> to make
> - * sure we have sufficient memory for other functions of the chip */
> -//#define GLAMO_FB_SIZE	(640*480*4)	/* == 0x12c000 */
> +/* Amount of memory present in the Glamo.
> + * FIXME: This should really by auto-detected */
> #define GLAMO_INTERNAL_RAM_SIZE 0x800000
> -#define GLAMO_MMC_BUFFER_SIZE (64 * 1024)
> -#define GLAMO_FB_SIZE	(GLAMO_INTERNAL_RAM_SIZE -  
> GLAMO_MMC_BUFFER_SIZE)
>
> +/* Memory allocations in Glamo's memory.
> + * - Just over a megabyte for the framebuffer
> + * - 64kiB for MMC buffer
> + * - The rest for 3D graphics stuff */
> +#define GLAMO_FB_SIZE		(640*480*4)	/* == 0x12c000 */
> +#define GLAMO_MMC_BUFFER_SIZE	(64 * 1024)
> +#define GLAMO_3DVRAM_SIZE	(GLAMO_INTERNAL_RAM_SIZE -		\
> +				 GLAMO_FB_SIZE - GLAMO_MMC_BUFFER_SIZE)
> +
> +/* Offsets in Glamo memory for the different uses.
> + * Framebuffer goes at lowest address, then MMC, then 3D. */
> +#define GLAMO_OFFSET_VRAM	0x800000
> +#define GLAMO_OFFSET_FB		(GLAMO_OFFSET_VRAM)
> +#define GLAMO_OFFSET_MMC	(GLAMO_OFFSET_FB + GLAMO_FB_SIZE)
> +#define GLAMO_OFFSET_3DVRAM	(GLAMO_OFFSET_MMC +  
> GLAMO_MMC_BUFFER_SIZE)
>
> struct glamo_core {
> 	int irq;
> -- 
> 1.5.6.3
>
> _______________________________________________
> devel mailing list
> devel at lists.openmoko.org
> https://lists.openmoko.org/mailman/listinfo/devel




More information about the devel mailing list