diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2005-10-29 15:19:15 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-10-29 15:19:15 -0400 |
commit | e9d52234e35b27ea4ea5f2ab64ca47b1a0c740ab (patch) | |
tree | 318d37a7d55c79e6f7d86163fb28e0eccbb0fe83 /drivers | |
parent | 955c5038823748e529a49f0e33ab635d92843500 (diff) | |
parent | 09af7b443c257460d45cb6c1896d29f173fef35b (diff) |
Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/char/lcd.c | 4 | ||||
-rw-r--r-- | drivers/char/lcd.h | 2 | ||||
-rw-r--r-- | drivers/char/qtronix.c | 5 | ||||
-rw-r--r-- | drivers/ide/Kconfig | 31 | ||||
-rw-r--r-- | drivers/ide/ide-proc.c | 1 | ||||
-rw-r--r-- | drivers/ide/mips/au1xxx-ide.c | 1250 | ||||
-rw-r--r-- | drivers/media/video/indycam.c | 10 | ||||
-rw-r--r-- | drivers/media/video/saa7191.c | 14 | ||||
-rw-r--r-- | drivers/media/video/vino.c | 7 | ||||
-rw-r--r-- | drivers/mmc/Kconfig | 9 | ||||
-rw-r--r-- | drivers/mmc/Makefile | 1 | ||||
-rw-r--r-- | drivers/mmc/au1xmmc.c | 1026 | ||||
-rw-r--r-- | drivers/mmc/au1xmmc.h | 96 | ||||
-rw-r--r-- | drivers/pcmcia/Makefile | 2 | ||||
-rw-r--r-- | drivers/pcmcia/au1000_db1x00.c | 21 | ||||
-rw-r--r-- | drivers/pcmcia/au1000_generic.c | 8 | ||||
-rw-r--r-- | drivers/pcmcia/au1000_generic.h | 4 | ||||
-rw-r--r-- | drivers/scsi/dec_esp.c | 2 | ||||
-rw-r--r-- | drivers/tc/tc.c | 89 | ||||
-rw-r--r-- | drivers/tc/zs.c | 32 | ||||
-rw-r--r-- | drivers/video/Kconfig | 8 | ||||
-rw-r--r-- | drivers/video/Makefile | 2 | ||||
-rw-r--r-- | drivers/video/au1100fb.c | 971 | ||||
-rw-r--r-- | drivers/video/au1100fb.h | 614 | ||||
-rw-r--r-- | drivers/video/console/newport_con.c | 1 | ||||
-rw-r--r-- | drivers/video/gbefb.c | 20 |
26 files changed, 3335 insertions, 895 deletions
diff --git a/drivers/char/lcd.c b/drivers/char/lcd.c index b77161146144..29963d8be667 100644 --- a/drivers/char/lcd.c +++ b/drivers/char/lcd.c | |||
@@ -575,8 +575,8 @@ static inline int button_pressed(void) | |||
575 | 575 | ||
576 | static int lcd_waiters = 0; | 576 | static int lcd_waiters = 0; |
577 | 577 | ||
578 | static long lcd_read(struct inode *inode, struct file *file, char *buf, | 578 | static ssize_t lcd_read(struct file *file, char *buf, |
579 | unsigned long count) | 579 | size_t count, loff_t *ofs) |
580 | { | 580 | { |
581 | long buttons_now; | 581 | long buttons_now; |
582 | 582 | ||
diff --git a/drivers/char/lcd.h b/drivers/char/lcd.h index 878a95280e87..a8d4ae737158 100644 --- a/drivers/char/lcd.h +++ b/drivers/char/lcd.h | |||
@@ -22,7 +22,7 @@ static int timeout(volatile unsigned long); | |||
22 | #define MAX_IDLE_TIME 120 | 22 | #define MAX_IDLE_TIME 120 |
23 | 23 | ||
24 | struct lcd_display { | 24 | struct lcd_display { |
25 | unsigned long buttons; | 25 | unsigned buttons; |
26 | int size1; | 26 | int size1; |
27 | int size2; | 27 | int size2; |
28 | unsigned char line1[LCD_CHARS_PER_LINE]; | 28 | unsigned char line1[LCD_CHARS_PER_LINE]; |
diff --git a/drivers/char/qtronix.c b/drivers/char/qtronix.c index 40a3cf62e1a8..601d09baf9d7 100644 --- a/drivers/char/qtronix.c +++ b/drivers/char/qtronix.c | |||
@@ -591,6 +591,11 @@ static int __init psaux_init(void) | |||
591 | return retval; | 591 | return retval; |
592 | 592 | ||
593 | queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL); | 593 | queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL); |
594 | if (!queue) { | ||
595 | misc_deregister(&psaux_mouse); | ||
596 | return -ENOMEM; | ||
597 | } | ||
598 | |||
594 | memset(queue, 0, sizeof(*queue)); | 599 | memset(queue, 0, sizeof(*queue)); |
595 | queue->head = queue->tail = 0; | 600 | queue->head = queue->tail = 0; |
596 | init_waitqueue_head(&queue->proc_list); | 601 | init_waitqueue_head(&queue->proc_list); |
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index 1cadd2c3cadd..a737886e39d1 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig | |||
@@ -778,6 +778,35 @@ config BLK_DEV_IDE_PMAC_BLINK | |||
778 | This option enables the use of the sleep LED as a hard drive | 778 | This option enables the use of the sleep LED as a hard drive |
779 | activity LED. | 779 | activity LED. |
780 | 780 | ||
781 | config BLK_DEV_IDE_AU1XXX | ||
782 | bool "IDE for AMD Alchemy Au1200" | ||
783 | depends on SOC_AU1200 | ||
784 | choice | ||
785 | prompt "IDE Mode for AMD Alchemy Au1200" | ||
786 | default CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA | ||
787 | depends on SOC_AU1200 && BLK_DEV_IDE_AU1XXX | ||
788 | |||
789 | config BLK_DEV_IDE_AU1XXX_PIO_DBDMA | ||
790 | bool "PIO+DbDMA IDE for AMD Alchemy Au1200" | ||
791 | |||
792 | config BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA | ||
793 | bool "MDMA2+DbDMA IDE for AMD Alchemy Au1200" | ||
794 | depends on SOC_AU1200 && BLK_DEV_IDE_AU1XXX | ||
795 | endchoice | ||
796 | |||
797 | config BLK_DEV_IDE_AU1XXX_BURSTABLE_ON | ||
798 | bool "Enable burstable Mode on DbDMA" | ||
799 | default false | ||
800 | depends BLK_DEV_IDE_AU1XXX | ||
801 | help | ||
802 | This option enable the burstable Flag on DbDMA controller | ||
803 | (cf. "AMD Alchemy 'Au1200' Processor Data Book - PRELIMINARY"). | ||
804 | |||
805 | config BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ | ||
806 | int "Maximum transfer size (KB) per request (up to 128)" | ||
807 | default "128" | ||
808 | depends BLK_DEV_IDE_AU1XXX | ||
809 | |||
781 | config IDE_ARM | 810 | config IDE_ARM |
782 | def_bool ARM && (ARCH_A5K || ARCH_CLPS7500 || ARCH_RPC || ARCH_SHARK) | 811 | def_bool ARM && (ARCH_A5K || ARCH_CLPS7500 || ARCH_RPC || ARCH_SHARK) |
783 | 812 | ||
@@ -1013,7 +1042,7 @@ config BLK_DEV_UMC8672 | |||
1013 | endif | 1042 | endif |
1014 | 1043 | ||
1015 | config BLK_DEV_IDEDMA | 1044 | config BLK_DEV_IDEDMA |
1016 | def_bool BLK_DEV_IDEDMA_PCI || BLK_DEV_IDEDMA_PMAC || BLK_DEV_IDEDMA_ICS | 1045 | def_bool BLK_DEV_IDEDMA_PCI || BLK_DEV_IDEDMA_PMAC || BLK_DEV_IDEDMA_ICS || BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA |
1017 | 1046 | ||
1018 | config IDEDMA_IVB | 1047 | config IDEDMA_IVB |
1019 | bool "IGNORE word93 Validation BITS" | 1048 | bool "IGNORE word93 Validation BITS" |
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c index 4063d2c34e3d..84665e2ba3c8 100644 --- a/drivers/ide/ide-proc.c +++ b/drivers/ide/ide-proc.c | |||
@@ -64,6 +64,7 @@ static int proc_ide_read_imodel | |||
64 | case ide_cy82c693: name = "cy82c693"; break; | 64 | case ide_cy82c693: name = "cy82c693"; break; |
65 | case ide_4drives: name = "4drives"; break; | 65 | case ide_4drives: name = "4drives"; break; |
66 | case ide_pmac: name = "mac-io"; break; | 66 | case ide_pmac: name = "mac-io"; break; |
67 | case ide_au1xxx: name = "au1xxx"; break; | ||
67 | default: name = "(unknown)"; break; | 68 | default: name = "(unknown)"; break; |
68 | } | 69 | } |
69 | len = sprintf(page, "%s\n", name); | 70 | len = sprintf(page, "%s\n", name); |
diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c new file mode 100644 index 000000000000..2b6327c576b9 --- /dev/null +++ b/drivers/ide/mips/au1xxx-ide.c | |||
@@ -0,0 +1,1250 @@ | |||
1 | /* | ||
2 | * linux/drivers/ide/mips/au1xxx-ide.c version 01.30.00 Aug. 02 2005 | ||
3 | * | ||
4 | * BRIEF MODULE DESCRIPTION | ||
5 | * AMD Alchemy Au1xxx IDE interface routines over the Static Bus | ||
6 | * | ||
7 | * Copyright (c) 2003-2005 AMD, Personal Connectivity Solutions | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it under | ||
10 | * the terms of the GNU General Public License as published by the Free Software | ||
11 | * Foundation; either version 2 of the License, or (at your option) any later | ||
12 | * version. | ||
13 | * | ||
14 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, | ||
15 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR | ||
17 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
18 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
19 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
20 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
21 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
22 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
23 | * POSSIBILITY OF SUCH DAMAGE. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License along with | ||
26 | * this program; if not, write to the Free Software Foundation, Inc., | ||
27 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
28 | * | ||
29 | * Note: for more information, please refer "AMD Alchemy Au1200/Au1550 IDE | ||
30 | * Interface and Linux Device Driver" Application Note. | ||
31 | */ | ||
32 | #undef REALLY_SLOW_IO /* most systems can safely undef this */ | ||
33 | |||
34 | #include <linux/config.h> /* for CONFIG_BLK_DEV_IDEPCI */ | ||
35 | #include <linux/types.h> | ||
36 | #include <linux/module.h> | ||
37 | #include <linux/kernel.h> | ||
38 | #include <linux/delay.h> | ||
39 | #include <linux/timer.h> | ||
40 | #include <linux/mm.h> | ||
41 | #include <linux/ioport.h> | ||
42 | #include <linux/hdreg.h> | ||
43 | #include <linux/init.h> | ||
44 | #include <linux/ide.h> | ||
45 | #include <linux/sysdev.h> | ||
46 | |||
47 | #include <linux/dma-mapping.h> | ||
48 | |||
49 | #include <asm/io.h> | ||
50 | #include <asm/mach-au1x00/au1xxx.h> | ||
51 | #include <asm/mach-au1x00/au1xxx_dbdma.h> | ||
52 | |||
53 | #if CONFIG_PM | ||
54 | #include <asm/mach-au1x00/au1xxx_pm.h> | ||
55 | #endif | ||
56 | |||
57 | #include <asm/mach-au1x00/au1xxx_ide.h> | ||
58 | |||
59 | #define DRV_NAME "au1200-ide" | ||
60 | #define DRV_VERSION "1.0" | ||
61 | #define DRV_AUTHOR "AMD PCS / Pete Popov <ppopov@embeddedalley.com>" | ||
62 | #define DRV_DESC "Au1200 IDE" | ||
63 | |||
64 | static _auide_hwif auide_hwif; | ||
65 | static spinlock_t ide_tune_drive_spin_lock = SPIN_LOCK_UNLOCKED; | ||
66 | static spinlock_t ide_tune_chipset_spin_lock = SPIN_LOCK_UNLOCKED; | ||
67 | static int dbdma_init_done = 0; | ||
68 | |||
69 | /* | ||
70 | * local I/O functions | ||
71 | */ | ||
72 | u8 auide_inb(unsigned long port) | ||
73 | { | ||
74 | return (au_readb(port)); | ||
75 | } | ||
76 | |||
77 | u16 auide_inw(unsigned long port) | ||
78 | { | ||
79 | return (au_readw(port)); | ||
80 | } | ||
81 | |||
82 | u32 auide_inl(unsigned long port) | ||
83 | { | ||
84 | return (au_readl(port)); | ||
85 | } | ||
86 | |||
87 | void auide_insw(unsigned long port, void *addr, u32 count) | ||
88 | { | ||
89 | #if defined(CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA) | ||
90 | |||
91 | _auide_hwif *ahwif = &auide_hwif; | ||
92 | chan_tab_t *ctp; | ||
93 | au1x_ddma_desc_t *dp; | ||
94 | |||
95 | if(!put_dest_flags(ahwif->rx_chan, (void*)addr, count << 1, | ||
96 | DDMA_FLAGS_NOIE)) { | ||
97 | printk(KERN_ERR "%s failed %d\n", __FUNCTION__, __LINE__); | ||
98 | return; | ||
99 | } | ||
100 | ctp = *((chan_tab_t **)ahwif->rx_chan); | ||
101 | dp = ctp->cur_ptr; | ||
102 | while (dp->dscr_cmd0 & DSCR_CMD0_V) | ||
103 | ; | ||
104 | ctp->cur_ptr = au1xxx_ddma_get_nextptr_virt(dp); | ||
105 | #else | ||
106 | while (count--) | ||
107 | { | ||
108 | *(u16 *)addr = au_readw(port); | ||
109 | addr +=2 ; | ||
110 | } | ||
111 | #endif | ||
112 | } | ||
113 | |||
114 | void auide_insl(unsigned long port, void *addr, u32 count) | ||
115 | { | ||
116 | while (count--) | ||
117 | { | ||
118 | *(u32 *)addr = au_readl(port); | ||
119 | /* NOTE: For IDE interfaces over PCMCIA, | ||
120 | * 32-bit access does not work | ||
121 | */ | ||
122 | addr += 4; | ||
123 | } | ||
124 | } | ||
125 | |||
126 | void auide_outb(u8 addr, unsigned long port) | ||
127 | { | ||
128 | return (au_writeb(addr, port)); | ||
129 | } | ||
130 | |||
131 | void auide_outbsync(ide_drive_t *drive, u8 addr, unsigned long port) | ||
132 | { | ||
133 | return (au_writeb(addr, port)); | ||
134 | } | ||
135 | |||
136 | void auide_outw(u16 addr, unsigned long port) | ||
137 | { | ||
138 | return (au_writew(addr, port)); | ||
139 | } | ||
140 | |||
141 | void auide_outl(u32 addr, unsigned long port) | ||
142 | { | ||
143 | return (au_writel(addr, port)); | ||
144 | } | ||
145 | |||
146 | void auide_outsw(unsigned long port, void *addr, u32 count) | ||
147 | { | ||
148 | #if defined(CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA) | ||
149 | _auide_hwif *ahwif = &auide_hwif; | ||
150 | chan_tab_t *ctp; | ||
151 | au1x_ddma_desc_t *dp; | ||
152 | |||
153 | if(!put_source_flags(ahwif->tx_chan, (void*)addr, | ||
154 | count << 1, DDMA_FLAGS_NOIE)) { | ||
155 | printk(KERN_ERR "%s failed %d\n", __FUNCTION__, __LINE__); | ||
156 | return; | ||
157 | } | ||
158 | ctp = *((chan_tab_t **)ahwif->tx_chan); | ||
159 | dp = ctp->cur_ptr; | ||
160 | while (dp->dscr_cmd0 & DSCR_CMD0_V) | ||
161 | ; | ||
162 | ctp->cur_ptr = au1xxx_ddma_get_nextptr_virt(dp); | ||
163 | #else | ||
164 | while (count--) | ||
165 | { | ||
166 | au_writew(*(u16 *)addr, port); | ||
167 | addr += 2; | ||
168 | } | ||
169 | #endif | ||
170 | } | ||
171 | |||
172 | void auide_outsl(unsigned long port, void *addr, u32 count) | ||
173 | { | ||
174 | while (count--) | ||
175 | { | ||
176 | au_writel(*(u32 *)addr, port); | ||
177 | /* NOTE: For IDE interfaces over PCMCIA, | ||
178 | * 32-bit access does not work | ||
179 | */ | ||
180 | addr += 4; | ||
181 | } | ||
182 | } | ||
183 | |||
184 | static void auide_tune_drive(ide_drive_t *drive, byte pio) | ||
185 | { | ||
186 | int mem_sttime; | ||
187 | int mem_stcfg; | ||
188 | unsigned long flags; | ||
189 | u8 speed; | ||
190 | |||
191 | /* get the best pio mode for the drive */ | ||
192 | pio = ide_get_best_pio_mode(drive, pio, 4, NULL); | ||
193 | |||
194 | printk("%s: setting Au1XXX IDE to PIO mode%d\n", | ||
195 | drive->name, pio); | ||
196 | |||
197 | spin_lock_irqsave(&ide_tune_drive_spin_lock, flags); | ||
198 | |||
199 | mem_sttime = 0; | ||
200 | mem_stcfg = au_readl(MEM_STCFG2); | ||
201 | |||
202 | /* set pio mode! */ | ||
203 | switch(pio) { | ||
204 | case 0: | ||
205 | /* set timing parameters for RCS2# */ | ||
206 | mem_sttime = SBC_IDE_PIO0_TWCS | ||
207 | | SBC_IDE_PIO0_TCSH | ||
208 | | SBC_IDE_PIO0_TCSOFF | ||
209 | | SBC_IDE_PIO0_TWP | ||
210 | | SBC_IDE_PIO0_TCSW | ||
211 | | SBC_IDE_PIO0_TPM | ||
212 | | SBC_IDE_PIO0_TA; | ||
213 | /* set configuration for RCS2# */ | ||
214 | mem_stcfg |= TS_MASK; | ||
215 | mem_stcfg &= ~TCSOE_MASK; | ||
216 | mem_stcfg &= ~TOECS_MASK; | ||
217 | mem_stcfg |= SBC_IDE_PIO0_TCSOE | SBC_IDE_PIO0_TOECS; | ||
218 | |||
219 | au_writel(mem_sttime,MEM_STTIME2); | ||
220 | au_writel(mem_stcfg,MEM_STCFG2); | ||
221 | break; | ||
222 | |||
223 | case 1: | ||
224 | /* set timing parameters for RCS2# */ | ||
225 | mem_sttime = SBC_IDE_PIO1_TWCS | ||
226 | | SBC_IDE_PIO1_TCSH | ||
227 | | SBC_IDE_PIO1_TCSOFF | ||
228 | | SBC_IDE_PIO1_TWP | ||
229 | | SBC_IDE_PIO1_TCSW | ||
230 | | SBC_IDE_PIO1_TPM | ||
231 | | SBC_IDE_PIO1_TA; | ||
232 | /* set configuration for RCS2# */ | ||
233 | mem_stcfg |= TS_MASK; | ||
234 | mem_stcfg &= ~TCSOE_MASK; | ||
235 | mem_stcfg &= ~TOECS_MASK; | ||
236 | mem_stcfg |= SBC_IDE_PIO1_TCSOE | SBC_IDE_PIO1_TOECS; | ||
237 | break; | ||
238 | |||
239 | case 2: | ||
240 | /* set timing parameters for RCS2# */ | ||
241 | mem_sttime = SBC_IDE_PIO2_TWCS | ||
242 | | SBC_IDE_PIO2_TCSH | ||
243 | | SBC_IDE_PIO2_TCSOFF | ||
244 | | SBC_IDE_PIO2_TWP | ||
245 | | SBC_IDE_PIO2_TCSW | ||
246 | | SBC_IDE_PIO2_TPM | ||
247 | | SBC_IDE_PIO2_TA; | ||
248 | /* set configuration for RCS2# */ | ||
249 | mem_stcfg &= ~TS_MASK; | ||
250 | mem_stcfg &= ~TCSOE_MASK; | ||
251 | mem_stcfg &= ~TOECS_MASK; | ||
252 | mem_stcfg |= SBC_IDE_PIO2_TCSOE | SBC_IDE_PIO2_TOECS; | ||
253 | break; | ||
254 | |||
255 | case 3: | ||
256 | /* set timing parameters for RCS2# */ | ||
257 | mem_sttime = SBC_IDE_PIO3_TWCS | ||
258 | | SBC_IDE_PIO3_TCSH | ||
259 | | SBC_IDE_PIO3_TCSOFF | ||
260 | | SBC_IDE_PIO3_TWP | ||
261 | | SBC_IDE_PIO3_TCSW | ||
262 | | SBC_IDE_PIO3_TPM | ||
263 | | SBC_IDE_PIO3_TA; | ||
264 | /* set configuration for RCS2# */ | ||
265 | mem_stcfg |= TS_MASK; | ||
266 | mem_stcfg &= ~TS_MASK; | ||
267 | mem_stcfg &= ~TCSOE_MASK; | ||
268 | mem_stcfg &= ~TOECS_MASK; | ||
269 | mem_stcfg |= SBC_IDE_PIO3_TCSOE | SBC_IDE_PIO3_TOECS; | ||
270 | |||
271 | break; | ||
272 | |||
273 | case 4: | ||
274 | /* set timing parameters for RCS2# */ | ||
275 | mem_sttime = SBC_IDE_PIO4_TWCS | ||
276 | | SBC_IDE_PIO4_TCSH | ||
277 | | SBC_IDE_PIO4_TCSOFF | ||
278 | | SBC_IDE_PIO4_TWP | ||
279 | | SBC_IDE_PIO4_TCSW | ||
280 | | SBC_IDE_PIO4_TPM | ||
281 | | SBC_IDE_PIO4_TA; | ||
282 | /* set configuration for RCS2# */ | ||
283 | mem_stcfg &= ~TS_MASK; | ||
284 | mem_stcfg &= ~TCSOE_MASK; | ||
285 | mem_stcfg &= ~TOECS_MASK; | ||
286 | mem_stcfg |= SBC_IDE_PIO4_TCSOE | SBC_IDE_PIO4_TOECS; | ||
287 | break; | ||
288 | } | ||
289 | |||
290 | au_writel(mem_sttime,MEM_STTIME2); | ||
291 | au_writel(mem_stcfg,MEM_STCFG2); | ||
292 | |||
293 | spin_unlock_irqrestore(&ide_tune_drive_spin_lock, flags); | ||
294 | |||
295 | speed = pio + XFER_PIO_0; | ||
296 | ide_config_drive_speed(drive, speed); | ||
297 | } | ||
298 | |||
299 | static int auide_tune_chipset (ide_drive_t *drive, u8 speed) | ||
300 | { | ||
301 | u8 mode = 0; | ||
302 | int mem_sttime; | ||
303 | int mem_stcfg; | ||
304 | unsigned long flags; | ||
305 | #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA | ||
306 | struct hd_driveid *id = drive->id; | ||
307 | |||
308 | /* | ||
309 | * Now see what the current drive is capable of, | ||
310 | * selecting UDMA only if the mate said it was ok. | ||
311 | */ | ||
312 | if (id && (id->capability & 1) && drive->autodma && | ||
313 | !__ide_dma_bad_drive(drive)) { | ||
314 | if (!mode && (id->field_valid & 2) && (id->dma_mword & 7)) { | ||
315 | if (id->dma_mword & 4) | ||
316 | mode = XFER_MW_DMA_2; | ||
317 | else if (id->dma_mword & 2) | ||
318 | mode = XFER_MW_DMA_1; | ||
319 | else if (id->dma_mword & 1) | ||
320 | mode = XFER_MW_DMA_0; | ||
321 | } | ||
322 | } | ||
323 | #endif | ||
324 | |||
325 | spin_lock_irqsave(&ide_tune_chipset_spin_lock, flags); | ||
326 | |||
327 | mem_sttime = 0; | ||
328 | mem_stcfg = au_readl(MEM_STCFG2); | ||
329 | |||
330 | switch(speed) { | ||
331 | case XFER_PIO_4: | ||
332 | case XFER_PIO_3: | ||
333 | case XFER_PIO_2: | ||
334 | case XFER_PIO_1: | ||
335 | case XFER_PIO_0: | ||
336 | auide_tune_drive(drive, (speed - XFER_PIO_0)); | ||
337 | break; | ||
338 | #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA | ||
339 | case XFER_MW_DMA_2: | ||
340 | /* set timing parameters for RCS2# */ | ||
341 | mem_sttime = SBC_IDE_MDMA2_TWCS | ||
342 | | SBC_IDE_MDMA2_TCSH | ||
343 | | SBC_IDE_MDMA2_TCSOFF | ||
344 | | SBC_IDE_MDMA2_TWP | ||
345 | | SBC_IDE_MDMA2_TCSW | ||
346 | | SBC_IDE_MDMA2_TPM | ||
347 | | SBC_IDE_MDMA2_TA; | ||
348 | /* set configuration for RCS2# */ | ||
349 | mem_stcfg &= ~TS_MASK; | ||
350 | mem_stcfg &= ~TCSOE_MASK; | ||
351 | mem_stcfg &= ~TOECS_MASK; | ||
352 | mem_stcfg |= SBC_IDE_MDMA2_TCSOE | SBC_IDE_MDMA2_TOECS; | ||
353 | |||
354 | mode = XFER_MW_DMA_2; | ||
355 | break; | ||
356 | case XFER_MW_DMA_1: | ||
357 | /* set timing parameters for RCS2# */ | ||
358 | mem_sttime = SBC_IDE_MDMA1_TWCS | ||
359 | | SBC_IDE_MDMA1_TCSH | ||
360 | | SBC_IDE_MDMA1_TCSOFF | ||
361 | | SBC_IDE_MDMA1_TWP | ||
362 | | SBC_IDE_MDMA1_TCSW | ||
363 | | SBC_IDE_MDMA1_TPM | ||
364 | | SBC_IDE_MDMA1_TA; | ||
365 | /* set configuration for RCS2# */ | ||
366 | mem_stcfg &= ~TS_MASK; | ||
367 | mem_stcfg &= ~TCSOE_MASK; | ||
368 | mem_stcfg &= ~TOECS_MASK; | ||
369 | mem_stcfg |= SBC_IDE_MDMA1_TCSOE | SBC_IDE_MDMA1_TOECS; | ||
370 | |||
371 | mode = XFER_MW_DMA_1; | ||
372 | break; | ||
373 | case XFER_MW_DMA_0: | ||
374 | /* set timing parameters for RCS2# */ | ||
375 | mem_sttime = SBC_IDE_MDMA0_TWCS | ||
376 | | SBC_IDE_MDMA0_TCSH | ||
377 | | SBC_IDE_MDMA0_TCSOFF | ||
378 | | SBC_IDE_MDMA0_TWP | ||
379 | | SBC_IDE_MDMA0_TCSW | ||
380 | | SBC_IDE_MDMA0_TPM | ||
381 | | SBC_IDE_MDMA0_TA; | ||
382 | /* set configuration for RCS2# */ | ||
383 | mem_stcfg |= TS_MASK; | ||
384 | mem_stcfg &= ~TCSOE_MASK; | ||
385 | mem_stcfg &= ~TOECS_MASK; | ||
386 | mem_stcfg |= SBC_IDE_MDMA0_TCSOE | SBC_IDE_MDMA0_TOECS; | ||
387 | |||
388 | mode = XFER_MW_DMA_0; | ||
389 | break; | ||
390 | #endif | ||
391 | default: | ||
392 | return 1; | ||
393 | } | ||
394 | |||
395 | /* | ||
396 | * Tell the drive to switch to the new mode; abort on failure. | ||
397 | */ | ||
398 | if (!mode || ide_config_drive_speed(drive, mode)) | ||
399 | { | ||
400 | return 1; /* failure */ | ||
401 | } | ||
402 | |||
403 | |||
404 | au_writel(mem_sttime,MEM_STTIME2); | ||
405 | au_writel(mem_stcfg,MEM_STCFG2); | ||
406 | |||
407 | spin_unlock_irqrestore(&ide_tune_chipset_spin_lock, flags); | ||
408 | |||
409 | return 0; | ||
410 | } | ||
411 | |||
412 | /* | ||
413 | * Multi-Word DMA + DbDMA functions | ||
414 | */ | ||
415 | #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA | ||
416 | |||
417 | static int in_drive_list(struct hd_driveid *id, | ||
418 | const struct drive_list_entry *drive_table) | ||
419 | { | ||
420 | for ( ; drive_table->id_model ; drive_table++){ | ||
421 | if ((!strcmp(drive_table->id_model, id->model)) && | ||
422 | ((strstr(drive_table->id_firmware, id->fw_rev)) || | ||
423 | (!strcmp(drive_table->id_firmware, "ALL"))) | ||
424 | ) | ||
425 | return 1; | ||
426 | } | ||
427 | return 0; | ||
428 | } | ||
429 | |||
430 | static int auide_build_sglist(ide_drive_t *drive, struct request *rq) | ||
431 | { | ||
432 | ide_hwif_t *hwif = drive->hwif; | ||
433 | _auide_hwif *ahwif = (_auide_hwif*)hwif->hwif_data; | ||
434 | struct scatterlist *sg = hwif->sg_table; | ||
435 | |||
436 | ide_map_sg(drive, rq); | ||
437 | |||
438 | if (rq_data_dir(rq) == READ) | ||
439 | hwif->sg_dma_direction = DMA_FROM_DEVICE; | ||
440 | else | ||
441 | hwif->sg_dma_direction = DMA_TO_DEVICE; | ||
442 | |||
443 | return dma_map_sg(ahwif->dev, sg, hwif->sg_nents, | ||
444 | hwif->sg_dma_direction); | ||
445 | } | ||
446 | |||
447 | static int auide_build_dmatable(ide_drive_t *drive) | ||
448 | { | ||
449 | int i, iswrite, count = 0; | ||
450 | ide_hwif_t *hwif = HWIF(drive); | ||
451 | |||
452 | struct request *rq = HWGROUP(drive)->rq; | ||
453 | |||
454 | _auide_hwif *ahwif = (_auide_hwif*)hwif->hwif_data; | ||
455 | struct scatterlist *sg; | ||
456 | |||
457 | iswrite = (rq_data_dir(rq) == WRITE); | ||
458 | /* Save for interrupt context */ | ||
459 | ahwif->drive = drive; | ||
460 | |||
461 | /* Build sglist */ | ||
462 | hwif->sg_nents = i = auide_build_sglist(drive, rq); | ||
463 | |||
464 | if (!i) | ||
465 | return 0; | ||
466 | |||
467 | /* fill the descriptors */ | ||
468 | sg = hwif->sg_table; | ||
469 | while (i && sg_dma_len(sg)) { | ||
470 | u32 cur_addr; | ||
471 | u32 cur_len; | ||
472 | |||
473 | cur_addr = sg_dma_address(sg); | ||
474 | cur_len = sg_dma_len(sg); | ||
475 | |||
476 | while (cur_len) { | ||
477 | u32 flags = DDMA_FLAGS_NOIE; | ||
478 | unsigned int tc = (cur_len < 0xfe00)? cur_len: 0xfe00; | ||
479 | |||
480 | if (++count >= PRD_ENTRIES) { | ||
481 | printk(KERN_WARNING "%s: DMA table too small\n", | ||
482 | drive->name); | ||
483 | goto use_pio_instead; | ||
484 | } | ||
485 | |||
486 | /* Lets enable intr for the last descriptor only */ | ||
487 | if (1==i) | ||
488 | flags = DDMA_FLAGS_IE; | ||
489 | else | ||
490 | flags = DDMA_FLAGS_NOIE; | ||
491 | |||
492 | if (iswrite) { | ||
493 | if(!put_source_flags(ahwif->tx_chan, | ||
494 | (void*)(page_address(sg->page) | ||
495 | + sg->offset), | ||
496 | tc, flags)) { | ||
497 | printk(KERN_ERR "%s failed %d\n", | ||
498 | __FUNCTION__, __LINE__); | ||
499 | } | ||
500 | } else | ||
501 | { | ||
502 | if(!put_dest_flags(ahwif->rx_chan, | ||
503 | (void*)(page_address(sg->page) | ||
504 | + sg->offset), | ||
505 | tc, flags)) { | ||
506 | printk(KERN_ERR "%s failed %d\n", | ||
507 | __FUNCTION__, __LINE__); | ||
508 | } | ||
509 | } | ||
510 | |||
511 | cur_addr += tc; | ||
512 | cur_len -= tc; | ||
513 | } | ||
514 | sg++; | ||
515 | i--; | ||
516 | } | ||
517 | |||
518 | if (count) | ||
519 | return 1; | ||
520 | |||
521 | use_pio_instead: | ||
522 | dma_unmap_sg(ahwif->dev, | ||
523 | hwif->sg_table, | ||
524 | hwif->sg_nents, | ||
525 | hwif->sg_dma_direction); | ||
526 | |||
527 | return 0; /* revert to PIO for this request */ | ||
528 | } | ||
529 | |||
530 | static int auide_dma_end(ide_drive_t *drive) | ||
531 | { | ||
532 | ide_hwif_t *hwif = HWIF(drive); | ||
533 | _auide_hwif *ahwif = (_auide_hwif*)hwif->hwif_data; | ||
534 | |||
535 | if (hwif->sg_nents) { | ||
536 | dma_unmap_sg(ahwif->dev, hwif->sg_table, hwif->sg_nents, | ||
537 | hwif->sg_dma_direction); | ||
538 | hwif->sg_nents = 0; | ||
539 | } | ||
540 | |||
541 | return 0; | ||
542 | } | ||
543 | |||
544 | static void auide_dma_start(ide_drive_t *drive ) | ||
545 | { | ||
546 | // printk("%s\n", __FUNCTION__); | ||
547 | } | ||
548 | |||
549 | ide_startstop_t auide_dma_intr(ide_drive_t *drive) | ||
550 | { | ||
551 | //printk("%s\n", __FUNCTION__); | ||
552 | |||
553 | u8 stat = 0, dma_stat = 0; | ||
554 | |||
555 | dma_stat = HWIF(drive)->ide_dma_end(drive); | ||
556 | stat = HWIF(drive)->INB(IDE_STATUS_REG); /* get drive status */ | ||
557 | if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) { | ||
558 | if (!dma_stat) { | ||
559 | struct request *rq = HWGROUP(drive)->rq; | ||
560 | |||
561 | ide_end_request(drive, 1, rq->nr_sectors); | ||
562 | return ide_stopped; | ||
563 | } | ||
564 | printk(KERN_ERR "%s: dma_intr: bad DMA status (dma_stat=%x)\n", | ||
565 | drive->name, dma_stat); | ||
566 | } | ||
567 | return ide_error(drive, "dma_intr", stat); | ||
568 | } | ||
569 | |||
570 | static void auide_dma_exec_cmd(ide_drive_t *drive, u8 command) | ||
571 | { | ||
572 | //printk("%s\n", __FUNCTION__); | ||
573 | |||
574 | /* issue cmd to drive */ | ||
575 | ide_execute_command(drive, command, &auide_dma_intr, | ||
576 | (2*WAIT_CMD), NULL); | ||
577 | } | ||
578 | |||
579 | static int auide_dma_setup(ide_drive_t *drive) | ||
580 | { | ||
581 | // printk("%s\n", __FUNCTION__); | ||
582 | |||
583 | if (drive->media != ide_disk) | ||
584 | return 1; | ||
585 | |||
586 | if (!auide_build_dmatable(drive)) | ||
587 | /* try PIO instead of DMA */ | ||
588 | return 1; | ||
589 | |||
590 | drive->waiting_for_dma = 1; | ||
591 | |||
592 | return 0; | ||
593 | } | ||
594 | |||
595 | static int auide_dma_check(ide_drive_t *drive) | ||
596 | { | ||
597 | // printk("%s\n", __FUNCTION__); | ||
598 | |||
599 | #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA | ||
600 | if( !dbdma_init_done ){ | ||
601 | auide_hwif.white_list = in_drive_list(drive->id, | ||
602 | dma_white_list); | ||
603 | auide_hwif.black_list = in_drive_list(drive->id, | ||
604 | dma_black_list); | ||
605 | auide_hwif.drive = drive; | ||
606 | auide_ddma_init(&auide_hwif); | ||
607 | dbdma_init_done = 1; | ||
608 | } | ||
609 | #endif | ||
610 | |||
611 | /* Is the drive in our DMA black list? */ | ||
612 | if ( auide_hwif.black_list ) { | ||
613 | drive->using_dma = 0; | ||
614 | printk("%s found in dma_blacklist[]! Disabling DMA.\n", | ||
615 | drive->id->model); | ||
616 | } | ||
617 | else | ||
618 | drive->using_dma = 1; | ||
619 | |||
620 | return HWIF(drive)->ide_dma_host_on(drive); | ||
621 | } | ||
622 | |||
623 | static int auide_dma_test_irq(ide_drive_t *drive) | ||
624 | { | ||
625 | // printk("%s\n", __FUNCTION__); | ||
626 | |||
627 | if (!drive->waiting_for_dma) | ||
628 | printk(KERN_WARNING "%s: ide_dma_test_irq \ | ||
629 | called while not waiting\n", drive->name); | ||
630 | |||
631 | /* If dbdma didn't execute the STOP command yet, the | ||
632 | * active bit is still set | ||
633 | */ | ||
634 | drive->waiting_for_dma++; | ||
635 | if (drive->waiting_for_dma >= DMA_WAIT_TIMEOUT) { | ||
636 | printk(KERN_WARNING "%s: timeout waiting for ddma to \ | ||
637 | complete\n", drive->name); | ||
638 | return 1; | ||
639 | } | ||
640 | udelay(10); | ||
641 | return 0; | ||
642 | } | ||
643 | |||
644 | static int auide_dma_host_on(ide_drive_t *drive) | ||
645 | { | ||
646 | // printk("%s\n", __FUNCTION__); | ||
647 | return 0; | ||
648 | } | ||
649 | |||
650 | static int auide_dma_on(ide_drive_t *drive) | ||
651 | { | ||
652 | // printk("%s\n", __FUNCTION__); | ||
653 | drive->using_dma = 1; | ||
654 | return auide_dma_host_on(drive); | ||
655 | } | ||
656 | |||
657 | |||
658 | static int auide_dma_host_off(ide_drive_t *drive) | ||
659 | { | ||
660 | // printk("%s\n", __FUNCTION__); | ||
661 | return 0; | ||
662 | } | ||
663 | |||
664 | static int auide_dma_off_quietly(ide_drive_t *drive) | ||
665 | { | ||
666 | // printk("%s\n", __FUNCTION__); | ||
667 | drive->using_dma = 0; | ||
668 | return auide_dma_host_off(drive); | ||
669 | } | ||
670 | |||
671 | static int auide_dma_lostirq(ide_drive_t *drive) | ||
672 | { | ||
673 | // printk("%s\n", __FUNCTION__); | ||
674 | |||
675 | printk(KERN_ERR "%s: IRQ lost\n", drive->name); | ||
676 | return 0; | ||
677 | } | ||
678 | |||
679 | static void auide_ddma_tx_callback(int irq, void *param, struct pt_regs *regs) | ||
680 | { | ||
681 | // printk("%s\n", __FUNCTION__); | ||
682 | |||
683 | _auide_hwif *ahwif = (_auide_hwif*)param; | ||
684 | ahwif->drive->waiting_for_dma = 0; | ||
685 | return; | ||
686 | } | ||
687 | |||
688 | static void auide_ddma_rx_callback(int irq, void *param, struct pt_regs *regs) | ||
689 | { | ||
690 | // printk("%s\n", __FUNCTION__); | ||
691 | |||
692 | _auide_hwif *ahwif = (_auide_hwif*)param; | ||
693 | ahwif->drive->waiting_for_dma = 0; | ||
694 | return; | ||
695 | } | ||
696 | |||
697 | static int auide_dma_timeout(ide_drive_t *drive) | ||
698 | { | ||
699 | // printk("%s\n", __FUNCTION__); | ||
700 | |||
701 | printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name); | ||
702 | |||
703 | if (HWIF(drive)->ide_dma_test_irq(drive)) | ||
704 | return 0; | ||
705 | |||
706 | return HWIF(drive)->ide_dma_end(drive); | ||
707 | } | ||
708 | #endif /* end CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA */ | ||
709 | |||
710 | |||
711 | static int auide_ddma_init( _auide_hwif *auide ) | ||
712 | { | ||
713 | // printk("%s\n", __FUNCTION__); | ||
714 | |||
715 | dbdev_tab_t source_dev_tab; | ||
716 | #if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA) | ||
717 | dbdev_tab_t target_dev_tab; | ||
718 | ide_hwif_t *hwif = auide->hwif; | ||
719 | char warning_output [2][80]; | ||
720 | int i; | ||
721 | #endif | ||
722 | |||
723 | /* Add our custom device to DDMA device table */ | ||
724 | /* Create our new device entries in the table */ | ||
725 | #if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA) | ||
726 | source_dev_tab.dev_id = AU1XXX_ATA_DDMA_REQ; | ||
727 | |||
728 | if( auide->white_list || auide->black_list ){ | ||
729 | source_dev_tab.dev_tsize = 8; | ||
730 | source_dev_tab.dev_devwidth = 32; | ||
731 | source_dev_tab.dev_physaddr = (u32)AU1XXX_ATA_PHYS_ADDR; | ||
732 | source_dev_tab.dev_intlevel = 0; | ||
733 | source_dev_tab.dev_intpolarity = 0; | ||
734 | |||
735 | /* init device table for target - static bus controller - */ | ||
736 | target_dev_tab.dev_id = DSCR_CMD0_ALWAYS; | ||
737 | target_dev_tab.dev_tsize = 8; | ||
738 | target_dev_tab.dev_devwidth = 32; | ||
739 | target_dev_tab.dev_physaddr = (u32)AU1XXX_ATA_PHYS_ADDR; | ||
740 | target_dev_tab.dev_intlevel = 0; | ||
741 | target_dev_tab.dev_intpolarity = 0; | ||
742 | target_dev_tab.dev_flags = DEV_FLAGS_ANYUSE; | ||
743 | } | ||
744 | else{ | ||
745 | source_dev_tab.dev_tsize = 1; | ||
746 | source_dev_tab.dev_devwidth = 16; | ||
747 | source_dev_tab.dev_physaddr = (u32)AU1XXX_ATA_PHYS_ADDR; | ||
748 | source_dev_tab.dev_intlevel = 0; | ||
749 | source_dev_tab.dev_intpolarity = 0; | ||
750 | |||
751 | /* init device table for target - static bus controller - */ | ||
752 | target_dev_tab.dev_id = DSCR_CMD0_ALWAYS; | ||
753 | target_dev_tab.dev_tsize = 1; | ||
754 | target_dev_tab.dev_devwidth = 16; | ||
755 | target_dev_tab.dev_physaddr = (u32)AU1XXX_ATA_PHYS_ADDR; | ||
756 | target_dev_tab.dev_intlevel = 0; | ||
757 | target_dev_tab.dev_intpolarity = 0; | ||
758 | target_dev_tab.dev_flags = DEV_FLAGS_ANYUSE; | ||
759 | |||
760 | sprintf(&warning_output[0][0], | ||
761 | "%s is not on ide driver white list.", | ||
762 | auide_hwif.drive->id->model); | ||
763 | for ( i=strlen(&warning_output[0][0]) ; i<76; i++ ){ | ||
764 | sprintf(&warning_output[0][i]," "); | ||
765 | } | ||
766 | |||
767 | sprintf(&warning_output[1][0], | ||
768 | "To add %s please read 'Documentation/mips/AU1xxx_IDE.README'.", | ||
769 | auide_hwif.drive->id->model); | ||
770 | for ( i=strlen(&warning_output[1][0]) ; i<76; i++ ){ | ||
771 | sprintf(&warning_output[1][i]," "); | ||
772 | } | ||
773 | |||
774 | printk("\n****************************************"); | ||
775 | printk("****************************************\n"); | ||
776 | printk("* %s *\n",&warning_output[0][0]); | ||
777 | printk("* Switch to safe MWDMA Mode! "); | ||
778 | printk(" *\n"); | ||
779 | printk("* %s *\n",&warning_output[1][0]); | ||
780 | printk("****************************************"); | ||
781 | printk("****************************************\n\n"); | ||
782 | } | ||
783 | #else | ||
784 | source_dev_tab.dev_id = DSCR_CMD0_ALWAYS; | ||
785 | source_dev_tab.dev_tsize = 8; | ||
786 | source_dev_tab.dev_devwidth = 32; | ||
787 | source_dev_tab.dev_physaddr = (u32)AU1XXX_ATA_PHYS_ADDR; | ||
788 | source_dev_tab.dev_intlevel = 0; | ||
789 | source_dev_tab.dev_intpolarity = 0; | ||
790 | #endif | ||
791 | |||
792 | #if CONFIG_BLK_DEV_IDE_AU1XXX_BURSTABLE_ON | ||
793 | /* set flags for tx channel */ | ||
794 | source_dev_tab.dev_flags = DEV_FLAGS_OUT | ||
795 | | DEV_FLAGS_SYNC | ||
796 | | DEV_FLAGS_BURSTABLE; | ||
797 | auide->tx_dev_id = au1xxx_ddma_add_device( &source_dev_tab ); | ||
798 | /* set flags for rx channel */ | ||
799 | source_dev_tab.dev_flags = DEV_FLAGS_IN | ||
800 | | DEV_FLAGS_SYNC | ||
801 | | DEV_FLAGS_BURSTABLE; | ||
802 | auide->rx_dev_id = au1xxx_ddma_add_device( &source_dev_tab ); | ||
803 | #else | ||
804 | /* set flags for tx channel */ | ||
805 | source_dev_tab.dev_flags = DEV_FLAGS_OUT | DEV_FLAGS_SYNC; | ||
806 | auide->tx_dev_id = au1xxx_ddma_add_device( &source_dev_tab ); | ||
807 | /* set flags for rx channel */ | ||
808 | source_dev_tab.dev_flags = DEV_FLAGS_IN | DEV_FLAGS_SYNC; | ||
809 | auide->rx_dev_id = au1xxx_ddma_add_device( &source_dev_tab ); | ||
810 | #endif | ||
811 | |||
812 | #if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA) | ||
813 | |||
814 | auide->target_dev_id = au1xxx_ddma_add_device(&target_dev_tab); | ||
815 | |||
816 | /* Get a channel for TX */ | ||
817 | auide->tx_chan = au1xxx_dbdma_chan_alloc(auide->target_dev_id, | ||
818 | auide->tx_dev_id, | ||
819 | auide_ddma_tx_callback, | ||
820 | (void*)auide); | ||
821 | /* Get a channel for RX */ | ||
822 | auide->rx_chan = au1xxx_dbdma_chan_alloc(auide->rx_dev_id, | ||
823 | auide->target_dev_id, | ||
824 | auide_ddma_rx_callback, | ||
825 | (void*)auide); | ||
826 | #else /* CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA */ | ||
827 | /* | ||
828 | * Note: if call back is not enabled, update ctp->cur_ptr manually | ||
829 | */ | ||
830 | auide->tx_chan = au1xxx_dbdma_chan_alloc(DSCR_CMD0_ALWAYS, | ||
831 | auide->tx_dev_id, | ||
832 | NULL, | ||
833 | (void*)auide); | ||
834 | auide->rx_chan = au1xxx_dbdma_chan_alloc(auide->rx_dev_id, | ||
835 | DSCR_CMD0_ALWAYS, | ||
836 | NULL, | ||
837 | (void*)auide); | ||
838 | #endif | ||
839 | auide->tx_desc_head = (void*)au1xxx_dbdma_ring_alloc(auide->tx_chan, | ||
840 | NUM_DESCRIPTORS); | ||
841 | auide->rx_desc_head = (void*)au1xxx_dbdma_ring_alloc(auide->rx_chan, | ||
842 | NUM_DESCRIPTORS); | ||
843 | |||
844 | #if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA) | ||
845 | hwif->dmatable_cpu = dma_alloc_coherent(auide->dev, | ||
846 | PRD_ENTRIES * PRD_BYTES, /* 1 Page */ | ||
847 | &hwif->dmatable_dma, GFP_KERNEL); | ||
848 | |||
849 | auide->sg_table = kmalloc(sizeof(struct scatterlist) * PRD_ENTRIES, | ||
850 | GFP_KERNEL|GFP_DMA); | ||
851 | if (auide->sg_table == NULL) { | ||
852 | return -ENOMEM; | ||
853 | } | ||
854 | #endif | ||
855 | au1xxx_dbdma_start( auide->tx_chan ); | ||
856 | au1xxx_dbdma_start( auide->rx_chan ); | ||
857 | return 0; | ||
858 | } | ||
859 | |||
860 | static void auide_setup_ports(hw_regs_t *hw, _auide_hwif *ahwif) | ||
861 | { | ||
862 | int i; | ||
863 | #define ide_ioreg_t unsigned long | ||
864 | ide_ioreg_t *ata_regs = hw->io_ports; | ||
865 | |||
866 | /* fixme */ | ||
867 | for (i = 0; i < IDE_CONTROL_OFFSET; i++) { | ||
868 | *ata_regs++ = (ide_ioreg_t) ahwif->regbase | ||
869 | + (ide_ioreg_t)(i << AU1XXX_ATA_REG_OFFSET); | ||
870 | } | ||
871 | |||
872 | /* set the Alternative Status register */ | ||
873 | *ata_regs = (ide_ioreg_t) ahwif->regbase | ||
874 | + (ide_ioreg_t)(14 << AU1XXX_ATA_REG_OFFSET); | ||
875 | } | ||
876 | |||
877 | static int au_ide_probe(struct device *dev) | ||
878 | { | ||
879 | struct platform_device *pdev = to_platform_device(dev); | ||
880 | _auide_hwif *ahwif = &auide_hwif; | ||
881 | ide_hwif_t *hwif; | ||
882 | struct resource *res; | ||
883 | int ret = 0; | ||
884 | |||
885 | #if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA) | ||
886 | char *mode = "MWDMA2"; | ||
887 | #elif defined(CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA) | ||
888 | char *mode = "PIO+DDMA(offload)"; | ||
889 | #endif | ||
890 | |||
891 | memset(&auide_hwif, 0, sizeof(_auide_hwif)); | ||
892 | auide_hwif.dev = 0; | ||
893 | |||
894 | ahwif->dev = dev; | ||
895 | ahwif->irq = platform_get_irq(pdev, 0); | ||
896 | |||
897 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
898 | |||
899 | if (res == NULL) { | ||
900 | pr_debug("%s %d: no base address\n", DRV_NAME, pdev->id); | ||
901 | ret = -ENODEV; | ||
902 | goto out; | ||
903 | } | ||
904 | |||
905 | if (!request_mem_region (res->start, res->end-res->start, pdev->name)) { | ||
906 | pr_debug("%s: request_mem_region failed\n", DRV_NAME); | ||
907 | ret = -EBUSY; | ||
908 | goto out; | ||
909 | } | ||
910 | |||
911 | ahwif->regbase = (u32)ioremap(res->start, res->end-res->start); | ||
912 | if (ahwif->regbase == 0) { | ||
913 | ret = -ENOMEM; | ||
914 | goto out; | ||
915 | } | ||
916 | |||
917 | hwif = &ide_hwifs[pdev->id]; | ||
918 | hw_regs_t *hw = &hwif->hw; | ||
919 | hwif->irq = hw->irq = ahwif->irq; | ||
920 | hwif->chipset = ide_au1xxx; | ||
921 | |||
922 | auide_setup_ports(hw, ahwif); | ||
923 | memcpy(hwif->io_ports, hw->io_ports, sizeof(hwif->io_ports)); | ||
924 | |||
925 | #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ | ||
926 | hwif->rqsize = CONFIG_BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ; | ||
927 | hwif->rqsize = ((hwif->rqsize > AU1XXX_ATA_RQSIZE) | ||
928 | || (hwif->rqsize < 32)) ? AU1XXX_ATA_RQSIZE : hwif->rqsize; | ||
929 | #else /* if kernel config is not set */ | ||
930 | hwif->rqsize = AU1XXX_ATA_RQSIZE; | ||
931 | #endif | ||
932 | |||
933 | hwif->ultra_mask = 0x0; /* Disable Ultra DMA */ | ||
934 | #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA | ||
935 | hwif->mwdma_mask = 0x07; /* Multimode-2 DMA */ | ||
936 | hwif->swdma_mask = 0x07; | ||
937 | #else | ||
938 | hwif->mwdma_mask = 0x0; | ||
939 | hwif->swdma_mask = 0x0; | ||
940 | #endif | ||
941 | //hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET]; | ||
942 | hwif->noprobe = 0; | ||
943 | hwif->drives[0].unmask = 1; | ||
944 | hwif->drives[1].unmask = 1; | ||
945 | |||
946 | /* hold should be on in all cases */ | ||
947 | hwif->hold = 1; | ||
948 | hwif->mmio = 2; | ||
949 | |||
950 | /* set up local I/O function entry points */ | ||
951 | hwif->INB = auide_inb; | ||
952 | hwif->INW = auide_inw; | ||
953 | hwif->INL = auide_inl; | ||
954 | hwif->INSW = auide_insw; | ||
955 | hwif->INSL = auide_insl; | ||
956 | hwif->OUTB = auide_outb; | ||
957 | hwif->OUTBSYNC = auide_outbsync; | ||
958 | hwif->OUTW = auide_outw; | ||
959 | hwif->OUTL = auide_outl; | ||
960 | hwif->OUTSW = auide_outsw; | ||
961 | hwif->OUTSL = auide_outsl; | ||
962 | |||
963 | hwif->tuneproc = &auide_tune_drive; | ||
964 | hwif->speedproc = &auide_tune_chipset; | ||
965 | |||
966 | #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA | ||
967 | hwif->ide_dma_off_quietly = &auide_dma_off_quietly; | ||
968 | hwif->ide_dma_timeout = &auide_dma_timeout; | ||
969 | |||
970 | hwif->ide_dma_check = &auide_dma_check; | ||
971 | hwif->dma_exec_cmd = &auide_dma_exec_cmd; | ||
972 | hwif->dma_start = &auide_dma_start; | ||
973 | hwif->ide_dma_end = &auide_dma_end; | ||
974 | hwif->dma_setup = &auide_dma_setup; | ||
975 | hwif->ide_dma_test_irq = &auide_dma_test_irq; | ||
976 | hwif->ide_dma_host_off = &auide_dma_host_off; | ||
977 | hwif->ide_dma_host_on = &auide_dma_host_on; | ||
978 | hwif->ide_dma_lostirq = &auide_dma_lostirq; | ||
979 | hwif->ide_dma_on = &auide_dma_on; | ||
980 | |||
981 | hwif->autodma = 1; | ||
982 | hwif->drives[0].autodma = hwif->autodma; | ||
983 | hwif->drives[1].autodma = hwif->autodma; | ||
984 | hwif->atapi_dma = 1; | ||
985 | hwif->drives[0].using_dma = 1; | ||
986 | hwif->drives[1].using_dma = 1; | ||
987 | #else /* !CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA */ | ||
988 | hwif->autodma = 0; | ||
989 | hwif->channel = 0; | ||
990 | hwif->hold = 1; | ||
991 | hwif->select_data = 0; /* no chipset-specific code */ | ||
992 | hwif->config_data = 0; /* no chipset-specific code */ | ||
993 | |||
994 | hwif->drives[0].autodma = 0; | ||
995 | hwif->drives[0].drive_data = 0; /* no drive data */ | ||
996 | hwif->drives[0].using_dma = 0; | ||
997 | hwif->drives[0].waiting_for_dma = 0; | ||
998 | hwif->drives[0].autotune = 1; /* 1=autotune, 2=noautotune, 0=default */ | ||
999 | /* secondary hdd not supported */ | ||
1000 | hwif->drives[1].autodma = 0; | ||
1001 | |||
1002 | hwif->drives[1].drive_data = 0; | ||
1003 | hwif->drives[1].using_dma = 0; | ||
1004 | hwif->drives[1].waiting_for_dma = 0; | ||
1005 | hwif->drives[1].autotune = 2; /* 1=autotune, 2=noautotune, 0=default */ | ||
1006 | #endif | ||
1007 | hwif->drives[0].io_32bit = 0; /* 0=16-bit, 1=32-bit, 2/3=32bit+sync */ | ||
1008 | hwif->drives[1].io_32bit = 0; /* 0=16-bit, 1=32-bit, 2/3=32bit+sync */ | ||
1009 | |||
1010 | /*Register Driver with PM Framework*/ | ||
1011 | #ifdef CONFIG_PM | ||
1012 | auide_hwif.pm.lock = SPIN_LOCK_UNLOCKED; | ||
1013 | auide_hwif.pm.stopped = 0; | ||
1014 | |||
1015 | auide_hwif.pm.dev = new_au1xxx_power_device( "ide", | ||
1016 | &au1200ide_pm_callback, | ||
1017 | NULL); | ||
1018 | if ( auide_hwif.pm.dev == NULL ) | ||
1019 | printk(KERN_INFO "Unable to create a power management \ | ||
1020 | device entry for the au1200-IDE.\n"); | ||
1021 | else | ||
1022 | printk(KERN_INFO "Power management device entry for the \ | ||
1023 | au1200-IDE loaded.\n"); | ||
1024 | #endif | ||
1025 | |||
1026 | auide_hwif.hwif = hwif; | ||
1027 | hwif->hwif_data = &auide_hwif; | ||
1028 | |||
1029 | #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA | ||
1030 | auide_ddma_init(&auide_hwif); | ||
1031 | dbdma_init_done = 1; | ||
1032 | #endif | ||
1033 | |||
1034 | probe_hwif_init(hwif); | ||
1035 | dev_set_drvdata(dev, hwif); | ||
1036 | |||
1037 | printk(KERN_INFO "Au1xxx IDE(builtin) configured for %s\n", mode ); | ||
1038 | |||
1039 | out: | ||
1040 | return ret; | ||
1041 | } | ||
1042 | |||
1043 | static int au_ide_remove(struct device *dev) | ||
1044 | { | ||
1045 | struct platform_device *pdev = to_platform_device(dev); | ||
1046 | struct resource *res; | ||
1047 | ide_hwif_t *hwif = dev_get_drvdata(dev); | ||
1048 | _auide_hwif *ahwif = &auide_hwif; | ||
1049 | |||
1050 | ide_unregister(hwif - ide_hwifs); | ||
1051 | |||
1052 | iounmap((void *)ahwif->regbase); | ||
1053 | |||
1054 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1055 | release_mem_region(res->start, res->end - res->start); | ||
1056 | |||
1057 | return 0; | ||
1058 | } | ||
1059 | |||
1060 | static struct device_driver au1200_ide_driver = { | ||
1061 | .name = "au1200-ide", | ||
1062 | .bus = &platform_bus_type, | ||
1063 | .probe = au_ide_probe, | ||
1064 | .remove = au_ide_remove, | ||
1065 | }; | ||
1066 | |||
1067 | static int __init au_ide_init(void) | ||
1068 | { | ||
1069 | return driver_register(&au1200_ide_driver); | ||
1070 | } | ||
1071 | |||
1072 | static void __init au_ide_exit(void) | ||
1073 | { | ||
1074 | driver_unregister(&au1200_ide_driver); | ||
1075 | } | ||
1076 | |||
1077 | #ifdef CONFIG_PM | ||
1078 | int au1200ide_pm_callback( au1xxx_power_dev_t *dev,\ | ||
1079 | au1xxx_request_t request, void *data) { | ||
1080 | |||
1081 | unsigned int d, err = 0; | ||
1082 | unsigned long flags; | ||
1083 | |||
1084 | spin_lock_irqsave(auide_hwif.pm.lock, flags); | ||
1085 | |||
1086 | switch (request){ | ||
1087 | case AU1XXX_PM_SLEEP: | ||
1088 | err = au1xxxide_pm_sleep(dev); | ||
1089 | break; | ||
1090 | case AU1XXX_PM_WAKEUP: | ||
1091 | d = *((unsigned int*)data); | ||
1092 | if ( d > 0 && d <= 99) { | ||
1093 | err = au1xxxide_pm_standby(dev); | ||
1094 | } | ||
1095 | else { | ||
1096 | err = au1xxxide_pm_resume(dev); | ||
1097 | } | ||
1098 | break; | ||
1099 | case AU1XXX_PM_GETSTATUS: | ||
1100 | err = au1xxxide_pm_getstatus(dev); | ||
1101 | break; | ||
1102 | case AU1XXX_PM_ACCESS: | ||
1103 | err = au1xxxide_pm_access(dev); | ||
1104 | break; | ||
1105 | case AU1XXX_PM_IDLE: | ||
1106 | err = au1xxxide_pm_idle(dev); | ||
1107 | break; | ||
1108 | case AU1XXX_PM_CLEANUP: | ||
1109 | err = au1xxxide_pm_cleanup(dev); | ||
1110 | break; | ||
1111 | default: | ||
1112 | err = -1; | ||
1113 | break; | ||
1114 | } | ||
1115 | |||
1116 | spin_unlock_irqrestore(auide_hwif.pm.lock, flags); | ||
1117 | |||
1118 | return err; | ||
1119 | } | ||
1120 | |||
1121 | static int au1xxxide_pm_standby( au1xxx_power_dev_t *dev ) { | ||
1122 | return 0; | ||
1123 | } | ||
1124 | |||
1125 | static int au1xxxide_pm_sleep( au1xxx_power_dev_t *dev ) { | ||
1126 | |||
1127 | int retval; | ||
1128 | ide_hwif_t *hwif = auide_hwif.hwif; | ||
1129 | struct request rq; | ||
1130 | struct request_pm_state rqpm; | ||
1131 | ide_task_t args; | ||
1132 | |||
1133 | if(auide_hwif.pm.stopped) | ||
1134 | return -1; | ||
1135 | |||
1136 | /* | ||
1137 | * wait until hard disc is ready | ||
1138 | */ | ||
1139 | if ( wait_for_ready(&hwif->drives[0], 35000) ) { | ||
1140 | printk("Wait for drive sleep timeout!\n"); | ||
1141 | retval = -1; | ||
1142 | } | ||
1143 | |||
1144 | /* | ||
1145 | * sequenz to tell the high level ide driver that pm is resuming | ||
1146 | */ | ||
1147 | memset(&rq, 0, sizeof(rq)); | ||
1148 | memset(&rqpm, 0, sizeof(rqpm)); | ||
1149 | memset(&args, 0, sizeof(args)); | ||
1150 | rq.flags = REQ_PM_SUSPEND; | ||
1151 | rq.special = &args; | ||
1152 | rq.pm = &rqpm; | ||
1153 | rqpm.pm_step = ide_pm_state_start_suspend; | ||
1154 | rqpm.pm_state = PMSG_SUSPEND; | ||
1155 | |||
1156 | retval = ide_do_drive_cmd(&hwif->drives[0], &rq, ide_wait); | ||
1157 | |||
1158 | if (wait_for_ready (&hwif->drives[0], 35000)) { | ||
1159 | printk("Wait for drive sleep timeout!\n"); | ||
1160 | retval = -1; | ||
1161 | } | ||
1162 | |||
1163 | /* | ||
1164 | * stop dbdma channels | ||
1165 | */ | ||
1166 | au1xxx_dbdma_reset(auide_hwif.tx_chan); | ||
1167 | au1xxx_dbdma_reset(auide_hwif.rx_chan); | ||
1168 | |||
1169 | auide_hwif.pm.stopped = 1; | ||
1170 | |||
1171 | return retval; | ||
1172 | } | ||
1173 | |||
1174 | static int au1xxxide_pm_resume( au1xxx_power_dev_t *dev ) { | ||
1175 | |||
1176 | int retval; | ||
1177 | ide_hwif_t *hwif = auide_hwif.hwif; | ||
1178 | struct request rq; | ||
1179 | struct request_pm_state rqpm; | ||
1180 | ide_task_t args; | ||
1181 | |||
1182 | if(!auide_hwif.pm.stopped) | ||
1183 | return -1; | ||
1184 | |||
1185 | /* | ||
1186 | * start dbdma channels | ||
1187 | */ | ||
1188 | au1xxx_dbdma_start(auide_hwif.tx_chan); | ||
1189 | au1xxx_dbdma_start(auide_hwif.rx_chan); | ||
1190 | |||
1191 | /* | ||
1192 | * wait until hard disc is ready | ||
1193 | */ | ||
1194 | if (wait_for_ready ( &hwif->drives[0], 35000)) { | ||
1195 | printk("Wait for drive wake up timeout!\n"); | ||
1196 | retval = -1; | ||
1197 | } | ||
1198 | |||
1199 | /* | ||
1200 | * sequenz to tell the high level ide driver that pm is resuming | ||
1201 | */ | ||
1202 | memset(&rq, 0, sizeof(rq)); | ||
1203 | memset(&rqpm, 0, sizeof(rqpm)); | ||
1204 | memset(&args, 0, sizeof(args)); | ||
1205 | rq.flags = REQ_PM_RESUME; | ||
1206 | rq.special = &args; | ||
1207 | rq.pm = &rqpm; | ||
1208 | rqpm.pm_step = ide_pm_state_start_resume; | ||
1209 | rqpm.pm_state = PMSG_ON; | ||
1210 | |||
1211 | retval = ide_do_drive_cmd(&hwif->drives[0], &rq, ide_head_wait); | ||
1212 | |||
1213 | /* | ||
1214 | * wait for hard disc | ||
1215 | */ | ||
1216 | if ( wait_for_ready(&hwif->drives[0], 35000) ) { | ||
1217 | printk("Wait for drive wake up timeout!\n"); | ||
1218 | retval = -1; | ||
1219 | } | ||
1220 | |||
1221 | auide_hwif.pm.stopped = 0; | ||
1222 | |||
1223 | return retval; | ||
1224 | } | ||
1225 | |||
1226 | static int au1xxxide_pm_getstatus( au1xxx_power_dev_t *dev ) { | ||
1227 | return dev->cur_state; | ||
1228 | } | ||
1229 | |||
1230 | static int au1xxxide_pm_access( au1xxx_power_dev_t *dev ) { | ||
1231 | if (dev->cur_state != AWAKE_STATE) | ||
1232 | return 0; | ||
1233 | else | ||
1234 | return -1; | ||
1235 | } | ||
1236 | |||
1237 | static int au1xxxide_pm_idle( au1xxx_power_dev_t *dev ) { | ||
1238 | return 0; | ||
1239 | } | ||
1240 | |||
1241 | static int au1xxxide_pm_cleanup( au1xxx_power_dev_t *dev ) { | ||
1242 | return 0; | ||
1243 | } | ||
1244 | #endif /* CONFIG_PM */ | ||
1245 | |||
1246 | MODULE_LICENSE("GPL"); | ||
1247 | MODULE_DESCRIPTION("AU1200 IDE driver"); | ||
1248 | |||
1249 | module_init(au_ide_init); | ||
1250 | module_exit(au_ide_exit); | ||
diff --git a/drivers/media/video/indycam.c b/drivers/media/video/indycam.c index b2b0384cd4b9..26dd06ec89a2 100644 --- a/drivers/media/video/indycam.c +++ b/drivers/media/video/indycam.c | |||
@@ -9,16 +9,16 @@ | |||
9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/delay.h> | 12 | #include <linux/delay.h> |
15 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
16 | #include <linux/fs.h> | 14 | #include <linux/fs.h> |
15 | #include <linux/init.h> | ||
17 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
18 | #include <linux/major.h> | 17 | #include <linux/major.h> |
19 | #include <linux/slab.h> | 18 | #include <linux/module.h> |
20 | #include <linux/mm.h> | 19 | #include <linux/mm.h> |
21 | #include <linux/sched.h> | 20 | #include <linux/sched.h> |
21 | #include <linux/slab.h> | ||
22 | 22 | ||
23 | #include <linux/videodev.h> | 23 | #include <linux/videodev.h> |
24 | /* IndyCam decodes stream of photons into digital image representation ;-) */ | 24 | /* IndyCam decodes stream of photons into digital image representation ;-) */ |
@@ -44,8 +44,6 @@ MODULE_LICENSE("GPL"); | |||
44 | #define indycam_regdump(client) | 44 | #define indycam_regdump(client) |
45 | #endif | 45 | #endif |
46 | 46 | ||
47 | #define VINO_ADAPTER (I2C_ALGO_SGI | I2C_HW_SGI_VINO) | ||
48 | |||
49 | struct indycam { | 47 | struct indycam { |
50 | struct i2c_client *client; | 48 | struct i2c_client *client; |
51 | int version; | 49 | int version; |
@@ -300,7 +298,7 @@ out_free_client: | |||
300 | static int indycam_probe(struct i2c_adapter *adap) | 298 | static int indycam_probe(struct i2c_adapter *adap) |
301 | { | 299 | { |
302 | /* Indy specific crap */ | 300 | /* Indy specific crap */ |
303 | if (adap->id == VINO_ADAPTER) | 301 | if (adap->id == I2C_HW_SGI_VINO) |
304 | return indycam_attach(adap, INDYCAM_ADDR, 0); | 302 | return indycam_attach(adap, INDYCAM_ADDR, 0); |
305 | /* Feel free to add probe here :-) */ | 303 | /* Feel free to add probe here :-) */ |
306 | return -ENODEV; | 304 | return -ENODEV; |
diff --git a/drivers/media/video/saa7191.c b/drivers/media/video/saa7191.c index 454f5c1199b4..3ddbb62312be 100644 --- a/drivers/media/video/saa7191.c +++ b/drivers/media/video/saa7191.c | |||
@@ -9,16 +9,16 @@ | |||
9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/delay.h> | 12 | #include <linux/delay.h> |
15 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
16 | #include <linux/fs.h> | 14 | #include <linux/fs.h> |
15 | #include <linux/init.h> | ||
17 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
18 | #include <linux/major.h> | 17 | #include <linux/major.h> |
19 | #include <linux/slab.h> | 18 | #include <linux/module.h> |
20 | #include <linux/mm.h> | 19 | #include <linux/mm.h> |
21 | #include <linux/sched.h> | 20 | #include <linux/sched.h> |
21 | #include <linux/slab.h> | ||
22 | 22 | ||
23 | #include <linux/videodev.h> | 23 | #include <linux/videodev.h> |
24 | #include <linux/video_decoder.h> | 24 | #include <linux/video_decoder.h> |
@@ -33,8 +33,6 @@ MODULE_VERSION(SAA7191_MODULE_VERSION); | |||
33 | MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>"); | 33 | MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>"); |
34 | MODULE_LICENSE("GPL"); | 34 | MODULE_LICENSE("GPL"); |
35 | 35 | ||
36 | #define VINO_ADAPTER (I2C_ALGO_SGI | I2C_HW_SGI_VINO) | ||
37 | |||
38 | struct saa7191 { | 36 | struct saa7191 { |
39 | struct i2c_client *client; | 37 | struct i2c_client *client; |
40 | 38 | ||
@@ -337,7 +335,7 @@ out_free_client: | |||
337 | static int saa7191_probe(struct i2c_adapter *adap) | 335 | static int saa7191_probe(struct i2c_adapter *adap) |
338 | { | 336 | { |
339 | /* Always connected to VINO */ | 337 | /* Always connected to VINO */ |
340 | if (adap->id == VINO_ADAPTER) | 338 | if (adap->id == I2C_HW_SGI_VINO) |
341 | return saa7191_attach(adap, SAA7191_ADDR, 0); | 339 | return saa7191_attach(adap, SAA7191_ADDR, 0); |
342 | /* Feel free to add probe here :-) */ | 340 | /* Feel free to add probe here :-) */ |
343 | return -ENODEV; | 341 | return -ENODEV; |
@@ -364,7 +362,7 @@ static int saa7191_command(struct i2c_client *client, unsigned int cmd, | |||
364 | 362 | ||
365 | cap->flags = VIDEO_DECODER_PAL | VIDEO_DECODER_NTSC | | 363 | cap->flags = VIDEO_DECODER_PAL | VIDEO_DECODER_NTSC | |
366 | VIDEO_DECODER_SECAM | VIDEO_DECODER_AUTO; | 364 | VIDEO_DECODER_SECAM | VIDEO_DECODER_AUTO; |
367 | cap->inputs = (client->adapter->id == VINO_ADAPTER) ? 2 : 1; | 365 | cap->inputs = (client->adapter->id == I2C_HW_SGI_VINO) ? 2 : 1; |
368 | cap->outputs = 1; | 366 | cap->outputs = 1; |
369 | break; | 367 | break; |
370 | } | 368 | } |
@@ -422,7 +420,7 @@ static int saa7191_command(struct i2c_client *client, unsigned int cmd, | |||
422 | int *iarg = arg; | 420 | int *iarg = arg; |
423 | 421 | ||
424 | switch (client->adapter->id) { | 422 | switch (client->adapter->id) { |
425 | case VINO_ADAPTER: | 423 | case I2C_HW_SGI_VINO: |
426 | return saa7191_set_input(client, *iarg); | 424 | return saa7191_set_input(client, *iarg); |
427 | default: | 425 | default: |
428 | if (*iarg != 0) | 426 | if (*iarg != 0) |
diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c index d8a0f763ca10..ed4394e854ab 100644 --- a/drivers/media/video/vino.c +++ b/drivers/media/video/vino.c | |||
@@ -26,14 +26,15 @@ | |||
26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
29 | #include <linux/dma-mapping.h> | ||
29 | #include <linux/errno.h> | 30 | #include <linux/errno.h> |
30 | #include <linux/fs.h> | 31 | #include <linux/fs.h> |
32 | #include <linux/interrupt.h> | ||
31 | #include <linux/kernel.h> | 33 | #include <linux/kernel.h> |
32 | #include <linux/mm.h> | 34 | #include <linux/mm.h> |
33 | #include <linux/interrupt.h> | ||
34 | #include <linux/dma-mapping.h> | ||
35 | #include <linux/time.h> | ||
36 | #include <linux/moduleparam.h> | 35 | #include <linux/moduleparam.h> |
36 | #include <linux/time.h> | ||
37 | #include <linux/version.h> | ||
37 | 38 | ||
38 | #ifdef CONFIG_KMOD | 39 | #ifdef CONFIG_KMOD |
39 | #include <linux/kmod.h> | 40 | #include <linux/kmod.h> |
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 4991bbd054f3..c483a863b116 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig | |||
@@ -60,4 +60,13 @@ config MMC_WBSD | |||
60 | 60 | ||
61 | If unsure, say N. | 61 | If unsure, say N. |
62 | 62 | ||
63 | config MMC_AU1X | ||
64 | tristate "Alchemy AU1XX0 MMC Card Interface support" | ||
65 | depends on SOC_AU1X00 && MMC | ||
66 | help | ||
67 | This selects the AMD Alchemy(R) Multimedia card interface. | ||
68 | iIf you have a Alchemy platform with a MMC slot, say Y or M here. | ||
69 | |||
70 | If unsure, say N. | ||
71 | |||
63 | endmenu | 72 | endmenu |
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 89510c2086c7..e351e71146e9 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile | |||
@@ -18,5 +18,6 @@ obj-$(CONFIG_MMC_BLOCK) += mmc_block.o | |||
18 | obj-$(CONFIG_MMC_ARMMMCI) += mmci.o | 18 | obj-$(CONFIG_MMC_ARMMMCI) += mmci.o |
19 | obj-$(CONFIG_MMC_PXA) += pxamci.o | 19 | obj-$(CONFIG_MMC_PXA) += pxamci.o |
20 | obj-$(CONFIG_MMC_WBSD) += wbsd.o | 20 | obj-$(CONFIG_MMC_WBSD) += wbsd.o |
21 | obj-$(CONFIG_MMC_AU1X) += au1xmmc.o | ||
21 | 22 | ||
22 | mmc_core-y := mmc.o mmc_queue.o mmc_sysfs.o | 23 | mmc_core-y := mmc.o mmc_queue.o mmc_sysfs.o |
diff --git a/drivers/mmc/au1xmmc.c b/drivers/mmc/au1xmmc.c new file mode 100644 index 000000000000..aaf04638054e --- /dev/null +++ b/drivers/mmc/au1xmmc.c | |||
@@ -0,0 +1,1026 @@ | |||
1 | /* | ||
2 | * linux/drivers/mmc/au1xmmc.c - AU1XX0 MMC driver | ||
3 | * | ||
4 | * Copyright (c) 2005, Advanced Micro Devices, Inc. | ||
5 | * | ||
6 | * Developed with help from the 2.4.30 MMC AU1XXX controller including | ||
7 | * the following copyright notices: | ||
8 | * Copyright (c) 2003-2004 Embedded Edge, LLC. | ||
9 | * Portions Copyright (C) 2002 Embedix, Inc | ||
10 | * Copyright 2002 Hewlett-Packard Company | ||
11 | |||
12 | * 2.6 version of this driver inspired by: | ||
13 | * (drivers/mmc/wbsd.c) Copyright (C) 2004-2005 Pierre Ossman, | ||
14 | * All Rights Reserved. | ||
15 | * (drivers/mmc/pxa.c) Copyright (C) 2003 Russell King, | ||
16 | * All Rights Reserved. | ||
17 | * | ||
18 | |||
19 | * This program is free software; you can redistribute it and/or modify | ||
20 | * it under the terms of the GNU General Public License version 2 as | ||
21 | * published by the Free Software Foundation. | ||
22 | */ | ||
23 | |||
24 | /* Why is a timer used to detect insert events? | ||
25 | * | ||
26 | * From the AU1100 MMC application guide: | ||
27 | * If the Au1100-based design is intended to support both MultiMediaCards | ||
28 | * and 1- or 4-data bit SecureDigital cards, then the solution is to | ||
29 | * connect a weak (560KOhm) pull-up resistor to connector pin 1. | ||
30 | * In doing so, a MMC card never enters SPI-mode communications, | ||
31 | * but now the SecureDigital card-detect feature of CD/DAT3 is ineffective | ||
32 | * (the low to high transition will not occur). | ||
33 | * | ||
34 | * So we use the timer to check the status manually. | ||
35 | */ | ||
36 | |||
37 | #include <linux/config.h> | ||
38 | #include <linux/module.h> | ||
39 | #include <linux/init.h> | ||
40 | #include <linux/device.h> | ||
41 | #include <linux/mm.h> | ||
42 | #include <linux/interrupt.h> | ||
43 | #include <linux/dma-mapping.h> | ||
44 | |||
45 | #include <linux/mmc/host.h> | ||
46 | #include <linux/mmc/protocol.h> | ||
47 | #include <asm/io.h> | ||
48 | #include <asm/mach-au1x00/au1000.h> | ||
49 | #include <asm/mach-au1x00/au1xxx_dbdma.h> | ||
50 | #include <asm/mach-au1x00/au1100_mmc.h> | ||
51 | #include <asm/scatterlist.h> | ||
52 | |||
53 | #include <au1xxx.h> | ||
54 | #include "au1xmmc.h" | ||
55 | |||
56 | #define DRIVER_NAME "au1xxx-mmc" | ||
57 | |||
58 | /* Set this to enable special debugging macros */ | ||
59 | /* #define MMC_DEBUG */ | ||
60 | |||
61 | #ifdef MMC_DEBUG | ||
62 | #define DEBUG(fmt, idx, args...) printk("au1xx(%d): DEBUG: " fmt, idx, ##args) | ||
63 | #else | ||
64 | #define DEBUG(fmt, idx, args...) | ||
65 | #endif | ||
66 | |||
67 | const struct { | ||
68 | u32 iobase; | ||
69 | u32 tx_devid, rx_devid; | ||
70 | u16 bcsrpwr; | ||
71 | u16 bcsrstatus; | ||
72 | u16 wpstatus; | ||
73 | } au1xmmc_card_table[] = { | ||
74 | { SD0_BASE, DSCR_CMD0_SDMS_TX0, DSCR_CMD0_SDMS_RX0, | ||
75 | BCSR_BOARD_SD0PWR, BCSR_INT_SD0INSERT, BCSR_STATUS_SD0WP }, | ||
76 | #ifndef CONFIG_MIPS_DB1200 | ||
77 | { SD1_BASE, DSCR_CMD0_SDMS_TX1, DSCR_CMD0_SDMS_RX1, | ||
78 | BCSR_BOARD_DS1PWR, BCSR_INT_SD1INSERT, BCSR_STATUS_SD1WP } | ||
79 | #endif | ||
80 | }; | ||
81 | |||
82 | #define AU1XMMC_CONTROLLER_COUNT \ | ||
83 | (sizeof(au1xmmc_card_table) / sizeof(au1xmmc_card_table[0])) | ||
84 | |||
85 | /* This array stores pointers for the hosts (used by the IRQ handler) */ | ||
86 | struct au1xmmc_host *au1xmmc_hosts[AU1XMMC_CONTROLLER_COUNT]; | ||
87 | static int dma = 1; | ||
88 | |||
89 | #ifdef MODULE | ||
90 | MODULE_PARM(dma, "i"); | ||
91 | MODULE_PARM_DESC(dma, "Use DMA engine for data transfers (0 = disabled)"); | ||
92 | #endif | ||
93 | |||
94 | static inline void IRQ_ON(struct au1xmmc_host *host, u32 mask) | ||
95 | { | ||
96 | u32 val = au_readl(HOST_CONFIG(host)); | ||
97 | val |= mask; | ||
98 | au_writel(val, HOST_CONFIG(host)); | ||
99 | au_sync(); | ||
100 | } | ||
101 | |||
102 | static inline void FLUSH_FIFO(struct au1xmmc_host *host) | ||
103 | { | ||
104 | u32 val = au_readl(HOST_CONFIG2(host)); | ||
105 | |||
106 | au_writel(val | SD_CONFIG2_FF, HOST_CONFIG2(host)); | ||
107 | au_sync_delay(1); | ||
108 | |||
109 | /* SEND_STOP will turn off clock control - this re-enables it */ | ||
110 | val &= ~SD_CONFIG2_DF; | ||
111 | |||
112 | au_writel(val, HOST_CONFIG2(host)); | ||
113 | au_sync(); | ||
114 | } | ||
115 | |||
116 | static inline void IRQ_OFF(struct au1xmmc_host *host, u32 mask) | ||
117 | { | ||
118 | u32 val = au_readl(HOST_CONFIG(host)); | ||
119 | val &= ~mask; | ||
120 | au_writel(val, HOST_CONFIG(host)); | ||
121 | au_sync(); | ||
122 | } | ||
123 | |||
124 | static inline void SEND_STOP(struct au1xmmc_host *host) | ||
125 | { | ||
126 | |||
127 | /* We know the value of CONFIG2, so avoid a read we don't need */ | ||
128 | u32 mask = SD_CONFIG2_EN; | ||
129 | |||
130 | WARN_ON(host->status != HOST_S_DATA); | ||
131 | host->status = HOST_S_STOP; | ||
132 | |||
133 | au_writel(mask | SD_CONFIG2_DF, HOST_CONFIG2(host)); | ||
134 | au_sync(); | ||
135 | |||
136 | /* Send the stop commmand */ | ||
137 | au_writel(STOP_CMD, HOST_CMD(host)); | ||
138 | } | ||
139 | |||
140 | static void au1xmmc_set_power(struct au1xmmc_host *host, int state) | ||
141 | { | ||
142 | |||
143 | u32 val = au1xmmc_card_table[host->id].bcsrpwr; | ||
144 | |||
145 | bcsr->board &= ~val; | ||
146 | if (state) bcsr->board |= val; | ||
147 | |||
148 | au_sync_delay(1); | ||
149 | } | ||
150 | |||
151 | static inline int au1xmmc_card_inserted(struct au1xmmc_host *host) | ||
152 | { | ||
153 | return (bcsr->sig_status & au1xmmc_card_table[host->id].bcsrstatus) | ||
154 | ? 1 : 0; | ||
155 | } | ||
156 | |||
157 | static inline int au1xmmc_card_readonly(struct au1xmmc_host *host) | ||
158 | { | ||
159 | return (bcsr->status & au1xmmc_card_table[host->id].wpstatus) | ||
160 | ? 1 : 0; | ||
161 | } | ||
162 | |||
163 | static void au1xmmc_finish_request(struct au1xmmc_host *host) | ||
164 | { | ||
165 | |||
166 | struct mmc_request *mrq = host->mrq; | ||
167 | |||
168 | host->mrq = NULL; | ||
169 | host->flags &= HOST_F_ACTIVE; | ||
170 | |||
171 | host->dma.len = 0; | ||
172 | host->dma.dir = 0; | ||
173 | |||
174 | host->pio.index = 0; | ||
175 | host->pio.offset = 0; | ||
176 | host->pio.len = 0; | ||
177 | |||
178 | host->status = HOST_S_IDLE; | ||
179 | |||
180 | bcsr->disk_leds |= (1 << 8); | ||
181 | |||
182 | mmc_request_done(host->mmc, mrq); | ||
183 | } | ||
184 | |||
185 | static void au1xmmc_tasklet_finish(unsigned long param) | ||
186 | { | ||
187 | struct au1xmmc_host *host = (struct au1xmmc_host *) param; | ||
188 | au1xmmc_finish_request(host); | ||
189 | } | ||
190 | |||
191 | static int au1xmmc_send_command(struct au1xmmc_host *host, int wait, | ||
192 | struct mmc_command *cmd) | ||
193 | { | ||
194 | |||
195 | u32 mmccmd = (cmd->opcode << SD_CMD_CI_SHIFT); | ||
196 | |||
197 | switch(cmd->flags) { | ||
198 | case MMC_RSP_R1: | ||
199 | mmccmd |= SD_CMD_RT_1; | ||
200 | break; | ||
201 | case MMC_RSP_R1B: | ||
202 | mmccmd |= SD_CMD_RT_1B; | ||
203 | break; | ||
204 | case MMC_RSP_R2: | ||
205 | mmccmd |= SD_CMD_RT_2; | ||
206 | break; | ||
207 | case MMC_RSP_R3: | ||
208 | mmccmd |= SD_CMD_RT_3; | ||
209 | break; | ||
210 | } | ||
211 | |||
212 | switch(cmd->opcode) { | ||
213 | case MMC_READ_SINGLE_BLOCK: | ||
214 | case SD_APP_SEND_SCR: | ||
215 | mmccmd |= SD_CMD_CT_2; | ||
216 | break; | ||
217 | case MMC_READ_MULTIPLE_BLOCK: | ||
218 | mmccmd |= SD_CMD_CT_4; | ||
219 | break; | ||
220 | case MMC_WRITE_BLOCK: | ||
221 | mmccmd |= SD_CMD_CT_1; | ||
222 | break; | ||
223 | |||
224 | case MMC_WRITE_MULTIPLE_BLOCK: | ||
225 | mmccmd |= SD_CMD_CT_3; | ||
226 | break; | ||
227 | case MMC_STOP_TRANSMISSION: | ||
228 | mmccmd |= SD_CMD_CT_7; | ||
229 | break; | ||
230 | } | ||
231 | |||
232 | au_writel(cmd->arg, HOST_CMDARG(host)); | ||
233 | au_sync(); | ||
234 | |||
235 | if (wait) | ||
236 | IRQ_OFF(host, SD_CONFIG_CR); | ||
237 | |||
238 | au_writel((mmccmd | SD_CMD_GO), HOST_CMD(host)); | ||
239 | au_sync(); | ||
240 | |||
241 | /* Wait for the command to go on the line */ | ||
242 | |||
243 | while(1) { | ||
244 | if (!(au_readl(HOST_CMD(host)) & SD_CMD_GO)) | ||
245 | break; | ||
246 | } | ||
247 | |||
248 | /* Wait for the command to come back */ | ||
249 | |||
250 | if (wait) { | ||
251 | u32 status = au_readl(HOST_STATUS(host)); | ||
252 | |||
253 | while(!(status & SD_STATUS_CR)) | ||
254 | status = au_readl(HOST_STATUS(host)); | ||
255 | |||
256 | /* Clear the CR status */ | ||
257 | au_writel(SD_STATUS_CR, HOST_STATUS(host)); | ||
258 | |||
259 | IRQ_ON(host, SD_CONFIG_CR); | ||
260 | } | ||
261 | |||
262 | return MMC_ERR_NONE; | ||
263 | } | ||
264 | |||
265 | static void au1xmmc_data_complete(struct au1xmmc_host *host, u32 status) | ||
266 | { | ||
267 | |||
268 | struct mmc_request *mrq = host->mrq; | ||
269 | struct mmc_data *data; | ||
270 | u32 crc; | ||
271 | |||
272 | WARN_ON(host->status != HOST_S_DATA && host->status != HOST_S_STOP); | ||
273 | |||
274 | if (host->mrq == NULL) | ||
275 | return; | ||
276 | |||
277 | data = mrq->cmd->data; | ||
278 | |||
279 | if (status == 0) | ||
280 | status = au_readl(HOST_STATUS(host)); | ||
281 | |||
282 | /* The transaction is really over when the SD_STATUS_DB bit is clear */ | ||
283 | |||
284 | while((host->flags & HOST_F_XMIT) && (status & SD_STATUS_DB)) | ||
285 | status = au_readl(HOST_STATUS(host)); | ||
286 | |||
287 | data->error = MMC_ERR_NONE; | ||
288 | dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, host->dma.dir); | ||
289 | |||
290 | /* Process any errors */ | ||
291 | |||
292 | crc = (status & (SD_STATUS_WC | SD_STATUS_RC)); | ||
293 | if (host->flags & HOST_F_XMIT) | ||
294 | crc |= ((status & 0x07) == 0x02) ? 0 : 1; | ||
295 | |||
296 | if (crc) | ||
297 | data->error = MMC_ERR_BADCRC; | ||
298 | |||
299 | /* Clear the CRC bits */ | ||
300 | au_writel(SD_STATUS_WC | SD_STATUS_RC, HOST_STATUS(host)); | ||
301 | |||
302 | data->bytes_xfered = 0; | ||
303 | |||
304 | if (data->error == MMC_ERR_NONE) { | ||
305 | if (host->flags & HOST_F_DMA) { | ||
306 | u32 chan = DMA_CHANNEL(host); | ||
307 | |||
308 | chan_tab_t *c = *((chan_tab_t **) chan); | ||
309 | au1x_dma_chan_t *cp = c->chan_ptr; | ||
310 | data->bytes_xfered = cp->ddma_bytecnt; | ||
311 | } | ||
312 | else | ||
313 | data->bytes_xfered = | ||
314 | (data->blocks * (1 << data->blksz_bits)) - | ||
315 | host->pio.len; | ||
316 | } | ||
317 | |||
318 | au1xmmc_finish_request(host); | ||
319 | } | ||
320 | |||
321 | static void au1xmmc_tasklet_data(unsigned long param) | ||
322 | { | ||
323 | struct au1xmmc_host *host = (struct au1xmmc_host *) param; | ||
324 | |||
325 | u32 status = au_readl(HOST_STATUS(host)); | ||
326 | au1xmmc_data_complete(host, status); | ||
327 | } | ||
328 | |||
329 | #define AU1XMMC_MAX_TRANSFER 8 | ||
330 | |||
331 | static void au1xmmc_send_pio(struct au1xmmc_host *host) | ||
332 | { | ||
333 | |||
334 | struct mmc_data *data = 0; | ||
335 | int sg_len, max, count = 0; | ||
336 | unsigned char *sg_ptr; | ||
337 | u32 status = 0; | ||
338 | struct scatterlist *sg; | ||
339 | |||
340 | data = host->mrq->data; | ||
341 | |||
342 | if (!(host->flags & HOST_F_XMIT)) | ||
343 | return; | ||
344 | |||
345 | /* This is the pointer to the data buffer */ | ||
346 | sg = &data->sg[host->pio.index]; | ||
347 | sg_ptr = page_address(sg->page) + sg->offset + host->pio.offset; | ||
348 | |||
349 | /* This is the space left inside the buffer */ | ||
350 | sg_len = data->sg[host->pio.index].length - host->pio.offset; | ||
351 | |||
352 | /* Check to if we need less then the size of the sg_buffer */ | ||
353 | |||
354 | max = (sg_len > host->pio.len) ? host->pio.len : sg_len; | ||
355 | if (max > AU1XMMC_MAX_TRANSFER) max = AU1XMMC_MAX_TRANSFER; | ||
356 | |||
357 | for(count = 0; count < max; count++ ) { | ||
358 | unsigned char val; | ||
359 | |||
360 | status = au_readl(HOST_STATUS(host)); | ||
361 | |||
362 | if (!(status & SD_STATUS_TH)) | ||
363 | break; | ||
364 | |||
365 | val = *sg_ptr++; | ||
366 | |||
367 | au_writel((unsigned long) val, HOST_TXPORT(host)); | ||
368 | au_sync(); | ||
369 | } | ||
370 | |||
371 | host->pio.len -= count; | ||
372 | host->pio.offset += count; | ||
373 | |||
374 | if (count == sg_len) { | ||
375 | host->pio.index++; | ||
376 | host->pio.offset = 0; | ||
377 | } | ||
378 | |||
379 | if (host->pio.len == 0) { | ||
380 | IRQ_OFF(host, SD_CONFIG_TH); | ||
381 | |||
382 | if (host->flags & HOST_F_STOP) | ||
383 | SEND_STOP(host); | ||
384 | |||
385 | tasklet_schedule(&host->data_task); | ||
386 | } | ||
387 | } | ||
388 | |||
389 | static void au1xmmc_receive_pio(struct au1xmmc_host *host) | ||
390 | { | ||
391 | |||
392 | struct mmc_data *data = 0; | ||
393 | int sg_len = 0, max = 0, count = 0; | ||
394 | unsigned char *sg_ptr = 0; | ||
395 | u32 status = 0; | ||
396 | struct scatterlist *sg; | ||
397 | |||
398 | data = host->mrq->data; | ||
399 | |||
400 | if (!(host->flags & HOST_F_RECV)) | ||
401 | return; | ||
402 | |||
403 | max = host->pio.len; | ||
404 | |||
405 | if (host->pio.index < host->dma.len) { | ||
406 | sg = &data->sg[host->pio.index]; | ||
407 | sg_ptr = page_address(sg->page) + sg->offset + host->pio.offset; | ||
408 | |||
409 | /* This is the space left inside the buffer */ | ||
410 | sg_len = sg_dma_len(&data->sg[host->pio.index]) - host->pio.offset; | ||
411 | |||
412 | /* Check to if we need less then the size of the sg_buffer */ | ||
413 | if (sg_len < max) max = sg_len; | ||
414 | } | ||
415 | |||
416 | if (max > AU1XMMC_MAX_TRANSFER) | ||
417 | max = AU1XMMC_MAX_TRANSFER; | ||
418 | |||
419 | for(count = 0; count < max; count++ ) { | ||
420 | u32 val; | ||
421 | status = au_readl(HOST_STATUS(host)); | ||
422 | |||
423 | if (!(status & SD_STATUS_NE)) | ||
424 | break; | ||
425 | |||
426 | if (status & SD_STATUS_RC) { | ||
427 | DEBUG("RX CRC Error [%d + %d].\n", host->id, | ||
428 | host->pio.len, count); | ||
429 | break; | ||
430 | } | ||
431 | |||
432 | if (status & SD_STATUS_RO) { | ||
433 | DEBUG("RX Overrun [%d + %d]\n", host->id, | ||
434 | host->pio.len, count); | ||
435 | break; | ||
436 | } | ||
437 | else if (status & SD_STATUS_RU) { | ||
438 | DEBUG("RX Underrun [%d + %d]\n", host->id, | ||
439 | host->pio.len, count); | ||
440 | break; | ||
441 | } | ||
442 | |||
443 | val = au_readl(HOST_RXPORT(host)); | ||
444 | |||
445 | if (sg_ptr) | ||
446 | *sg_ptr++ = (unsigned char) (val & 0xFF); | ||
447 | } | ||
448 | |||
449 | host->pio.len -= count; | ||
450 | host->pio.offset += count; | ||
451 | |||
452 | if (sg_len && count == sg_len) { | ||
453 | host->pio.index++; | ||
454 | host->pio.offset = 0; | ||
455 | } | ||
456 | |||
457 | if (host->pio.len == 0) { | ||
458 | //IRQ_OFF(host, SD_CONFIG_RA | SD_CONFIG_RF); | ||
459 | IRQ_OFF(host, SD_CONFIG_NE); | ||
460 | |||
461 | if (host->flags & HOST_F_STOP) | ||
462 | SEND_STOP(host); | ||
463 | |||
464 | tasklet_schedule(&host->data_task); | ||
465 | } | ||
466 | } | ||
467 | |||
468 | /* static void au1xmmc_cmd_complete | ||
469 | This is called when a command has been completed - grab the response | ||
470 | and check for errors. Then start the data transfer if it is indicated. | ||
471 | */ | ||
472 | |||
473 | static void au1xmmc_cmd_complete(struct au1xmmc_host *host, u32 status) | ||
474 | { | ||
475 | |||
476 | struct mmc_request *mrq = host->mrq; | ||
477 | struct mmc_command *cmd; | ||
478 | int trans; | ||
479 | |||
480 | if (!host->mrq) | ||
481 | return; | ||
482 | |||
483 | cmd = mrq->cmd; | ||
484 | cmd->error = MMC_ERR_NONE; | ||
485 | |||
486 | if ((cmd->flags & MMC_RSP_MASK) == MMC_RSP_SHORT) { | ||
487 | |||
488 | /* Techincally, we should be getting all 48 bits of the response | ||
489 | * (SD_RESP1 + SD_RESP2), but because our response omits the CRC, | ||
490 | * our data ends up being shifted 8 bits to the right. In this case, | ||
491 | * that means that the OSR data starts at bit 31, so we can just | ||
492 | * read RESP0 and return that | ||
493 | */ | ||
494 | |||
495 | cmd->resp[0] = au_readl(host->iobase + SD_RESP0); | ||
496 | } | ||
497 | else if ((cmd->flags & MMC_RSP_MASK) == MMC_RSP_LONG) { | ||
498 | u32 r[4]; | ||
499 | int i; | ||
500 | |||
501 | r[0] = au_readl(host->iobase + SD_RESP3); | ||
502 | r[1] = au_readl(host->iobase + SD_RESP2); | ||
503 | r[2] = au_readl(host->iobase + SD_RESP1); | ||
504 | r[3] = au_readl(host->iobase + SD_RESP0); | ||
505 | |||
506 | /* The CRC is omitted from the response, so really we only got | ||
507 | * 120 bytes, but the engine expects 128 bits, so we have to shift | ||
508 | * things up | ||
509 | */ | ||
510 | |||
511 | for(i = 0; i < 4; i++) { | ||
512 | cmd->resp[i] = (r[i] & 0x00FFFFFF) << 8; | ||
513 | if (i != 3) cmd->resp[i] |= (r[i + 1] & 0xFF000000) >> 24; | ||
514 | } | ||
515 | } | ||
516 | |||
517 | /* Figure out errors */ | ||
518 | |||
519 | if (status & (SD_STATUS_SC | SD_STATUS_WC | SD_STATUS_RC)) | ||
520 | cmd->error = MMC_ERR_BADCRC; | ||
521 | |||
522 | trans = host->flags & (HOST_F_XMIT | HOST_F_RECV); | ||
523 | |||
524 | if (!trans || cmd->error != MMC_ERR_NONE) { | ||
525 | |||
526 | IRQ_OFF(host, SD_CONFIG_TH | SD_CONFIG_RA|SD_CONFIG_RF); | ||
527 | tasklet_schedule(&host->finish_task); | ||
528 | return; | ||
529 | } | ||
530 | |||
531 | host->status = HOST_S_DATA; | ||
532 | |||
533 | if (host->flags & HOST_F_DMA) { | ||
534 | u32 channel = DMA_CHANNEL(host); | ||
535 | |||
536 | /* Start the DMA as soon as the buffer gets something in it */ | ||
537 | |||
538 | if (host->flags & HOST_F_RECV) { | ||
539 | u32 mask = SD_STATUS_DB | SD_STATUS_NE; | ||
540 | |||
541 | while((status & mask) != mask) | ||
542 | status = au_readl(HOST_STATUS(host)); | ||
543 | } | ||
544 | |||
545 | au1xxx_dbdma_start(channel); | ||
546 | } | ||
547 | } | ||
548 | |||
549 | static void au1xmmc_set_clock(struct au1xmmc_host *host, int rate) | ||
550 | { | ||
551 | |||
552 | unsigned int pbus = get_au1x00_speed(); | ||
553 | unsigned int divisor; | ||
554 | u32 config; | ||
555 | |||
556 | /* From databook: | ||
557 | divisor = ((((cpuclock / sbus_divisor) / 2) / mmcclock) / 2) - 1 | ||
558 | */ | ||
559 | |||
560 | pbus /= ((au_readl(SYS_POWERCTRL) & 0x3) + 2); | ||
561 | pbus /= 2; | ||
562 | |||
563 | divisor = ((pbus / rate) / 2) - 1; | ||
564 | |||
565 | config = au_readl(HOST_CONFIG(host)); | ||
566 | |||
567 | config &= ~(SD_CONFIG_DIV); | ||
568 | config |= (divisor & SD_CONFIG_DIV) | SD_CONFIG_DE; | ||
569 | |||
570 | au_writel(config, HOST_CONFIG(host)); | ||
571 | au_sync(); | ||
572 | } | ||
573 | |||
574 | static int | ||
575 | au1xmmc_prepare_data(struct au1xmmc_host *host, struct mmc_data *data) | ||
576 | { | ||
577 | |||
578 | int datalen = data->blocks * (1 << data->blksz_bits); | ||
579 | |||
580 | if (dma != 0) | ||
581 | host->flags |= HOST_F_DMA; | ||
582 | |||
583 | if (data->flags & MMC_DATA_READ) | ||
584 | host->flags |= HOST_F_RECV; | ||
585 | else | ||
586 | host->flags |= HOST_F_XMIT; | ||
587 | |||
588 | if (host->mrq->stop) | ||
589 | host->flags |= HOST_F_STOP; | ||
590 | |||
591 | host->dma.dir = DMA_BIDIRECTIONAL; | ||
592 | |||
593 | host->dma.len = dma_map_sg(mmc_dev(host->mmc), data->sg, | ||
594 | data->sg_len, host->dma.dir); | ||
595 | |||
596 | if (host->dma.len == 0) | ||
597 | return MMC_ERR_TIMEOUT; | ||
598 | |||
599 | au_writel((1 << data->blksz_bits) - 1, HOST_BLKSIZE(host)); | ||
600 | |||
601 | if (host->flags & HOST_F_DMA) { | ||
602 | int i; | ||
603 | u32 channel = DMA_CHANNEL(host); | ||
604 | |||
605 | au1xxx_dbdma_stop(channel); | ||
606 | |||
607 | for(i = 0; i < host->dma.len; i++) { | ||
608 | u32 ret = 0, flags = DDMA_FLAGS_NOIE; | ||
609 | struct scatterlist *sg = &data->sg[i]; | ||
610 | int sg_len = sg->length; | ||
611 | |||
612 | int len = (datalen > sg_len) ? sg_len : datalen; | ||
613 | |||
614 | if (i == host->dma.len - 1) | ||
615 | flags = DDMA_FLAGS_IE; | ||
616 | |||
617 | if (host->flags & HOST_F_XMIT){ | ||
618 | ret = au1xxx_dbdma_put_source_flags(channel, | ||
619 | (void *) (page_address(sg->page) + | ||
620 | sg->offset), | ||
621 | len, flags); | ||
622 | } | ||
623 | else { | ||
624 | ret = au1xxx_dbdma_put_dest_flags(channel, | ||
625 | (void *) (page_address(sg->page) + | ||
626 | sg->offset), | ||
627 | len, flags); | ||
628 | } | ||
629 | |||
630 | if (!ret) | ||
631 | goto dataerr; | ||
632 | |||
633 | datalen -= len; | ||
634 | } | ||
635 | } | ||
636 | else { | ||
637 | host->pio.index = 0; | ||
638 | host->pio.offset = 0; | ||
639 | host->pio.len = datalen; | ||
640 | |||
641 | if (host->flags & HOST_F_XMIT) | ||
642 | IRQ_ON(host, SD_CONFIG_TH); | ||
643 | else | ||
644 | IRQ_ON(host, SD_CONFIG_NE); | ||
645 | //IRQ_ON(host, SD_CONFIG_RA|SD_CONFIG_RF); | ||
646 | } | ||
647 | |||
648 | return MMC_ERR_NONE; | ||
649 | |||
650 | dataerr: | ||
651 | dma_unmap_sg(mmc_dev(host->mmc),data->sg,data->sg_len,host->dma.dir); | ||
652 | return MMC_ERR_TIMEOUT; | ||
653 | } | ||
654 | |||
655 | /* static void au1xmmc_request | ||
656 | This actually starts a command or data transaction | ||
657 | */ | ||
658 | |||
659 | static void au1xmmc_request(struct mmc_host* mmc, struct mmc_request* mrq) | ||
660 | { | ||
661 | |||
662 | struct au1xmmc_host *host = mmc_priv(mmc); | ||
663 | int ret = MMC_ERR_NONE; | ||
664 | |||
665 | WARN_ON(irqs_disabled()); | ||
666 | WARN_ON(host->status != HOST_S_IDLE); | ||
667 | |||
668 | host->mrq = mrq; | ||
669 | host->status = HOST_S_CMD; | ||
670 | |||
671 | bcsr->disk_leds &= ~(1 << 8); | ||
672 | |||
673 | if (mrq->data) { | ||
674 | FLUSH_FIFO(host); | ||
675 | ret = au1xmmc_prepare_data(host, mrq->data); | ||
676 | } | ||
677 | |||
678 | if (ret == MMC_ERR_NONE) | ||
679 | ret = au1xmmc_send_command(host, 0, mrq->cmd); | ||
680 | |||
681 | if (ret != MMC_ERR_NONE) { | ||
682 | mrq->cmd->error = ret; | ||
683 | au1xmmc_finish_request(host); | ||
684 | } | ||
685 | } | ||
686 | |||
687 | static void au1xmmc_reset_controller(struct au1xmmc_host *host) | ||
688 | { | ||
689 | |||
690 | /* Apply the clock */ | ||
691 | au_writel(SD_ENABLE_CE, HOST_ENABLE(host)); | ||
692 | au_sync_delay(1); | ||
693 | |||
694 | au_writel(SD_ENABLE_R | SD_ENABLE_CE, HOST_ENABLE(host)); | ||
695 | au_sync_delay(5); | ||
696 | |||
697 | au_writel(~0, HOST_STATUS(host)); | ||
698 | au_sync(); | ||
699 | |||
700 | au_writel(0, HOST_BLKSIZE(host)); | ||
701 | au_writel(0x001fffff, HOST_TIMEOUT(host)); | ||
702 | au_sync(); | ||
703 | |||
704 | au_writel(SD_CONFIG2_EN, HOST_CONFIG2(host)); | ||
705 | au_sync(); | ||
706 | |||
707 | au_writel(SD_CONFIG2_EN | SD_CONFIG2_FF, HOST_CONFIG2(host)); | ||
708 | au_sync_delay(1); | ||
709 | |||
710 | au_writel(SD_CONFIG2_EN, HOST_CONFIG2(host)); | ||
711 | au_sync(); | ||
712 | |||
713 | /* Configure interrupts */ | ||
714 | au_writel(AU1XMMC_INTERRUPTS, HOST_CONFIG(host)); | ||
715 | au_sync(); | ||
716 | } | ||
717 | |||
718 | |||
719 | static void au1xmmc_set_ios(struct mmc_host* mmc, struct mmc_ios* ios) | ||
720 | { | ||
721 | struct au1xmmc_host *host = mmc_priv(mmc); | ||
722 | |||
723 | DEBUG("set_ios (power=%u, clock=%uHz, vdd=%u, mode=%u)\n", | ||
724 | host->id, ios->power_mode, ios->clock, ios->vdd, | ||
725 | ios->bus_mode); | ||
726 | |||
727 | if (ios->power_mode == MMC_POWER_OFF) | ||
728 | au1xmmc_set_power(host, 0); | ||
729 | else if (ios->power_mode == MMC_POWER_ON) { | ||
730 | au1xmmc_set_power(host, 1); | ||
731 | } | ||
732 | |||
733 | if (ios->clock && ios->clock != host->clock) { | ||
734 | au1xmmc_set_clock(host, ios->clock); | ||
735 | host->clock = ios->clock; | ||
736 | } | ||
737 | } | ||
738 | |||
739 | static void au1xmmc_dma_callback(int irq, void *dev_id, struct pt_regs *regs) | ||
740 | { | ||
741 | struct au1xmmc_host *host = (struct au1xmmc_host *) dev_id; | ||
742 | u32 status; | ||
743 | |||
744 | /* Avoid spurious interrupts */ | ||
745 | |||
746 | if (!host->mrq) | ||
747 | return; | ||
748 | |||
749 | if (host->flags & HOST_F_STOP) | ||
750 | SEND_STOP(host); | ||
751 | |||
752 | tasklet_schedule(&host->data_task); | ||
753 | } | ||
754 | |||
755 | #define STATUS_TIMEOUT (SD_STATUS_RAT | SD_STATUS_DT) | ||
756 | #define STATUS_DATA_IN (SD_STATUS_NE) | ||
757 | #define STATUS_DATA_OUT (SD_STATUS_TH) | ||
758 | |||
759 | static irqreturn_t au1xmmc_irq(int irq, void *dev_id, struct pt_regs *regs) | ||
760 | { | ||
761 | |||
762 | u32 status; | ||
763 | int i, ret = 0; | ||
764 | |||
765 | disable_irq(AU1100_SD_IRQ); | ||
766 | |||
767 | for(i = 0; i < AU1XMMC_CONTROLLER_COUNT; i++) { | ||
768 | struct au1xmmc_host * host = au1xmmc_hosts[i]; | ||
769 | u32 handled = 1; | ||
770 | |||
771 | status = au_readl(HOST_STATUS(host)); | ||
772 | |||
773 | if (host->mrq && (status & STATUS_TIMEOUT)) { | ||
774 | if (status & SD_STATUS_RAT) | ||
775 | host->mrq->cmd->error = MMC_ERR_TIMEOUT; | ||
776 | |||
777 | else if (status & SD_STATUS_DT) | ||
778 | host->mrq->data->error = MMC_ERR_TIMEOUT; | ||
779 | |||
780 | /* In PIO mode, interrupts might still be enabled */ | ||
781 | IRQ_OFF(host, SD_CONFIG_NE | SD_CONFIG_TH); | ||
782 | |||
783 | //IRQ_OFF(host, SD_CONFIG_TH|SD_CONFIG_RA|SD_CONFIG_RF); | ||
784 | tasklet_schedule(&host->finish_task); | ||
785 | } | ||
786 | #if 0 | ||
787 | else if (status & SD_STATUS_DD) { | ||
788 | |||
789 | /* Sometimes we get a DD before a NE in PIO mode */ | ||
790 | |||
791 | if (!(host->flags & HOST_F_DMA) && | ||
792 | (status & SD_STATUS_NE)) | ||
793 | au1xmmc_receive_pio(host); | ||
794 | else { | ||
795 | au1xmmc_data_complete(host, status); | ||
796 | //tasklet_schedule(&host->data_task); | ||
797 | } | ||
798 | } | ||
799 | #endif | ||
800 | else if (status & (SD_STATUS_CR)) { | ||
801 | if (host->status == HOST_S_CMD) | ||
802 | au1xmmc_cmd_complete(host,status); | ||
803 | } | ||
804 | else if (!(host->flags & HOST_F_DMA)) { | ||
805 | if ((host->flags & HOST_F_XMIT) && | ||
806 | (status & STATUS_DATA_OUT)) | ||
807 | au1xmmc_send_pio(host); | ||
808 | else if ((host->flags & HOST_F_RECV) && | ||
809 | (status & STATUS_DATA_IN)) | ||
810 | au1xmmc_receive_pio(host); | ||
811 | } | ||
812 | else if (status & 0x203FBC70) { | ||
813 | DEBUG("Unhandled status %8.8x\n", host->id, status); | ||
814 | handled = 0; | ||
815 | } | ||
816 | |||
817 | au_writel(status, HOST_STATUS(host)); | ||
818 | au_sync(); | ||
819 | |||
820 | ret |= handled; | ||
821 | } | ||
822 | |||
823 | enable_irq(AU1100_SD_IRQ); | ||
824 | return ret; | ||
825 | } | ||
826 | |||
827 | static void au1xmmc_poll_event(unsigned long arg) | ||
828 | { | ||
829 | struct au1xmmc_host *host = (struct au1xmmc_host *) arg; | ||
830 | |||
831 | int card = au1xmmc_card_inserted(host); | ||
832 | int controller = (host->flags & HOST_F_ACTIVE) ? 1 : 0; | ||
833 | |||
834 | if (card != controller) { | ||
835 | host->flags &= ~HOST_F_ACTIVE; | ||
836 | if (card) host->flags |= HOST_F_ACTIVE; | ||
837 | mmc_detect_change(host->mmc, 0); | ||
838 | } | ||
839 | |||
840 | if (host->mrq != NULL) { | ||
841 | u32 status = au_readl(HOST_STATUS(host)); | ||
842 | DEBUG("PENDING - %8.8x\n", host->id, status); | ||
843 | } | ||
844 | |||
845 | mod_timer(&host->timer, jiffies + AU1XMMC_DETECT_TIMEOUT); | ||
846 | } | ||
847 | |||
848 | static dbdev_tab_t au1xmmc_mem_dbdev = | ||
849 | { | ||
850 | DSCR_CMD0_ALWAYS, DEV_FLAGS_ANYUSE, 0, 8, 0x00000000, 0, 0 | ||
851 | }; | ||
852 | |||
853 | static void au1xmmc_init_dma(struct au1xmmc_host *host) | ||
854 | { | ||
855 | |||
856 | u32 rxchan, txchan; | ||
857 | |||
858 | int txid = au1xmmc_card_table[host->id].tx_devid; | ||
859 | int rxid = au1xmmc_card_table[host->id].rx_devid; | ||
860 | |||
861 | /* DSCR_CMD0_ALWAYS has a stride of 32 bits, we need a stride | ||
862 | of 8 bits. And since devices are shared, we need to create | ||
863 | our own to avoid freaking out other devices | ||
864 | */ | ||
865 | |||
866 | int memid = au1xxx_ddma_add_device(&au1xmmc_mem_dbdev); | ||
867 | |||
868 | txchan = au1xxx_dbdma_chan_alloc(memid, txid, | ||
869 | au1xmmc_dma_callback, (void *) host); | ||
870 | |||
871 | rxchan = au1xxx_dbdma_chan_alloc(rxid, memid, | ||
872 | au1xmmc_dma_callback, (void *) host); | ||
873 | |||
874 | au1xxx_dbdma_set_devwidth(txchan, 8); | ||
875 | au1xxx_dbdma_set_devwidth(rxchan, 8); | ||
876 | |||
877 | au1xxx_dbdma_ring_alloc(txchan, AU1XMMC_DESCRIPTOR_COUNT); | ||
878 | au1xxx_dbdma_ring_alloc(rxchan, AU1XMMC_DESCRIPTOR_COUNT); | ||
879 | |||
880 | host->tx_chan = txchan; | ||
881 | host->rx_chan = rxchan; | ||
882 | } | ||
883 | |||
884 | struct mmc_host_ops au1xmmc_ops = { | ||
885 | .request = au1xmmc_request, | ||
886 | .set_ios = au1xmmc_set_ios, | ||
887 | }; | ||
888 | |||
889 | static int au1xmmc_probe(struct device *dev) | ||
890 | { | ||
891 | |||
892 | int i, ret = 0; | ||
893 | |||
894 | /* THe interrupt is shared among all controllers */ | ||
895 | ret = request_irq(AU1100_SD_IRQ, au1xmmc_irq, SA_INTERRUPT, "MMC", 0); | ||
896 | |||
897 | if (ret) { | ||
898 | printk(DRIVER_NAME "ERROR: Couldn't get int %d: %d\n", | ||
899 | AU1100_SD_IRQ, ret); | ||
900 | return -ENXIO; | ||
901 | } | ||
902 | |||
903 | disable_irq(AU1100_SD_IRQ); | ||
904 | |||
905 | for(i = 0; i < AU1XMMC_CONTROLLER_COUNT; i++) { | ||
906 | struct mmc_host *mmc = mmc_alloc_host(sizeof(struct au1xmmc_host), dev); | ||
907 | struct au1xmmc_host *host = 0; | ||
908 | |||
909 | if (!mmc) { | ||
910 | printk(DRIVER_NAME "ERROR: no mem for host %d\n", i); | ||
911 | au1xmmc_hosts[i] = 0; | ||
912 | continue; | ||
913 | } | ||
914 | |||
915 | mmc->ops = &au1xmmc_ops; | ||
916 | |||
917 | mmc->f_min = 450000; | ||
918 | mmc->f_max = 24000000; | ||
919 | |||
920 | mmc->max_seg_size = AU1XMMC_DESCRIPTOR_SIZE; | ||
921 | mmc->max_phys_segs = AU1XMMC_DESCRIPTOR_COUNT; | ||
922 | |||
923 | mmc->ocr_avail = AU1XMMC_OCR; | ||
924 | |||
925 | host = mmc_priv(mmc); | ||
926 | host->mmc = mmc; | ||
927 | |||
928 | host->id = i; | ||
929 | host->iobase = au1xmmc_card_table[host->id].iobase; | ||
930 | host->clock = 0; | ||
931 | host->power_mode = MMC_POWER_OFF; | ||
932 | |||
933 | host->flags = au1xmmc_card_inserted(host) ? HOST_F_ACTIVE : 0; | ||
934 | host->status = HOST_S_IDLE; | ||
935 | |||
936 | init_timer(&host->timer); | ||
937 | |||
938 | host->timer.function = au1xmmc_poll_event; | ||
939 | host->timer.data = (unsigned long) host; | ||
940 | host->timer.expires = jiffies + AU1XMMC_DETECT_TIMEOUT; | ||
941 | |||
942 | tasklet_init(&host->data_task, au1xmmc_tasklet_data, | ||
943 | (unsigned long) host); | ||
944 | |||
945 | tasklet_init(&host->finish_task, au1xmmc_tasklet_finish, | ||
946 | (unsigned long) host); | ||
947 | |||
948 | spin_lock_init(&host->lock); | ||
949 | |||
950 | if (dma != 0) | ||
951 | au1xmmc_init_dma(host); | ||
952 | |||
953 | au1xmmc_reset_controller(host); | ||
954 | |||
955 | mmc_add_host(mmc); | ||
956 | au1xmmc_hosts[i] = host; | ||
957 | |||
958 | add_timer(&host->timer); | ||
959 | |||
960 | printk(KERN_INFO DRIVER_NAME ": MMC Controller %d set up at %8.8X (mode=%s)\n", | ||
961 | host->id, host->iobase, dma ? "dma" : "pio"); | ||
962 | } | ||
963 | |||
964 | enable_irq(AU1100_SD_IRQ); | ||
965 | |||
966 | return 0; | ||
967 | } | ||
968 | |||
969 | static int au1xmmc_remove(struct device *dev) | ||
970 | { | ||
971 | |||
972 | int i; | ||
973 | |||
974 | disable_irq(AU1100_SD_IRQ); | ||
975 | |||
976 | for(i = 0; i < AU1XMMC_CONTROLLER_COUNT; i++) { | ||
977 | struct au1xmmc_host *host = au1xmmc_hosts[i]; | ||
978 | if (!host) continue; | ||
979 | |||
980 | tasklet_kill(&host->data_task); | ||
981 | tasklet_kill(&host->finish_task); | ||
982 | |||
983 | del_timer_sync(&host->timer); | ||
984 | au1xmmc_set_power(host, 0); | ||
985 | |||
986 | mmc_remove_host(host->mmc); | ||
987 | |||
988 | au1xxx_dbdma_chan_free(host->tx_chan); | ||
989 | au1xxx_dbdma_chan_free(host->rx_chan); | ||
990 | |||
991 | au_writel(0x0, HOST_ENABLE(host)); | ||
992 | au_sync(); | ||
993 | } | ||
994 | |||
995 | free_irq(AU1100_SD_IRQ, 0); | ||
996 | return 0; | ||
997 | } | ||
998 | |||
999 | static struct device_driver au1xmmc_driver = { | ||
1000 | .name = DRIVER_NAME, | ||
1001 | .bus = &platform_bus_type, | ||
1002 | .probe = au1xmmc_probe, | ||
1003 | .remove = au1xmmc_remove, | ||
1004 | .suspend = NULL, | ||
1005 | .resume = NULL | ||
1006 | }; | ||
1007 | |||
1008 | static int __init au1xmmc_init(void) | ||
1009 | { | ||
1010 | return driver_register(&au1xmmc_driver); | ||
1011 | } | ||
1012 | |||
1013 | static void __exit au1xmmc_exit(void) | ||
1014 | { | ||
1015 | driver_unregister(&au1xmmc_driver); | ||
1016 | } | ||
1017 | |||
1018 | module_init(au1xmmc_init); | ||
1019 | module_exit(au1xmmc_exit); | ||
1020 | |||
1021 | #ifdef MODULE | ||
1022 | MODULE_AUTHOR("Advanced Micro Devices, Inc"); | ||
1023 | MODULE_DESCRIPTION("MMC/SD driver for the Alchemy Au1XXX"); | ||
1024 | MODULE_LICENSE("GPL"); | ||
1025 | #endif | ||
1026 | |||
diff --git a/drivers/mmc/au1xmmc.h b/drivers/mmc/au1xmmc.h new file mode 100644 index 000000000000..341cbdf0baca --- /dev/null +++ b/drivers/mmc/au1xmmc.h | |||
@@ -0,0 +1,96 @@ | |||
1 | #ifndef _AU1XMMC_H_ | ||
2 | #define _AU1XMMC_H_ | ||
3 | |||
4 | /* Hardware definitions */ | ||
5 | |||
6 | #define AU1XMMC_DESCRIPTOR_COUNT 1 | ||
7 | #define AU1XMMC_DESCRIPTOR_SIZE 2048 | ||
8 | |||
9 | #define AU1XMMC_OCR ( MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30 | \ | ||
10 | MMC_VDD_30_31 | MMC_VDD_31_32 | MMC_VDD_32_33 | \ | ||
11 | MMC_VDD_33_34 | MMC_VDD_34_35 | MMC_VDD_35_36) | ||
12 | |||
13 | /* Easy access macros */ | ||
14 | |||
15 | #define HOST_STATUS(h) ((h)->iobase + SD_STATUS) | ||
16 | #define HOST_CONFIG(h) ((h)->iobase + SD_CONFIG) | ||
17 | #define HOST_ENABLE(h) ((h)->iobase + SD_ENABLE) | ||
18 | #define HOST_TXPORT(h) ((h)->iobase + SD_TXPORT) | ||
19 | #define HOST_RXPORT(h) ((h)->iobase + SD_RXPORT) | ||
20 | #define HOST_CMDARG(h) ((h)->iobase + SD_CMDARG) | ||
21 | #define HOST_BLKSIZE(h) ((h)->iobase + SD_BLKSIZE) | ||
22 | #define HOST_CMD(h) ((h)->iobase + SD_CMD) | ||
23 | #define HOST_CONFIG2(h) ((h)->iobase + SD_CONFIG2) | ||
24 | #define HOST_TIMEOUT(h) ((h)->iobase + SD_TIMEOUT) | ||
25 | #define HOST_DEBUG(h) ((h)->iobase + SD_DEBUG) | ||
26 | |||
27 | #define DMA_CHANNEL(h) \ | ||
28 | ( ((h)->flags & HOST_F_XMIT) ? (h)->tx_chan : (h)->rx_chan) | ||
29 | |||
30 | /* This gives us a hard value for the stop command that we can write directly | ||
31 | * to the command register | ||
32 | */ | ||
33 | |||
34 | #define STOP_CMD (SD_CMD_RT_1B|SD_CMD_CT_7|(0xC << SD_CMD_CI_SHIFT)|SD_CMD_GO) | ||
35 | |||
36 | /* This is the set of interrupts that we configure by default */ | ||
37 | |||
38 | #if 0 | ||
39 | #define AU1XMMC_INTERRUPTS (SD_CONFIG_SC | SD_CONFIG_DT | SD_CONFIG_DD | \ | ||
40 | SD_CONFIG_RAT | SD_CONFIG_CR | SD_CONFIG_I) | ||
41 | #endif | ||
42 | |||
43 | #define AU1XMMC_INTERRUPTS (SD_CONFIG_SC | SD_CONFIG_DT | \ | ||
44 | SD_CONFIG_RAT | SD_CONFIG_CR | SD_CONFIG_I) | ||
45 | /* The poll event (looking for insert/remove events runs twice a second */ | ||
46 | #define AU1XMMC_DETECT_TIMEOUT (HZ/2) | ||
47 | |||
48 | struct au1xmmc_host { | ||
49 | struct mmc_host *mmc; | ||
50 | struct mmc_request *mrq; | ||
51 | |||
52 | u32 id; | ||
53 | |||
54 | u32 flags; | ||
55 | u32 iobase; | ||
56 | u32 clock; | ||
57 | u32 bus_width; | ||
58 | u32 power_mode; | ||
59 | |||
60 | int status; | ||
61 | |||
62 | struct { | ||
63 | int len; | ||
64 | int dir; | ||
65 | } dma; | ||
66 | |||
67 | struct { | ||
68 | int index; | ||
69 | int offset; | ||
70 | int len; | ||
71 | } pio; | ||
72 | |||
73 | u32 tx_chan; | ||
74 | u32 rx_chan; | ||
75 | |||
76 | struct timer_list timer; | ||
77 | struct tasklet_struct finish_task; | ||
78 | struct tasklet_struct data_task; | ||
79 | |||
80 | spinlock_t lock; | ||
81 | }; | ||
82 | |||
83 | /* Status flags used by the host structure */ | ||
84 | |||
85 | #define HOST_F_XMIT 0x0001 | ||
86 | #define HOST_F_RECV 0x0002 | ||
87 | #define HOST_F_DMA 0x0010 | ||
88 | #define HOST_F_ACTIVE 0x0100 | ||
89 | #define HOST_F_STOP 0x1000 | ||
90 | |||
91 | #define HOST_S_IDLE 0x0001 | ||
92 | #define HOST_S_CMD 0x0002 | ||
93 | #define HOST_S_DATA 0x0003 | ||
94 | #define HOST_S_STOP 0x0004 | ||
95 | |||
96 | #endif | ||
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile index a41fbb38fdcb..77ecee7f987b 100644 --- a/drivers/pcmcia/Makefile +++ b/drivers/pcmcia/Makefile | |||
@@ -42,9 +42,11 @@ pxa2xx_core-y += soc_common.o pxa2xx_base.o | |||
42 | au1x00_ss-y += au1000_generic.o | 42 | au1x00_ss-y += au1000_generic.o |
43 | au1x00_ss-$(CONFIG_MIPS_PB1000) += au1000_pb1x00.o | 43 | au1x00_ss-$(CONFIG_MIPS_PB1000) += au1000_pb1x00.o |
44 | au1x00_ss-$(CONFIG_MIPS_PB1100) += au1000_pb1x00.o | 44 | au1x00_ss-$(CONFIG_MIPS_PB1100) += au1000_pb1x00.o |
45 | au1x00_ss-$(CONFIG_MIPS_PB1200) += au1000_db1x00.o | ||
45 | au1x00_ss-$(CONFIG_MIPS_PB1500) += au1000_pb1x00.o | 46 | au1x00_ss-$(CONFIG_MIPS_PB1500) += au1000_pb1x00.o |
46 | au1x00_ss-$(CONFIG_MIPS_DB1000) += au1000_db1x00.o | 47 | au1x00_ss-$(CONFIG_MIPS_DB1000) += au1000_db1x00.o |
47 | au1x00_ss-$(CONFIG_MIPS_DB1100) += au1000_db1x00.o | 48 | au1x00_ss-$(CONFIG_MIPS_DB1100) += au1000_db1x00.o |
49 | au1x00_ss-$(CONFIG_MIPS_DB1200) += au1000_db1x00.o | ||
48 | au1x00_ss-$(CONFIG_MIPS_DB1500) += au1000_db1x00.o | 50 | au1x00_ss-$(CONFIG_MIPS_DB1500) += au1000_db1x00.o |
49 | au1x00_ss-$(CONFIG_MIPS_DB1550) += au1000_db1x00.o | 51 | au1x00_ss-$(CONFIG_MIPS_DB1550) += au1000_db1x00.o |
50 | au1x00_ss-$(CONFIG_MIPS_XXS1500) += au1000_xxs1500.o | 52 | au1x00_ss-$(CONFIG_MIPS_XXS1500) += au1000_xxs1500.o |
diff --git a/drivers/pcmcia/au1000_db1x00.c b/drivers/pcmcia/au1000_db1x00.c index 42cf8bfbcc98..24cfee1a412c 100644 --- a/drivers/pcmcia/au1000_db1x00.c +++ b/drivers/pcmcia/au1000_db1x00.c | |||
@@ -40,7 +40,15 @@ | |||
40 | #include <asm/irq.h> | 40 | #include <asm/irq.h> |
41 | #include <asm/signal.h> | 41 | #include <asm/signal.h> |
42 | #include <asm/mach-au1x00/au1000.h> | 42 | #include <asm/mach-au1x00/au1000.h> |
43 | #include <asm/mach-db1x00/db1x00.h> | 43 | |
44 | #if defined(CONFIG_MIPS_DB1200) | ||
45 | #include <db1200.h> | ||
46 | #elif defined(CONFIG_MIPS_PB1200) | ||
47 | #include <pb1200.h> | ||
48 | #else | ||
49 | #include <asm/mach-db1x00/db1x00.h> | ||
50 | static BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR; | ||
51 | #endif | ||
44 | 52 | ||
45 | #include "au1000_generic.h" | 53 | #include "au1000_generic.h" |
46 | 54 | ||
@@ -50,7 +58,6 @@ | |||
50 | #define debug(x,args...) | 58 | #define debug(x,args...) |
51 | #endif | 59 | #endif |
52 | 60 | ||
53 | static BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR; | ||
54 | 61 | ||
55 | struct au1000_pcmcia_socket au1000_pcmcia_socket[PCMCIA_NUM_SOCKS]; | 62 | struct au1000_pcmcia_socket au1000_pcmcia_socket[PCMCIA_NUM_SOCKS]; |
56 | extern int au1x00_pcmcia_socket_probe(struct device *, struct pcmcia_low_level *, int, int); | 63 | extern int au1x00_pcmcia_socket_probe(struct device *, struct pcmcia_low_level *, int, int); |
@@ -59,6 +66,8 @@ static int db1x00_pcmcia_hw_init(struct au1000_pcmcia_socket *skt) | |||
59 | { | 66 | { |
60 | #ifdef CONFIG_MIPS_DB1550 | 67 | #ifdef CONFIG_MIPS_DB1550 |
61 | skt->irq = skt->nr ? AU1000_GPIO_5 : AU1000_GPIO_3; | 68 | skt->irq = skt->nr ? AU1000_GPIO_5 : AU1000_GPIO_3; |
69 | #elif defined(CONFIG_MIPS_DB1200) || defined(CONFIG_MIPS_PB1200) | ||
70 | skt->irq = skt->nr ? BOARD_PC1_INT : BOARD_PC0_INT; | ||
62 | #else | 71 | #else |
63 | skt->irq = skt->nr ? AU1000_GPIO_5 : AU1000_GPIO_2; | 72 | skt->irq = skt->nr ? AU1000_GPIO_5 : AU1000_GPIO_2; |
64 | #endif | 73 | #endif |
@@ -85,11 +94,19 @@ db1x00_pcmcia_socket_state(struct au1000_pcmcia_socket *skt, struct pcmcia_state | |||
85 | switch (skt->nr) { | 94 | switch (skt->nr) { |
86 | case 0: | 95 | case 0: |
87 | vs = bcsr->status & 0x3; | 96 | vs = bcsr->status & 0x3; |
97 | #if defined(CONFIG_MIPS_DB1200) || defined(CONFIG_MIPS_PB1200) | ||
98 | inserted = BOARD_CARD_INSERTED(0); | ||
99 | #else | ||
88 | inserted = !(bcsr->status & (1<<4)); | 100 | inserted = !(bcsr->status & (1<<4)); |
101 | #endif | ||
89 | break; | 102 | break; |
90 | case 1: | 103 | case 1: |
91 | vs = (bcsr->status & 0xC)>>2; | 104 | vs = (bcsr->status & 0xC)>>2; |
105 | #if defined(CONFIG_MIPS_DB1200) || defined(CONFIG_MIPS_PB1200) | ||
106 | inserted = BOARD_CARD_INSERTED(1); | ||
107 | #else | ||
92 | inserted = !(bcsr->status & (1<<5)); | 108 | inserted = !(bcsr->status & (1<<5)); |
109 | #endif | ||
93 | break; | 110 | break; |
94 | default:/* should never happen */ | 111 | default:/* should never happen */ |
95 | return; | 112 | return; |
diff --git a/drivers/pcmcia/au1000_generic.c b/drivers/pcmcia/au1000_generic.c index d90a634cebf5..ba48cef3a9dc 100644 --- a/drivers/pcmcia/au1000_generic.c +++ b/drivers/pcmcia/au1000_generic.c | |||
@@ -490,7 +490,7 @@ int au1x00_drv_pcmcia_remove(struct device *dev) | |||
490 | flush_scheduled_work(); | 490 | flush_scheduled_work(); |
491 | skt->ops->hw_shutdown(skt); | 491 | skt->ops->hw_shutdown(skt); |
492 | au1x00_pcmcia_config_skt(skt, &dead_socket); | 492 | au1x00_pcmcia_config_skt(skt, &dead_socket); |
493 | iounmap(skt->virt_io); | 493 | iounmap(skt->virt_io + (u32)mips_io_port_base); |
494 | skt->virt_io = NULL; | 494 | skt->virt_io = NULL; |
495 | } | 495 | } |
496 | 496 | ||
@@ -528,10 +528,6 @@ static struct device_driver au1x00_pcmcia_driver = { | |||
528 | .resume = pcmcia_socket_dev_resume, | 528 | .resume = pcmcia_socket_dev_resume, |
529 | }; | 529 | }; |
530 | 530 | ||
531 | static struct platform_device au1x00_device = { | ||
532 | .name = "au1x00-pcmcia", | ||
533 | .id = 0, | ||
534 | }; | ||
535 | 531 | ||
536 | /* au1x00_pcmcia_init() | 532 | /* au1x00_pcmcia_init() |
537 | * | 533 | * |
@@ -545,7 +541,6 @@ static int __init au1x00_pcmcia_init(void) | |||
545 | int error = 0; | 541 | int error = 0; |
546 | if ((error = driver_register(&au1x00_pcmcia_driver))) | 542 | if ((error = driver_register(&au1x00_pcmcia_driver))) |
547 | return error; | 543 | return error; |
548 | platform_device_register(&au1x00_device); | ||
549 | return error; | 544 | return error; |
550 | } | 545 | } |
551 | 546 | ||
@@ -556,7 +551,6 @@ static int __init au1x00_pcmcia_init(void) | |||
556 | static void __exit au1x00_pcmcia_exit(void) | 551 | static void __exit au1x00_pcmcia_exit(void) |
557 | { | 552 | { |
558 | driver_unregister(&au1x00_pcmcia_driver); | 553 | driver_unregister(&au1x00_pcmcia_driver); |
559 | platform_device_unregister(&au1x00_device); | ||
560 | } | 554 | } |
561 | 555 | ||
562 | module_init(au1x00_pcmcia_init); | 556 | module_init(au1x00_pcmcia_init); |
diff --git a/drivers/pcmcia/au1000_generic.h b/drivers/pcmcia/au1000_generic.h index d5122b1ea94b..b0e7908392a7 100644 --- a/drivers/pcmcia/au1000_generic.h +++ b/drivers/pcmcia/au1000_generic.h | |||
@@ -44,13 +44,13 @@ | |||
44 | /* pcmcia socket 1 needs external glue logic so the memory map | 44 | /* pcmcia socket 1 needs external glue logic so the memory map |
45 | * differs from board to board. | 45 | * differs from board to board. |
46 | */ | 46 | */ |
47 | #if defined(CONFIG_MIPS_PB1000) || defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_PB1550) | 47 | #if defined(CONFIG_MIPS_PB1000) || defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_PB1550) || defined(CONFIG_MIPS_PB1200) |
48 | #define AU1X_SOCK1_IO 0xF08000000 | 48 | #define AU1X_SOCK1_IO 0xF08000000 |
49 | #define AU1X_SOCK1_PHYS_ATTR 0xF48000000 | 49 | #define AU1X_SOCK1_PHYS_ATTR 0xF48000000 |
50 | #define AU1X_SOCK1_PHYS_MEM 0xF88000000 | 50 | #define AU1X_SOCK1_PHYS_MEM 0xF88000000 |
51 | #define AU1X_SOCK1_PSEUDO_PHYS_ATTR 0xF4800000 | 51 | #define AU1X_SOCK1_PSEUDO_PHYS_ATTR 0xF4800000 |
52 | #define AU1X_SOCK1_PSEUDO_PHYS_MEM 0xF8800000 | 52 | #define AU1X_SOCK1_PSEUDO_PHYS_MEM 0xF8800000 |
53 | #elif defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100) || defined(CONFIG_MIPS_DB1500) || defined(CONFIG_MIPS_DB1550) | 53 | #elif defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100) || defined(CONFIG_MIPS_DB1500) || defined(CONFIG_MIPS_DB1550) || defined(CONFIG_MIPS_DB1200) |
54 | #define AU1X_SOCK1_IO 0xF04000000 | 54 | #define AU1X_SOCK1_IO 0xF04000000 |
55 | #define AU1X_SOCK1_PHYS_ATTR 0xF44000000 | 55 | #define AU1X_SOCK1_PHYS_ATTR 0xF44000000 |
56 | #define AU1X_SOCK1_PHYS_MEM 0xF84000000 | 56 | #define AU1X_SOCK1_PHYS_MEM 0xF84000000 |
diff --git a/drivers/scsi/dec_esp.c b/drivers/scsi/dec_esp.c index 315f95a0d6c0..4f39890b44ac 100644 --- a/drivers/scsi/dec_esp.c +++ b/drivers/scsi/dec_esp.c | |||
@@ -228,7 +228,7 @@ static int dec_esp_detect(Scsi_Host_Template * tpnt) | |||
228 | mem_start = get_tc_base_addr(slot); | 228 | mem_start = get_tc_base_addr(slot); |
229 | 229 | ||
230 | /* Store base addr into esp struct */ | 230 | /* Store base addr into esp struct */ |
231 | esp->slot = PHYSADDR(mem_start); | 231 | esp->slot = CPHYSADDR(mem_start); |
232 | 232 | ||
233 | esp->dregs = 0; | 233 | esp->dregs = 0; |
234 | esp->eregs = (struct ESP_regs *) (mem_start + DEC_SCSI_SREG); | 234 | esp->eregs = (struct ESP_regs *) (mem_start + DEC_SCSI_SREG); |
diff --git a/drivers/tc/tc.c b/drivers/tc/tc.c index a89ef4df80c3..a0e5af638e0e 100644 --- a/drivers/tc/tc.c +++ b/drivers/tc/tc.c | |||
@@ -8,33 +8,31 @@ | |||
8 | * for more details. | 8 | * for more details. |
9 | * | 9 | * |
10 | * Copyright (c) Harald Koerfgen, 1998 | 10 | * Copyright (c) Harald Koerfgen, 1998 |
11 | * Copyright (c) 2001, 2003 Maciej W. Rozycki | 11 | * Copyright (c) 2001, 2003, 2005 Maciej W. Rozycki |
12 | */ | 12 | */ |
13 | #include <linux/string.h> | ||
14 | #include <linux/init.h> | 13 | #include <linux/init.h> |
15 | #include <linux/ioport.h> | ||
16 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
17 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/string.h> | ||
17 | #include <linux/types.h> | ||
18 | 18 | ||
19 | #include <asm/addrspace.h> | 19 | #include <asm/addrspace.h> |
20 | #include <asm/bug.h> | ||
20 | #include <asm/errno.h> | 21 | #include <asm/errno.h> |
22 | #include <asm/io.h> | ||
23 | #include <asm/paccess.h> | ||
24 | |||
21 | #include <asm/dec/machtype.h> | 25 | #include <asm/dec/machtype.h> |
22 | #include <asm/dec/prom.h> | 26 | #include <asm/dec/prom.h> |
23 | #include <asm/dec/tcinfo.h> | 27 | #include <asm/dec/tcinfo.h> |
24 | #include <asm/dec/tcmodule.h> | 28 | #include <asm/dec/tcmodule.h> |
25 | #include <asm/dec/interrupts.h> | 29 | #include <asm/dec/interrupts.h> |
26 | #include <asm/paccess.h> | ||
27 | #include <asm/ptrace.h> | ||
28 | |||
29 | #define TC_DEBUG | ||
30 | 30 | ||
31 | MODULE_LICENSE("GPL"); | 31 | MODULE_LICENSE("GPL"); |
32 | slot_info tc_bus[MAX_SLOT]; | 32 | slot_info tc_bus[MAX_SLOT]; |
33 | static int num_tcslots; | 33 | static int num_tcslots; |
34 | static tcinfo *info; | 34 | static tcinfo *info; |
35 | 35 | ||
36 | unsigned long system_base; | ||
37 | |||
38 | /* | 36 | /* |
39 | * Interface to the world. Read comment in include/asm-mips/tc.h. | 37 | * Interface to the world. Read comment in include/asm-mips/tc.h. |
40 | */ | 38 | */ |
@@ -97,13 +95,16 @@ unsigned long get_tc_speed(void) | |||
97 | static void __init tc_probe(unsigned long startaddr, unsigned long size, | 95 | static void __init tc_probe(unsigned long startaddr, unsigned long size, |
98 | int slots) | 96 | int slots) |
99 | { | 97 | { |
98 | unsigned long slotaddr; | ||
100 | int i, slot, err; | 99 | int i, slot, err; |
101 | long offset; | 100 | long offset; |
102 | unsigned char pattern[4]; | 101 | u8 pattern[4]; |
103 | unsigned char *module; | 102 | volatile u8 *module; |
104 | 103 | ||
105 | for (slot = 0; slot < slots; slot++) { | 104 | for (slot = 0; slot < slots; slot++) { |
106 | module = (char *)(startaddr + slot * size); | 105 | slotaddr = startaddr + slot * size; |
106 | module = ioremap_nocache(slotaddr, size); | ||
107 | BUG_ON(!module); | ||
107 | 108 | ||
108 | offset = OLDCARD; | 109 | offset = OLDCARD; |
109 | 110 | ||
@@ -112,8 +113,10 @@ static void __init tc_probe(unsigned long startaddr, unsigned long size, | |||
112 | err |= get_dbe(pattern[1], module + OLDCARD + TC_PATTERN1); | 113 | err |= get_dbe(pattern[1], module + OLDCARD + TC_PATTERN1); |
113 | err |= get_dbe(pattern[2], module + OLDCARD + TC_PATTERN2); | 114 | err |= get_dbe(pattern[2], module + OLDCARD + TC_PATTERN2); |
114 | err |= get_dbe(pattern[3], module + OLDCARD + TC_PATTERN3); | 115 | err |= get_dbe(pattern[3], module + OLDCARD + TC_PATTERN3); |
115 | if (err) | 116 | if (err) { |
117 | iounmap(module); | ||
116 | continue; | 118 | continue; |
119 | } | ||
117 | 120 | ||
118 | if (pattern[0] != 0x55 || pattern[1] != 0x00 || | 121 | if (pattern[0] != 0x55 || pattern[1] != 0x00 || |
119 | pattern[2] != 0xaa || pattern[3] != 0xff) { | 122 | pattern[2] != 0xaa || pattern[3] != 0xff) { |
@@ -124,16 +127,20 @@ static void __init tc_probe(unsigned long startaddr, unsigned long size, | |||
124 | err |= get_dbe(pattern[1], module + TC_PATTERN1); | 127 | err |= get_dbe(pattern[1], module + TC_PATTERN1); |
125 | err |= get_dbe(pattern[2], module + TC_PATTERN2); | 128 | err |= get_dbe(pattern[2], module + TC_PATTERN2); |
126 | err |= get_dbe(pattern[3], module + TC_PATTERN3); | 129 | err |= get_dbe(pattern[3], module + TC_PATTERN3); |
127 | if (err) | 130 | if (err) { |
131 | iounmap(module); | ||
128 | continue; | 132 | continue; |
133 | } | ||
129 | } | 134 | } |
130 | 135 | ||
131 | if (pattern[0] != 0x55 || pattern[1] != 0x00 || | 136 | if (pattern[0] != 0x55 || pattern[1] != 0x00 || |
132 | pattern[2] != 0xaa || pattern[3] != 0xff) | 137 | pattern[2] != 0xaa || pattern[3] != 0xff) { |
138 | iounmap(module); | ||
133 | continue; | 139 | continue; |
140 | } | ||
134 | 141 | ||
135 | tc_bus[slot].base_addr = (unsigned long)module; | 142 | tc_bus[slot].base_addr = slotaddr; |
136 | for(i = 0; i < 8; i++) { | 143 | for (i = 0; i < 8; i++) { |
137 | tc_bus[slot].firmware[i] = | 144 | tc_bus[slot].firmware[i] = |
138 | module[TC_FIRM_VER + offset + 4 * i]; | 145 | module[TC_FIRM_VER + offset + 4 * i]; |
139 | tc_bus[slot].vendor[i] = | 146 | tc_bus[slot].vendor[i] = |
@@ -171,13 +178,15 @@ static void __init tc_probe(unsigned long startaddr, unsigned long size, | |||
171 | tc_bus[slot].interrupt = -1; | 178 | tc_bus[slot].interrupt = -1; |
172 | break; | 179 | break; |
173 | } | 180 | } |
181 | |||
182 | iounmap(module); | ||
174 | } | 183 | } |
175 | } | 184 | } |
176 | 185 | ||
177 | /* | 186 | /* |
178 | * the main entry | 187 | * the main entry |
179 | */ | 188 | */ |
180 | void __init tc_init(void) | 189 | static int __init tc_init(void) |
181 | { | 190 | { |
182 | int tc_clock; | 191 | int tc_clock; |
183 | int i; | 192 | int i; |
@@ -185,7 +194,7 @@ void __init tc_init(void) | |||
185 | unsigned long slot_size; | 194 | unsigned long slot_size; |
186 | 195 | ||
187 | if (!TURBOCHANNEL) | 196 | if (!TURBOCHANNEL) |
188 | return; | 197 | return 0; |
189 | 198 | ||
190 | for (i = 0; i < MAX_SLOT; i++) { | 199 | for (i = 0; i < MAX_SLOT; i++) { |
191 | tc_bus[i].base_addr = 0; | 200 | tc_bus[i].base_addr = 0; |
@@ -196,8 +205,8 @@ void __init tc_init(void) | |||
196 | tc_bus[i].flags = FREE; | 205 | tc_bus[i].flags = FREE; |
197 | } | 206 | } |
198 | 207 | ||
199 | info = (tcinfo *) rex_gettcinfo(); | 208 | info = rex_gettcinfo(); |
200 | slot0addr = (unsigned long)KSEG1ADDR(rex_slot_address(0)); | 209 | slot0addr = CPHYSADDR((long)rex_slot_address(0)); |
201 | 210 | ||
202 | switch (mips_machtype) { | 211 | switch (mips_machtype) { |
203 | case MACH_DS5000_200: | 212 | case MACH_DS5000_200: |
@@ -216,37 +225,24 @@ void __init tc_init(void) | |||
216 | 225 | ||
217 | tc_clock = 10000 / info->clk_period; | 226 | tc_clock = 10000 / info->clk_period; |
218 | 227 | ||
219 | if (TURBOCHANNEL && info->slot_size && slot0addr) { | 228 | if (info->slot_size && slot0addr) { |
220 | printk("TURBOchannel rev. %1d at %2d.%1d MHz ", info->revision, | 229 | pr_info("TURBOchannel rev. %d at %d.%d MHz (with%s parity)\n", |
221 | tc_clock / 10, tc_clock % 10); | 230 | info->revision, tc_clock / 10, tc_clock % 10, |
222 | printk("(with%s parity)\n", info->parity ? "" : "out"); | 231 | info->parity ? "" : "out"); |
223 | 232 | ||
224 | slot_size = info->slot_size << 20; | 233 | slot_size = info->slot_size << 20; |
225 | 234 | ||
226 | tc_probe(slot0addr, slot_size, num_tcslots); | 235 | tc_probe(slot0addr, slot_size, num_tcslots); |
227 | 236 | ||
228 | /* | 237 | for (i = 0; i < num_tcslots; i++) { |
229 | * All TURBOchannel DECstations have the onboard devices | 238 | if (!tc_bus[i].base_addr) |
230 | * where the (num_tcslots + 0 or 1 on DS5k/xx) Option Module | 239 | continue; |
231 | * would be. | 240 | pr_info(" slot %d: %s %s %s\n", i, tc_bus[i].vendor, |
232 | */ | 241 | tc_bus[i].name, tc_bus[i].firmware); |
233 | if(mips_machtype == MACH_DS5000_XX) | 242 | } |
234 | i = 1; | ||
235 | else | ||
236 | i = 0; | ||
237 | |||
238 | system_base = slot0addr + slot_size * (num_tcslots + i); | ||
239 | |||
240 | #ifdef TC_DEBUG | ||
241 | for (i = 0; i < num_tcslots; i++) | ||
242 | if (tc_bus[i].base_addr) { | ||
243 | printk(" slot %d: ", i); | ||
244 | printk("%s %s %s\n", tc_bus[i].vendor, | ||
245 | tc_bus[i].name, tc_bus[i].firmware); | ||
246 | } | ||
247 | #endif | ||
248 | ioport_resource.end = KSEG2 - 1; | ||
249 | } | 243 | } |
244 | |||
245 | return 0; | ||
250 | } | 246 | } |
251 | 247 | ||
252 | subsys_initcall(tc_init); | 248 | subsys_initcall(tc_init); |
@@ -257,4 +253,3 @@ EXPORT_SYMBOL(release_tc_card); | |||
257 | EXPORT_SYMBOL(get_tc_base_addr); | 253 | EXPORT_SYMBOL(get_tc_base_addr); |
258 | EXPORT_SYMBOL(get_tc_irq_nr); | 254 | EXPORT_SYMBOL(get_tc_irq_nr); |
259 | EXPORT_SYMBOL(get_tc_speed); | 255 | EXPORT_SYMBOL(get_tc_speed); |
260 | EXPORT_SYMBOL(system_base); | ||
diff --git a/drivers/tc/zs.c b/drivers/tc/zs.c index 6bed8713897e..c52af73a251b 100644 --- a/drivers/tc/zs.c +++ b/drivers/tc/zs.c | |||
@@ -65,14 +65,14 @@ | |||
65 | #include <asm/system.h> | 65 | #include <asm/system.h> |
66 | #include <asm/uaccess.h> | 66 | #include <asm/uaccess.h> |
67 | #include <asm/bootinfo.h> | 67 | #include <asm/bootinfo.h> |
68 | #include <asm/dec/serial.h> | ||
69 | 68 | ||
70 | #ifdef CONFIG_MACH_DECSTATION | ||
71 | #include <asm/dec/interrupts.h> | 69 | #include <asm/dec/interrupts.h> |
70 | #include <asm/dec/ioasic_addrs.h> | ||
72 | #include <asm/dec/machtype.h> | 71 | #include <asm/dec/machtype.h> |
72 | #include <asm/dec/serial.h> | ||
73 | #include <asm/dec/system.h> | ||
73 | #include <asm/dec/tc.h> | 74 | #include <asm/dec/tc.h> |
74 | #include <asm/dec/ioasic_addrs.h> | 75 | |
75 | #endif | ||
76 | #ifdef CONFIG_KGDB | 76 | #ifdef CONFIG_KGDB |
77 | #include <asm/kgdb.h> | 77 | #include <asm/kgdb.h> |
78 | #endif | 78 | #endif |
@@ -192,18 +192,6 @@ static void probe_sccs(void); | |||
192 | static void change_speed(struct dec_serial *info); | 192 | static void change_speed(struct dec_serial *info); |
193 | static void rs_wait_until_sent(struct tty_struct *tty, int timeout); | 193 | static void rs_wait_until_sent(struct tty_struct *tty, int timeout); |
194 | 194 | ||
195 | /* | ||
196 | * tmp_buf is used as a temporary buffer by serial_write. We need to | ||
197 | * lock it in case the copy_from_user blocks while swapping in a page, | ||
198 | * and some other program tries to do a serial write at the same time. | ||
199 | * Since the lock will only come under contention when the system is | ||
200 | * swapping and available memory is low, it makes sense to share one | ||
201 | * buffer across all the serial ports, since it significantly saves | ||
202 | * memory if large numbers of serial ports are open. | ||
203 | */ | ||
204 | static unsigned char tmp_buf[4096]; /* This is cheating */ | ||
205 | static DECLARE_MUTEX(tmp_buf_sem); | ||
206 | |||
207 | static inline int serial_paranoia_check(struct dec_serial *info, | 195 | static inline int serial_paranoia_check(struct dec_serial *info, |
208 | char *name, const char *routine) | 196 | char *name, const char *routine) |
209 | { | 197 | { |
@@ -1628,30 +1616,22 @@ static void __init probe_sccs(void) | |||
1628 | return; | 1616 | return; |
1629 | } | 1617 | } |
1630 | 1618 | ||
1631 | /* | ||
1632 | * When serial console is activated, tc_init has not been called yet | ||
1633 | * and system_base is undefined. Unfortunately we have to hardcode | ||
1634 | * system_base for this case :-(. HK | ||
1635 | */ | ||
1636 | switch(mips_machtype) { | 1619 | switch(mips_machtype) { |
1637 | #ifdef CONFIG_MACH_DECSTATION | 1620 | #ifdef CONFIG_MACH_DECSTATION |
1638 | case MACH_DS5000_2X0: | 1621 | case MACH_DS5000_2X0: |
1639 | case MACH_DS5900: | 1622 | case MACH_DS5900: |
1640 | system_base = KSEG1ADDR(0x1f800000); | ||
1641 | n_chips = 2; | 1623 | n_chips = 2; |
1642 | zs_parms = &ds_parms; | 1624 | zs_parms = &ds_parms; |
1643 | zs_parms->irq0 = dec_interrupt[DEC_IRQ_SCC0]; | 1625 | zs_parms->irq0 = dec_interrupt[DEC_IRQ_SCC0]; |
1644 | zs_parms->irq1 = dec_interrupt[DEC_IRQ_SCC1]; | 1626 | zs_parms->irq1 = dec_interrupt[DEC_IRQ_SCC1]; |
1645 | break; | 1627 | break; |
1646 | case MACH_DS5000_1XX: | 1628 | case MACH_DS5000_1XX: |
1647 | system_base = KSEG1ADDR(0x1c000000); | ||
1648 | n_chips = 2; | 1629 | n_chips = 2; |
1649 | zs_parms = &ds_parms; | 1630 | zs_parms = &ds_parms; |
1650 | zs_parms->irq0 = dec_interrupt[DEC_IRQ_SCC0]; | 1631 | zs_parms->irq0 = dec_interrupt[DEC_IRQ_SCC0]; |
1651 | zs_parms->irq1 = dec_interrupt[DEC_IRQ_SCC1]; | 1632 | zs_parms->irq1 = dec_interrupt[DEC_IRQ_SCC1]; |
1652 | break; | 1633 | break; |
1653 | case MACH_DS5000_XX: | 1634 | case MACH_DS5000_XX: |
1654 | system_base = KSEG1ADDR(0x1c000000); | ||
1655 | n_chips = 1; | 1635 | n_chips = 1; |
1656 | zs_parms = &ds_parms; | 1636 | zs_parms = &ds_parms; |
1657 | zs_parms->irq0 = dec_interrupt[DEC_IRQ_SCC0]; | 1637 | zs_parms->irq0 = dec_interrupt[DEC_IRQ_SCC0]; |
@@ -1673,10 +1653,10 @@ static void __init probe_sccs(void) | |||
1673 | * The sccs reside on the high byte of the 16 bit IOBUS | 1653 | * The sccs reside on the high byte of the 16 bit IOBUS |
1674 | */ | 1654 | */ |
1675 | zs_channels[n_channels].control = | 1655 | zs_channels[n_channels].control = |
1676 | (volatile unsigned char *)system_base + | 1656 | (volatile void *)CKSEG1ADDR(dec_kn_slot_base + |
1677 | (0 == chip ? zs_parms->scc0 : zs_parms->scc1) + | 1657 | (0 == chip ? zs_parms->scc0 : zs_parms->scc1) + |
1678 | (0 == channel ? zs_parms->channel_a_offset : | 1658 | (0 == channel ? zs_parms->channel_a_offset : |
1679 | zs_parms->channel_b_offset); | 1659 | zs_parms->channel_b_offset)); |
1680 | zs_channels[n_channels].data = | 1660 | zs_channels[n_channels].data = |
1681 | zs_channels[n_channels].control + 4; | 1661 | zs_channels[n_channels].control + 4; |
1682 | 1662 | ||
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 1cd942abb580..7e297947a2b2 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
@@ -1376,7 +1376,7 @@ config FB_HIT | |||
1376 | 1376 | ||
1377 | config FB_PMAG_AA | 1377 | config FB_PMAG_AA |
1378 | bool "PMAG-AA TURBOchannel framebuffer support" | 1378 | bool "PMAG-AA TURBOchannel framebuffer support" |
1379 | depends on (FB = y) && MACH_DECSTATION && TC | 1379 | depends on (FB = y) && TC |
1380 | select FB_CFB_FILLRECT | 1380 | select FB_CFB_FILLRECT |
1381 | select FB_CFB_COPYAREA | 1381 | select FB_CFB_COPYAREA |
1382 | select FB_CFB_IMAGEBLIT | 1382 | select FB_CFB_IMAGEBLIT |
@@ -1387,7 +1387,7 @@ config FB_PMAG_AA | |||
1387 | 1387 | ||
1388 | config FB_PMAG_BA | 1388 | config FB_PMAG_BA |
1389 | bool "PMAG-BA TURBOchannel framebuffer support" | 1389 | bool "PMAG-BA TURBOchannel framebuffer support" |
1390 | depends on (FB = y) && MACH_DECSTATION && TC | 1390 | depends on (FB = y) && TC |
1391 | select FB_CFB_FILLRECT | 1391 | select FB_CFB_FILLRECT |
1392 | select FB_CFB_COPYAREA | 1392 | select FB_CFB_COPYAREA |
1393 | select FB_CFB_IMAGEBLIT | 1393 | select FB_CFB_IMAGEBLIT |
@@ -1398,7 +1398,7 @@ config FB_PMAG_BA | |||
1398 | 1398 | ||
1399 | config FB_PMAGB_B | 1399 | config FB_PMAGB_B |
1400 | bool "PMAGB-B TURBOchannel framebuffer support" | 1400 | bool "PMAGB-B TURBOchannel framebuffer support" |
1401 | depends on (FB = y) && MACH_DECSTATION && TC | 1401 | depends on (FB = y) && TC |
1402 | select FB_CFB_FILLRECT | 1402 | select FB_CFB_FILLRECT |
1403 | select FB_CFB_COPYAREA | 1403 | select FB_CFB_COPYAREA |
1404 | select FB_CFB_IMAGEBLIT | 1404 | select FB_CFB_IMAGEBLIT |
@@ -1410,7 +1410,7 @@ config FB_PMAGB_B | |||
1410 | 1410 | ||
1411 | config FB_MAXINE | 1411 | config FB_MAXINE |
1412 | bool "Maxine (Personal DECstation) onboard framebuffer support" | 1412 | bool "Maxine (Personal DECstation) onboard framebuffer support" |
1413 | depends on (FB = y) && MACH_DECSTATION && TC | 1413 | depends on (FB = y) && MACH_DECSTATION |
1414 | select FB_CFB_FILLRECT | 1414 | select FB_CFB_FILLRECT |
1415 | select FB_CFB_COPYAREA | 1415 | select FB_CFB_COPYAREA |
1416 | select FB_CFB_IMAGEBLIT | 1416 | select FB_CFB_IMAGEBLIT |
diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 1fff29f48ca8..97c5d03ac8d9 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile | |||
@@ -86,7 +86,7 @@ obj-$(CONFIG_FB_CIRRUS) += cirrusfb.o | |||
86 | obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o | 86 | obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o |
87 | obj-$(CONFIG_FB_PXA) += pxafb.o | 87 | obj-$(CONFIG_FB_PXA) += pxafb.o |
88 | obj-$(CONFIG_FB_W100) += w100fb.o | 88 | obj-$(CONFIG_FB_W100) += w100fb.o |
89 | obj-$(CONFIG_FB_AU1100) += au1100fb.o fbgen.o | 89 | obj-$(CONFIG_FB_AU1100) += au1100fb.o |
90 | obj-$(CONFIG_FB_PMAG_AA) += pmag-aa-fb.o | 90 | obj-$(CONFIG_FB_PMAG_AA) += pmag-aa-fb.o |
91 | obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o | 91 | obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o |
92 | obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o | 92 | obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o |
diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c index b6fe30c3ad62..a5129806172f 100644 --- a/drivers/video/au1100fb.c +++ b/drivers/video/au1100fb.c | |||
@@ -2,6 +2,11 @@ | |||
2 | * BRIEF MODULE DESCRIPTION | 2 | * BRIEF MODULE DESCRIPTION |
3 | * Au1100 LCD Driver. | 3 | * Au1100 LCD Driver. |
4 | * | 4 | * |
5 | * Rewritten for 2.6 by Embedded Alley Solutions | ||
6 | * <source@embeddedalley.com>, based on submissions by | ||
7 | * Karl Lessard <klessard@sunrisetelecom.com> | ||
8 | * <c.pellegrin@exadron.com> | ||
9 | * | ||
5 | * Copyright 2002 MontaVista Software | 10 | * Copyright 2002 MontaVista Software |
6 | * Author: MontaVista Software, Inc. | 11 | * Author: MontaVista Software, Inc. |
7 | * ppopov@mvista.com or source@mvista.com | 12 | * ppopov@mvista.com or source@mvista.com |
@@ -33,298 +38,253 @@ | |||
33 | * with this program; if not, write to the Free Software Foundation, Inc., | 38 | * with this program; if not, write to the Free Software Foundation, Inc., |
34 | * 675 Mass Ave, Cambridge, MA 02139, USA. | 39 | * 675 Mass Ave, Cambridge, MA 02139, USA. |
35 | */ | 40 | */ |
36 | 41 | #include <linux/config.h> | |
37 | #include <linux/module.h> | 42 | #include <linux/module.h> |
38 | #include <linux/kernel.h> | 43 | #include <linux/kernel.h> |
39 | #include <linux/errno.h> | 44 | #include <linux/errno.h> |
40 | #include <linux/string.h> | 45 | #include <linux/string.h> |
41 | #include <linux/mm.h> | 46 | #include <linux/mm.h> |
42 | #include <linux/tty.h> | ||
43 | #include <linux/slab.h> | ||
44 | #include <linux/delay.h> | ||
45 | #include <linux/fb.h> | 47 | #include <linux/fb.h> |
46 | #include <linux/init.h> | 48 | #include <linux/init.h> |
47 | #include <linux/pci.h> | 49 | #include <linux/interrupt.h> |
50 | #include <linux/ctype.h> | ||
51 | #include <linux/dma-mapping.h> | ||
48 | 52 | ||
49 | #include <asm/au1000.h> | 53 | #include <asm/mach-au1x00/au1000.h> |
50 | #include <asm/pb1100.h> | ||
51 | #include "au1100fb.h" | ||
52 | 54 | ||
53 | #include <video/fbcon.h> | 55 | #define DEBUG 0 |
54 | #include <video/fbcon-mfb.h> | 56 | |
55 | #include <video/fbcon-cfb2.h> | 57 | #include "au1100fb.h" |
56 | #include <video/fbcon-cfb4.h> | ||
57 | #include <video/fbcon-cfb8.h> | ||
58 | #include <video/fbcon-cfb16.h> | ||
59 | 58 | ||
60 | /* | 59 | /* |
61 | * Sanity check. If this is a new Au1100 based board, search for | 60 | * Sanity check. If this is a new Au1100 based board, search for |
62 | * the PB1100 ifdefs to make sure you modify the code accordingly. | 61 | * the PB1100 ifdefs to make sure you modify the code accordingly. |
63 | */ | 62 | */ |
64 | #if defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_DB1100) || defined(CONFIG_MIPS_HYDROGEN3) | 63 | #if defined(CONFIG_MIPS_PB1100) |
64 | #include <asm/mach-pb1x00/pb1100.h> | ||
65 | #elif defined(CONFIG_MIPS_DB1100) | ||
66 | #include <asm/mach-db1x00/db1x00.h> | ||
65 | #else | 67 | #else |
66 | error Unknown Au1100 board | 68 | #error "Unknown Au1100 board, Au1100 FB driver not supported" |
67 | #endif | 69 | #endif |
68 | 70 | ||
69 | #define CMAPSIZE 16 | 71 | #define DRIVER_NAME "au1100fb" |
70 | 72 | #define DRIVER_DESC "LCD controller driver for AU1100 processors" | |
71 | static int my_lcd_index; /* default is zero */ | ||
72 | struct known_lcd_panels *p_lcd; | ||
73 | AU1100_LCD *p_lcd_reg = (AU1100_LCD *)AU1100_LCD_ADDR; | ||
74 | |||
75 | struct au1100fb_info { | ||
76 | struct fb_info_gen gen; | ||
77 | unsigned long fb_virt_start; | ||
78 | unsigned long fb_size; | ||
79 | unsigned long fb_phys; | ||
80 | int mmaped; | ||
81 | int nohwcursor; | ||
82 | 73 | ||
83 | struct { unsigned red, green, blue, pad; } palette[256]; | 74 | #define to_au1100fb_device(_info) \ |
75 | (_info ? container_of(_info, struct au1100fb_device, info) : NULL); | ||
84 | 76 | ||
85 | #if defined(FBCON_HAS_CFB16) | 77 | /* Bitfields format supported by the controller. Note that the order of formats |
86 | u16 fbcon_cmap16[16]; | 78 | * SHOULD be the same as in the LCD_CONTROL_SBPPF field, so we can retrieve the |
87 | #endif | 79 | * right pixel format by doing rgb_bitfields[LCD_CONTROL_SBPPF_XXX >> LCD_CONTROL_SBPPF] |
80 | */ | ||
81 | struct fb_bitfield rgb_bitfields[][4] = | ||
82 | { | ||
83 | /* Red, Green, Blue, Transp */ | ||
84 | { { 10, 6, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } }, | ||
85 | { { 11, 5, 0 }, { 5, 6, 0 }, { 0, 5, 0 }, { 0, 0, 0 } }, | ||
86 | { { 11, 5, 0 }, { 6, 5, 0 }, { 0, 6, 0 }, { 0, 0, 0 } }, | ||
87 | { { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 15, 1, 0 } }, | ||
88 | { { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 1, 0 } }, | ||
89 | |||
90 | /* The last is used to describe 12bpp format */ | ||
91 | { { 8, 4, 0 }, { 4, 4, 0 }, { 0, 4, 0 }, { 0, 0, 0 } }, | ||
88 | }; | 92 | }; |
89 | 93 | ||
90 | 94 | static struct fb_fix_screeninfo au1100fb_fix __initdata = { | |
91 | struct au1100fb_par { | 95 | .id = "AU1100 FB", |
92 | struct fb_var_screeninfo var; | 96 | .xpanstep = 1, |
93 | 97 | .ypanstep = 1, | |
94 | int line_length; // in bytes | 98 | .type = FB_TYPE_PACKED_PIXELS, |
95 | int cmap_len; // color-map length | 99 | .accel = FB_ACCEL_NONE, |
96 | }; | 100 | }; |
97 | 101 | ||
98 | 102 | static struct fb_var_screeninfo au1100fb_var __initdata = { | |
99 | static struct au1100fb_info fb_info; | 103 | .activate = FB_ACTIVATE_NOW, |
100 | static struct au1100fb_par current_par; | 104 | .height = -1, |
101 | static struct display disp; | 105 | .width = -1, |
102 | 106 | .vmode = FB_VMODE_NONINTERLACED, | |
103 | int au1100fb_init(void); | ||
104 | void au1100fb_setup(char *options, int *ints); | ||
105 | static int au1100fb_mmap(struct fb_info *fb, struct file *file, | ||
106 | struct vm_area_struct *vma); | ||
107 | static int au1100_blank(int blank_mode, struct fb_info_gen *info); | ||
108 | static int au1100fb_ioctl(struct inode *inode, struct file *file, u_int cmd, | ||
109 | u_long arg, int con, struct fb_info *info); | ||
110 | |||
111 | void au1100_nocursor(struct display *p, int mode, int xx, int yy){}; | ||
112 | |||
113 | static struct fb_ops au1100fb_ops = { | ||
114 | .owner = THIS_MODULE, | ||
115 | .fb_get_fix = fbgen_get_fix, | ||
116 | .fb_get_var = fbgen_get_var, | ||
117 | .fb_set_var = fbgen_set_var, | ||
118 | .fb_get_cmap = fbgen_get_cmap, | ||
119 | .fb_set_cmap = fbgen_set_cmap, | ||
120 | .fb_pan_display = fbgen_pan_display, | ||
121 | .fb_ioctl = au1100fb_ioctl, | ||
122 | .fb_mmap = au1100fb_mmap, | ||
123 | }; | 107 | }; |
124 | 108 | ||
125 | static void au1100_detect(void) | 109 | static struct au1100fb_drv_info drv_info; |
126 | { | ||
127 | /* | ||
128 | * This function should detect the current video mode settings | ||
129 | * and store it as the default video mode | ||
130 | */ | ||
131 | 110 | ||
132 | /* | 111 | /* |
133 | * Yeh, well, we're not going to change any settings so we're | 112 | * Set hardware with var settings. This will enable the controller with a specific |
134 | * always stuck with the default ... | 113 | * mode, normally validated with the fb_check_var method |
135 | */ | 114 | */ |
136 | 115 | int au1100fb_setmode(struct au1100fb_device *fbdev) | |
137 | } | ||
138 | |||
139 | static int au1100_encode_fix(struct fb_fix_screeninfo *fix, | ||
140 | const void *_par, struct fb_info_gen *_info) | ||
141 | { | 116 | { |
142 | struct au1100fb_info *info = (struct au1100fb_info *) _info; | 117 | struct fb_info *info = &fbdev->info; |
143 | struct au1100fb_par *par = (struct au1100fb_par *) _par; | 118 | u32 words; |
144 | struct fb_var_screeninfo *var = &par->var; | 119 | int index; |
145 | |||
146 | memset(fix, 0, sizeof(struct fb_fix_screeninfo)); | ||
147 | |||
148 | fix->smem_start = info->fb_phys; | ||
149 | fix->smem_len = info->fb_size; | ||
150 | fix->type = FB_TYPE_PACKED_PIXELS; | ||
151 | fix->type_aux = 0; | ||
152 | fix->visual = (var->bits_per_pixel == 8) ? | ||
153 | FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; | ||
154 | fix->ywrapstep = 0; | ||
155 | fix->xpanstep = 1; | ||
156 | fix->ypanstep = 1; | ||
157 | fix->line_length = current_par.line_length; | ||
158 | return 0; | ||
159 | } | ||
160 | 120 | ||
161 | static void set_color_bitfields(struct fb_var_screeninfo *var) | 121 | if (!fbdev) |
162 | { | 122 | return -EINVAL; |
163 | switch (var->bits_per_pixel) { | 123 | |
164 | case 8: | 124 | /* Update var-dependent FB info */ |
165 | var->red.offset = 0; | 125 | if (panel_is_active(fbdev->panel) || panel_is_color(fbdev->panel)) { |
166 | var->red.length = 8; | 126 | if (info->var.bits_per_pixel <= 8) { |
167 | var->green.offset = 0; | 127 | /* palettized */ |
168 | var->green.length = 8; | 128 | info->var.red.offset = 0; |
169 | var->blue.offset = 0; | 129 | info->var.red.length = info->var.bits_per_pixel; |
170 | var->blue.length = 8; | 130 | info->var.red.msb_right = 0; |
171 | var->transp.offset = 0; | 131 | |
172 | var->transp.length = 0; | 132 | info->var.green.offset = 0; |
173 | break; | 133 | info->var.green.length = info->var.bits_per_pixel; |
174 | case 16: /* RGB 565 */ | 134 | info->var.green.msb_right = 0; |
175 | var->red.offset = 11; | 135 | |
176 | var->red.length = 5; | 136 | info->var.blue.offset = 0; |
177 | var->green.offset = 5; | 137 | info->var.blue.length = info->var.bits_per_pixel; |
178 | var->green.length = 6; | 138 | info->var.blue.msb_right = 0; |
179 | var->blue.offset = 0; | 139 | |
180 | var->blue.length = 5; | 140 | info->var.transp.offset = 0; |
181 | var->transp.offset = 0; | 141 | info->var.transp.length = 0; |
182 | var->transp.length = 0; | 142 | info->var.transp.msb_right = 0; |
183 | break; | 143 | |
144 | info->fix.visual = FB_VISUAL_PSEUDOCOLOR; | ||
145 | info->fix.line_length = info->var.xres_virtual / | ||
146 | (8/info->var.bits_per_pixel); | ||
147 | } else { | ||
148 | /* non-palettized */ | ||
149 | index = (fbdev->panel->control_base & LCD_CONTROL_SBPPF_MASK) >> LCD_CONTROL_SBPPF_BIT; | ||
150 | info->var.red = rgb_bitfields[index][0]; | ||
151 | info->var.green = rgb_bitfields[index][1]; | ||
152 | info->var.blue = rgb_bitfields[index][2]; | ||
153 | info->var.transp = rgb_bitfields[index][3]; | ||
154 | |||
155 | info->fix.visual = FB_VISUAL_TRUECOLOR; | ||
156 | info->fix.line_length = info->var.xres_virtual << 1; /* depth=16 */ | ||
157 | } | ||
158 | } else { | ||
159 | /* mono */ | ||
160 | info->fix.visual = FB_VISUAL_MONO10; | ||
161 | info->fix.line_length = info->var.xres_virtual / 8; | ||
184 | } | 162 | } |
185 | 163 | ||
186 | var->red.msb_right = 0; | 164 | info->screen_size = info->fix.line_length * info->var.yres_virtual; |
187 | var->green.msb_right = 0; | ||
188 | var->blue.msb_right = 0; | ||
189 | var->transp.msb_right = 0; | ||
190 | } | ||
191 | 165 | ||
192 | static int au1100_decode_var(const struct fb_var_screeninfo *var, | 166 | /* Determine BPP mode and format */ |
193 | void *_par, struct fb_info_gen *_info) | 167 | fbdev->regs->lcd_control = fbdev->panel->control_base | |
194 | { | 168 | ((info->var.rotate/90) << LCD_CONTROL_SM_BIT); |
195 | 169 | ||
196 | struct au1100fb_par *par = (struct au1100fb_par *)_par; | 170 | fbdev->regs->lcd_intenable = 0; |
171 | fbdev->regs->lcd_intstatus = 0; | ||
197 | 172 | ||
198 | /* | 173 | fbdev->regs->lcd_horztiming = fbdev->panel->horztiming; |
199 | * Don't allow setting any of these yet: xres and yres don't | ||
200 | * make sense for LCD panels. | ||
201 | */ | ||
202 | if (var->xres != p_lcd->xres || | ||
203 | var->yres != p_lcd->yres || | ||
204 | var->xres != p_lcd->xres || | ||
205 | var->yres != p_lcd->yres) { | ||
206 | return -EINVAL; | ||
207 | } | ||
208 | if(var->bits_per_pixel != p_lcd->bpp) { | ||
209 | return -EINVAL; | ||
210 | } | ||
211 | 174 | ||
212 | memset(par, 0, sizeof(struct au1100fb_par)); | 175 | fbdev->regs->lcd_verttiming = fbdev->panel->verttiming; |
213 | par->var = *var; | 176 | |
214 | 177 | fbdev->regs->lcd_clkcontrol = fbdev->panel->clkcontrol_base; | |
215 | /* FIXME */ | ||
216 | switch (var->bits_per_pixel) { | ||
217 | case 8: | ||
218 | par->var.bits_per_pixel = 8; | ||
219 | break; | ||
220 | case 16: | ||
221 | par->var.bits_per_pixel = 16; | ||
222 | break; | ||
223 | default: | ||
224 | printk("color depth %d bpp not supported\n", | ||
225 | var->bits_per_pixel); | ||
226 | return -EINVAL; | ||
227 | 178 | ||
179 | fbdev->regs->lcd_dmaaddr0 = LCD_DMA_SA_N(fbdev->fb_phys); | ||
180 | |||
181 | if (panel_is_dual(fbdev->panel)) { | ||
182 | /* Second panel display seconf half of screen if possible, | ||
183 | * otherwise display the same as the first panel */ | ||
184 | if (info->var.yres_virtual >= (info->var.yres << 1)) { | ||
185 | fbdev->regs->lcd_dmaaddr1 = LCD_DMA_SA_N(fbdev->fb_phys + | ||
186 | (info->fix.line_length * | ||
187 | (info->var.yres_virtual >> 1))); | ||
188 | } else { | ||
189 | fbdev->regs->lcd_dmaaddr1 = LCD_DMA_SA_N(fbdev->fb_phys); | ||
190 | } | ||
228 | } | 191 | } |
229 | set_color_bitfields(&par->var); | ||
230 | par->cmap_len = (par->var.bits_per_pixel == 8) ? 256 : 16; | ||
231 | return 0; | ||
232 | } | ||
233 | 192 | ||
234 | static int au1100_encode_var(struct fb_var_screeninfo *var, | 193 | words = info->fix.line_length / sizeof(u32); |
235 | const void *par, struct fb_info_gen *_info) | 194 | if (!info->var.rotate || (info->var.rotate == 180)) { |
236 | { | 195 | words *= info->var.yres_virtual; |
196 | if (info->var.rotate /* 180 */) { | ||
197 | words -= (words % 8); /* should be divisable by 8 */ | ||
198 | } | ||
199 | } | ||
200 | fbdev->regs->lcd_words = LCD_WRD_WRDS_N(words); | ||
237 | 201 | ||
238 | *var = ((struct au1100fb_par *)par)->var; | 202 | fbdev->regs->lcd_pwmdiv = 0; |
239 | return 0; | 203 | fbdev->regs->lcd_pwmhi = 0; |
240 | } | ||
241 | 204 | ||
242 | static void | 205 | /* Resume controller */ |
243 | au1100_get_par(void *_par, struct fb_info_gen *_info) | 206 | fbdev->regs->lcd_control |= LCD_CONTROL_GO; |
244 | { | ||
245 | *(struct au1100fb_par *)_par = current_par; | ||
246 | } | ||
247 | 207 | ||
248 | static void au1100_set_par(const void *par, struct fb_info_gen *info) | 208 | return 0; |
249 | { | ||
250 | /* nothing to do: we don't change any settings */ | ||
251 | } | 209 | } |
252 | 210 | ||
253 | static int au1100_getcolreg(unsigned regno, unsigned *red, unsigned *green, | 211 | /* fb_setcolreg |
254 | unsigned *blue, unsigned *transp, | 212 | * Set color in LCD palette. |
255 | struct fb_info *info) | 213 | */ |
214 | int au1100fb_fb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *fbi) | ||
256 | { | 215 | { |
216 | struct au1100fb_device *fbdev = to_au1100fb_device(fbi); | ||
217 | u32 *palette = fbdev->regs->lcd_pallettebase; | ||
218 | u32 value; | ||
257 | 219 | ||
258 | struct au1100fb_info* i = (struct au1100fb_info*)info; | 220 | if (regno > (AU1100_LCD_NBR_PALETTE_ENTRIES - 1)) |
259 | 221 | return -EINVAL; | |
260 | if (regno > 255) | ||
261 | return 1; | ||
262 | 222 | ||
263 | *red = i->palette[regno].red; | 223 | if (fbi->var.grayscale) { |
264 | *green = i->palette[regno].green; | 224 | /* Convert color to grayscale */ |
265 | *blue = i->palette[regno].blue; | 225 | red = green = blue = |
266 | *transp = 0; | 226 | (19595 * red + 38470 * green + 7471 * blue) >> 16; |
227 | } | ||
267 | 228 | ||
268 | return 0; | 229 | if (fbi->fix.visual == FB_VISUAL_TRUECOLOR) { |
269 | } | 230 | /* Place color in the pseudopalette */ |
231 | if (regno > 16) | ||
232 | return -EINVAL; | ||
270 | 233 | ||
271 | static int au1100_setcolreg(unsigned regno, unsigned red, unsigned green, | 234 | palette = (u32*)fbi->pseudo_palette; |
272 | unsigned blue, unsigned transp, | 235 | |
273 | struct fb_info *info) | 236 | red >>= (16 - fbi->var.red.length); |
274 | { | 237 | green >>= (16 - fbi->var.green.length); |
275 | struct au1100fb_info* i = (struct au1100fb_info *)info; | 238 | blue >>= (16 - fbi->var.blue.length); |
276 | u32 rgbcol; | 239 | |
277 | 240 | value = (red << fbi->var.red.offset) | | |
278 | if (regno > 255) | 241 | (green << fbi->var.green.offset)| |
279 | return 1; | 242 | (blue << fbi->var.blue.offset); |
280 | 243 | value &= 0xFFFF; | |
281 | i->palette[regno].red = red; | 244 | |
282 | i->palette[regno].green = green; | 245 | } else if (panel_is_active(fbdev->panel)) { |
283 | i->palette[regno].blue = blue; | 246 | /* COLOR TFT PALLETTIZED (use RGB 565) */ |
284 | 247 | value = (red & 0xF800)|((green >> 5) & 0x07E0)|((blue >> 11) & 0x001F); | |
285 | switch(p_lcd->bpp) { | 248 | value &= 0xFFFF; |
286 | #ifdef FBCON_HAS_CFB8 | 249 | |
287 | case 8: | 250 | } else if (panel_is_color(fbdev->panel)) { |
288 | red >>= 10; | 251 | /* COLOR STN MODE */ |
289 | green >>= 10; | 252 | value = (((panel_swap_rgb(fbdev->panel) ? blue : red) >> 12) & 0x000F) | |
290 | blue >>= 10; | 253 | ((green >> 8) & 0x00F0) | |
291 | p_lcd_reg->lcd_pallettebase[regno] = (blue&0x1f) | | 254 | (((panel_swap_rgb(fbdev->panel) ? red : blue) >> 4) & 0x0F00); |
292 | ((green&0x3f)<<5) | ((red&0x1f)<<11); | 255 | value &= 0xFFF; |
293 | break; | 256 | } else { |
294 | #endif | 257 | /* MONOCHROME MODE */ |
295 | #ifdef FBCON_HAS_CFB16 | 258 | value = (green >> 12) & 0x000F; |
296 | case 16: | 259 | value &= 0xF; |
297 | i->fbcon_cmap16[regno] = | ||
298 | ((red & 0xf800) >> 0) | | ||
299 | ((green & 0xfc00) >> 5) | | ||
300 | ((blue & 0xf800) >> 11); | ||
301 | break; | ||
302 | #endif | ||
303 | default: | ||
304 | break; | ||
305 | } | 260 | } |
306 | 261 | ||
262 | palette[regno] = value; | ||
263 | |||
307 | return 0; | 264 | return 0; |
308 | } | 265 | } |
309 | 266 | ||
310 | 267 | /* fb_blank | |
311 | static int au1100_blank(int blank_mode, struct fb_info_gen *_info) | 268 | * Blank the screen. Depending on the mode, the screen will be |
269 | * activated with the backlight color, or desactivated | ||
270 | */ | ||
271 | int au1100fb_fb_blank(int blank_mode, struct fb_info *fbi) | ||
312 | { | 272 | { |
273 | struct au1100fb_device *fbdev = to_au1100fb_device(fbi); | ||
274 | |||
275 | print_dbg("fb_blank %d %p", blank_mode, fbi); | ||
313 | 276 | ||
314 | switch (blank_mode) { | 277 | switch (blank_mode) { |
278 | |||
315 | case VESA_NO_BLANKING: | 279 | case VESA_NO_BLANKING: |
316 | /* turn on panel */ | 280 | /* Turn on panel */ |
317 | //printk("turn on panel\n"); | 281 | fbdev->regs->lcd_control |= LCD_CONTROL_GO; |
318 | #ifdef CONFIG_MIPS_PB1100 | 282 | #ifdef CONFIG_MIPS_PB1100 |
319 | p_lcd_reg->lcd_control |= LCD_CONTROL_GO; | 283 | if (drv_info.panel_idx == 1) { |
320 | au_writew(au_readw(PB1100_G_CONTROL) | p_lcd->mode_backlight, | 284 | au_writew(au_readw(PB1100_G_CONTROL) |
285 | | (PB1100_G_CONTROL_BL | PB1100_G_CONTROL_VDD), | ||
321 | PB1100_G_CONTROL); | 286 | PB1100_G_CONTROL); |
322 | #endif | 287 | } |
323 | #ifdef CONFIG_MIPS_HYDROGEN3 | ||
324 | /* Turn controller & power supply on, GPIO213 */ | ||
325 | au_writel(0x20002000, 0xB1700008); | ||
326 | au_writel(0x00040000, 0xB1900108); | ||
327 | au_writel(0x01000100, 0xB1700008); | ||
328 | #endif | 288 | #endif |
329 | au_sync(); | 289 | au_sync(); |
330 | break; | 290 | break; |
@@ -332,12 +292,14 @@ static int au1100_blank(int blank_mode, struct fb_info_gen *_info) | |||
332 | case VESA_VSYNC_SUSPEND: | 292 | case VESA_VSYNC_SUSPEND: |
333 | case VESA_HSYNC_SUSPEND: | 293 | case VESA_HSYNC_SUSPEND: |
334 | case VESA_POWERDOWN: | 294 | case VESA_POWERDOWN: |
335 | /* turn off panel */ | 295 | /* Turn off panel */ |
336 | //printk("turn off panel\n"); | 296 | fbdev->regs->lcd_control &= ~LCD_CONTROL_GO; |
337 | #ifdef CONFIG_MIPS_PB1100 | 297 | #ifdef CONFIG_MIPS_PB1100 |
338 | au_writew(au_readw(PB1100_G_CONTROL) & ~p_lcd->mode_backlight, | 298 | if (drv_info.panel_idx == 1) { |
299 | au_writew(au_readw(PB1100_G_CONTROL) | ||
300 | & ~(PB1100_G_CONTROL_BL | PB1100_G_CONTROL_VDD), | ||
339 | PB1100_G_CONTROL); | 301 | PB1100_G_CONTROL); |
340 | p_lcd_reg->lcd_control &= ~LCD_CONTROL_GO; | 302 | } |
341 | #endif | 303 | #endif |
342 | au_sync(); | 304 | au_sync(); |
343 | break; | 305 | break; |
@@ -348,49 +310,87 @@ static int au1100_blank(int blank_mode, struct fb_info_gen *_info) | |||
348 | return 0; | 310 | return 0; |
349 | } | 311 | } |
350 | 312 | ||
351 | static void au1100_set_disp(const void *unused, struct display *disp, | 313 | /* fb_pan_display |
352 | struct fb_info_gen *info) | 314 | * Pan display in x and/or y as specified |
315 | */ | ||
316 | int au1100fb_fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fbi) | ||
353 | { | 317 | { |
354 | disp->screen_base = (char *)fb_info.fb_virt_start; | 318 | struct au1100fb_device *fbdev = to_au1100fb_device(fbi); |
355 | 319 | int dy; | |
356 | switch (disp->var.bits_per_pixel) { | 320 | |
357 | #ifdef FBCON_HAS_CFB8 | 321 | print_dbg("fb_pan_display %p %p", var, fbi); |
358 | case 8: | 322 | |
359 | disp->dispsw = &fbcon_cfb8; | 323 | if (!var || !fbdev) { |
360 | if (fb_info.nohwcursor) | 324 | return -EINVAL; |
361 | fbcon_cfb8.cursor = au1100_nocursor; | 325 | } |
362 | break; | 326 | |
363 | #endif | 327 | if (var->xoffset - fbi->var.xoffset) { |
364 | #ifdef FBCON_HAS_CFB16 | 328 | /* No support for X panning for now! */ |
365 | case 16: | 329 | return -EINVAL; |
366 | disp->dispsw = &fbcon_cfb16; | 330 | } |
367 | disp->dispsw_data = fb_info.fbcon_cmap16; | 331 | |
368 | if (fb_info.nohwcursor) | 332 | print_dbg("fb_pan_display 2 %p %p", var, fbi); |
369 | fbcon_cfb16.cursor = au1100_nocursor; | 333 | dy = var->yoffset - fbi->var.yoffset; |
370 | break; | 334 | if (dy) { |
371 | #endif | 335 | |
372 | default: | 336 | u32 dmaaddr; |
373 | disp->dispsw = &fbcon_dummy; | 337 | |
374 | disp->dispsw_data = NULL; | 338 | print_dbg("Panning screen of %d lines", dy); |
375 | break; | 339 | |
340 | dmaaddr = fbdev->regs->lcd_dmaaddr0; | ||
341 | dmaaddr += (fbi->fix.line_length * dy); | ||
342 | |||
343 | /* TODO: Wait for current frame to finished */ | ||
344 | fbdev->regs->lcd_dmaaddr0 = LCD_DMA_SA_N(dmaaddr); | ||
345 | |||
346 | if (panel_is_dual(fbdev->panel)) { | ||
347 | dmaaddr = fbdev->regs->lcd_dmaaddr1; | ||
348 | dmaaddr += (fbi->fix.line_length * dy); | ||
349 | fbdev->regs->lcd_dmaaddr0 = LCD_DMA_SA_N(dmaaddr); | ||
350 | } | ||
351 | } | ||
352 | print_dbg("fb_pan_display 3 %p %p", var, fbi); | ||
353 | |||
354 | return 0; | ||
355 | } | ||
356 | |||
357 | /* fb_rotate | ||
358 | * Rotate the display of this angle. This doesn't seems to be used by the core, | ||
359 | * but as our hardware supports it, so why not implementing it... | ||
360 | */ | ||
361 | void au1100fb_fb_rotate(struct fb_info *fbi, int angle) | ||
362 | { | ||
363 | struct au1100fb_device *fbdev = to_au1100fb_device(fbi); | ||
364 | |||
365 | print_dbg("fb_rotate %p %d", fbi, angle); | ||
366 | |||
367 | if (fbdev && (angle > 0) && !(angle % 90)) { | ||
368 | |||
369 | fbdev->regs->lcd_control &= ~LCD_CONTROL_GO; | ||
370 | |||
371 | fbdev->regs->lcd_control &= ~(LCD_CONTROL_SM_MASK); | ||
372 | fbdev->regs->lcd_control |= ((angle/90) << LCD_CONTROL_SM_BIT); | ||
373 | |||
374 | fbdev->regs->lcd_control |= LCD_CONTROL_GO; | ||
376 | } | 375 | } |
377 | } | 376 | } |
378 | 377 | ||
379 | static int | 378 | /* fb_mmap |
380 | au1100fb_mmap(struct fb_info *_fb, | 379 | * Map video memory in user space. We don't use the generic fb_mmap method mainly |
381 | struct file *file, | 380 | * to allow the use of the TLB streaming flag (CCA=6) |
382 | struct vm_area_struct *vma) | 381 | */ |
382 | int au1100fb_fb_mmap(struct fb_info *fbi, struct file *file, struct vm_area_struct *vma) | ||
383 | { | 383 | { |
384 | struct au1100fb_device *fbdev = to_au1100fb_device(fbi); | ||
384 | unsigned int len; | 385 | unsigned int len; |
385 | unsigned long start=0, off; | 386 | unsigned long start=0, off; |
386 | struct au1100fb_info *fb = (struct au1100fb_info *)_fb; | ||
387 | 387 | ||
388 | if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) { | 388 | if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) { |
389 | return -EINVAL; | 389 | return -EINVAL; |
390 | } | 390 | } |
391 | 391 | ||
392 | start = fb_info.fb_phys & PAGE_MASK; | 392 | start = fbdev->fb_phys & PAGE_MASK; |
393 | len = PAGE_ALIGN((start & ~PAGE_MASK) + fb_info.fb_size); | 393 | len = PAGE_ALIGN((start & ~PAGE_MASK) + fbdev->fb_len); |
394 | 394 | ||
395 | off = vma->vm_pgoff << PAGE_SHIFT; | 395 | off = vma->vm_pgoff << PAGE_SHIFT; |
396 | 396 | ||
@@ -401,276 +401,309 @@ au1100fb_mmap(struct fb_info *_fb, | |||
401 | off += start; | 401 | off += start; |
402 | vma->vm_pgoff = off >> PAGE_SHIFT; | 402 | vma->vm_pgoff = off >> PAGE_SHIFT; |
403 | 403 | ||
404 | pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK; | 404 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); |
405 | //pgprot_val(vma->vm_page_prot) |= _CACHE_CACHABLE_NONCOHERENT; | ||
406 | pgprot_val(vma->vm_page_prot) |= (6 << 9); //CCA=6 | 405 | pgprot_val(vma->vm_page_prot) |= (6 << 9); //CCA=6 |
407 | 406 | ||
408 | /* This is an IO map - tell maydump to skip this VMA */ | ||
409 | vma->vm_flags |= VM_IO; | 407 | vma->vm_flags |= VM_IO; |
410 | 408 | ||
411 | if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, | 409 | if (io_remap_page_range(vma, vma->vm_start, off, |
412 | vma->vm_end - vma->vm_start, | 410 | vma->vm_end - vma->vm_start, |
413 | vma->vm_page_prot)) { | 411 | vma->vm_page_prot)) { |
414 | return -EAGAIN; | 412 | return -EAGAIN; |
415 | } | 413 | } |
416 | 414 | ||
417 | fb->mmaped = 1; | ||
418 | return 0; | 415 | return 0; |
419 | } | 416 | } |
420 | 417 | ||
421 | int au1100_pan_display(const struct fb_var_screeninfo *var, | 418 | static struct fb_ops au1100fb_ops = |
422 | struct fb_info_gen *info) | ||
423 | { | 419 | { |
424 | return 0; | 420 | .owner = THIS_MODULE, |
425 | } | 421 | .fb_setcolreg = au1100fb_fb_setcolreg, |
422 | .fb_blank = au1100fb_fb_blank, | ||
423 | .fb_pan_display = au1100fb_fb_pan_display, | ||
424 | .fb_fillrect = cfb_fillrect, | ||
425 | .fb_copyarea = cfb_copyarea, | ||
426 | .fb_imageblit = cfb_imageblit, | ||
427 | .fb_rotate = au1100fb_fb_rotate, | ||
428 | .fb_mmap = au1100fb_fb_mmap, | ||
429 | }; | ||
426 | 430 | ||
427 | static int au1100fb_ioctl(struct inode *inode, struct file *file, u_int cmd, | ||
428 | u_long arg, int con, struct fb_info *info) | ||
429 | { | ||
430 | /* nothing to do yet */ | ||
431 | return -EINVAL; | ||
432 | } | ||
433 | 431 | ||
434 | static struct fbgen_hwswitch au1100_switch = { | 432 | /*-------------------------------------------------------------------------*/ |
435 | au1100_detect, | ||
436 | au1100_encode_fix, | ||
437 | au1100_decode_var, | ||
438 | au1100_encode_var, | ||
439 | au1100_get_par, | ||
440 | au1100_set_par, | ||
441 | au1100_getcolreg, | ||
442 | au1100_setcolreg, | ||
443 | au1100_pan_display, | ||
444 | au1100_blank, | ||
445 | au1100_set_disp | ||
446 | }; | ||
447 | 433 | ||
434 | /* AU1100 LCD controller device driver */ | ||
448 | 435 | ||
449 | int au1100_setmode(void) | 436 | int au1100fb_drv_probe(struct device *dev) |
450 | { | 437 | { |
451 | int words; | 438 | struct au1100fb_device *fbdev = NULL; |
452 | 439 | struct resource *regs_res; | |
453 | /* FIXME Need to accomodate for swivel mode and 12bpp, <8bpp*/ | 440 | unsigned long page; |
454 | switch (p_lcd->mode_control & LCD_CONTROL_SM) | 441 | u32 sys_clksrc; |
455 | { | 442 | |
456 | case LCD_CONTROL_SM_0: | 443 | if (!dev) |
457 | case LCD_CONTROL_SM_180: | ||
458 | words = (p_lcd->xres * p_lcd->yres * p_lcd->bpp) / 32; | ||
459 | break; | ||
460 | case LCD_CONTROL_SM_90: | ||
461 | case LCD_CONTROL_SM_270: | ||
462 | /* is this correct? */ | ||
463 | words = (p_lcd->xres * p_lcd->bpp) / 8; | ||
464 | break; | ||
465 | default: | ||
466 | printk("mode_control reg not initialized\n"); | ||
467 | return -EINVAL; | 444 | return -EINVAL; |
445 | |||
446 | /* Allocate new device private */ | ||
447 | if (!(fbdev = kmalloc(sizeof(struct au1100fb_device), GFP_KERNEL))) { | ||
448 | print_err("fail to allocate device private record"); | ||
449 | return -ENOMEM; | ||
468 | } | 450 | } |
451 | memset((void*)fbdev, 0, sizeof(struct au1100fb_device)); | ||
469 | 452 | ||
470 | /* | 453 | fbdev->panel = &known_lcd_panels[drv_info.panel_idx]; |
471 | * Setup LCD controller | ||
472 | */ | ||
473 | 454 | ||
474 | p_lcd_reg->lcd_control = p_lcd->mode_control; | 455 | dev_set_drvdata(dev, (void*)fbdev); |
475 | p_lcd_reg->lcd_intstatus = 0; | ||
476 | p_lcd_reg->lcd_intenable = 0; | ||
477 | p_lcd_reg->lcd_horztiming = p_lcd->mode_horztiming; | ||
478 | p_lcd_reg->lcd_verttiming = p_lcd->mode_verttiming; | ||
479 | p_lcd_reg->lcd_clkcontrol = p_lcd->mode_clkcontrol; | ||
480 | p_lcd_reg->lcd_words = words - 1; | ||
481 | p_lcd_reg->lcd_dmaaddr0 = fb_info.fb_phys; | ||
482 | 456 | ||
483 | /* turn on panel */ | 457 | /* Allocate region for our registers and map them */ |
484 | #ifdef CONFIG_MIPS_PB1100 | 458 | if (!(regs_res = platform_get_resource(to_platform_device(dev), |
485 | au_writew(au_readw(PB1100_G_CONTROL) | p_lcd->mode_backlight, | 459 | IORESOURCE_MEM, 0))) { |
486 | PB1100_G_CONTROL); | 460 | print_err("fail to retrieve registers resource"); |
487 | #endif | 461 | return -EFAULT; |
488 | #ifdef CONFIG_MIPS_HYDROGEN3 | 462 | } |
489 | /* Turn controller & power supply on, GPIO213 */ | ||
490 | au_writel(0x20002000, 0xB1700008); | ||
491 | au_writel(0x00040000, 0xB1900108); | ||
492 | au_writel(0x01000100, 0xB1700008); | ||
493 | #endif | ||
494 | 463 | ||
495 | p_lcd_reg->lcd_control |= LCD_CONTROL_GO; | 464 | au1100fb_fix.mmio_start = regs_res->start; |
465 | au1100fb_fix.mmio_len = regs_res->end - regs_res->start + 1; | ||
496 | 466 | ||
497 | return 0; | 467 | if (!request_mem_region(au1100fb_fix.mmio_start, au1100fb_fix.mmio_len, |
498 | } | 468 | DRIVER_NAME)) { |
469 | print_err("fail to lock memory region at 0x%08x", | ||
470 | au1100fb_fix.mmio_start); | ||
471 | return -EBUSY; | ||
472 | } | ||
499 | 473 | ||
474 | fbdev->regs = (struct au1100fb_regs*)KSEG1ADDR(au1100fb_fix.mmio_start); | ||
500 | 475 | ||
501 | int __init au1100fb_init(void) | 476 | print_dbg("Register memory map at %p", fbdev->regs); |
502 | { | 477 | print_dbg("phys=0x%08x, size=%d", fbdev->regs_phys, fbdev->regs_len); |
503 | uint32 sys_clksrc; | ||
504 | unsigned long page; | ||
505 | 478 | ||
506 | /* | ||
507 | * Get the panel information/display mode and update the registry | ||
508 | */ | ||
509 | p_lcd = &panels[my_lcd_index]; | ||
510 | |||
511 | switch (p_lcd->mode_control & LCD_CONTROL_SM) | ||
512 | { | ||
513 | case LCD_CONTROL_SM_0: | ||
514 | case LCD_CONTROL_SM_180: | ||
515 | p_lcd->xres = | ||
516 | (p_lcd->mode_horztiming & LCD_HORZTIMING_PPL) + 1; | ||
517 | p_lcd->yres = | ||
518 | (p_lcd->mode_verttiming & LCD_VERTTIMING_LPP) + 1; | ||
519 | break; | ||
520 | case LCD_CONTROL_SM_90: | ||
521 | case LCD_CONTROL_SM_270: | ||
522 | p_lcd->yres = | ||
523 | (p_lcd->mode_horztiming & LCD_HORZTIMING_PPL) + 1; | ||
524 | p_lcd->xres = | ||
525 | (p_lcd->mode_verttiming & LCD_VERTTIMING_LPP) + 1; | ||
526 | break; | ||
527 | } | ||
528 | 479 | ||
529 | /* | ||
530 | * Panel dimensions x bpp must be divisible by 32 | ||
531 | */ | ||
532 | if (((p_lcd->yres * p_lcd->bpp) % 32) != 0) | ||
533 | printk("VERT %% 32\n"); | ||
534 | if (((p_lcd->xres * p_lcd->bpp) % 32) != 0) | ||
535 | printk("HORZ %% 32\n"); | ||
536 | 480 | ||
537 | /* | 481 | /* Allocate the framebuffer to the maximum screen size * nbr of video buffers */ |
538 | * Allocate LCD framebuffer from system memory | 482 | fbdev->fb_len = fbdev->panel->xres * fbdev->panel->yres * |
539 | */ | 483 | (fbdev->panel->bpp >> 3) * AU1100FB_NBR_VIDEO_BUFFERS; |
540 | fb_info.fb_size = (p_lcd->xres * p_lcd->yres * p_lcd->bpp) / 8; | 484 | |
541 | 485 | fbdev->fb_mem = dma_alloc_coherent(dev, PAGE_ALIGN(fbdev->fb_len), | |
542 | current_par.var.xres = p_lcd->xres; | 486 | &fbdev->fb_phys, GFP_KERNEL); |
543 | current_par.var.xres_virtual = p_lcd->xres; | 487 | if (!fbdev->fb_mem) { |
544 | current_par.var.yres = p_lcd->yres; | 488 | print_err("fail to allocate frambuffer (size: %dK))", |
545 | current_par.var.yres_virtual = p_lcd->yres; | 489 | fbdev->fb_len / 1024); |
546 | current_par.var.bits_per_pixel = p_lcd->bpp; | ||
547 | |||
548 | /* FIX!!! only works for 8/16 bpp */ | ||
549 | current_par.line_length = p_lcd->xres * p_lcd->bpp / 8; /* in bytes */ | ||
550 | fb_info.fb_virt_start = (unsigned long ) | ||
551 | __get_free_pages(GFP_ATOMIC | GFP_DMA, | ||
552 | get_order(fb_info.fb_size + 0x1000)); | ||
553 | if (!fb_info.fb_virt_start) { | ||
554 | printk("Unable to allocate fb memory\n"); | ||
555 | return -ENOMEM; | 490 | return -ENOMEM; |
556 | } | 491 | } |
557 | fb_info.fb_phys = virt_to_bus((void *)fb_info.fb_virt_start); | 492 | |
493 | au1100fb_fix.smem_start = fbdev->fb_phys; | ||
494 | au1100fb_fix.smem_len = fbdev->fb_len; | ||
558 | 495 | ||
559 | /* | 496 | /* |
560 | * Set page reserved so that mmap will work. This is necessary | 497 | * Set page reserved so that mmap will work. This is necessary |
561 | * since we'll be remapping normal memory. | 498 | * since we'll be remapping normal memory. |
562 | */ | 499 | */ |
563 | for (page = fb_info.fb_virt_start; | 500 | for (page = (unsigned long)fbdev->fb_mem; |
564 | page < PAGE_ALIGN(fb_info.fb_virt_start + fb_info.fb_size); | 501 | page < PAGE_ALIGN((unsigned long)fbdev->fb_mem + fbdev->fb_len); |
565 | page += PAGE_SIZE) { | 502 | page += PAGE_SIZE) { |
503 | #if CONFIG_DMA_NONCOHERENT | ||
504 | SetPageReserved(virt_to_page(CAC_ADDR(page))); | ||
505 | #else | ||
566 | SetPageReserved(virt_to_page(page)); | 506 | SetPageReserved(virt_to_page(page)); |
507 | #endif | ||
567 | } | 508 | } |
568 | 509 | ||
569 | memset((void *)fb_info.fb_virt_start, 0, fb_info.fb_size); | 510 | print_dbg("Framebuffer memory map at %p", fbdev->fb_mem); |
570 | 511 | print_dbg("phys=0x%08x, size=%dK", fbdev->fb_phys, fbdev->fb_len / 1024); | |
571 | /* set freqctrl now to allow more time to stabilize */ | 512 | |
572 | /* zero-out out LCD bits */ | 513 | /* Setup LCD clock to AUX (48 MHz) */ |
573 | sys_clksrc = au_readl(SYS_CLKSRC) & ~0x000003e0; | 514 | sys_clksrc = au_readl(SYS_CLKSRC) & ~(SYS_CS_ML_MASK | SYS_CS_DL | SYS_CS_CL); |
574 | sys_clksrc |= p_lcd->mode_toyclksrc; | 515 | au_writel((sys_clksrc | (1 << SYS_CS_ML_BIT)), SYS_CLKSRC); |
575 | au_writel(sys_clksrc, SYS_CLKSRC); | 516 | |
576 | 517 | /* load the panel info into the var struct */ | |
577 | /* FIXME add check to make sure auxpll is what is expected! */ | 518 | au1100fb_var.bits_per_pixel = fbdev->panel->bpp; |
578 | au1100_setmode(); | 519 | au1100fb_var.xres = fbdev->panel->xres; |
579 | 520 | au1100fb_var.xres_virtual = au1100fb_var.xres; | |
580 | fb_info.gen.parsize = sizeof(struct au1100fb_par); | 521 | au1100fb_var.yres = fbdev->panel->yres; |
581 | fb_info.gen.fbhw = &au1100_switch; | 522 | au1100fb_var.yres_virtual = au1100fb_var.yres; |
582 | 523 | ||
583 | strcpy(fb_info.gen.info.modename, "Au1100 LCD"); | 524 | fbdev->info.screen_base = fbdev->fb_mem; |
584 | fb_info.gen.info.changevar = NULL; | 525 | fbdev->info.fbops = &au1100fb_ops; |
585 | fb_info.gen.info.node = -1; | 526 | fbdev->info.fix = au1100fb_fix; |
586 | 527 | ||
587 | fb_info.gen.info.fbops = &au1100fb_ops; | 528 | if (!(fbdev->info.pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL))) { |
588 | fb_info.gen.info.disp = &disp; | 529 | return -ENOMEM; |
589 | fb_info.gen.info.switch_con = &fbgen_switch; | 530 | } |
590 | fb_info.gen.info.updatevar = &fbgen_update_var; | 531 | memset(fbdev->info.pseudo_palette, 0, sizeof(u32) * 16); |
591 | fb_info.gen.info.blank = &fbgen_blank; | 532 | |
592 | fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT; | 533 | if (fb_alloc_cmap(&fbdev->info.cmap, AU1100_LCD_NBR_PALETTE_ENTRIES, 0) < 0) { |
593 | 534 | print_err("Fail to allocate colormap (%d entries)", | |
594 | /* This should give a reasonable default video mode */ | 535 | AU1100_LCD_NBR_PALETTE_ENTRIES); |
595 | fbgen_get_var(&disp.var, -1, &fb_info.gen.info); | 536 | kfree(fbdev->info.pseudo_palette); |
596 | fbgen_do_set_var(&disp.var, 1, &fb_info.gen); | 537 | return -EFAULT; |
597 | fbgen_set_disp(-1, &fb_info.gen); | 538 | } |
598 | fbgen_install_cmap(0, &fb_info.gen); | 539 | |
599 | if (register_framebuffer(&fb_info.gen.info) < 0) | 540 | fbdev->info.var = au1100fb_var; |
600 | return -EINVAL; | 541 | |
601 | printk(KERN_INFO "fb%d: %s frame buffer device\n", | 542 | /* Set h/w registers */ |
602 | GET_FB_IDX(fb_info.gen.info.node), | 543 | au1100fb_setmode(fbdev); |
603 | fb_info.gen.info.modename); | 544 | |
545 | /* Register new framebuffer */ | ||
546 | if (register_framebuffer(&fbdev->info) < 0) { | ||
547 | print_err("cannot register new framebuffer"); | ||
548 | goto failed; | ||
549 | } | ||
550 | |||
551 | return 0; | ||
552 | |||
553 | failed: | ||
554 | if (fbdev->regs) { | ||
555 | release_mem_region(fbdev->regs_phys, fbdev->regs_len); | ||
556 | } | ||
557 | if (fbdev->fb_mem) { | ||
558 | dma_free_noncoherent(dev, fbdev->fb_len, fbdev->fb_mem, fbdev->fb_phys); | ||
559 | } | ||
560 | if (fbdev->info.cmap.len != 0) { | ||
561 | fb_dealloc_cmap(&fbdev->info.cmap); | ||
562 | } | ||
563 | kfree(fbdev); | ||
564 | dev_set_drvdata(dev, NULL); | ||
604 | 565 | ||
605 | return 0; | 566 | return 0; |
606 | } | 567 | } |
607 | 568 | ||
569 | int au1100fb_drv_remove(struct device *dev) | ||
570 | { | ||
571 | struct au1100fb_device *fbdev = NULL; | ||
572 | |||
573 | if (!dev) | ||
574 | return -ENODEV; | ||
575 | |||
576 | fbdev = (struct au1100fb_device*) dev_get_drvdata(dev); | ||
577 | |||
578 | #if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO) | ||
579 | au1100fb_fb_blank(VESA_POWERDOWN, &fbdev->info); | ||
580 | #endif | ||
581 | fbdev->regs->lcd_control &= ~LCD_CONTROL_GO; | ||
608 | 582 | ||
609 | void au1100fb_cleanup(struct fb_info *info) | 583 | /* Clean up all probe data */ |
584 | unregister_framebuffer(&fbdev->info); | ||
585 | |||
586 | release_mem_region(fbdev->regs_phys, fbdev->regs_len); | ||
587 | |||
588 | dma_free_coherent(dev, PAGE_ALIGN(fbdev->fb_len), fbdev->fb_mem, fbdev->fb_phys); | ||
589 | |||
590 | fb_dealloc_cmap(&fbdev->info.cmap); | ||
591 | kfree(fbdev->info.pseudo_palette); | ||
592 | kfree((void*)fbdev); | ||
593 | |||
594 | return 0; | ||
595 | } | ||
596 | |||
597 | int au1100fb_drv_suspend(struct device *dev, u32 state, u32 level) | ||
598 | { | ||
599 | /* TODO */ | ||
600 | return 0; | ||
601 | } | ||
602 | |||
603 | int au1100fb_drv_resume(struct device *dev, u32 level) | ||
610 | { | 604 | { |
611 | unregister_framebuffer(info); | 605 | /* TODO */ |
606 | return 0; | ||
612 | } | 607 | } |
613 | 608 | ||
609 | static struct device_driver au1100fb_driver = { | ||
610 | .name = "au1100-lcd", | ||
611 | .bus = &platform_bus_type, | ||
614 | 612 | ||
615 | void au1100fb_setup(char *options, int *ints) | 613 | .probe = au1100fb_drv_probe, |
614 | .remove = au1100fb_drv_remove, | ||
615 | .suspend = au1100fb_drv_suspend, | ||
616 | .resume = au1100fb_drv_resume, | ||
617 | }; | ||
618 | |||
619 | /*-------------------------------------------------------------------------*/ | ||
620 | |||
621 | /* Kernel driver */ | ||
622 | |||
623 | int au1100fb_setup(char *options) | ||
616 | { | 624 | { |
617 | char* this_opt; | 625 | char* this_opt; |
618 | int i; | 626 | int num_panels = ARRAY_SIZE(known_lcd_panels); |
619 | int num_panels = sizeof(panels)/sizeof(struct known_lcd_panels); | 627 | char* mode = NULL; |
628 | int panel_idx = 0; | ||
620 | 629 | ||
630 | if (num_panels <= 0) { | ||
631 | print_err("No LCD panels supported by driver!"); | ||
632 | return -EFAULT; | ||
633 | } | ||
621 | 634 | ||
622 | if (!options || !*options) | 635 | if (options) { |
623 | return; | 636 | while ((this_opt = strsep(&options,",")) != NULL) { |
624 | 637 | /* Panel option */ | |
625 | for(this_opt=strtok(options, ","); this_opt; | ||
626 | this_opt=strtok(NULL, ",")) { | ||
627 | if (!strncmp(this_opt, "panel:", 6)) { | 638 | if (!strncmp(this_opt, "panel:", 6)) { |
628 | #if defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_DB1100) | 639 | int i; |
629 | /* Read Pb1100 Switch S10 ? */ | 640 | this_opt += 6; |
630 | if (!strncmp(this_opt+6, "s10", 3)) | 641 | for (i = 0; i < num_panels; i++) { |
631 | { | 642 | if (!strncmp(this_opt, |
632 | int panel; | 643 | known_lcd_panels[i].name, |
633 | panel = *(volatile int *)0xAE000008; /* BCSR SWITCHES */ | ||
634 | panel >>= 8; | ||
635 | panel &= 0x0F; | ||
636 | if (panel >= num_panels) panel = 0; | ||
637 | my_lcd_index = panel; | ||
638 | } | ||
639 | else | ||
640 | #endif | ||
641 | /* Get the panel name, everything else if fixed */ | ||
642 | for (i=0; i<num_panels; i++) { | ||
643 | if (!strncmp(this_opt+6, panels[i].panel_name, | ||
644 | strlen(this_opt))) { | 644 | strlen(this_opt))) { |
645 | my_lcd_index = i; | 645 | panel_idx = i; |
646 | break; | 646 | break; |
647 | } | 647 | } |
648 | } | 648 | } |
649 | if (i >= num_panels) { | ||
650 | print_warn("Panel %s not supported!", this_opt); | ||
651 | } | ||
652 | } | ||
653 | /* Mode option (only option that start with digit) */ | ||
654 | else if (isdigit(this_opt[0])) { | ||
655 | mode = kmalloc(strlen(this_opt) + 1, GFP_KERNEL); | ||
656 | strncpy(mode, this_opt, strlen(this_opt) + 1); | ||
657 | } | ||
658 | /* Unsupported option */ | ||
659 | else { | ||
660 | print_warn("Unsupported option \"%s\"", this_opt); | ||
649 | } | 661 | } |
650 | else if (!strncmp(this_opt, "nohwcursor", 10)) { | ||
651 | printk("nohwcursor\n"); | ||
652 | fb_info.nohwcursor = 1; | ||
653 | } | 662 | } |
654 | } | 663 | } |
655 | 664 | ||
656 | printk("au1100fb: Panel %d %s\n", my_lcd_index, | 665 | drv_info.panel_idx = panel_idx; |
657 | panels[my_lcd_index].panel_name); | 666 | drv_info.opt_mode = mode; |
658 | } | ||
659 | 667 | ||
668 | print_info("Panel=%s Mode=%s", | ||
669 | known_lcd_panels[drv_info.panel_idx].name, | ||
670 | drv_info.opt_mode ? drv_info.opt_mode : "default"); | ||
660 | 671 | ||
672 | return 0; | ||
673 | } | ||
661 | 674 | ||
662 | #ifdef MODULE | 675 | int __init au1100fb_init(void) |
663 | MODULE_LICENSE("GPL"); | ||
664 | int init_module(void) | ||
665 | { | 676 | { |
666 | return au1100fb_init(); | 677 | char* options; |
678 | int ret; | ||
679 | |||
680 | print_info("" DRIVER_DESC ""); | ||
681 | |||
682 | memset(&drv_info, 0, sizeof(drv_info)); | ||
683 | |||
684 | if (fb_get_options(DRIVER_NAME, &options)) | ||
685 | return -ENODEV; | ||
686 | |||
687 | /* Setup driver with options */ | ||
688 | ret = au1100fb_setup(options); | ||
689 | if (ret < 0) { | ||
690 | print_err("Fail to setup driver"); | ||
691 | return ret; | ||
692 | } | ||
693 | |||
694 | return driver_register(&au1100fb_driver); | ||
667 | } | 695 | } |
668 | 696 | ||
669 | void cleanup_module(void) | 697 | void __exit au1100fb_cleanup(void) |
670 | { | 698 | { |
671 | au1100fb_cleanup(void); | 699 | driver_unregister(&au1100fb_driver); |
700 | |||
701 | if (drv_info.opt_mode) | ||
702 | kfree(drv_info.opt_mode); | ||
672 | } | 703 | } |
673 | 704 | ||
674 | MODULE_AUTHOR("Pete Popov <ppopov@mvista.com>"); | 705 | module_init(au1100fb_init); |
675 | MODULE_DESCRIPTION("Au1100 LCD framebuffer device driver"); | 706 | module_exit(au1100fb_cleanup); |
676 | #endif /* MODULE */ | 707 | |
708 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
709 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/au1100fb.h b/drivers/video/au1100fb.h index 657c560ab73c..2855534dc235 100644 --- a/drivers/video/au1100fb.h +++ b/drivers/video/au1100fb.h | |||
@@ -30,352 +30,352 @@ | |||
30 | #ifndef _AU1100LCD_H | 30 | #ifndef _AU1100LCD_H |
31 | #define _AU1100LCD_H | 31 | #define _AU1100LCD_H |
32 | 32 | ||
33 | #include <asm/mach-au1x00/au1000.h> | ||
34 | |||
35 | #define print_err(f, arg...) printk(KERN_ERR DRIVER_NAME ": " f "\n", ## arg) | ||
36 | #define print_warn(f, arg...) printk(KERN_WARNING DRIVER_NAME ": " f "\n", ## arg) | ||
37 | #define print_info(f, arg...) printk(KERN_INFO DRIVER_NAME ": " f "\n", ## arg) | ||
38 | |||
39 | #if DEBUG | ||
40 | #define print_dbg(f, arg...) printk(__FILE__ ": " f "\n", ## arg) | ||
41 | #else | ||
42 | #define print_dbg(f, arg...) do {} while (0) | ||
43 | #endif | ||
44 | |||
45 | #if defined(__BIG_ENDIAN) | ||
46 | #define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_11 | ||
47 | #else | ||
48 | #define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_00 | ||
49 | #endif | ||
50 | #define LCD_CONTROL_DEFAULT_SBPPF LCD_CONTROL_SBPPF_565 | ||
51 | |||
33 | /********************************************************************/ | 52 | /********************************************************************/ |
34 | #define uint32 unsigned long | 53 | |
35 | typedef volatile struct | 54 | /* LCD controller restrictions */ |
36 | { | 55 | #define AU1100_LCD_MAX_XRES 800 |
37 | uint32 lcd_control; | 56 | #define AU1100_LCD_MAX_YRES 600 |
38 | uint32 lcd_intstatus; | 57 | #define AU1100_LCD_MAX_BPP 16 |
39 | uint32 lcd_intenable; | 58 | #define AU1100_LCD_MAX_CLK 48000000 |
40 | uint32 lcd_horztiming; | 59 | #define AU1100_LCD_NBR_PALETTE_ENTRIES 256 |
41 | uint32 lcd_verttiming; | 60 | |
42 | uint32 lcd_clkcontrol; | 61 | /* Default number of visible screen buffer to allocate */ |
43 | uint32 lcd_dmaaddr0; | 62 | #define AU1100FB_NBR_VIDEO_BUFFERS 4 |
44 | uint32 lcd_dmaaddr1; | ||
45 | uint32 lcd_words; | ||
46 | uint32 lcd_pwmdiv; | ||
47 | uint32 lcd_pwmhi; | ||
48 | uint32 reserved[(0x0400-0x002C)/4]; | ||
49 | uint32 lcd_pallettebase[256]; | ||
50 | |||
51 | } AU1100_LCD; | ||
52 | 63 | ||
53 | /********************************************************************/ | 64 | /********************************************************************/ |
54 | 65 | ||
55 | #define AU1100_LCD_ADDR 0xB5000000 | 66 | struct au1100fb_panel |
67 | { | ||
68 | const char name[25]; /* Full name <vendor>_<model> */ | ||
56 | 69 | ||
57 | /* | 70 | u32 control_base; /* Mode-independent control values */ |
58 | * Register bit definitions | 71 | u32 clkcontrol_base; /* Panel pixclock preferences */ |
59 | */ | ||
60 | 72 | ||
61 | /* lcd_control */ | 73 | u32 horztiming; |
62 | #define LCD_CONTROL_SBPPF (7<<18) | 74 | u32 verttiming; |
63 | #define LCD_CONTROL_SBPPF_655 (0<<18) | ||
64 | #define LCD_CONTROL_SBPPF_565 (1<<18) | ||
65 | #define LCD_CONTROL_SBPPF_556 (2<<18) | ||
66 | #define LCD_CONTROL_SBPPF_1555 (3<<18) | ||
67 | #define LCD_CONTROL_SBPPF_5551 (4<<18) | ||
68 | #define LCD_CONTROL_WP (1<<17) | ||
69 | #define LCD_CONTROL_WD (1<<16) | ||
70 | #define LCD_CONTROL_C (1<<15) | ||
71 | #define LCD_CONTROL_SM (3<<13) | ||
72 | #define LCD_CONTROL_SM_0 (0<<13) | ||
73 | #define LCD_CONTROL_SM_90 (1<<13) | ||
74 | #define LCD_CONTROL_SM_180 (2<<13) | ||
75 | #define LCD_CONTROL_SM_270 (3<<13) | ||
76 | #define LCD_CONTROL_DB (1<<12) | ||
77 | #define LCD_CONTROL_CCO (1<<11) | ||
78 | #define LCD_CONTROL_DP (1<<10) | ||
79 | #define LCD_CONTROL_PO (3<<8) | ||
80 | #define LCD_CONTROL_PO_00 (0<<8) | ||
81 | #define LCD_CONTROL_PO_01 (1<<8) | ||
82 | #define LCD_CONTROL_PO_10 (2<<8) | ||
83 | #define LCD_CONTROL_PO_11 (3<<8) | ||
84 | #define LCD_CONTROL_MPI (1<<7) | ||
85 | #define LCD_CONTROL_PT (1<<6) | ||
86 | #define LCD_CONTROL_PC (1<<5) | ||
87 | #define LCD_CONTROL_BPP (7<<1) | ||
88 | #define LCD_CONTROL_BPP_1 (0<<1) | ||
89 | #define LCD_CONTROL_BPP_2 (1<<1) | ||
90 | #define LCD_CONTROL_BPP_4 (2<<1) | ||
91 | #define LCD_CONTROL_BPP_8 (3<<1) | ||
92 | #define LCD_CONTROL_BPP_12 (4<<1) | ||
93 | #define LCD_CONTROL_BPP_16 (5<<1) | ||
94 | #define LCD_CONTROL_GO (1<<0) | ||
95 | |||
96 | /* lcd_intstatus, lcd_intenable */ | ||
97 | #define LCD_INT_SD (1<<7) | ||
98 | #define LCD_INT_OF (1<<6) | ||
99 | #define LCD_INT_UF (1<<5) | ||
100 | #define LCD_INT_SA (1<<3) | ||
101 | #define LCD_INT_SS (1<<2) | ||
102 | #define LCD_INT_S1 (1<<1) | ||
103 | #define LCD_INT_S0 (1<<0) | ||
104 | |||
105 | /* lcd_horztiming */ | ||
106 | #define LCD_HORZTIMING_HN2 (255<<24) | ||
107 | #define LCD_HORZTIMING_HN2_N(N) (((N)-1)<<24) | ||
108 | #define LCD_HORZTIMING_HN1 (255<<16) | ||
109 | #define LCD_HORZTIMING_HN1_N(N) (((N)-1)<<16) | ||
110 | #define LCD_HORZTIMING_HPW (63<<10) | ||
111 | #define LCD_HORZTIMING_HPW_N(N) (((N)-1)<<10) | ||
112 | #define LCD_HORZTIMING_PPL (1023<<0) | ||
113 | #define LCD_HORZTIMING_PPL_N(N) (((N)-1)<<0) | ||
114 | |||
115 | /* lcd_verttiming */ | ||
116 | #define LCD_VERTTIMING_VN2 (255<<24) | ||
117 | #define LCD_VERTTIMING_VN2_N(N) (((N)-1)<<24) | ||
118 | #define LCD_VERTTIMING_VN1 (255<<16) | ||
119 | #define LCD_VERTTIMING_VN1_N(N) (((N)-1)<<16) | ||
120 | #define LCD_VERTTIMING_VPW (63<<10) | ||
121 | #define LCD_VERTTIMING_VPW_N(N) (((N)-1)<<10) | ||
122 | #define LCD_VERTTIMING_LPP (1023<<0) | ||
123 | #define LCD_VERTTIMING_LPP_N(N) (((N)-1)<<0) | ||
124 | |||
125 | /* lcd_clkcontrol */ | ||
126 | #define LCD_CLKCONTROL_IB (1<<18) | ||
127 | #define LCD_CLKCONTROL_IC (1<<17) | ||
128 | #define LCD_CLKCONTROL_IH (1<<16) | ||
129 | #define LCD_CLKCONTROL_IV (1<<15) | ||
130 | #define LCD_CLKCONTROL_BF (31<<10) | ||
131 | #define LCD_CLKCONTROL_BF_N(N) (((N)-1)<<10) | ||
132 | #define LCD_CLKCONTROL_PCD (1023<<0) | ||
133 | #define LCD_CLKCONTROL_PCD_N(N) ((N)<<0) | ||
134 | |||
135 | /* lcd_pwmdiv */ | ||
136 | #define LCD_PWMDIV_EN (1<<12) | ||
137 | #define LCD_PWMDIV_PWMDIV (2047<<0) | ||
138 | #define LCD_PWMDIV_PWMDIV_N(N) (((N)-1)<<0) | ||
139 | |||
140 | /* lcd_pwmhi */ | ||
141 | #define LCD_PWMHI_PWMHI1 (2047<<12) | ||
142 | #define LCD_PWMHI_PWMHI1_N(N) ((N)<<12) | ||
143 | #define LCD_PWMHI_PWMHI0 (2047<<0) | ||
144 | #define LCD_PWMHI_PWMHI0_N(N) ((N)<<0) | ||
145 | |||
146 | /* lcd_pallettebase - MONOCHROME */ | ||
147 | #define LCD_PALLETTE_MONO_MI (15<<0) | ||
148 | #define LCD_PALLETTE_MONO_MI_N(N) ((N)<<0) | ||
149 | |||
150 | /* lcd_pallettebase - COLOR */ | ||
151 | #define LCD_PALLETTE_COLOR_BI (15<<8) | ||
152 | #define LCD_PALLETTE_COLOR_BI_N(N) ((N)<<8) | ||
153 | #define LCD_PALLETTE_COLOR_GI (15<<4) | ||
154 | #define LCD_PALLETTE_COLOR_GI_N(N) ((N)<<4) | ||
155 | #define LCD_PALLETTE_COLOR_RI (15<<0) | ||
156 | #define LCD_PALLETTE_COLOR_RI_N(N) ((N)<<0) | ||
157 | |||
158 | /* lcd_palletebase - COLOR TFT PALLETIZED */ | ||
159 | #define LCD_PALLETTE_TFT_DC (65535<<0) | ||
160 | #define LCD_PALLETTE_TFT_DC_N(N) ((N)<<0) | ||
161 | 75 | ||
162 | /********************************************************************/ | 76 | u32 xres; /* Maximum horizontal resolution */ |
77 | u32 yres; /* Maximum vertical resolution */ | ||
78 | u32 bpp; /* Maximum depth supported */ | ||
79 | }; | ||
163 | 80 | ||
164 | struct known_lcd_panels | 81 | struct au1100fb_regs |
165 | { | 82 | { |
166 | uint32 xres; | 83 | u32 lcd_control; |
167 | uint32 yres; | 84 | u32 lcd_intstatus; |
168 | uint32 bpp; | 85 | u32 lcd_intenable; |
169 | unsigned char panel_name[256]; | 86 | u32 lcd_horztiming; |
170 | uint32 mode_control; | 87 | u32 lcd_verttiming; |
171 | uint32 mode_horztiming; | 88 | u32 lcd_clkcontrol; |
172 | uint32 mode_verttiming; | 89 | u32 lcd_dmaaddr0; |
173 | uint32 mode_clkcontrol; | 90 | u32 lcd_dmaaddr1; |
174 | uint32 mode_pwmdiv; | 91 | u32 lcd_words; |
175 | uint32 mode_pwmhi; | 92 | u32 lcd_pwmdiv; |
176 | uint32 mode_toyclksrc; | 93 | u32 lcd_pwmhi; |
177 | uint32 mode_backlight; | 94 | u32 reserved[(0x0400-0x002C)/4]; |
95 | u32 lcd_pallettebase[256]; | ||
96 | }; | ||
97 | |||
98 | struct au1100fb_device { | ||
99 | |||
100 | struct fb_info info; /* FB driver info record */ | ||
178 | 101 | ||
102 | struct au1100fb_panel *panel; /* Panel connected to this device */ | ||
103 | |||
104 | struct au1100fb_regs* regs; /* Registers memory map */ | ||
105 | size_t regs_len; | ||
106 | unsigned int regs_phys; | ||
107 | |||
108 | unsigned char* fb_mem; /* FrameBuffer memory map */ | ||
109 | size_t fb_len; | ||
110 | dma_addr_t fb_phys; | ||
179 | }; | 111 | }; |
180 | 112 | ||
181 | #if defined(__BIG_ENDIAN) | 113 | /********************************************************************/ |
182 | #define LCD_DEFAULT_PIX_FORMAT LCD_CONTROL_PO_11 | ||
183 | #else | ||
184 | #define LCD_DEFAULT_PIX_FORMAT LCD_CONTROL_PO_00 | ||
185 | #endif | ||
186 | 114 | ||
187 | /* | 115 | #define LCD_CONTROL (AU1100_LCD_BASE + 0x0) |
188 | * The fb driver assumes that AUX PLL is at 48MHz. That can | 116 | #define LCD_CONTROL_SBB_BIT 21 |
189 | * cover up to 800x600 resolution; if you need higher resolution, | 117 | #define LCD_CONTROL_SBB_MASK (0x3 << LCD_CONTROL_SBB_BIT) |
190 | * you should modify the driver as needed, not just this structure. | 118 | #define LCD_CONTROL_SBB_1 (0 << LCD_CONTROL_SBB_BIT) |
119 | #define LCD_CONTROL_SBB_2 (1 << LCD_CONTROL_SBB_BIT) | ||
120 | #define LCD_CONTROL_SBB_3 (2 << LCD_CONTROL_SBB_BIT) | ||
121 | #define LCD_CONTROL_SBB_4 (3 << LCD_CONTROL_SBB_BIT) | ||
122 | #define LCD_CONTROL_SBPPF_BIT 18 | ||
123 | #define LCD_CONTROL_SBPPF_MASK (0x7 << LCD_CONTROL_SBPPF_BIT) | ||
124 | #define LCD_CONTROL_SBPPF_655 (0 << LCD_CONTROL_SBPPF_BIT) | ||
125 | #define LCD_CONTROL_SBPPF_565 (1 << LCD_CONTROL_SBPPF_BIT) | ||
126 | #define LCD_CONTROL_SBPPF_556 (2 << LCD_CONTROL_SBPPF_BIT) | ||
127 | #define LCD_CONTROL_SBPPF_1555 (3 << LCD_CONTROL_SBPPF_BIT) | ||
128 | #define LCD_CONTROL_SBPPF_5551 (4 << LCD_CONTROL_SBPPF_BIT) | ||
129 | #define LCD_CONTROL_WP (1<<17) | ||
130 | #define LCD_CONTROL_WD (1<<16) | ||
131 | #define LCD_CONTROL_C (1<<15) | ||
132 | #define LCD_CONTROL_SM_BIT 13 | ||
133 | #define LCD_CONTROL_SM_MASK (0x3 << LCD_CONTROL_SM_BIT) | ||
134 | #define LCD_CONTROL_SM_0 (0 << LCD_CONTROL_SM_BIT) | ||
135 | #define LCD_CONTROL_SM_90 (1 << LCD_CONTROL_SM_BIT) | ||
136 | #define LCD_CONTROL_SM_180 (2 << LCD_CONTROL_SM_BIT) | ||
137 | #define LCD_CONTROL_SM_270 (3 << LCD_CONTROL_SM_BIT) | ||
138 | #define LCD_CONTROL_DB (1<<12) | ||
139 | #define LCD_CONTROL_CCO (1<<11) | ||
140 | #define LCD_CONTROL_DP (1<<10) | ||
141 | #define LCD_CONTROL_PO_BIT 8 | ||
142 | #define LCD_CONTROL_PO_MASK (0x3 << LCD_CONTROL_PO_BIT) | ||
143 | #define LCD_CONTROL_PO_00 (0 << LCD_CONTROL_PO_BIT) | ||
144 | #define LCD_CONTROL_PO_01 (1 << LCD_CONTROL_PO_BIT) | ||
145 | #define LCD_CONTROL_PO_10 (2 << LCD_CONTROL_PO_BIT) | ||
146 | #define LCD_CONTROL_PO_11 (3 << LCD_CONTROL_PO_BIT) | ||
147 | #define LCD_CONTROL_MPI (1<<7) | ||
148 | #define LCD_CONTROL_PT (1<<6) | ||
149 | #define LCD_CONTROL_PC (1<<5) | ||
150 | #define LCD_CONTROL_BPP_BIT 1 | ||
151 | #define LCD_CONTROL_BPP_MASK (0x7 << LCD_CONTROL_BPP_BIT) | ||
152 | #define LCD_CONTROL_BPP_1 (0 << LCD_CONTROL_BPP_BIT) | ||
153 | #define LCD_CONTROL_BPP_2 (1 << LCD_CONTROL_BPP_BIT) | ||
154 | #define LCD_CONTROL_BPP_4 (2 << LCD_CONTROL_BPP_BIT) | ||
155 | #define LCD_CONTROL_BPP_8 (3 << LCD_CONTROL_BPP_BIT) | ||
156 | #define LCD_CONTROL_BPP_12 (4 << LCD_CONTROL_BPP_BIT) | ||
157 | #define LCD_CONTROL_BPP_16 (5 << LCD_CONTROL_BPP_BIT) | ||
158 | #define LCD_CONTROL_GO (1<<0) | ||
159 | |||
160 | #define LCD_INTSTATUS (AU1100_LCD_BASE + 0x4) | ||
161 | #define LCD_INTENABLE (AU1100_LCD_BASE + 0x8) | ||
162 | #define LCD_INT_SD (1<<7) | ||
163 | #define LCD_INT_OF (1<<6) | ||
164 | #define LCD_INT_UF (1<<5) | ||
165 | #define LCD_INT_SA (1<<3) | ||
166 | #define LCD_INT_SS (1<<2) | ||
167 | #define LCD_INT_S1 (1<<1) | ||
168 | #define LCD_INT_S0 (1<<0) | ||
169 | |||
170 | #define LCD_HORZTIMING (AU1100_LCD_BASE + 0xC) | ||
171 | #define LCD_HORZTIMING_HN2_BIT 24 | ||
172 | #define LCD_HORZTIMING_HN2_MASK (0xFF << LCD_HORZTIMING_HN2_BIT) | ||
173 | #define LCD_HORZTIMING_HN2_N(N) ((((N)-1) << LCD_HORZTIMING_HN2_BIT) & LCD_HORZTIMING_HN2_MASK) | ||
174 | #define LCD_HORZTIMING_HN1_BIT 16 | ||
175 | #define LCD_HORZTIMING_HN1_MASK (0xFF << LCD_HORZTIMING_HN1_BIT) | ||
176 | #define LCD_HORZTIMING_HN1_N(N) ((((N)-1) << LCD_HORZTIMING_HN1_BIT) & LCD_HORZTIMING_HN1_MASK) | ||
177 | #define LCD_HORZTIMING_HPW_BIT 10 | ||
178 | #define LCD_HORZTIMING_HPW_MASK (0x3F << LCD_HORZTIMING_HPW_BIT) | ||
179 | #define LCD_HORZTIMING_HPW_N(N) ((((N)-1) << LCD_HORZTIMING_HPW_BIT) & LCD_HORZTIMING_HPW_MASK) | ||
180 | #define LCD_HORZTIMING_PPL_BIT 0 | ||
181 | #define LCD_HORZTIMING_PPL_MASK (0x3FF << LCD_HORZTIMING_PPL_BIT) | ||
182 | #define LCD_HORZTIMING_PPL_N(N) ((((N)-1) << LCD_HORZTIMING_PPL_BIT) & LCD_HORZTIMING_PPL_MASK) | ||
183 | |||
184 | #define LCD_VERTTIMING (AU1100_LCD_BASE + 0x10) | ||
185 | #define LCD_VERTTIMING_VN2_BIT 24 | ||
186 | #define LCD_VERTTIMING_VN2_MASK (0xFF << LCD_VERTTIMING_VN2_BIT) | ||
187 | #define LCD_VERTTIMING_VN2_N(N) ((((N)-1) << LCD_VERTTIMING_VN2_BIT) & LCD_VERTTIMING_VN2_MASK) | ||
188 | #define LCD_VERTTIMING_VN1_BIT 16 | ||
189 | #define LCD_VERTTIMING_VN1_MASK (0xFF << LCD_VERTTIMING_VN1_BIT) | ||
190 | #define LCD_VERTTIMING_VN1_N(N) ((((N)-1) << LCD_VERTTIMING_VN1_BIT) & LCD_VERTTIMING_VN1_MASK) | ||
191 | #define LCD_VERTTIMING_VPW_BIT 10 | ||
192 | #define LCD_VERTTIMING_VPW_MASK (0x3F << LCD_VERTTIMING_VPW_BIT) | ||
193 | #define LCD_VERTTIMING_VPW_N(N) ((((N)-1) << LCD_VERTTIMING_VPW_BIT) & LCD_VERTTIMING_VPW_MASK) | ||
194 | #define LCD_VERTTIMING_LPP_BIT 0 | ||
195 | #define LCD_VERTTIMING_LPP_MASK (0x3FF << LCD_VERTTIMING_LPP_BIT) | ||
196 | #define LCD_VERTTIMING_LPP_N(N) ((((N)-1) << LCD_VERTTIMING_LPP_BIT) & LCD_VERTTIMING_LPP_MASK) | ||
197 | |||
198 | #define LCD_CLKCONTROL (AU1100_LCD_BASE + 0x14) | ||
199 | #define LCD_CLKCONTROL_IB (1<<18) | ||
200 | #define LCD_CLKCONTROL_IC (1<<17) | ||
201 | #define LCD_CLKCONTROL_IH (1<<16) | ||
202 | #define LCD_CLKCONTROL_IV (1<<15) | ||
203 | #define LCD_CLKCONTROL_BF_BIT 10 | ||
204 | #define LCD_CLKCONTROL_BF_MASK (0x1F << LCD_CLKCONTROL_BF_BIT) | ||
205 | #define LCD_CLKCONTROL_BF_N(N) ((((N)-1) << LCD_CLKCONTROL_BF_BIT) & LCD_CLKCONTROL_BF_MASK) | ||
206 | #define LCD_CLKCONTROL_PCD_BIT 0 | ||
207 | #define LCD_CLKCONTROL_PCD_MASK (0x3FF << LCD_CLKCONTROL_PCD_BIT) | ||
208 | #define LCD_CLKCONTROL_PCD_N(N) (((N) << LCD_CLKCONTROL_PCD_BIT) & LCD_CLKCONTROL_PCD_MASK) | ||
209 | |||
210 | #define LCD_DMAADDR0 (AU1100_LCD_BASE + 0x18) | ||
211 | #define LCD_DMAADDR1 (AU1100_LCD_BASE + 0x1C) | ||
212 | #define LCD_DMA_SA_BIT 5 | ||
213 | #define LCD_DMA_SA_MASK (0x7FFFFFF << LCD_DMA_SA_BIT) | ||
214 | #define LCD_DMA_SA_N(N) ((N) & LCD_DMA_SA_MASK) | ||
215 | |||
216 | #define LCD_WORDS (AU1100_LCD_BASE + 0x20) | ||
217 | #define LCD_WRD_WRDS_BIT 0 | ||
218 | #define LCD_WRD_WRDS_MASK (0xFFFFFFFF << LCD_WRD_WRDS_BIT) | ||
219 | #define LCD_WRD_WRDS_N(N) ((((N)-1) << LCD_WRD_WRDS_BIT) & LCD_WRD_WRDS_MASK) | ||
220 | |||
221 | #define LCD_PWMDIV (AU1100_LCD_BASE + 0x24) | ||
222 | #define LCD_PWMDIV_EN (1<<12) | ||
223 | #define LCD_PWMDIV_PWMDIV_BIT 0 | ||
224 | #define LCD_PWMDIV_PWMDIV_MASK (0xFFF << LCD_PWMDIV_PWMDIV_BIT) | ||
225 | #define LCD_PWMDIV_PWMDIV_N(N) ((((N)-1) << LCD_PWMDIV_PWMDIV_BIT) & LCD_PWMDIV_PWMDIV_MASK) | ||
226 | |||
227 | #define LCD_PWMHI (AU1100_LCD_BASE + 0x28) | ||
228 | #define LCD_PWMHI_PWMHI1_BIT 12 | ||
229 | #define LCD_PWMHI_PWMHI1_MASK (0xFFF << LCD_PWMHI_PWMHI1_BIT) | ||
230 | #define LCD_PWMHI_PWMHI1_N(N) (((N) << LCD_PWMHI_PWMHI1_BIT) & LCD_PWMHI_PWMHI1_MASK) | ||
231 | #define LCD_PWMHI_PWMHI0_BIT 0 | ||
232 | #define LCD_PWMHI_PWMHI0_MASK (0xFFF << LCD_PWMHI_PWMHI0_BIT) | ||
233 | #define LCD_PWMHI_PWMHI0_N(N) (((N) << LCD_PWMHI_PWMHI0_BIT) & LCD_PWMHI_PWMHI0_MASK) | ||
234 | |||
235 | #define LCD_PALLETTEBASE (AU1100_LCD_BASE + 0x400) | ||
236 | #define LCD_PALLETTE_MONO_MI_BIT 0 | ||
237 | #define LCD_PALLETTE_MONO_MI_MASK (0xF << LCD_PALLETTE_MONO_MI_BIT) | ||
238 | #define LCD_PALLETTE_MONO_MI_N(N) (((N)<< LCD_PALLETTE_MONO_MI_BIT) & LCD_PALLETTE_MONO_MI_MASK) | ||
239 | |||
240 | #define LCD_PALLETTE_COLOR_RI_BIT 8 | ||
241 | #define LCD_PALLETTE_COLOR_RI_MASK (0xF << LCD_PALLETTE_COLOR_RI_BIT) | ||
242 | #define LCD_PALLETTE_COLOR_RI_N(N) (((N)<< LCD_PALLETTE_COLOR_RI_BIT) & LCD_PALLETTE_COLOR_RI_MASK) | ||
243 | #define LCD_PALLETTE_COLOR_GI_BIT 4 | ||
244 | #define LCD_PALLETTE_COLOR_GI_MASK (0xF << LCD_PALLETTE_COLOR_GI_BIT) | ||
245 | #define LCD_PALLETTE_COLOR_GI_N(N) (((N)<< LCD_PALLETTE_COLOR_GI_BIT) & LCD_PALLETTE_COLOR_GI_MASK) | ||
246 | #define LCD_PALLETTE_COLOR_BI_BIT 0 | ||
247 | #define LCD_PALLETTE_COLOR_BI_MASK (0xF << LCD_PALLETTE_COLOR_BI_BIT) | ||
248 | #define LCD_PALLETTE_COLOR_BI_N(N) (((N)<< LCD_PALLETTE_COLOR_BI_BIT) & LCD_PALLETTE_COLOR_BI_MASK) | ||
249 | |||
250 | #define LCD_PALLETTE_TFT_DC_BIT 0 | ||
251 | #define LCD_PALLETTE_TFT_DC_MASK (0xFFFF << LCD_PALLETTE_TFT_DC_BIT) | ||
252 | #define LCD_PALLETTE_TFT_DC_N(N) (((N)<< LCD_PALLETTE_TFT_DC_BIT) & LCD_PALLETTE_TFT_DC_MASK) | ||
253 | |||
254 | /********************************************************************/ | ||
255 | |||
256 | /* List of panels known to work with the AU1100 LCD controller. | ||
257 | * To add a new panel, enter the same specifications as the | ||
258 | * Generic_TFT one, and MAKE SURE that it doesn't conflicts | ||
259 | * with the controller restrictions. Restrictions are: | ||
260 | * | ||
261 | * STN color panels: max_bpp <= 12 | ||
262 | * STN mono panels: max_bpp <= 4 | ||
263 | * TFT panels: max_bpp <= 16 | ||
264 | * max_xres <= 800 | ||
265 | * max_yres <= 600 | ||
191 | */ | 266 | */ |
192 | struct known_lcd_panels panels[] = | 267 | static struct au1100fb_panel known_lcd_panels[] = |
193 | { | 268 | { |
194 | { /* 0: Pb1100 LCDA: Sharp 320x240 TFT panel */ | 269 | /* 800x600x16bpp CRT */ |
195 | 320, /* xres */ | 270 | [0] = { |
196 | 240, /* yres */ | 271 | .name = "CRT_800x600_16", |
197 | 16, /* bpp */ | 272 | .xres = 800, |
198 | 273 | .yres = 600, | |
199 | "Sharp_320x240_16", | 274 | .bpp = 16, |
200 | /* mode_control */ | 275 | .control_base = 0x0004886A | |
276 | LCD_CONTROL_DEFAULT_PO | LCD_CONTROL_DEFAULT_SBPPF | | ||
277 | LCD_CONTROL_BPP_16, | ||
278 | .clkcontrol_base = 0x00020000, | ||
279 | .horztiming = 0x005aff1f, | ||
280 | .verttiming = 0x16000e57, | ||
281 | }, | ||
282 | /* just the standard LCD */ | ||
283 | [1] = { | ||
284 | .name = "WWPC LCD", | ||
285 | .xres = 240, | ||
286 | .yres = 320, | ||
287 | .bpp = 16, | ||
288 | .control_base = 0x0006806A, | ||
289 | .horztiming = 0x0A1010EF, | ||
290 | .verttiming = 0x0301013F, | ||
291 | .clkcontrol_base = 0x00018001, | ||
292 | }, | ||
293 | /* Sharp 320x240 TFT panel */ | ||
294 | [2] = { | ||
295 | .name = "Sharp_LQ038Q5DR01", | ||
296 | .xres = 320, | ||
297 | .yres = 240, | ||
298 | .bpp = 16, | ||
299 | .control_base = | ||
201 | ( LCD_CONTROL_SBPPF_565 | 300 | ( LCD_CONTROL_SBPPF_565 |
202 | /*LCD_CONTROL_WP*/ | ||
203 | /*LCD_CONTROL_WD*/ | ||
204 | | LCD_CONTROL_C | 301 | | LCD_CONTROL_C |
205 | | LCD_CONTROL_SM_0 | 302 | | LCD_CONTROL_SM_0 |
206 | /*LCD_CONTROL_DB*/ | 303 | | LCD_CONTROL_DEFAULT_PO |
207 | /*LCD_CONTROL_CCO*/ | ||
208 | /*LCD_CONTROL_DP*/ | ||
209 | | LCD_DEFAULT_PIX_FORMAT | ||
210 | /*LCD_CONTROL_MPI*/ | ||
211 | | LCD_CONTROL_PT | 304 | | LCD_CONTROL_PT |
212 | | LCD_CONTROL_PC | 305 | | LCD_CONTROL_PC |
213 | | LCD_CONTROL_BPP_16 ), | 306 | | LCD_CONTROL_BPP_16 ), |
214 | 307 | .horztiming = | |
215 | /* mode_horztiming */ | ||
216 | ( LCD_HORZTIMING_HN2_N(8) | 308 | ( LCD_HORZTIMING_HN2_N(8) |
217 | | LCD_HORZTIMING_HN1_N(60) | 309 | | LCD_HORZTIMING_HN1_N(60) |
218 | | LCD_HORZTIMING_HPW_N(12) | 310 | | LCD_HORZTIMING_HPW_N(12) |
219 | | LCD_HORZTIMING_PPL_N(320) ), | 311 | | LCD_HORZTIMING_PPL_N(320) ), |
220 | 312 | .verttiming = | |
221 | /* mode_verttiming */ | ||
222 | ( LCD_VERTTIMING_VN2_N(5) | 313 | ( LCD_VERTTIMING_VN2_N(5) |
223 | | LCD_VERTTIMING_VN1_N(17) | 314 | | LCD_VERTTIMING_VN1_N(17) |
224 | | LCD_VERTTIMING_VPW_N(1) | 315 | | LCD_VERTTIMING_VPW_N(1) |
225 | | LCD_VERTTIMING_LPP_N(240) ), | 316 | | LCD_VERTTIMING_LPP_N(240) ), |
226 | 317 | .clkcontrol_base = LCD_CLKCONTROL_PCD_N(1), | |
227 | /* mode_clkcontrol */ | ||
228 | ( 0 | ||
229 | /*LCD_CLKCONTROL_IB*/ | ||
230 | /*LCD_CLKCONTROL_IC*/ | ||
231 | /*LCD_CLKCONTROL_IH*/ | ||
232 | /*LCD_CLKCONTROL_IV*/ | ||
233 | | LCD_CLKCONTROL_PCD_N(1) ), | ||
234 | |||
235 | /* mode_pwmdiv */ | ||
236 | 0, | ||
237 | |||
238 | /* mode_pwmhi */ | ||
239 | 0, | ||
240 | |||
241 | /* mode_toyclksrc */ | ||
242 | ((1<<7) | (1<<6) | (1<<5)), | ||
243 | |||
244 | /* mode_backlight */ | ||
245 | 6 | ||
246 | }, | 318 | }, |
247 | 319 | ||
248 | { /* 1: Pb1100 LCDC 640x480 TFT panel */ | 320 | /* Hitachi SP14Q005 and possibly others */ |
249 | 640, /* xres */ | 321 | [3] = { |
250 | 480, /* yres */ | 322 | .name = "Hitachi_SP14Qxxx", |
251 | 16, /* bpp */ | 323 | .xres = 320, |
252 | 324 | .yres = 240, | |
253 | "Generic_640x480_16", | 325 | .bpp = 4, |
254 | 326 | .control_base = | |
255 | /* mode_control */ | 327 | ( LCD_CONTROL_C |
256 | 0x004806a | LCD_DEFAULT_PIX_FORMAT, | 328 | | LCD_CONTROL_BPP_4 ), |
257 | 329 | .horztiming = | |
258 | /* mode_horztiming */ | 330 | ( LCD_HORZTIMING_HN2_N(1) |
259 | 0x3434d67f, | 331 | | LCD_HORZTIMING_HN1_N(1) |
260 | 332 | | LCD_HORZTIMING_HPW_N(1) | |
261 | /* mode_verttiming */ | 333 | | LCD_HORZTIMING_PPL_N(320) ), |
262 | 0x0e0e39df, | 334 | .verttiming = |
263 | 335 | ( LCD_VERTTIMING_VN2_N(1) | |
264 | /* mode_clkcontrol */ | 336 | | LCD_VERTTIMING_VN1_N(1) |
265 | ( 0 | 337 | | LCD_VERTTIMING_VPW_N(1) |
266 | /*LCD_CLKCONTROL_IB*/ | 338 | | LCD_VERTTIMING_LPP_N(240) ), |
267 | /*LCD_CLKCONTROL_IC*/ | 339 | .clkcontrol_base = LCD_CLKCONTROL_PCD_N(4), |
268 | /*LCD_CLKCONTROL_IH*/ | ||
269 | /*LCD_CLKCONTROL_IV*/ | ||
270 | | LCD_CLKCONTROL_PCD_N(1) ), | ||
271 | |||
272 | /* mode_pwmdiv */ | ||
273 | 0, | ||
274 | |||
275 | /* mode_pwmhi */ | ||
276 | 0, | ||
277 | |||
278 | /* mode_toyclksrc */ | ||
279 | ((1<<7) | (1<<6) | (0<<5)), | ||
280 | |||
281 | /* mode_backlight */ | ||
282 | 7 | ||
283 | }, | 340 | }, |
284 | 341 | ||
285 | { /* 2: Pb1100 LCDB 640x480 PrimeView TFT panel */ | 342 | /* Generic 640x480 TFT panel */ |
286 | 640, /* xres */ | 343 | [4] = { |
287 | 480, /* yres */ | 344 | .name = "TFT_640x480_16", |
288 | 16, /* bpp */ | 345 | .xres = 640, |
289 | 346 | .yres = 480, | |
290 | "PrimeView_640x480_16", | 347 | .bpp = 16, |
291 | 348 | .control_base = 0x004806a | LCD_CONTROL_DEFAULT_PO, | |
292 | /* mode_control */ | 349 | .horztiming = 0x3434d67f, |
293 | 0x0004886a | LCD_DEFAULT_PIX_FORMAT, | 350 | .verttiming = 0x0e0e39df, |
294 | 351 | .clkcontrol_base = LCD_CLKCONTROL_PCD_N(1), | |
295 | /* mode_horztiming */ | ||
296 | 0x0e4bfe7f, | ||
297 | |||
298 | /* mode_verttiming */ | ||
299 | 0x210805df, | ||
300 | |||
301 | /* mode_clkcontrol */ | ||
302 | 0x00038001, | ||
303 | |||
304 | /* mode_pwmdiv */ | ||
305 | 0, | ||
306 | |||
307 | /* mode_pwmhi */ | ||
308 | 0, | ||
309 | |||
310 | /* mode_toyclksrc */ | ||
311 | ((1<<7) | (1<<6) | (0<<5)), | ||
312 | |||
313 | /* mode_backlight */ | ||
314 | 7 | ||
315 | }, | 352 | }, |
316 | 353 | ||
317 | { /* 3: Pb1100 800x600x16bpp NEON CRT */ | 354 | /* Pb1100 LCDB 640x480 PrimeView TFT panel */ |
318 | 800, /* xres */ | 355 | [5] = { |
319 | 600, /* yres */ | 356 | .name = "PrimeView_640x480_16", |
320 | 16, /* bpp */ | 357 | .xres = 640, |
321 | 358 | .yres = 480, | |
322 | "NEON_800x600_16", | 359 | .bpp = 16, |
323 | 360 | .control_base = 0x0004886a | LCD_CONTROL_DEFAULT_PO, | |
324 | /* mode_control */ | 361 | .horztiming = 0x0e4bfe7f, |
325 | 0x0004886A | LCD_DEFAULT_PIX_FORMAT, | 362 | .verttiming = 0x210805df, |
326 | 363 | .clkcontrol_base = 0x00038001, | |
327 | /* mode_horztiming */ | ||
328 | 0x005AFF1F, | ||
329 | |||
330 | /* mode_verttiming */ | ||
331 | 0x16000E57, | ||
332 | |||
333 | /* mode_clkcontrol */ | ||
334 | 0x00020000, | ||
335 | |||
336 | /* mode_pwmdiv */ | ||
337 | 0, | ||
338 | |||
339 | /* mode_pwmhi */ | ||
340 | 0, | ||
341 | |||
342 | /* mode_toyclksrc */ | ||
343 | ((1<<7) | (1<<6) | (0<<5)), | ||
344 | |||
345 | /* mode_backlight */ | ||
346 | 7 | ||
347 | }, | 364 | }, |
365 | }; | ||
348 | 366 | ||
349 | { /* 4: Pb1100 640x480x16bpp NEON CRT */ | 367 | struct au1100fb_drv_info { |
350 | 640, /* xres */ | 368 | int panel_idx; |
351 | 480, /* yres */ | 369 | char *opt_mode; |
352 | 16, /* bpp */ | 370 | }; |
353 | |||
354 | "NEON_640x480_16", | ||
355 | |||
356 | /* mode_control */ | ||
357 | 0x0004886A | LCD_DEFAULT_PIX_FORMAT, | ||
358 | |||
359 | /* mode_horztiming */ | ||
360 | 0x0052E27F, | ||
361 | |||
362 | /* mode_verttiming */ | ||
363 | 0x18000DDF, | ||
364 | |||
365 | /* mode_clkcontrol */ | ||
366 | 0x00020000, | ||
367 | 371 | ||
368 | /* mode_pwmdiv */ | 372 | /********************************************************************/ |
369 | 0, | ||
370 | 373 | ||
371 | /* mode_pwmhi */ | 374 | /* Inline helpers */ |
372 | 0, | ||
373 | 375 | ||
374 | /* mode_toyclksrc */ | 376 | #define panel_is_dual(panel) (panel->control_base & LCD_CONTROL_DP) |
375 | ((1<<7) | (1<<6) | (0<<5)), | 377 | #define panel_is_active(panel)(panel->control_base & LCD_CONTROL_PT) |
378 | #define panel_is_color(panel) (panel->control_base & LCD_CONTROL_PC) | ||
379 | #define panel_swap_rgb(panel) (panel->control_base & LCD_CONTROL_CCO) | ||
376 | 380 | ||
377 | /* mode_backlight */ | ||
378 | 7 | ||
379 | }, | ||
380 | }; | ||
381 | #endif /* _AU1100LCD_H */ | 381 | #endif /* _AU1100LCD_H */ |
diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c index e793ffd39db5..762c7a593141 100644 --- a/drivers/video/console/newport_con.c +++ b/drivers/video/console/newport_con.c | |||
@@ -32,7 +32,6 @@ | |||
32 | #include <linux/font.h> | 32 | #include <linux/font.h> |
33 | 33 | ||
34 | 34 | ||
35 | extern struct font_desc font_vga_8x16; | ||
36 | extern unsigned long sgi_gfxaddr; | 35 | extern unsigned long sgi_gfxaddr; |
37 | 36 | ||
38 | #define FONT_DATA ((unsigned char *)font_vga_8x16.data) | 37 | #define FONT_DATA ((unsigned char *)font_vga_8x16.data) |
diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c index d3c1922cb13a..485604cd4462 100644 --- a/drivers/video/gbefb.c +++ b/drivers/video/gbefb.c | |||
@@ -1126,7 +1126,7 @@ static int __init gbefb_probe(struct device *dev) | |||
1126 | gbefb_setup(options); | 1126 | gbefb_setup(options); |
1127 | #endif | 1127 | #endif |
1128 | 1128 | ||
1129 | if (!request_mem_region(GBE_BASE, sizeof(struct sgi_gbe), "GBE")) { | 1129 | if (!request_region(GBE_BASE, sizeof(struct sgi_gbe), "GBE")) { |
1130 | printk(KERN_ERR "gbefb: couldn't reserve mmio region\n"); | 1130 | printk(KERN_ERR "gbefb: couldn't reserve mmio region\n"); |
1131 | ret = -EBUSY; | 1131 | ret = -EBUSY; |
1132 | goto out_release_framebuffer; | 1132 | goto out_release_framebuffer; |
@@ -1152,12 +1152,24 @@ static int __init gbefb_probe(struct device *dev) | |||
1152 | if (gbe_mem_phys) { | 1152 | if (gbe_mem_phys) { |
1153 | /* memory was allocated at boot time */ | 1153 | /* memory was allocated at boot time */ |
1154 | gbe_mem = ioremap_nocache(gbe_mem_phys, gbe_mem_size); | 1154 | gbe_mem = ioremap_nocache(gbe_mem_phys, gbe_mem_size); |
1155 | if (!gbe_mem) { | ||
1156 | printk(KERN_ERR "gbefb: couldn't map framebuffer\n"); | ||
1157 | ret = -ENOMEM; | ||
1158 | goto out_tiles_free; | ||
1159 | } | ||
1160 | |||
1155 | gbe_dma_addr = 0; | 1161 | gbe_dma_addr = 0; |
1156 | } else { | 1162 | } else { |
1157 | /* try to allocate memory with the classical allocator | 1163 | /* try to allocate memory with the classical allocator |
1158 | * this has high chance to fail on low memory machines */ | 1164 | * this has high chance to fail on low memory machines */ |
1159 | gbe_mem = dma_alloc_coherent(NULL, gbe_mem_size, &gbe_dma_addr, | 1165 | gbe_mem = dma_alloc_coherent(NULL, gbe_mem_size, &gbe_dma_addr, |
1160 | GFP_KERNEL); | 1166 | GFP_KERNEL); |
1167 | if (!gbe_mem) { | ||
1168 | printk(KERN_ERR "gbefb: couldn't allocate framebuffer memory\n"); | ||
1169 | ret = -ENOMEM; | ||
1170 | goto out_tiles_free; | ||
1171 | } | ||
1172 | |||
1161 | gbe_mem_phys = (unsigned long) gbe_dma_addr; | 1173 | gbe_mem_phys = (unsigned long) gbe_dma_addr; |
1162 | } | 1174 | } |
1163 | 1175 | ||
@@ -1165,12 +1177,6 @@ static int __init gbefb_probe(struct device *dev) | |||
1165 | mtrr_add(gbe_mem_phys, gbe_mem_size, MTRR_TYPE_WRCOMB, 1); | 1177 | mtrr_add(gbe_mem_phys, gbe_mem_size, MTRR_TYPE_WRCOMB, 1); |
1166 | #endif | 1178 | #endif |
1167 | 1179 | ||
1168 | if (!gbe_mem) { | ||
1169 | printk(KERN_ERR "gbefb: couldn't map framebuffer\n"); | ||
1170 | ret = -ENXIO; | ||
1171 | goto out_tiles_free; | ||
1172 | } | ||
1173 | |||
1174 | /* map framebuffer memory into tiles table */ | 1180 | /* map framebuffer memory into tiles table */ |
1175 | for (i = 0; i < (gbe_mem_size >> TILE_SHIFT); i++) | 1181 | for (i = 0; i < (gbe_mem_size >> TILE_SHIFT); i++) |
1176 | gbe_tiles.cpu[i] = (gbe_mem_phys >> TILE_SHIFT) + i; | 1182 | gbe_tiles.cpu[i] = (gbe_mem_phys >> TILE_SHIFT) + i; |