r2179 - trunk/src/target/kernel/patches

laforge at sita.openmoko.org laforge at sita.openmoko.org
Wed Jun 6 21:30:34 CEST 2007


Author: laforge
Date: 2007-06-06 21:30:04 +0200 (Wed, 06 Jun 2007)
New Revision: 2179

Added:
   trunk/src/target/kernel/patches/smedia-glamo.patch
Modified:
   trunk/src/target/kernel/patches/series
Log:
Add way incomplete and totally untested Smedia Glamo driver base for GTA02


Modified: trunk/src/target/kernel/patches/series
===================================================================
--- trunk/src/target/kernel/patches/series	2007-06-06 18:08:19 UTC (rev 2178)
+++ trunk/src/target/kernel/patches/series	2007-06-06 19:30:04 UTC (rev 2179)
@@ -37,3 +37,4 @@
 s3c2440-nand-disable-hwecc.patch
 hxd8-tsl256x.patch
 pcf50633.patch
+smedia-glamo.patch

Added: trunk/src/target/kernel/patches/smedia-glamo.patch
===================================================================
--- trunk/src/target/kernel/patches/smedia-glamo.patch	2007-06-06 18:08:19 UTC (rev 2178)
+++ trunk/src/target/kernel/patches/smedia-glamo.patch	2007-06-06 19:30:04 UTC (rev 2179)
@@ -0,0 +1,1481 @@
+Index: linux-2.6.21.3-moko/drivers/video/Kconfig
+===================================================================
+--- linux-2.6.21.3-moko.orig/drivers/video/Kconfig
++++ linux-2.6.21.3-moko/drivers/video/Kconfig
+@@ -1633,6 +1633,32 @@
+ 	  The default value can be overridden on the kernel command line
+ 	  using the "ps3fb" option (e.g. "ps3fb=9M");
+ 
++config GLAMO
++	bool
++
++config FB_GLAMO
++	tristate "Smedia Glamo 336x/337x framebuffer support"
++	depends on FB
++	select GLAMO
++	help
++	  Frame buffer driver for the LCD controller in the Smedia Glamo
++	  336x/337x.
++
++	  This driver is also available as a module ( = code which can be
++	  inserted and removed from the running kernel whenever you want). The
++	  module will be called glamofb. If you want to compile it as a module,
++	  say M here and read <file:Documentation/modules.txt>.
++
++	  If unsure, say N.
++
++config FB_GLAMO_SPI
++       bool "Enable SPI Support"
++       depends on FB_GLAMO
++       help
++         Enable a bitbanging SPI adapter driver for the Smedia Glamo. This
++	 SPI interface is frequently used to interconnect the LCM control
++	 interface.
++
+ config FB_VIRTUAL
+ 	tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)"
+ 	depends on FB
+Index: linux-2.6.21.3-moko/drivers/video/Makefile
+===================================================================
+--- linux-2.6.21.3-moko.orig/drivers/video/Makefile
++++ linux-2.6.21.3-moko/drivers/video/Makefile
+@@ -99,6 +99,7 @@
+ obj-$(CONFIG_FB_IBM_GXT4500)	  += gxt4500.o
+ obj-$(CONFIG_FB_PS3)		  += ps3fb.o
+ obj-$(CONFIG_FB_SM501)            += sm501fb.o
++obj-$(CONFIG_FB_GLAMO)		  += glamo/
+ 
+ # Platform or fallback drivers go here
+ obj-$(CONFIG_FB_VESA)             += vesafb.o
+Index: linux-2.6.21.3-moko/drivers/video/glamo/Makefile
+===================================================================
+--- /dev/null
++++ linux-2.6.21.3-moko/drivers/video/glamo/Makefile
+@@ -0,0 +1,10 @@
++#
++# Makefile for the Smedia Glamo framebuffer driver
++#
++
++obj-$(CONFIG_GLAMO)	+= glamo-core.o
++obj-$(CONFIG_FB_GLAMO)	+= glamofb.o
++
++glamofb-objs		:= glamo-fb.o
++
++obj-$(CONFIG_FB_GLAMO_SPI)	+= glamo-spi.o
+Index: linux-2.6.21.3-moko/drivers/video/glamo/glamo-regs.h
+===================================================================
+--- /dev/null
++++ linux-2.6.21.3-moko/drivers/video/glamo/glamo-regs.h
+@@ -0,0 +1,385 @@
++#ifndef _GLAMO_REGS_H
++#define _GLAMO_REGS_H
++
++/* Smedia Glamo 336x/337x driver
++ *
++ * (C) 2007 by OpenMoko, Inc.
++ * Author: Harald Welte <laforge at openmoko.org>
++ * All rights reserved.
++ *
++ * 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
++ */
++
++enum glamo_regster_offsets {
++	GLAMO_REGOFS_GENERIC	= 0x0000,
++	GLAMO_REGOFS_HOSTBUS	= 0x0200,
++	GLAMO_REGOFS_MEMORY	= 0x0300,
++	GLAMO_REGOFS_VIDCAP	= 0x0400,
++	GLAMO_REGOFS_ISP	= 0x0500,
++	GLAMO_REGOFS_JPEG	= 0x0800,
++	GLAMO_REGOFS_MPEG	= 0x0c00,
++	GLAMO_REGOFS_LCD	= 0x1100,
++	GLAMO_REGOFS_MMC	= 0x1400,
++	GLAMO_REGOFS_MPROC0	= 0x1500,
++	GLAMO_REGOFS_MPROC1	= 0x1580,
++	GLAMO_REGOFS_CMDQUEUE	= 0x1600,
++	GLAMO_REGOFS_RISC	= 0x1680,
++	GLAMO_REGOFS_2D		= 0x1700,
++	GLAMO_REGOFS_3D		= 0x1b00,
++};
++
++
++enum glamo_register_generic {
++	GLAMO_REG_GCONF1	= 0x0000,
++	GLAMO_REG_GCONF2	= 0x0002,
++#define	GLAMO_REG_DEVICE_ID	GLAMO_REG_GCONF2
++	GLAMO_REG_GCONF3	= 0x0004,
++#define	GLAMO_REG_REVISION_ID	GLAMO_REG_GCONF3
++	GLAMO_REG_IRQ_GEN1	= 0x0006,
++#define GLAMO_REG_IRQ_ENABLE	GLAMO_REG_IRQ_GEN1
++	GLAMO_REG_IRQ_GEN2	= 0x0008,
++#define GLAMO_REG_IRQ_SET	GLAMO_REG_IRQ_GEN2
++	GLAMO_REG_IRQ_GEN3	= 0x000a,
++#define GLAMO_REG_IRQ_CLEAR	GLAMO_REG_IRQ_GEN3
++	GLAMO_REG_IRQ_GEN4	= 0x000c,
++#define GLAMO_REG_IRQ_STATUS	GLAMO_REG_IRQ_GEN4
++	GLAMO_REG_CLOCK_HOST	= 0x0010,
++	GLAMO_REG_CLOCK_MEMORY	= 0x0012,
++	GLAMO_REG_CLOCK_LCD	= 0x0014,
++	GLAMO_REG_CLOCK_MMC	= 0x0016,
++	GLAMO_REG_CLOCK_ISP	= 0x0018,
++	GLAMO_REG_CLOCK_JPEG	= 0x001a,
++	GLAMO_REG_CLOCK_3D	= 0x001c,
++	GLAMO_REG_CLOCK_2D	= 0x001e,
++	GLAMO_REG_CLOCK_RISC1	= 0x0020,	/* 3365 only? */
++	GLAMO_REG_CLOCK_RISC2	= 0x0022,	/* 3365 only? */
++	GLAMO_REG_CLOCK_MPEG	= 0x0024,
++	GLAMO_REG_CLOCK_MPROC	= 0x0026,
++
++	GLAMO_REG_CLOCK_GEN5_1	= 0x0030,
++	GLAMO_REG_CLOCK_GEN5_2	= 0x0032,
++	GLAMO_REG_CLOCK_GEN6	= 0x0034,
++	GLAMO_REG_CLOCK_GEN7	= 0x0036,
++	GLAMO_REG_CLOCK_GEN8	= 0x0038,
++	GLAMO_REG_CLOCK_GEN9	= 0x003a,
++	GLAMO_REG_CLOCK_GEN10	= 0x003c,
++	GLAMO_REG_CLOCK_GEN11	= 0x003e,
++	GLAMO_REG_PLL_GEN1	= 0x0040,
++	GLAMO_REG_PLL_GEN2	= 0x0042,
++	GLAMO_REG_PLL_GEN3	= 0x0044,
++	GLAMO_REG_PLL_GEN4	= 0x0046,
++	GLAMO_REG_PLL_GEN5	= 0x0048,
++	GLAMO_REG_GPIO_GEN1	= 0x0050,
++	GLAMO_REG_GPIO_GEN2	= 0x0052,
++	GLAMO_REG_GPIO_GEN3	= 0x0054,
++	GLAMO_REG_GPIO_GEN4	= 0x0056,
++	GLAMO_REG_GPIO_GEN5	= 0x0058,
++	GLAMO_REG_GPIO_GEN6	= 0x005a,
++	GLAMO_REG_GPIO_GEN7	= 0x005c,
++	GLAMO_REG_GPIO_GEN8	= 0x005e,
++	GLAMO_REG_GPIO_GEN9	= 0x0060,
++	GLAMO_REG_GPIO_GEN10	= 0x0062,
++	GLAMO_REG_DFT_GEN1	= 0x0070,
++	GLAMO_REG_DFT_GEN2	= 0x0072,
++	GLAMO_REG_DFT_GEN3	= 0x0074,
++	GLAMO_REG_DFT_GEN4	= 0x0076,
++
++	GLAMO_REG_PLL_GEN6	= 0x01e0,
++	GLAMO_REG_PLL_GEN7	= 0x01f0,
++};
++
++#define GLAMO_REG_HOSTBUS(x)	(GLAMO_REGOFS_HOSTBUS-2+(x*2))
++
++#define REG_MEM(x)		(GLAMO_REGOFS_MEMORY+(x))
++#define GLAMO_REG_MEM_TIMING(x)	(GLAMO_REG_MEM_TIMING1-2+(x*2))
++
++enum glamo_register_mem {
++	GLAMO_REG_MEM_TYPE	= REG_MEM(0x00),
++	GLAMO_REG_MEM_GEN	= REG_MEM(0x02),
++	GLAMO_REG_MEM_TIMING1	= REG_MEM(0x04),
++	GLAMO_REG_MEM_TIMING2	= REG_MEM(0x06),
++	GLAMO_REG_MEM_TIMING3	= REG_MEM(0x08),
++	GLAMO_REG_MEM_TIMING4	= REG_MEM(0x0a),
++	GLAMO_REG_MEM_TIMING5	= REG_MEM(0x0c),
++	GLAMO_REG_MEM_TIMING6	= REG_MEM(0x0e),
++	GLAMO_REG_MEM_TIMING7	= REG_MEM(0x10),
++	GLAMO_REG_MEM_TIMING8	= REG_MEM(0x12),
++	GLAMO_REG_MEM_TIMING9	= REG_MEM(0x14),
++	GLAMO_REG_MEM_TIMING10	= REG_MEM(0x16),
++	GLAMO_REG_MEM_TIMING11	= REG_MEM(0x18),
++	GLAMO_REG_MEM_POWER1	= REG_MEM(0x1a),
++	GLAMO_REG_MEM_POWER2	= REG_MEM(0x1c),
++	GLAMO_REG_MEM_LCD_BUF1	= REG_MEM(0x1e),
++	GLAMO_REG_MEM_LCD_BUF2	= REG_MEM(0x20),
++	GLAMO_REG_MEM_LCD_BUF3	= REG_MEM(0x22),
++	GLAMO_REG_MEM_LCD_BUF4	= REG_MEM(0x24),
++	GLAMO_REG_MEM_BIST1	= REG_MEM(0x26),
++	GLAMO_REG_MEM_BIST2	= REG_MEM(0x28),
++	GLAMO_REG_MEM_BIST3	= REG_MEM(0x2a),
++	GLAMO_REG_MEM_BIST4	= REG_MEM(0x2c),
++	GLAMO_REG_MEM_BIST5	= REG_MEM(0x2e),
++	GLAMO_REG_MEM_MAH1	= REG_MEM(0x30),
++	GLAMO_REG_MEM_MAH2	= REG_MEM(0x32),
++	GLAMO_REG_MEM_DRAM1	= REG_MEM(0x34),
++	GLAMO_REG_MEM_DRAM2	= REG_MEM(0x36),
++	GLAMO_REG_MEM_CRC	= REG_MEM(0x38),
++};
++
++enum glamo_irq {
++	GLAMO_IRQ_HOSTBUS	= 0x0001,
++	GLAMO_IRQ_JPEG		= 0x0002,
++	GLAMO_IRQ_MPEG		= 0x0004,
++	GLAMO_IRQ_MPROC1	= 0x0008,
++	GLAMO_IRQ_MPROC0	= 0x0010,
++	GLAMO_IRQ_CMDQUEUE	= 0x0020,
++	GLAMO_IRQ_2D		= 0x0040,
++	GLAMO_IRQ_MMC		= 0x0080,
++	GLAMO_IRQ_RISC		= 0x0100,
++};
++
++enum glamo_reg_clock_host {
++	GLAMO_CLOCK_HOST_DG_BCLK	= 0x0001,
++	GLAMO_CLOCK_HOST_DG_M0CLK	= 0x0004,
++	GLAMO_CLOCK_HOST_RESET		= 0x1000,
++};
++
++enum glamo_reg_clock_mem {
++	GLAMO_CLOCK_MEM_DG_M1CLK	= 0x0001,
++	GLAMO_CLOCK_MEM_EN_M1CLK	= 0x0002,
++	GLAMO_CLOCK_MEM_DG_MOCACLK	= 0x0004,
++	GLAMO_CLOCK_MEM_EN_MOCACLK	= 0x0008,
++	GLAMO_CLOCK_MEM_RESET		= 0x1000,
++	GLAMO_CLOCK_MOCA_RESET		= 0x2000,
++};
++
++enum glamo_reg_clock_lcd {
++	GLAMO_CLOCK_LCD_DG_DCLK		= 0x0001,
++	GLAMO_CLOCK_LCD_EN_DCLK		= 0x0002,
++	GLAMO_CLOCK_LCD_DG_DMCLK	= 0x0004,
++	GLAMO_CLOCK_LCD_EN_DMCLK	= 0x0008,
++	//
++	GLAMO_CLOCK_LCD_EN_DHCLK	= 0x0020,
++	GLAMO_CLOCK_LCD_DG_M5CLK	= 0x0040,
++	GLAMO_CLOCK_LCD_EN_M5CLK	= 0x0080,
++	GLAMO_CLOCK_LCD_RESET		= 0x1000,
++};
++
++enum glamo_reg_clock_mmc {
++	GLAMO_CLOCK_MMC_DG_TCLK		= 0x0001,
++	GLAMO_CLOCK_MMC_EN_TCLK		= 0x0002,
++	GLAMO_CLOCK_MMC_DG_M9CLK	= 0x0004,
++	GLAMO_CLOCK_MMC_EN_M9CLK	= 0x0008,
++	GLAMO_CLOCK_MMC_RESET		= 0x1000,
++};
++
++enum glamo_reg_clock_isp {
++	GLAMO_CLOCK_ISP_DG_I1CLK	= 0x0001,
++	GLAMO_CLOCK_ISP_EN_I1CLK	= 0x0002,
++	GLAMO_CLOCK_ISP_DG_CCLK		= 0x0004,
++	GLAMO_CLOCK_ISP_EN_CCLK		= 0x0008,
++	//
++	GLAMO_CLOCK_ISP_EN_SCLK		= 0x0020,
++	GLAMO_CLOCK_ISP_DG_M2CLK	= 0x0040,
++	GLAMO_CLOCK_ISP_EN_M2CLK	= 0x0080,
++	GLAMO_CLOCK_ISP_DG_M15CLK	= 0x0100,
++	GLAMO_CLOCK_ISP_EN_M15CLK	= 0x0200,
++	GLAMO_CLOCK_ISP1_RESET		= 0x1000,
++	GLAMO_CLOCK_ISP2_RESET		= 0x2000,
++};
++
++enum glamo_reg_clock_jpeg {
++	GLAMO_CLOCK_JPEG_DG_JCLK	= 0x0001,
++	GLAMO_CLOCK_JPEG_EN_JCLK	= 0x0002,
++	GLAMO_CLOCK_JPEG_DG_M3CLK	= 0x0004,
++	GLAMO_CLOCK_JPEG_EN_M3CLK	= 0x0008,
++	GLAMO_CLOCK_JPEG_RESET		= 0x1000,
++};
++
++enum glamo_reg_clock_3d {
++	GLAMO_CLOCK_3D_DG_GCLK		= 0x0001,
++	GLAMO_CLOCK_3D_EN_GCLK		= 0x0002,
++	GLAMO_CLOCK_3D_DG_M7CLK		= 0x0004,
++	GLAMO_CLOCK_3D_EN_M7CLK		= 0x0008,
++	GLAMO_CLOCK_3D_DG_M6CLK		= 0x0010,
++	GLAMO_CLOCK_3D_EN_M6CLK		= 0x0020,
++	GLAMO_CLOCK_3D_2D_RESET		= 0x1000,
++	GLAMO_CLOCK_3D_CQ_RESET		= 0x2000,
++};
++
++enum glamo_reg_clock_mpeg {
++	GLAMO_CLOCK_MPEG_DG_X0CLK	= 0x0001,
++	GLAMO_CLOCK_MPEG_EN_X0CLK	= 0x0002,
++	GLAMO_CLOCK_MPEG_DG_X1CLK	= 0x0004,
++	GLAMO_CLOCK_MPEG_EN_X1CLK	= 0x0008,
++	GLAMO_CLOCK_MPEG_DG_X2CLK	= 0x0010,
++	GLAMO_CLOCK_MPEG_EN_X2CLK	= 0x0020,
++	GLAMO_CLOCK_MPEG_DG_X3CLK	= 0x0040,
++	GLAMO_CLOCK_MPEG_EN_X3CLK	= 0x0080,
++	GLAMO_CLOCK_MPEG_DG_X4CLK	= 0x0100,
++	GLAMO_CLOCK_MPEG_EN_X4CLK	= 0x0200,
++	GLAMO_CLOCK_MPEG_DG_X6CLK	= 0x0400,
++	GLAMO_CLOCK_MPEG_EN_X6CLK	= 0x0800,
++	GLAMO_CLOCK_MPEG_ENC_RESET	= 0x1000,
++	GLAMO_CLOCK_MPEG_DEC_RESET	= 0x2000,
++};
++
++/* LCD Controller */
++
++#define REG_LCD(x)	(x)
++enum glamo_reg_lcd {
++	GLAMO_REG_LCD_MODE1		= REG_LCD(0x00),
++	GLAMO_REG_LCD_MODE2		= REG_LCD(0x02),
++	GLAMO_REG_LCD_MODE3		= REG_LCD(0x04),
++	GLAMO_REG_LCD_WIDTH		= REG_LCD(0x06),
++	GLAMO_REG_LCD_HEIGHT		= REG_LCD(0x08),
++	GLAMO_REG_LCD_POLARITY		= REG_LCD(0x0a),
++	GLAMO_REG_LCD_A_BASE1		= REG_LCD(0x0c),
++	GLAMO_REG_LCD_A_BASE2		= REG_LCD(0x0e),
++	GLAMO_REG_LCD_B_BASE1		= REG_LCD(0x10),
++	GLAMO_REG_LCD_B_BASE2		= REG_LCD(0x12),
++	GLAMO_REG_LCD_C_BASE1		= REG_LCD(0x14),
++	GLAMO_REG_LCD_C_BASE2		= REG_LCD(0x16),
++	GLAMO_REG_LCD_PITCH		= REG_LCD(0x18),
++	/* RES */
++	GLAMO_REG_LCD_HORIZ_TOTAL	= REG_LCD(0x1c),
++	/* RES */
++	GLAMO_REG_LCD_HORIZ_RETR_START	= REG_LCD(0x20),
++	/* RES */
++	GLAMO_REG_LCD_HORIZ_RETR_END	= REG_LCD(0x24),
++	/* RES */
++	GLAMO_REG_LCD_HORIZ_DISP_START	= REG_LCD(0x28),
++	/* RES */
++	GLAMO_REG_LCD_HORIZ_DISP_END	= REG_LCD(0x2c),
++	/* RES */
++	GLAMO_REG_LCD_VERT_TOTAL	= REG_LCD(0x30),
++	/* RES */
++	GLAMO_REG_LCD_VERT_RETR_START	= REG_LCD(0x34),
++	/* RES */
++	GLAMO_REG_LCD_VERT_RETR_END	= REG_LCD(0x38),
++	/* RES */
++	GLAMO_REG_LCD_VERT_DISP_START	= REG_LCD(0x3c),
++	/* RES */
++	GLAMO_REG_LCD_VERT_DISP_END	= REG_LCD(0x40),
++	/* RES */
++	GLAMO_REG_LCD_POL		= REG_LCD(0x44),
++	GLAMO_REG_LCD_DATA_START	= REG_LCD(0x46),
++	GLAMO_REG_LCD_FRATE_CONTRO	= REG_LCD(0x48),
++	GLAMO_REG_LCD_DATA_CMD_HDR	= REG_LCD(0x4a),
++	GLAMO_REG_LCD_SP_START		= REG_LCD(0x4c),
++	GLAMO_REG_LCD_SP_END		= REG_LCD(0x4e),
++	GLAMO_REG_LCD_CURSOR_BASE1	= REG_LCD(0x50),
++	GLAMO_REG_LCD_CURSOR_BASE2	= REG_LCD(0x52),
++	GLAMO_REG_LCD_CURSOR_PITCH	= REG_LCD(0x54),
++	GLAMO_REG_LCD_CURSOR_X_SIZE	= REG_LCD(0x56),
++	GLAMO_REG_LCD_CURSOR_Y_SIZE	= REG_LCD(0x58),
++	GLAMO_REG_LCD_CURSOR_X_POS	= REG_LCD(0x5a),
++	GLAMO_REG_LCD_CURSOR_Y_POS	= REG_LCD(0x5c),
++	GLAMO_REG_LCD_CURSOR_PRESET	= REG_LCD(0x5e),
++	GLAMO_REG_LCD_CURSOR_FG_COLOR	= REG_LCD(0x60),
++	/* RES */
++	GLAMO_REG_LCD_CURSOR_BG_COLOR	= REG_LCD(0x64),
++	/* RES */
++	GLAMO_REG_LCD_CURSOR_DST_COLOR	= REG_LCD(0x68),
++	/* RES */
++	GLAMO_REG_LCD_STATUS1		= REG_LCD(0x80),
++	GLAMO_REG_LCD_STATUS2		= REG_LCD(0x82),
++	GLAMO_REG_LCD_STATUS3		= REG_LCD(0x84),
++	GLAMO_REG_LCD_STATUS4		= REG_LCD(0x86),
++	/* RES */
++	GLAMO_REG_LCD_COMMAND1		= REG_LCD(0xa0),
++	GLAMO_REG_LCD_COMMAND2		= REG_LCD(0xa2),
++	/* RES */
++	GLAMO_REG_LCD_WFORM_DELAY1	= REG_LCD(0xb0),
++	GLAMO_REG_LCD_WFORM_DELAY2	= REG_LCD(0xb2),
++	/* RES */
++	GLAMO_REG_LCD_GAMMA_CORR	= REG_LCD(0x100),
++	/* RES */
++	GLAMO_REG_LCD_GAMMA_R_ENTRY01	= REG_LCD(0x110),
++	GLAMO_REG_LCD_GAMMA_R_ENTRY23	= REG_LCD(0x112),
++	GLAMO_REG_LCD_GAMMA_R_ENTRY45	= REG_LCD(0x114),
++	GLAMO_REG_LCD_GAMMA_R_ENTRY67	= REG_LCD(0x116),
++	GLAMO_REG_LCD_GAMMA_R_ENTRY8	= REG_LCD(0x118),
++	/* RES */
++	GLAMO_REG_LCD_GAMMA_G_ENTRY01	= REG_LCD(0x130),
++	GLAMO_REG_LCD_GAMMA_G_ENTRY23	= REG_LCD(0x132),
++	GLAMO_REG_LCD_GAMMA_G_ENTRY45	= REG_LCD(0x134),
++	GLAMO_REG_LCD_GAMMA_G_ENTRY67	= REG_LCD(0x136),
++	GLAMO_REG_LCD_GAMMA_G_ENTRY8	= REG_LCD(0x138),
++	/* RES */
++	GLAMO_REG_LCD_GAMMA_B_ENTRY01	= REG_LCD(0x150),
++	GLAMO_REG_LCD_GAMMA_B_ENTRY23	= REG_LCD(0x152),
++	GLAMO_REG_LCD_GAMMA_B_ENTRY45	= REG_LCD(0x154),
++	GLAMO_REG_LCD_GAMMA_B_ENTRY67	= REG_LCD(0x156),
++	GLAMO_REG_LCD_GAMMA_B_ENTRY8	= REG_LCD(0x158),
++	/* RES */
++	GLAMO_REG_LCD_SRAM_DRIVING1	= REG_LCD(0x160),
++	GLAMO_REG_LCD_SRAM_DRIVING2	= REG_LCD(0x162),
++	GLAMO_REG_LCD_SRAM_DRIVING3	= REG_LCD(0x164),
++};
++
++enum glamo_reg_lcd_mode1 {
++	GLAMO_LCD_MODE1_PWRSAVE		= 0x0001,
++	GLAMO_LCD_MODE1_PARTIAL_PRT	= 0x0002,
++	GLAMO_LCD_MODE1_HWFLIP		= 0x0004,
++	GLAMO_LCD_MODE1_LCD2		= 0x0008,
++	/* RES */
++	GLAMO_LCD_MODE1_PARTIAL_MODE	= 0x0020,
++	GLAMO_LCD_MODE1_CURSOR_DSTCOLOR	= 0x0040,
++	GLAMO_LCD_MODE1_PARTIAL_ENABLE	= 0x0080,
++	GLAMO_LCD_MODE1_TVCLK_IN_ENABLE	= 0x0100,
++	GLAMO_LCD_MODE1_HSYNC_HIGH_ACT	= 0x0200,
++	GLAMO_LCD_MODE1_VSYNC_HIGH_ACT	= 0x0400,
++	GLAMO_LCD_MODE1_HSYNC_FLIP	= 0x0800,
++	GLAMO_LCD_MODE1_GAMMA_COR_EN	= 0x1000,
++	GLAMO_LCD_MODE1_DITHER_EN	= 0x2000,
++	GLAMO_LCD_MODE1_CURSOR_EN	= 0x4000,
++	GLAMO_LCD_MODE1_ROTATE_EN	= 0x8000,
++};
++
++enum glamo_reg_lcd_mode2 {
++	GLAMO_LCD_MODE2_CRC_CHECK_EN	= 0x0001,
++	GLAMO_LCD_MODE2_DCMD_PER_LINE	= 0x0002,
++	GLAMO_LCD_MODE2_NOUSE_BDEF	= 0x0004,
++	GLAMO_LCD_MODE2_OUT_POS_MODE	= 0x0008,
++	GLAMO_LCD_MODE2_FRATE_CTRL_EN	= 0x0010,
++	GLAMO_LCD_MODE2_SINGLE_BUFFER	= 0x0020,
++	GLAMO_LCD_MODE2_SER_LSB_TO_MSB	= 0x0040,
++	/* FIXME */
++};
++
++enum glamo_reg_lcd_mode3 {
++	/* LCD color source data format */
++	GLAMO_LCD_SRC_RGB565		= 0x0000,
++	GLAMO_LCD_SRC_ARGB1555		= 0x4000,
++	GLAMO_LCD_SRC_ARGB4444		= 0x8000,
++	/* interface type */
++	GLAMO_LCD_MODE3_LCD		= 0x1000,
++	GLAMO_LCD_MODE3_RGB		= 0x0800,
++	GLAMO_LCD_MODE3_CPU		= 0x0000,
++	/* mode */
++	GLAMO_LCD_MODE3_RGB332		= 0x0000,
++	GLAMO_LCD_MODE3_RGB444		= 0x0100,
++	GLAMO_LCD_MODE3_RGB565		= 0x0200,
++	GLAMO_LCD_MODE3_RGB666		= 0x0300,
++	/* depth */
++	GLAMO_LCD_MODE3_6BITS		= 0x0000,
++	GLAMO_LCD_MODE3_8BITS		= 0x0010,
++	GLAMO_LCD_MODE3_9BITS		= 0x0020,
++	GLAMO_LCD_MODE3_16BITS		= 0x0030,
++	GLAMO_LCD_MODE3_18BITS		= 0x0040,
++};
++
++#endif /* _GLAMO_REGS_H */
+Index: linux-2.6.21.3-moko/drivers/video/glamo/glamo-spi.c
+===================================================================
+--- /dev/null
++++ linux-2.6.21.3-moko/drivers/video/glamo/glamo-spi.c
+@@ -0,0 +1,203 @@
++/*
++ * Copyright (C) 2007 OpenMoko, Inc.
++ * Author: Harald Welte <laforge at openmoko.org>
++ *
++ * Smedia Glamo GPIO based SPI driver
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++*/
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/spinlock.h>
++#include <linux/workqueue.h>
++#include <linux/platform_device.h>
++
++#include <linux/spi/spi.h>
++#include <linux/spi/spi_bitbang.h>
++
++#include <asm/arch/regs-gpio.h>
++#include <asm/arch/spi-gpio.h>
++#include <asm/hardware.h>
++
++struct glamo_spigpio {
++	struct spi_bitbang		 bitbang;
++
++	struct glamo_spigpio_info	*info;
++	struct platform_device		*dev;
++};
++
++static inline struct glamo_spigpio *spidev_to_sg(struct spi_device *spi)
++{
++	return spi->controller_data;
++}
++
++static inline void setsck(struct spi_device *dev, int on)
++{
++	struct glamp_spigpio *sg = spidev_to_sg(dev);
++	s3c2410_gpio_setpin(sg->info->pin_clk, on ? 1 : 0);
++}
++
++static inline void setmosi(struct spi_device *dev, int on)
++{
++	struct glamo_spigpio *sg = spidev_to_sg(dev);
++	s3c2410_gpio_setpin(sg->info->pin_mosi, on ? 1 : 0);
++}
++
++static inline u32 getmiso(struct spi_device *dev)
++{
++	struct glamo_spigpio *sg = spidev_to_sg(dev);
++	return s3c2410_gpio_getpin(sg->info->pin_miso) ? 1 : 0;
++}
++
++#define spidelay(x) ndelay(x)
++
++#define	EXPAND_BITBANG_TXRX
++#include <linux/spi/spi_bitbang.h>
++
++
++static u32 glamo_spigpio_txrx_mode0(struct spi_device *spi,
++				      unsigned nsecs, u32 word, u8 bits)
++{
++	return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits);
++}
++
++static u32 glamo_spigpio_txrx_mode1(struct spi_device *spi,
++				      unsigned nsecs, u32 word, u8 bits)
++{
++	return bitbang_txrx_be_cpha1(spi, nsecs, 0, word, bits);
++}
++
++static u32 glamo_spigpio_txrx_mode2(struct spi_device *spi,
++				      unsigned nsecs, u32 word, u8 bits)
++{
++	return bitbang_txrx_be_cpha0(spi, nsecs, 1, word, bits);
++}
++
++static u32 glamo_spigpio_txrx_mode3(struct spi_device *spi,
++				      unsigned nsecs, u32 word, u8 bits)
++{
++	return bitbang_txrx_be_cpha1(spi, nsecs, 1, word, bits);
++}
++
++
++static void glamo_spigpio_chipselect(struct spi_device *dev, int value)
++{
++	struct glamo_spigpio *sg = spidev_to_sg(dev);
++
++	if (sg->info && sg->info->chip_select)
++		(sg->info->chip_select)(sg->info, value);
++}
++
++static int glamo_spigpio_probe(struct platform_device *dev)
++{
++	struct spi_master *master;
++	struct glamo_spigpio *sp;
++	int ret;
++	int i;
++
++	master = spi_alloc_master(&dev->dev, sizeof(struct glamo_spigpio));
++	if (master == NULL) {
++		dev_err(&dev->dev, "failed to allocate spi master\n");
++		ret = -ENOMEM;
++		goto err;
++	}
++
++	sp = spi_master_get_devdata(master);
++
++	platform_set_drvdata(dev, sp);
++
++	/* copy in the plkatform data */
++	sp->info = dev->dev.platform_data;
++
++	/* setup spi bitbang adaptor */
++	sp->bitbang.master = spi_master_get(master);
++	sp->bitbang.chipselect = glamo_spigpio_chipselect;
++
++	sp->bitbang.txrx_word[SPI_MODE_0] = glamo_spigpio_txrx_mode0;
++	sp->bitbang.txrx_word[SPI_MODE_1] = glamo_spigpio_txrx_mode1;
++	sp->bitbang.txrx_word[SPI_MODE_2] = glamo_spigpio_txrx_mode2;
++	sp->bitbang.txrx_word[SPI_MODE_3] = glamo_spigpio_txrx_mode3;
++
++#if 0
++	/* set state of spi pins */
++	s3c2410_gpio_setpin(sp->info->pin_clk, 0);
++	s3c2410_gpio_setpin(sp->info->pin_mosi, 0);
++
++	s3c2410_gpio_cfgpin(sp->info->pin_clk, S3C2410_GPIO_OUTPUT);
++	s3c2410_gpio_cfgpin(sp->info->pin_mosi, S3C2410_GPIO_OUTPUT);
++	s3c2410_gpio_cfgpin(sp->info->pin_miso, S3C2410_GPIO_INPUT);
++#endif
++
++	ret = spi_bitbang_start(&sp->bitbang);
++	if (ret)
++		goto err_no_bitbang;
++
++	/* register the chips to go with the board */
++
++	for (i = 0; i < sp->info->board_size; i++) {
++		dev_info(&dev->dev, "registering %p: %s\n",
++			 &sp->info->board_info[i],
++			 sp->info->board_info[i].modalias);
++
++		sp->info->board_info[i].controller_data = sp;
++		spi_new_device(master, sp->info->board_info + i);
++	}
++
++	return 0;
++
++ err_no_bitbang:
++	spi_master_put(sp->bitbang.master);
++ err:
++	return ret;
++
++}
++
++static int glamo_spigpio_remove(struct platform_device *dev)
++{
++	struct glamo_spigpio *sp = platform_get_drvdata(dev);
++
++	spi_bitbang_stop(&sp->bitbang);
++	spi_master_put(sp->bitbang.master);
++
++	return 0;
++}
++
++/* all gpio should be held over suspend/resume, so we should
++ * not need to deal with this
++*/
++
++#define glamo_spigpio_suspend NULL
++#define glamo_spigpio_resume NULL
++
++static struct platform_driver glamo_spigpio_drv = {
++	.probe		= glamo_spigpio_probe,
++        .remove		= glamo_spigpio_remove,
++        .suspend	= glamo_spigpio_suspend,
++        .resume		= glamo_spigpio_resume,
++        .driver		= {
++		.name	= "glamo-spi",
++		.owner	= THIS_MODULE,
++        },
++};
++
++static int __init glamo_spigpio_init(void)
++{
++        return platform_driver_register(&glamo_spigpio_drv);
++}
++
++static void __exit glamo_spigpio_exit(void)
++{
++        platform_driver_unregister(&glamo_spigpio_drv);
++}
++
++module_init(glamo_spigpio_init);
++module_exit(glamo_spigpio_exit);
++
++MODULE_DESCRIPTION("Smedia Glamo 336x/337x SPI Driver");
++MODULE_AUTHOR("Harald Welte <laforge at openmoko.org>")
++MODULE_LICENSE("GPL");
+Index: linux-2.6.21.3-moko/drivers/video/glamo/glamo-core.c
+===================================================================
+--- /dev/null
++++ linux-2.6.21.3-moko/drivers/video/glamo/glamo-core.c
+@@ -0,0 +1,389 @@
++/* Smedia Glamo 336x/337x driver
++ *
++ * (C) 2007 by OpenMoko, Inc.
++ * Author: Harald Welte <laforge at openmoko.org>
++ * All rights reserved.
++ *
++ * 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/kernel.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/mm.h>
++#include <linux/tty.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include <linux/fb.h>
++#include <linux/init.h>
++#include <linux/irq.h>
++#include <linux/vmalloc.h>
++#include <linux/dma-mapping.h>
++#include <linux/interrupt.h>
++#include <linux/workqueue.h>
++#include <linux/wait.h>
++#include <linux/platform_device.h>
++#include <linux/kernel_stat.h>
++#include <linux/clk.h>
++
++#include <asm/io.h>
++#include <asm/uaccess.h>
++#include <asm/div64.h>
++
++#ifdef CONFIG_PM
++#include <linux/pm.h>
++#endif
++
++#include "glamo-regs.h"
++
++#define RESSIZE(ressource) (((ressource)->end - (ressource)->start)+1)
++
++struct glamo_core {
++	int irq;
++	struct resource *mem;
++	void __iomem *base;
++};
++
++static struct glamo_core *glamo_handle;
++
++static inline void __reg_write(struct glamo_core *glamo,
++				u_int16_t reg, u_int16_t val)
++{
++	writew(val, glamo->base + reg);
++}
++
++static inline u_int16_t __reg_read(struct glamo_core *glamo,
++				   u_int16_t reg)
++{
++	return readw(glamo->base + reg);
++}
++
++/* resources of 'sibling' devices */
++
++#if 0
++static struct resource glamo_core_resources[] = {
++	{
++		.start	= GLAMO_REGOFS_GENERIC,
++		.end	= GLAMO_REGOFS_GENERIC + 0x400,
++		.flags	= IORESOURCE_MEM,
++	}, {
++		.start	= 0,
++		.end	= 0,
++		.flags	= IORESOURCE_IRQ,
++	},
++};
++
++static struct platform_device glamo_core_dev = {
++	.name		= "glamo-core",
++	.resource	= &glamo_core_resources,
++	.num_resources	= ARRAY_SIZE(glamo_core_resources),
++};
++#endif
++
++static struct resource glamo_mmc_resources[] = {
++	{
++		/* FIXME: those need to be incremented by parent base */
++		.start	= GLAMO_REGOFS_MMC,
++		.end	= GLAMO_REGOFS_MMC + 0x100,
++		.flags	= IORESOURCE_MEM
++	}, {
++		.start	= IRQ_GLAMO_MMC,
++		.end	= IRQ_GLAMO_MMC,
++		.flags	= IORESOURCE_IRQ,
++	},
++};
++
++static struct platform_device glamo_mmc_dev = {
++	.name		= "glamo-mmc",
++	.resource	= glamo_mmc_resources,
++	.num_resources	= ARRAY_SIZE(glamo_mmc_resources),
++};
++
++/* 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 */
++
++static struct resource glamo_fb_resources[] = {
++	/* FIXME: those need to be incremented by parent base */
++	{
++		.name	= "glamo-fb-regs",
++		.start	= GLAMO_REGOFS_LCD,
++		.end	= GLAMO_REGOFS_LCD + 0x100,
++		.flags	= IORESOURCE_MEM,
++	}, {
++		.name	= "glamo-fb-mem",
++		.start	= GLAMO_OFFSET_FB,
++		.end	= GLAMO_OFFSET_FB + GLAMO_FB_SIZE,
++		.flags	= IORESOURCE_MEM,
++	},
++};
++
++static struct platform_device glamo_fb_dev = {
++	.name		= "glamo-fb",
++	.resource	= glamo_fb_resources,
++	.num_resources	= ARRAY_SIZE(glamo_fb_resources),
++};
++
++static void mangle_mem_resources(struct resource *res, int num_res,
++				 struct resource *parent)
++{
++	int i;
++
++	for (i = 0; i < num_res; i++) {
++		if (res[i].flags != IORESOURCE_MEM)
++			continue;
++		res[i].start += parent->start;
++		res[i].end += parent->start;
++		res[i].parent = parent;
++	}
++}
++
++#define irq2glamo(x)	(x - IRQ_GLAMO(0))
++
++/* IRQ demultiplexer */
++static void glamo_ack_irq(unsigned int irq)
++{
++	/* clear interrupt source */
++	__reg_write(glamo_handle, GLAMO_REG_IRQ_CLEAR,
++		    1 << irq2glamo(irq));
++}
++
++static void glamo_mask_irq(unsigned int irq)
++{
++	u_int16_t tmp;
++
++	/* clear bit in enable register */
++	tmp = __reg_read(glamo_handle, GLAMO_REG_IRQ_ENABLE);
++	tmp &= ~(1 << irq2glamo(irq));
++	__reg_write(glamo_handle, GLAMO_REG_IRQ_ENABLE, tmp);
++}
++
++static void glamo_unmask_irq(unsigned int irq)
++{
++	u_int16_t tmp;
++
++	/* set bit in enable register */
++	tmp = __reg_read(glamo_handle, GLAMO_REG_IRQ_ENABLE);
++	tmp |= (1 << irq2glamo(irq));
++	__reg_write(glamo_handle, GLAMO_REG_IRQ_ENABLE, tmp);
++}
++
++static struct irq_chip glamo_irq_chip = {
++	.ack	= glamo_ack_irq,
++	.mask	= glamo_mask_irq,
++	.unmask	= glamo_unmask_irq,
++};
++
++static void glamo_irq_demux_handler(unsigned int irq, struct irq_desc *desc)
++{
++	const unsigned int cpu = smp_processor_id();
++
++	spin_lock(&desc->lock);
++
++	desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
++
++	if (unlikely(desc->status & IRQ_INPROGRESS)) {
++		desc->status |= (IRQ_PENDING | IRQ_MASKED);
++		desc->chip->mask(irq);
++		desc->chip->ack(irq);
++		goto out_unlock;
++	}
++
++	kstat_cpu(cpu).irqs[irq]++;
++	desc->chip->ack(irq);
++	desc->status |= IRQ_INPROGRESS;
++
++	do {
++		u_int16_t irqstatus;
++		int i;
++
++		if (unlikely((desc->status &
++				(IRQ_PENDING | IRQ_MASKED | IRQ_DISABLED)) ==
++				(IRQ_PENDING | IRQ_MASKED))) {
++			/* dealing with pending IRQ, unmasking */
++			desc->chip->unmask(irq);
++			desc->status &= ~IRQ_MASKED;
++		}
++
++		desc->status &= ~IRQ_PENDING;
++
++		/* read IRQ status register */
++		irqstatus = __reg_read(glamo_handle, GLAMO_REG_IRQ_STATUS);
++		for (i = 0; i < 9; i++) {
++			if (irqstatus & (1 << i)) {
++				irq = IRQ_GLAMO(0) + i;
++				desc = irq_desc + irq;
++				desc_handle_irq(irq, desc);
++			}
++		}
++
++	} while ((desc->status & (IRQ_PENDING | IRQ_DISABLED)) == IRQ_PENDING);
++
++	desc->status &= ~IRQ_INPROGRESS;
++
++out_unlock:
++	spin_unlock(&desc->lock);
++}
++
++static int __init glamo_probe(struct platform_device *pdev)
++{
++	int rc, irq;
++	struct glamo_core *glamo;
++
++	if (glamo_handle) {
++		dev_err(&pdev->dev,
++			"This driver supports only one instance\n");
++		return -EBUSY;
++	}
++
++	glamo = kmalloc(GFP_KERNEL, sizeof(*glamo));
++	if (!glamo)
++		return -ENOMEM;
++
++	glamo->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	glamo->irq = platform_get_irq(pdev, 0);
++	if (!glamo->irq || !glamo->mem) {
++		dev_err(&pdev->dev, "platform device with no IRQ/MEM ?\n");
++		rc = -ENOENT;
++		goto out_free;
++	}
++
++	glamo->mem = request_mem_region(glamo->mem->start,
++					RESSIZE(glamo->mem), pdev->name);
++	if (!glamo->mem) {
++		dev_err(&pdev->dev, "failed to request memory region\n");
++		goto out_free;
++	}
++
++	/* we want to remap only the registers required for this core
++	 * driver. */
++	glamo->base = ioremap(glamo->mem->start, GLAMO_REGOFS_VIDCAP);
++	if (!glamo->base) {
++		dev_err(&pdev->dev, "failed to ioremap() memory region\n");
++		goto out_free;
++	}
++
++	/* ... and register a number of sibling devices whoise IOMEM resources
++	 * are siblings of pdev's IOMEM resource */
++#if 0
++	glamo_core_dev.dev.parent = &pdev.dev;
++	mangle_mem_resources(glamo_core_dev.resources,
++			     glamo_core_dev.num_resources, glamo->mem);
++	glamo_core_dev.resources[1].start = glamo->irq;
++	glamo_core_dev.resources[1].end = glamo->irq;
++#endif
++
++	glamo_mmc_dev.dev.parent = &pdev->dev;
++	mangle_mem_resources(glamo_mmc_dev.resource,
++			     glamo_mmc_dev.num_resources, glamo->mem);
++	platform_device_register(&glamo_mmc_dev);
++
++	glamo_fb_dev.dev.parent = &pdev->dev;
++	mangle_mem_resources(glamo_fb_dev.resource,
++			     glamo_fb_dev.num_resources, glamo->mem);
++	platform_device_register(&glamo_fb_dev);
++
++	platform_set_drvdata(pdev, glamo);
++
++	/* FIXME: do we need to request_irq() it ? */
++	for (irq = IRQ_GLAMO(0); irq <= IRQ_GLAMO(8); irq++) {
++		set_irq_chip(irq, &glamo_irq_chip);
++		set_irq_handler(irq, handle_level_irq);
++		set_irq_flags(irq, IRQF_VALID);
++	}
++	set_irq_chained_handler(glamo->irq, glamo_irq_demux_handler);
++	set_irq_type(glamo->irq, IRQT_FALLING);
++
++	return 0;
++
++out_free:
++	kfree(glamo);
++	return rc;
++}
++
++static int __exit glamo_remove(struct platform_device *pdev)
++{
++	struct glamo_core *glamo = platform_get_drvdata(pdev);
++	int irq;
++
++	disable_irq(glamo->irq);
++	set_irq_chained_handler(glamo->irq, NULL);
++
++	for (irq = IRQ_GLAMO(0); irq <= IRQ_GLAMO(8); irq++) {
++		set_irq_flags(irq, 0);
++		set_irq_chip(irq, NULL);
++	}
++
++	platform_set_drvdata(pdev, NULL);
++	platform_device_unregister(&glamo_fb_dev);
++	platform_device_unregister(&glamo_mmc_dev);
++	iounmap(glamo->base);
++	release_mem_region(glamo->mem->start, GLAMO_REGOFS_VIDCAP);
++	glamo_handle = NULL;
++	kfree(glamo);
++
++	return 0;
++}
++
++#ifdef CONFIG_PM
++static int glamo_suspend(struct platform_device *pdev, pm_message_t state)
++{
++	return 0;
++}
++
++static int glamo_resume(struct platform_device *pdev)
++{
++	return 0;
++}
++#else
++#define glamo_suspend NULL
++#define glamo_resume  NULL
++#endif
++
++static struct platform_driver glamo_driver = {
++	.probe		= glamo_probe,
++	.remove		= glamo_remove,
++	.suspend	= glamo_suspend,
++	.resume		= glamo_resume,
++	.driver		= {
++		.name	= "glamo3362",
++		.owner	= THIS_MODULE,
++	},
++};
++
++static int __devinit glamo_init(void)
++{
++	return platform_driver_register(&glamo_driver);
++}
++
++static void __exit glamo_cleanup(void)
++{
++	platform_driver_unregister(&glamo_driver);
++}
++
++module_init(glamo_init);
++module_exit(glamo_cleanup);
++
++MODULE_AUTHOR("Harald Welte <laforge at openmoko.org>");
++MODULE_DESCRIPTION("Smedia Glamo 336x/337x core/resource driver");
++MODULE_LICENSE("GPL");
+Index: linux-2.6.21.3-moko/include/asm-arm/arch-s3c2410/irqs.h
+===================================================================
+--- linux-2.6.21.3-moko.orig/include/asm-arm/arch-s3c2410/irqs.h
++++ linux-2.6.21.3-moko/include/asm-arm/arch-s3c2410/irqs.h
+@@ -148,9 +148,37 @@
+ #define IRQ_S3C2443_AC97	S3C2410_IRQSUB(28)
+ 
+ #ifdef CONFIG_CPU_S3C2443
+-#define NR_IRQS (IRQ_S3C2443_AC97+1)
++#define _NR_IRQS (IRQ_S3C2443_AC97+1)
+ #else
+-#define NR_IRQS (IRQ_S3C2440_AC97+1)
++#define _NR_IRQS (IRQ_S3C2440_AC97+1)
+ #endif
+ 
++/*
++ * The next 16 interrupts are for board specific purposes.  Since
++ * the kernel can only run on one machine at a time, we can re-use
++ * these.  If you need more, increase IRQ_BOARD_END, but keep it
++ * within sensible limits.
++ */
++#define IRQ_BOARD_START		_NR_IRQS
++#define IRQ_BOARD_END		(_NR_IRQS + 1)
++
++#if defined(CONFIG_MACH_NEO1973_GTA02)
++#define NR_IRQS			(IRQ_BOARD_END)
++#else
++#define NR_IRQS			(IRQ_BOARD_START)
++#endif
++
++/* Neo1973 GTA02 interrupts */
++#define NEO1973_GTA02_IRQ(x)	(IRQ_BOARD_START + (x))
++#define IRQ_GLAMO(x)		NEO1973_GTA02_IRQ(x)
++#define IRQ_GLAMO_HOSTBUS	IRQ_GLAMO(0)
++#define IRQ_GLAMO_JPEG		IRQ_GLAMO(1)
++#define IRQ_GLAMO_MPEG		IRQ_GLAMO(2)
++#define IRQ_GLAMO_MPROC1	IRQ_GLAMO(3)
++#define IRQ_GLAMO_MPROC0	IRQ_GLAMO(4)
++#define IRQ_GLAMO_CMDQUEUE	IRQ_GLAMO(5)
++#define IRQ_GLAMO_2D		IRQ_GLAMO(6)
++#define IRQ_GLAMO_MMC		IRQ_GLAMO(7)
++#define IRQ_GLAMO_RISC		IRQ_GLAMO(8)
++
+ #endif /* __ASM_ARCH_IRQ_H */
+Index: linux-2.6.21.3-moko/drivers/video/glamo/glamo-fb.c
+===================================================================
+--- /dev/null
++++ linux-2.6.21.3-moko/drivers/video/glamo/glamo-fb.c
+@@ -0,0 +1,353 @@
++/* Smedia Glamo 336x/337x driver
++ *
++ * (C) 2007 by OpenMoko, Inc.
++ * Author: Harald Welte <laforge at openmoko.org>
++ * All rights reserved.
++ *
++ * 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/kernel.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/mm.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include <linux/fb.h>
++#include <linux/init.h>
++#include <linux/vmalloc.h>
++#include <linux/dma-mapping.h>
++#include <linux/interrupt.h>
++#include <linux/workqueue.h>
++#include <linux/wait.h>
++#include <linux/platform_device.h>
++#include <linux/clk.h>
++
++#include <asm/io.h>
++#include <asm/uaccess.h>
++#include <asm/div64.h>
++
++#ifdef CONFIG_PM
++#include <linux/pm.h>
++#endif
++
++#include <linux/glamofb.h>
++
++#include "glamo-regs.h"
++
++#define RESSIZE(ressource) (((ressource)->end - (ressource)->start)+1)
++
++struct glamofb_handle {
++	struct fb_info *fb;
++	struct device *dev;
++	struct resource *reg;
++	struct resource *fb_res;
++	char __iomem *base;
++	struct glamofb_platform_data *mach_info;
++};
++
++static inline int reg_read(struct glamofb_handle *glamo,
++			   u_int16_t reg)
++{
++	return readw(glamo->base + reg);
++}
++
++static int glamofb_check_var(struct fb_var_screeninfo *var,
++			     struct fb_info *info)
++{
++	struct glamofb_handle *glamo = info->par;
++	u_int16_t mode;
++
++	if (var->yres > glamo->mach_info->yres.max)
++		var->yres = glamo->mach_info->yres.max;
++	else if (var->yres < glamo->mach_info->yres.min)
++		var->yres = glamo->mach_info->yres.min;
++
++	if (var->xres > glamo->mach_info->xres.max)
++		var->xres = glamo->mach_info->xres.max;
++	else if (var->xres < glamo->mach_info->xres.min)
++		var->xres = glamo->mach_info->xres.min;
++
++	if (var->bits_per_pixel > glamo->mach_info->bpp.max)
++		var->bits_per_pixel = glamo->mach_info->bpp.max;
++	else if (var->bits_per_pixel < glamo->mach_info->bpp.min)
++		var->bits_per_pixel = glamo->mach_info->bpp.min;
++
++	/* FIXME: set rgb positions */
++	switch (var->bits_per_pixel) {
++	case 16:
++		switch (reg_read(glamo, GLAMO_REG_LCD_MODE3) & 0xc000) {
++		case GLAMO_LCD_SRC_RGB565:
++			var->red.offset		= 11;
++			var->green.offset	= 5;
++			var->blue.offset	= 0;
++			var->red.length		= 5;
++			var->green.length	= 6;
++			var->blue.length	= 5;
++			var->transp.length	= 0;
++			break;
++		case GLAMO_LCD_SRC_ARGB1555:
++			var->transp.offset	= 15;
++			var->red.offset		= 10;
++			var->green.offset	= 5;
++			var->blue.offset	= 0;
++			var->transp.length	= 1;
++			var->red.length		= 5;
++			var->green.length	= 5;
++			var->blue.length	= 5;
++			break;
++		case GLAMO_LCD_SRC_ARGB4444:
++			var->transp.offset	= 12;
++			var->red.offset		= 8;
++			var->green.offset	= 4;
++			var->blue.offset	= 0;
++			var->transp.length	= 4;
++			var->red.length		= 4;
++			var->green.length	= 4;
++			var->blue.length	= 4;
++			break;
++		}
++	case 24:
++	case 32:
++	default:
++		/* The Smedia Glamo doesn't support anything but 16bit color */
++		return -EINVAL;
++		break;
++	}
++}
++
++static int glamofb_set_par(struct fb_info *info)
++{
++	struct glamofb_handle *glamo = info->par;
++	struct fb_var_screeninfo *var = &info->var;
++
++	/* FIXME */
++	return 0;
++}
++
++static int glamofb_blank(int blank_mode, struct fb_info *info)
++{
++	/* FIXME */
++	return 0;
++}
++
++static int glamofb_setcolreg(unsigned regno,
++			     unsigned red, unsigned green, unsigned blue,
++			     unsigned transp, struct fb_info *info)
++{
++	return 0;
++}
++
++static struct fb_ops glamofb_ops = {
++	.owner		= THIS_MODULE,
++	.fb_check_var	= glamofb_check_var,
++	.fb_set_par	= glamofb_set_par,
++	.fb_blank	= glamofb_blank,
++	.fb_setcolreg	= glamofb_setcolreg,
++	.fb_fillrect	= cfb_fillrect,
++	.fb_copyarea	= cfb_copyarea,
++	.fb_imageblit	= cfb_imageblit,
++};
++
++static int __init glamofb_probe(struct platform_device *pdev)
++{
++	int rc = -EIO;
++	struct fb_info *fbinfo;
++	struct glamofb_handle *glamofb;
++	struct glamofb_platform_data *mach_info = pdev->dev.platform_data;
++
++	fbinfo = framebuffer_alloc(sizeof(struct glamofb_handle), &pdev->dev);
++	if (!fbinfo)
++		return -ENOMEM;
++
++	glamofb = fbinfo->par;
++	glamofb->fb = fbinfo;
++	glamofb->dev = &pdev->dev;
++
++	strcpy(fbinfo->fix.id, "SMedia Glamo");
++
++	glamofb->reg = platform_get_resource_byname(pdev, IORESOURCE_MEM,
++						    "glamo-fb-regs");
++	if (!glamofb->reg) {
++		dev_err(&pdev->dev, "platform device with no registers?\n");
++		rc = -ENOENT;
++		goto out_free;
++	}
++
++	glamofb->fb_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
++							"glamo-fb-mem");
++	if (!glamofb->fb_res) {
++		dev_err(&pdev->dev, "platform device with no memory ?\n");
++		rc = -ENOENT;
++		goto out_free;
++	}
++
++	glamofb->reg = request_mem_region(glamofb->reg->start,
++					  RESSIZE(glamofb->reg), pdev->name);
++	if (!glamofb->reg) {
++		dev_err(&pdev->dev, "failed to request memory region\n");
++		goto out_free;
++	}
++
++	glamofb->fb_res = request_mem_region(glamofb->fb_res->start,
++					  RESSIZE(glamofb->fb_res), pdev->name);
++	if (!glamofb->fb_res) {
++		dev_err(&pdev->dev, "failed to request memory region\n");
++		goto out_release_reg;
++	}
++
++	/* we want to remap only the registers required for this core
++	 * driver. */
++	glamofb->base = ioremap(glamofb->reg->start, GLAMO_REGOFS_VIDCAP);
++	if (!glamofb->base) {
++		dev_err(&pdev->dev, "failed to ioremap() memory region\n");
++		goto out_release_fb;
++	}
++	fbinfo->fix.smem_start = (unsigned long) glamofb->base;
++
++	fbinfo->screen_base = ioremap(glamofb->fb_res->start,
++				       RESSIZE(glamofb->fb_res));
++	if (!fbinfo->screen_base) {
++		dev_err(&pdev->dev, "failed to ioremap() memory region\n");
++		goto out_release_fb;
++	}
++
++	platform_set_drvdata(pdev, fbinfo);
++
++	glamofb->mach_info = pdev->dev.platform_data;
++
++	fbinfo->fix.type = FB_TYPE_PACKED_PIXELS;
++	fbinfo->fix.type_aux = 0;
++	fbinfo->fix.xpanstep = 0;
++	fbinfo->fix.ypanstep = 0;
++	fbinfo->fix.ywrapstep = 0;
++	fbinfo->fix.accel = FB_ACCEL_NONE; /* FIXME */
++
++	fbinfo->var.nonstd = 0;
++	fbinfo->var.activate = FB_ACTIVATE_NOW;
++	fbinfo->var.height = mach_info->height;
++	fbinfo->var.width = mach_info->width;
++	fbinfo->var.accel_flags = 0;
++	fbinfo->var.vmode = FB_VMODE_NONINTERLACED;
++
++	fbinfo->fbops = &glamofb_ops;
++	fbinfo->flags = FBINFO_FLAG_DEFAULT;
++	//fbinfo->pseudo_palette =
++
++	fbinfo->var.xres = mach_info->xres.defval;
++	fbinfo->var.xres_virtual = mach_info->xres.defval;
++	fbinfo->var.yres = mach_info->yres.defval;
++	fbinfo->var.yres_virtual = mach_info->yres.defval;
++	fbinfo->var.bits_per_pixel = mach_info->bpp.defval;
++
++#if 0
++	fbinfo->var.upper_margin =
++	fbinfo->var.lower_margin =
++	fbinfo->var.vsync_len =
++
++	fbinfo->var.left_margin =
++	fbinfo->var.right_margin =
++	fbinfo->var.hsync_len =
++#endif
++
++	fbinfo->var.red.offset = 11;
++	fbinfo->var.green.offset = 5;
++	fbinfo->var.blue.offset = 0;
++	fbinfo->var.transp.offset = 0;
++	fbinfo->var.red.length = 5;
++	fbinfo->var.green.length = 6;
++	fbinfo->var.blue.length = 5;
++	fbinfo->var.transp.length = 0;
++	fbinfo->fix.smem_len = mach_info->xres.max *
++			       mach_info->yres.max *
++			       mach_info->bpp.max / 8;
++
++	rc = register_framebuffer(fbinfo);
++	if (rc < 0) {
++		dev_err(&pdev->dev, "failed to register framebuffer\n");
++		goto out_unmap_fb;
++	}
++
++	return 0;
++
++out_unmap_fb:
++	iounmap(fbinfo->screen_base);
++out_unmap:
++	iounmap(glamofb->base);
++out_release_fb:
++	release_mem_region(glamofb->fb_res->start, RESSIZE(glamofb->fb_res));
++out_release_reg:
++	release_mem_region(glamofb->reg->start, RESSIZE(glamofb->reg));
++out_free:
++	framebuffer_release(fbinfo);
++	return rc;
++}
++
++static int __exit glamofb_remove(struct platform_device *pdev)
++{
++	struct glamofb_handle *glamofb = platform_get_drvdata(pdev);
++
++	platform_set_drvdata(pdev, NULL);
++	iounmap(glamofb->base);
++	release_mem_region(glamofb->reg->start, RESSIZE(glamofb->reg));
++	kfree(glamofb);
++
++	return 0;
++}
++
++#ifdef CONFIG_PM
++static int glamofb_suspend(struct platform_device *pdev, pm_message_t state)
++{
++	return 0;
++}
++
++static int glamofb_resume(struct platform_device *pdev)
++{
++	return 0;
++}
++#else
++#define glamofb_suspend NULL
++#define glamofb_resume  NULL
++#endif
++
++static struct platform_driver glamofb_driver = {
++	.probe		= glamofb_probe,
++	.remove		= glamofb_remove,
++	.suspend	= glamofb_suspend,
++	.resume		= glamofb_resume,
++	.driver		= {
++		.name	= "glamo-fb",
++		.owner	= THIS_MODULE,
++	},
++};
++
++static int __devinit glamofb_init(void)
++{
++	return platform_driver_register(&glamofb_driver);
++}
++
++static void __exit glamofb_cleanup(void)
++{
++	platform_driver_unregister(&glamofb_driver);
++}
++
++module_init(glamofb_init);
++module_exit(glamofb_cleanup);
++
++MODULE_AUTHOR("Harald Welte <laforge at openmoko.org>");
++MODULE_DESCRIPTION("Smedia Glamo 336x/337x framebuffer driver");
++MODULE_LICENSE("GPL");
+Index: linux-2.6.21.3-moko/include/linux/glamofb.h
+===================================================================
+--- /dev/null
++++ linux-2.6.21.3-moko/include/linux/glamofb.h
+@@ -0,0 +1,18 @@
++#ifndef _LINUX_GLAMOFB_H
++#define _LINUX_GLAMOFB_H
++
++struct glamofb_val {
++	unsigned int defval;
++	unsigned int min;
++	unsigned int max;
++};
++
++struct glamofb_platform_data {
++	int width, height;
++
++	struct glamofb_val xres;
++	struct glamofb_val yres;
++	struct glamofb_val bpp;
++};
++
++#endif





More information about the commitlog mailing list