1/*
2 *  linux/drivers/video/sa1100fb.c
3 *
4 *  Copyright (C) 1999 Eric A. Thomas
5 *   Based on acornfb.c Copyright (C) Russell King.
6 *
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License.  See the file COPYING in the main directory of this archive for
9 * more details.
10 *
11 *	        StrongARM 1100 LCD Controller Frame Buffer Driver
12 *
13 * Please direct your questions and comments on this driver to the following
14 * email address:
15 *
16 *	linux-arm-kernel@lists.arm.linux.org.uk
17 *
18 * Clean patches should be sent to the ARM Linux Patch System.  Please see the
19 * following web page for more information:
20 *
21 *	http://www.arm.linux.org.uk/developer/patches/info.shtml
22 *
23 * Thank you.
24 *
25 * Known problems:
26 *	- With the Neponset plugged into an Assabet, LCD powerdown
27 *	  doesn't work (LCD stays powered up).  Therefore we shouldn't
28 *	  blank the screen.
29 *	- We don't limit the CPU clock rate nor the mode selection
30 *	  according to the available SDRAM bandwidth.
31 *
32 * Other notes:
33 *	- Linear grayscale palettes and the kernel.
34 *	  Such code does not belong in the kernel.  The kernel frame buffer
35 *	  drivers do not expect a linear colourmap, but a colourmap based on
36 *	  the VT100 standard mapping.
37 *
38 *	  If your _userspace_ requires a linear colourmap, then the setup of
39 *	  such a colourmap belongs _in userspace_, not in the kernel.  Code
40 *	  to set the colourmap correctly from user space has been sent to
41 *	  David Neuer.  It's around 8 lines of C code, plus another 4 to
42 *	  detect if we are using grayscale.
43 *
44 *	- The following must never be specified in a panel definition:
45 *	     LCCR0_LtlEnd, LCCR3_PixClkDiv, LCCR3_VrtSnchL, LCCR3_HorSnchL
46 *
47 *	- The following should be specified:
48 *	     either LCCR0_Color or LCCR0_Mono
49 *	     either LCCR0_Sngl or LCCR0_Dual
50 *	     either LCCR0_Act or LCCR0_Pas
51 *	     either LCCR3_OutEnH or LCCD3_OutEnL
52 *	     either LCCR3_PixRsEdg or LCCR3_PixFlEdg
53 *	     either LCCR3_ACBsDiv or LCCR3_ACBsCntOff
54 *
55 * Code Status:
56 * 1999/04/01:
57 *	- Driver appears to be working for Brutus 320x200x8bpp mode.  Other
58 *	  resolutions are working, but only the 8bpp mode is supported.
59 *	  Changes need to be made to the palette encode and decode routines
60 *	  to support 4 and 16 bpp modes.
61 *	  Driver is not designed to be a module.  The FrameBuffer is statically
62 *	  allocated since dynamic allocation of a 300k buffer cannot be
63 *	  guaranteed.
64 *
65 * 1999/06/17:
66 *	- FrameBuffer memory is now allocated at run-time when the
67 *	  driver is initialized.
68 *
69 * 2000/04/10: Nicolas Pitre <nico@cam.org>
70 *	- Big cleanup for dynamic selection of machine type at run time.
71 *
72 * 2000/07/19: Jamey Hicks <jamey@crl.dec.com>
73 *	- Support for Bitsy aka Compaq iPAQ H3600 added.
74 *
75 * 2000/08/07: Tak-Shing Chan <tchan.rd@idthk.com>
76 *	       Jeff Sutherland <jsutherland@accelent.com>
77 *	- Resolved an issue caused by a change made to the Assabet's PLD
78 *	  earlier this year which broke the framebuffer driver for newer
79 *	  Phase 4 Assabets.  Some other parameters were changed to optimize
80 *	  for the Sharp display.
81 *
82 * 2000/08/09: Kunihiko IMAI <imai@vasara.co.jp>
83 *	- XP860 support added
84 *
85 * 2000/08/19: Mark Huang <mhuang@livetoy.com>
86 *	- Allows standard options to be passed on the kernel command line
87 *	  for most common passive displays.
88 *
89 * 2000/08/29:
90 *	- s/save_flags_cli/local_irq_save/
91 *	- remove unneeded extra save_flags_cli in sa1100fb_enable_lcd_controller
92 *
93 * 2000/10/10: Erik Mouw <J.A.K.Mouw@its.tudelft.nl>
94 *	- Updated LART stuff. Fixed some minor bugs.
95 *
96 * 2000/10/30: Murphy Chen <murphy@mail.dialogue.com.tw>
97 *	- Pangolin support added
98 *
99 * 2000/10/31: Roman Jordan <jor@hoeft-wessel.de>
100 *	- Huw Webpanel support added
101 *
102 * 2000/11/23: Eric Peng <ericpeng@coventive.com>
103 *	- Freebird add
104 *
105 * 2001/02/07: Jamey Hicks <jamey.hicks@compaq.com>
106 *	       Cliff Brake <cbrake@accelent.com>
107 *	- Added PM callback
108 *
109 * 2001/05/26: <rmk@arm.linux.org.uk>
110 *	- Fix 16bpp so that (a) we use the right colours rather than some
111 *	  totally random colour depending on what was in page 0, and (b)
112 *	  we don't de-reference a NULL pointer.
113 *	- remove duplicated implementation of consistent_alloc()
114 *	- convert dma address types to dma_addr_t
115 *	- remove unused 'montype' stuff
116 *	- remove redundant zero inits of init_var after the initial
117 *	  memzero.
118 *	- remove allow_modeset (acornfb idea does not belong here)
119 *
120 * 2001/05/28: <rmk@arm.linux.org.uk>
121 *	- massive cleanup - move machine dependent data into structures
122 *	- I've left various #warnings in - if you see one, and know
123 *	  the hardware concerned, please get in contact with me.
124 *
125 * 2001/05/31: <rmk@arm.linux.org.uk>
126 *	- Fix LCCR1 HSW value, fix all machine type specifications to
127 *	  keep values in line.  (Please check your machine type specs)
128 *
129 * 2001/06/10: <rmk@arm.linux.org.uk>
130 *	- Fiddle with the LCD controller from task context only; mainly
131 *	  so that we can run with interrupts on, and sleep.
132 *	- Convert #warnings into #errors.  No pain, no gain. ;)
133 *
134 * 2001/06/14: <rmk@arm.linux.org.uk>
135 *	- Make the palette BPS value for 12bpp come out correctly.
136 *	- Take notice of "greyscale" on any colour depth.
137 *	- Make truecolor visuals use the RGB channel encoding information.
138 *
139 * 2001/07/02: <rmk@arm.linux.org.uk>
140 *	- Fix colourmap problems.
141 *
142 * 2001/07/13: <abraham@2d3d.co.za>
143 *	- Added support for the ICP LCD-Kit01 on LART. This LCD is
144 *	  manufactured by Prime View, model no V16C6448AB
145 *
146 * 2001/07/23: <rmk@arm.linux.org.uk>
147 *	- Hand merge version from handhelds.org CVS tree.  See patch
148 *	  notes for 595/1 for more information.
149 *	- Drop 12bpp (it's 16bpp with different colour register mappings).
150 *	- This hardware can not do direct colour.  Therefore we don't
151 *	  support it.
152 *
153 * 2001/07/27: <rmk@arm.linux.org.uk>
154 *	- Halve YRES on dual scan LCDs.
155 *
156 * 2001/08/22: <rmk@arm.linux.org.uk>
157 *	- Add b/w iPAQ pixclock value.
158 *
159 * 2001/10/12: <rmk@arm.linux.org.uk>
160 *	- Add patch 681/1 and clean up stork definitions.
161 */
162
163#include <linux/module.h>
164#include <linux/kernel.h>
165#include <linux/sched.h>
166#include <linux/errno.h>
167#include <linux/string.h>
168#include <linux/interrupt.h>
169#include <linux/slab.h>
170#include <linux/fb.h>
171#include <linux/delay.h>
172#include <linux/init.h>
173#include <linux/ioport.h>
174#include <linux/cpufreq.h>
175#include <linux/platform_device.h>
176#include <linux/dma-mapping.h>
177
178#include <asm/hardware.h>
179#include <asm/io.h>
180#include <asm/mach-types.h>
181#include <asm/uaccess.h>
182#include <asm/arch/assabet.h>
183#include <asm/arch/shannon.h>
184
185/*
186 * debugging?
187 */
188#define DEBUG 0
189/*
190 * Complain if VAR is out of range.
191 */
192#define DEBUG_VAR 1
193
194#undef ASSABET_PAL_VIDEO
195
196#include "sa1100fb.h"
197
198extern void (*sa1100fb_backlight_power)(int on);
199extern void (*sa1100fb_lcd_power)(int on);
200
201/*
202 * IMHO this looks wrong.  In 8BPP, length should be 8.
203 */
204static struct sa1100fb_rgb rgb_8 = {
205	.red	= { .offset = 0,  .length = 4, },
206	.green	= { .offset = 0,  .length = 4, },
207	.blue	= { .offset = 0,  .length = 4, },
208	.transp	= { .offset = 0,  .length = 0, },
209};
210
211static struct sa1100fb_rgb def_rgb_16 = {
212	.red	= { .offset = 11, .length = 5, },
213	.green	= { .offset = 5,  .length = 6, },
214	.blue	= { .offset = 0,  .length = 5, },
215	.transp	= { .offset = 0,  .length = 0, },
216};
217
218#ifdef CONFIG_SA1100_ASSABET
219#ifndef ASSABET_PAL_VIDEO
220/*
221 * The assabet uses a sharp LQ039Q2DS54 LCD module.  It is actually
222 * takes an RGB666 signal, but we provide it with an RGB565 signal
223 * instead (def_rgb_16).
224 */
225static struct sa1100fb_mach_info lq039q2ds54_info __initdata = {
226	.pixclock	= 171521,	.bpp		= 16,
227	.xres		= 320,		.yres		= 240,
228
229	.hsync_len	= 5,		.vsync_len	= 1,
230	.left_margin	= 61,		.upper_margin	= 3,
231	.right_margin	= 9,		.lower_margin	= 0,
232
233	.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
234
235	.lccr0		= LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
236	.lccr3		= LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
237};
238#else
239static struct sa1100fb_mach_info pal_info __initdata = {
240	.pixclock	= 67797,	.bpp		= 16,
241	.xres		= 640,		.yres		= 512,
242
243	.hsync_len	= 64,		.vsync_len	= 6,
244	.left_margin	= 125,		.upper_margin	= 70,
245	.right_margin	= 115,		.lower_margin	= 36,
246
247	.lccr0		= LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
248	.lccr3		= LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(512),
249};
250#endif
251#endif
252
253#ifdef CONFIG_SA1100_H3800
254static struct sa1100fb_mach_info h3800_info __initdata = {
255	.pixclock	= 174757, 	.bpp		= 16,
256	.xres		= 320,		.yres		= 240,
257
258	.hsync_len	= 3,		.vsync_len	= 3,
259	.left_margin	= 12,		.upper_margin	= 10,
260	.right_margin	= 17,		.lower_margin	= 1,
261
262	.cmap_static	= 1,
263
264	.lccr0		= LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
265	.lccr3		= LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
266};
267#endif
268
269#ifdef CONFIG_SA1100_H3600
270static struct sa1100fb_mach_info h3600_info __initdata = {
271	.pixclock	= 174757, 	.bpp		= 16,
272	.xres		= 320,		.yres		= 240,
273
274	.hsync_len	= 3,		.vsync_len	= 3,
275	.left_margin	= 12,		.upper_margin	= 10,
276	.right_margin	= 17,		.lower_margin	= 1,
277
278	.cmap_static	= 1,
279
280	.lccr0		= LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
281	.lccr3		= LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
282};
283
284static struct sa1100fb_rgb h3600_rgb_16 = {
285	.red	= { .offset = 12, .length = 4, },
286	.green	= { .offset = 7,  .length = 4, },
287	.blue	= { .offset = 1,  .length = 4, },
288	.transp	= { .offset = 0,  .length = 0, },
289};
290#endif
291
292#ifdef CONFIG_SA1100_H3100
293static struct sa1100fb_mach_info h3100_info __initdata = {
294	.pixclock	= 406977, 	.bpp		= 4,
295	.xres		= 320,		.yres		= 240,
296
297	.hsync_len	= 26,		.vsync_len	= 41,
298	.left_margin	= 4,		.upper_margin	= 0,
299	.right_margin	= 4,		.lower_margin	= 0,
300
301	.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
302	.cmap_greyscale	= 1,
303	.cmap_inverse	= 1,
304
305	.lccr0		= LCCR0_Mono | LCCR0_4PixMono | LCCR0_Sngl | LCCR0_Pas,
306	.lccr3		= LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
307};
308#endif
309
310#ifdef CONFIG_SA1100_COLLIE
311static struct sa1100fb_mach_info collie_info __initdata = {
312	.pixclock	= 171521,	.bpp		= 16,
313	.xres		= 320,		.yres		= 240,
314
315	.hsync_len	= 5,		.vsync_len	= 1,
316	.left_margin	= 11,		.upper_margin	= 2,
317	.right_margin	= 30,		.lower_margin	= 0,
318
319	.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
320
321	.lccr0		= LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
322	.lccr3		= LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
323};
324#endif
325
326#ifdef LART_GREY_LCD
327static struct sa1100fb_mach_info lart_grey_info __initdata = {
328	.pixclock	= 150000,	.bpp		= 4,
329	.xres		= 320,		.yres		= 240,
330
331	.hsync_len	= 1,		.vsync_len	= 1,
332	.left_margin	= 4,		.upper_margin	= 0,
333	.right_margin	= 2,		.lower_margin	= 0,
334
335	.cmap_greyscale	= 1,
336	.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
337
338	.lccr0		= LCCR0_Mono | LCCR0_Sngl | LCCR0_Pas | LCCR0_4PixMono,
339	.lccr3		= LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(512),
340};
341#endif
342#ifdef LART_COLOR_LCD
343static struct sa1100fb_mach_info lart_color_info __initdata = {
344	.pixclock	= 150000,	.bpp		= 16,
345	.xres		= 320,		.yres		= 240,
346
347	.hsync_len	= 2,		.vsync_len	= 3,
348	.left_margin	= 69,		.upper_margin	= 14,
349	.right_margin	= 8,		.lower_margin	= 4,
350
351	.lccr0		= LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
352	.lccr3		= LCCR3_OutEnH | LCCR3_PixFlEdg | LCCR3_ACBsDiv(512),
353};
354#endif
355#ifdef LART_VIDEO_OUT
356static struct sa1100fb_mach_info lart_video_info __initdata = {
357	.pixclock	= 39721,	.bpp		= 16,
358	.xres		= 640,		.yres		= 480,
359
360	.hsync_len	= 95,		.vsync_len	= 2,
361	.left_margin	= 40,		.upper_margin	= 32,
362	.right_margin	= 24,		.lower_margin	= 11,
363
364	.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
365
366	.lccr0		= LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
367	.lccr3		= LCCR3_OutEnL | LCCR3_PixFlEdg | LCCR3_ACBsDiv(512),
368};
369#endif
370
371#ifdef LART_KIT01_LCD
372static struct sa1100fb_mach_info lart_kit01_info __initdata = {
373	.pixclock	= 63291,	.bpp		= 16,
374	.xres		= 640,		.yres		= 480,
375
376	.hsync_len	= 64,		.vsync_len	= 3,
377	.left_margin	= 122,		.upper_margin	= 45,
378	.right_margin	= 10,		.lower_margin	= 10,
379
380	.lccr0		= LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
381	.lccr3		= LCCR3_OutEnH | LCCR3_PixFlEdg
382};
383#endif
384
385#ifdef CONFIG_SA1100_SHANNON
386static struct sa1100fb_mach_info shannon_info __initdata = {
387	.pixclock	= 152500,	.bpp		= 8,
388	.xres		= 640,		.yres		= 480,
389
390	.hsync_len	= 4,		.vsync_len	= 3,
391	.left_margin	= 2,		.upper_margin	= 0,
392	.right_margin	= 1,		.lower_margin	= 0,
393
394	.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
395
396	.lccr0		= LCCR0_Color | LCCR0_Dual | LCCR0_Pas,
397	.lccr3		= LCCR3_ACBsDiv(512),
398};
399#endif
400
401
402
403static struct sa1100fb_mach_info * __init
404sa1100fb_get_machine_info(struct sa1100fb_info *fbi)
405{
406	struct sa1100fb_mach_info *inf = NULL;
407
408	/*
409	 *            R        G       B       T
410	 * default  {11,5}, { 5,6}, { 0,5}, { 0,0}
411	 * h3600    {12,4}, { 7,4}, { 1,4}, { 0,0}
412	 * freebird { 8,4}, { 4,4}, { 0,4}, {12,4}
413	 */
414#ifdef CONFIG_SA1100_ASSABET
415	if (machine_is_assabet()) {
416#ifndef ASSABET_PAL_VIDEO
417		inf = &lq039q2ds54_info;
418#else
419		inf = &pal_info;
420#endif
421	}
422#endif
423#ifdef CONFIG_SA1100_H3100
424	if (machine_is_h3100()) {
425		inf = &h3100_info;
426	}
427#endif
428#ifdef CONFIG_SA1100_H3600
429	if (machine_is_h3600()) {
430		inf = &h3600_info;
431		fbi->rgb[RGB_16] = &h3600_rgb_16;
432	}
433#endif
434#ifdef CONFIG_SA1100_H3800
435	if (machine_is_h3800()) {
436		inf = &h3800_info;
437	}
438#endif
439#ifdef CONFIG_SA1100_COLLIE
440	if (machine_is_collie()) {
441		inf = &collie_info;
442	}
443#endif
444#ifdef CONFIG_SA1100_LART
445	if (machine_is_lart()) {
446#ifdef LART_GREY_LCD
447		inf = &lart_grey_info;
448#endif
449#ifdef LART_COLOR_LCD
450		inf = &lart_color_info;
451#endif
452#ifdef LART_VIDEO_OUT
453		inf = &lart_video_info;
454#endif
455#ifdef LART_KIT01_LCD
456		inf = &lart_kit01_info;
457#endif
458	}
459#endif
460#ifdef CONFIG_SA1100_SHANNON
461	if (machine_is_shannon()) {
462		inf = &shannon_info;
463	}
464#endif
465	return inf;
466}
467
468static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_info *);
469static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state);
470
471static inline void sa1100fb_schedule_work(struct sa1100fb_info *fbi, u_int state)
472{
473	unsigned long flags;
474
475	local_irq_save(flags);
476	/*
477	 * We need to handle two requests being made at the same time.
478	 * There are two important cases:
479	 *  1. When we are changing VT (C_REENABLE) while unblanking (C_ENABLE)
480	 *     We must perform the unblanking, which will do our REENABLE for us.
481	 *  2. When we are blanking, but immediately unblank before we have
482	 *     blanked.  We do the "REENABLE" thing here as well, just to be sure.
483	 */
484	if (fbi->task_state == C_ENABLE && state == C_REENABLE)
485		state = (u_int) -1;
486	if (fbi->task_state == C_DISABLE && state == C_ENABLE)
487		state = C_REENABLE;
488
489	if (state != (u_int)-1) {
490		fbi->task_state = state;
491		schedule_work(&fbi->task);
492	}
493	local_irq_restore(flags);
494}
495
496static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
497{
498	chan &= 0xffff;
499	chan >>= 16 - bf->length;
500	return chan << bf->offset;
501}
502
503/*
504 * Convert bits-per-pixel to a hardware palette PBS value.
505 */
506static inline u_int palette_pbs(struct fb_var_screeninfo *var)
507{
508	int ret = 0;
509	switch (var->bits_per_pixel) {
510	case 4:  ret = 0 << 12;	break;
511	case 8:  ret = 1 << 12; break;
512	case 16: ret = 2 << 12; break;
513	}
514	return ret;
515}
516
517static int
518sa1100fb_setpalettereg(u_int regno, u_int red, u_int green, u_int blue,
519		       u_int trans, struct fb_info *info)
520{
521	struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
522	u_int val, ret = 1;
523
524	if (regno < fbi->palette_size) {
525		val = ((red >> 4) & 0xf00);
526		val |= ((green >> 8) & 0x0f0);
527		val |= ((blue >> 12) & 0x00f);
528
529		if (regno == 0)
530			val |= palette_pbs(&fbi->fb.var);
531
532		fbi->palette_cpu[regno] = val;
533		ret = 0;
534	}
535	return ret;
536}
537
538static int
539sa1100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
540		   u_int trans, struct fb_info *info)
541{
542	struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
543	unsigned int val;
544	int ret = 1;
545
546	/*
547	 * If inverse mode was selected, invert all the colours
548	 * rather than the register number.  The register number
549	 * is what you poke into the framebuffer to produce the
550	 * colour you requested.
551	 */
552	if (fbi->cmap_inverse) {
553		red   = 0xffff - red;
554		green = 0xffff - green;
555		blue  = 0xffff - blue;
556	}
557
558	/*
559	 * If greyscale is true, then we convert the RGB value
560	 * to greyscale no mater what visual we are using.
561	 */
562	if (fbi->fb.var.grayscale)
563		red = green = blue = (19595 * red + 38470 * green +
564					7471 * blue) >> 16;
565
566	switch (fbi->fb.fix.visual) {
567	case FB_VISUAL_TRUECOLOR:
568		/*
569		 * 12 or 16-bit True Colour.  We encode the RGB value
570		 * according to the RGB bitfield information.
571		 */
572		if (regno < 16) {
573			u32 *pal = fbi->fb.pseudo_palette;
574
575			val  = chan_to_field(red, &fbi->fb.var.red);
576			val |= chan_to_field(green, &fbi->fb.var.green);
577			val |= chan_to_field(blue, &fbi->fb.var.blue);
578
579			pal[regno] = val;
580			ret = 0;
581		}
582		break;
583
584	case FB_VISUAL_STATIC_PSEUDOCOLOR:
585	case FB_VISUAL_PSEUDOCOLOR:
586		ret = sa1100fb_setpalettereg(regno, red, green, blue, trans, info);
587		break;
588	}
589
590	return ret;
591}
592
593#ifdef CONFIG_CPU_FREQ
594/*
595 *  sa1100fb_display_dma_period()
596 *    Calculate the minimum period (in picoseconds) between two DMA
597 *    requests for the LCD controller.  If we hit this, it means we're
598 *    doing nothing but LCD DMA.
599 */
600static inline unsigned int sa1100fb_display_dma_period(struct fb_var_screeninfo *var)
601{
602	/*
603	 * Period = pixclock * bits_per_byte * bytes_per_transfer
604	 *		/ memory_bits_per_pixel;
605	 */
606	return var->pixclock * 8 * 16 / var->bits_per_pixel;
607}
608#endif
609
610/*
611 *  sa1100fb_check_var():
612 *    Round up in the following order: bits_per_pixel, xres,
613 *    yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale,
614 *    bitfields, horizontal timing, vertical timing.
615 */
616static int
617sa1100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
618{
619	struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
620	int rgbidx;
621
622	if (var->xres < MIN_XRES)
623		var->xres = MIN_XRES;
624	if (var->yres < MIN_YRES)
625		var->yres = MIN_YRES;
626	if (var->xres > fbi->max_xres)
627		var->xres = fbi->max_xres;
628	if (var->yres > fbi->max_yres)
629		var->yres = fbi->max_yres;
630	var->xres_virtual = max(var->xres_virtual, var->xres);
631	var->yres_virtual = max(var->yres_virtual, var->yres);
632
633	DPRINTK("var->bits_per_pixel=%d\n", var->bits_per_pixel);
634	switch (var->bits_per_pixel) {
635	case 4:
636		rgbidx = RGB_8;
637		break;
638	case 8:
639		rgbidx = RGB_8;
640		break;
641	case 16:
642		rgbidx = RGB_16;
643		break;
644	default:
645		return -EINVAL;
646	}
647
648	/*
649	 * Copy the RGB parameters for this display
650	 * from the machine specific parameters.
651	 */
652	var->red    = fbi->rgb[rgbidx]->red;
653	var->green  = fbi->rgb[rgbidx]->green;
654	var->blue   = fbi->rgb[rgbidx]->blue;
655	var->transp = fbi->rgb[rgbidx]->transp;
656
657	DPRINTK("RGBT length = %d:%d:%d:%d\n",
658		var->red.length, var->green.length, var->blue.length,
659		var->transp.length);
660
661	DPRINTK("RGBT offset = %d:%d:%d:%d\n",
662		var->red.offset, var->green.offset, var->blue.offset,
663		var->transp.offset);
664
665#ifdef CONFIG_CPU_FREQ
666	printk(KERN_DEBUG "dma period = %d ps, clock = %d kHz\n",
667		sa1100fb_display_dma_period(var),
668		cpufreq_get(smp_processor_id()));
669#endif
670
671	return 0;
672}
673
674static inline void sa1100fb_set_truecolor(u_int is_true_color)
675{
676	if (machine_is_assabet()) {
677		if (is_true_color)
678			ASSABET_BCR_set(ASSABET_BCR_LCD_12RGB);
679		else
680			ASSABET_BCR_clear(ASSABET_BCR_LCD_12RGB);
681	}
682}
683
684/*
685 * sa1100fb_set_par():
686 *	Set the user defined part of the display for the specified console
687 */
688static int sa1100fb_set_par(struct fb_info *info)
689{
690	struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
691	struct fb_var_screeninfo *var = &info->var;
692	unsigned long palette_mem_size;
693
694	DPRINTK("set_par\n");
695
696	if (var->bits_per_pixel == 16)
697		fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR;
698	else if (!fbi->cmap_static)
699		fbi->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
700	else {
701		/*
702		 * Some people have weird ideas about wanting static
703		 * pseudocolor maps.  I suspect their user space
704		 * applications are broken.
705		 */
706		fbi->fb.fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
707	}
708
709	fbi->fb.fix.line_length = var->xres_virtual *
710				  var->bits_per_pixel / 8;
711	fbi->palette_size = var->bits_per_pixel == 8 ? 256 : 16;
712
713	palette_mem_size = fbi->palette_size * sizeof(u16);
714
715	DPRINTK("palette_mem_size = 0x%08lx\n", (u_long) palette_mem_size);
716
717	fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size);
718	fbi->palette_dma = fbi->map_dma + PAGE_SIZE - palette_mem_size;
719
720	/*
721	 * Set (any) board control register to handle new color depth
722	 */
723	sa1100fb_set_truecolor(fbi->fb.fix.visual == FB_VISUAL_TRUECOLOR);
724	sa1100fb_activate_var(var, fbi);
725
726	return 0;
727}
728
729
730/*
731 * Formal definition of the VESA spec:
732 *  On
733 *  	This refers to the state of the display when it is in full operation
734 *  Stand-By
735 *  	This defines an optional operating state of minimal power reduction with
736 *  	the shortest recovery time
737 *  Suspend
738 *  	This refers to a level of power management in which substantial power
739 *  	reduction is achieved by the display.  The display can have a longer
740 *  	recovery time from this state than from the Stand-by state
741 *  Off
742 *  	This indicates that the display is consuming the lowest level of power
743 *  	and is non-operational. Recovery from this state may optionally require
744 *  	the user to manually power on the monitor
745 *
746 *  Now, the fbdev driver adds an additional state, (blank), where they
747 *  turn off the video (maybe by colormap tricks), but don't mess with the
748 *  video itself: think of it semantically between on and Stand-By.
749 *
750 *  So here's what we should do in our fbdev blank routine:
751 *
752 *  	VESA_NO_BLANKING (mode 0)	Video on,  front/back light on
753 *  	VESA_VSYNC_SUSPEND (mode 1)  	Video on,  front/back light off
754 *  	VESA_HSYNC_SUSPEND (mode 2)  	Video on,  front/back light off
755 *  	VESA_POWERDOWN (mode 3)		Video off, front/back light off
756 *
757 *  This will match the matrox implementation.
758 */
759/*
760 * sa1100fb_blank():
761 *	Blank the display by setting all palette values to zero.  Note, the
762 * 	12 and 16 bpp modes don't really use the palette, so this will not
763 *      blank the display in all modes.
764 */
765static int sa1100fb_blank(int blank, struct fb_info *info)
766{
767	struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
768	int i;
769
770	DPRINTK("sa1100fb_blank: blank=%d\n", blank);
771
772	switch (blank) {
773	case FB_BLANK_POWERDOWN:
774	case FB_BLANK_VSYNC_SUSPEND:
775	case FB_BLANK_HSYNC_SUSPEND:
776	case FB_BLANK_NORMAL:
777		if (fbi->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR ||
778		    fbi->fb.fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
779			for (i = 0; i < fbi->palette_size; i++)
780				sa1100fb_setpalettereg(i, 0, 0, 0, 0, info);
781		sa1100fb_schedule_work(fbi, C_DISABLE);
782		break;
783
784	case FB_BLANK_UNBLANK:
785		if (fbi->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR ||
786		    fbi->fb.fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
787			fb_set_cmap(&fbi->fb.cmap, info);
788		sa1100fb_schedule_work(fbi, C_ENABLE);
789	}
790	return 0;
791}
792
793static int sa1100fb_mmap(struct fb_info *info,
794			 struct vm_area_struct *vma)
795{
796	struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
797	unsigned long start, len, off = vma->vm_pgoff << PAGE_SHIFT;
798
799	if (off < info->fix.smem_len) {
800		vma->vm_pgoff += 1; /* skip over the palette */
801		return dma_mmap_writecombine(fbi->dev, vma, fbi->map_cpu,
802					     fbi->map_dma, fbi->map_size);
803	}
804
805	start = info->fix.mmio_start;
806	len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len);
807
808	if ((vma->vm_end - vma->vm_start + off) > len)
809		return -EINVAL;
810
811	off += start & PAGE_MASK;
812	vma->vm_pgoff = off >> PAGE_SHIFT;
813	vma->vm_flags |= VM_IO;
814	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
815	return io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
816				   vma->vm_end - vma->vm_start,
817				   vma->vm_page_prot);
818}
819
820static struct fb_ops sa1100fb_ops = {
821	.owner		= THIS_MODULE,
822	.fb_check_var	= sa1100fb_check_var,
823	.fb_set_par	= sa1100fb_set_par,
824//	.fb_set_cmap	= sa1100fb_set_cmap,
825	.fb_setcolreg	= sa1100fb_setcolreg,
826	.fb_fillrect	= cfb_fillrect,
827	.fb_copyarea	= cfb_copyarea,
828	.fb_imageblit	= cfb_imageblit,
829	.fb_blank	= sa1100fb_blank,
830	.fb_mmap	= sa1100fb_mmap,
831};
832
833/*
834 * Calculate the PCD value from the clock rate (in picoseconds).
835 * We take account of the PPCR clock setting.
836 */
837static inline unsigned int get_pcd(unsigned int pixclock, unsigned int cpuclock)
838{
839	unsigned int pcd = cpuclock / 100;
840
841	pcd *= pixclock;
842	pcd /= 10000000;
843
844	return pcd + 1;	/* make up for integer math truncations */
845}
846
847/*
848 * sa1100fb_activate_var():
849 *	Configures LCD Controller based on entries in var parameter.  Settings are
850 *	only written to the controller if changes were made.
851 */
852static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_info *fbi)
853{
854	struct sa1100fb_lcd_reg new_regs;
855	u_int half_screen_size, yres, pcd;
856	u_long flags;
857
858	DPRINTK("Configuring SA1100 LCD\n");
859
860	DPRINTK("var: xres=%d hslen=%d lm=%d rm=%d\n",
861		var->xres, var->hsync_len,
862		var->left_margin, var->right_margin);
863	DPRINTK("var: yres=%d vslen=%d um=%d bm=%d\n",
864		var->yres, var->vsync_len,
865		var->upper_margin, var->lower_margin);
866
867#if DEBUG_VAR
868	if (var->xres < 16        || var->xres > 1024)
869		printk(KERN_ERR "%s: invalid xres %d\n",
870			fbi->fb.fix.id, var->xres);
871	if (var->hsync_len < 1    || var->hsync_len > 64)
872		printk(KERN_ERR "%s: invalid hsync_len %d\n",
873			fbi->fb.fix.id, var->hsync_len);
874	if (var->left_margin < 1  || var->left_margin > 255)
875		printk(KERN_ERR "%s: invalid left_margin %d\n",
876			fbi->fb.fix.id, var->left_margin);
877	if (var->right_margin < 1 || var->right_margin > 255)
878		printk(KERN_ERR "%s: invalid right_margin %d\n",
879			fbi->fb.fix.id, var->right_margin);
880	if (var->yres < 1         || var->yres > 1024)
881		printk(KERN_ERR "%s: invalid yres %d\n",
882			fbi->fb.fix.id, var->yres);
883	if (var->vsync_len < 1    || var->vsync_len > 64)
884		printk(KERN_ERR "%s: invalid vsync_len %d\n",
885			fbi->fb.fix.id, var->vsync_len);
886	if (var->upper_margin < 0 || var->upper_margin > 255)
887		printk(KERN_ERR "%s: invalid upper_margin %d\n",
888			fbi->fb.fix.id, var->upper_margin);
889	if (var->lower_margin < 0 || var->lower_margin > 255)
890		printk(KERN_ERR "%s: invalid lower_margin %d\n",
891			fbi->fb.fix.id, var->lower_margin);
892#endif
893
894	new_regs.lccr0 = fbi->lccr0 |
895		LCCR0_LEN | LCCR0_LDM | LCCR0_BAM |
896		LCCR0_ERM | LCCR0_LtlEnd | LCCR0_DMADel(0);
897
898	new_regs.lccr1 =
899		LCCR1_DisWdth(var->xres) +
900		LCCR1_HorSnchWdth(var->hsync_len) +
901		LCCR1_BegLnDel(var->left_margin) +
902		LCCR1_EndLnDel(var->right_margin);
903
904	/*
905	 * If we have a dual scan LCD, then we need to halve
906	 * the YRES parameter.
907	 */
908	yres = var->yres;
909	if (fbi->lccr0 & LCCR0_Dual)
910		yres /= 2;
911
912	new_regs.lccr2 =
913		LCCR2_DisHght(yres) +
914		LCCR2_VrtSnchWdth(var->vsync_len) +
915		LCCR2_BegFrmDel(var->upper_margin) +
916		LCCR2_EndFrmDel(var->lower_margin);
917
918	pcd = get_pcd(var->pixclock, cpufreq_get(0));
919	new_regs.lccr3 = LCCR3_PixClkDiv(pcd) | fbi->lccr3 |
920		(var->sync & FB_SYNC_HOR_HIGH_ACT ? LCCR3_HorSnchH : LCCR3_HorSnchL) |
921		(var->sync & FB_SYNC_VERT_HIGH_ACT ? LCCR3_VrtSnchH : LCCR3_VrtSnchL);
922
923	DPRINTK("nlccr0 = 0x%08lx\n", new_regs.lccr0);
924	DPRINTK("nlccr1 = 0x%08lx\n", new_regs.lccr1);
925	DPRINTK("nlccr2 = 0x%08lx\n", new_regs.lccr2);
926	DPRINTK("nlccr3 = 0x%08lx\n", new_regs.lccr3);
927
928	half_screen_size = var->bits_per_pixel;
929	half_screen_size = half_screen_size * var->xres * var->yres / 16;
930
931	/* Update shadow copy atomically */
932	local_irq_save(flags);
933	fbi->dbar1 = fbi->palette_dma;
934	fbi->dbar2 = fbi->screen_dma + half_screen_size;
935
936	fbi->reg_lccr0 = new_regs.lccr0;
937	fbi->reg_lccr1 = new_regs.lccr1;
938	fbi->reg_lccr2 = new_regs.lccr2;
939	fbi->reg_lccr3 = new_regs.lccr3;
940	local_irq_restore(flags);
941
942	/*
943	 * Only update the registers if the controller is enabled
944	 * and something has changed.
945	 */
946	if ((LCCR0 != fbi->reg_lccr0)       || (LCCR1 != fbi->reg_lccr1) ||
947	    (LCCR2 != fbi->reg_lccr2)       || (LCCR3 != fbi->reg_lccr3) ||
948	    (DBAR1 != fbi->dbar1) || (DBAR2 != fbi->dbar2))
949		sa1100fb_schedule_work(fbi, C_REENABLE);
950
951	return 0;
952}
953
954/*
955 * NOTE!  The following functions are purely helpers for set_ctrlr_state.
956 * Do not call them directly; set_ctrlr_state does the correct serialisation
957 * to ensure that things happen in the right way 100% of time time.
958 *	-- rmk
959 */
960static inline void __sa1100fb_backlight_power(struct sa1100fb_info *fbi, int on)
961{
962	DPRINTK("backlight o%s\n", on ? "n" : "ff");
963
964	if (sa1100fb_backlight_power)
965		sa1100fb_backlight_power(on);
966}
967
968static inline void __sa1100fb_lcd_power(struct sa1100fb_info *fbi, int on)
969{
970	DPRINTK("LCD power o%s\n", on ? "n" : "ff");
971
972	if (sa1100fb_lcd_power)
973		sa1100fb_lcd_power(on);
974}
975
976static void sa1100fb_setup_gpio(struct sa1100fb_info *fbi)
977{
978	u_int mask = 0;
979
980	/*
981	 * Enable GPIO<9:2> for LCD use if:
982	 *  1. Active display, or
983	 *  2. Color Dual Passive display
984	 *
985	 * see table 11.8 on page 11-27 in the SA1100 manual
986	 *   -- Erik.
987	 *
988	 * SA1110 spec update nr. 25 says we can and should
989	 * clear LDD15 to 12 for 4 or 8bpp modes with active
990	 * panels.
991	 */
992	if ((fbi->reg_lccr0 & LCCR0_CMS) == LCCR0_Color &&
993	    (fbi->reg_lccr0 & (LCCR0_Dual|LCCR0_Act)) != 0) {
994		mask = GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9  | GPIO_LDD8;
995
996		if (fbi->fb.var.bits_per_pixel > 8 ||
997		    (fbi->reg_lccr0 & (LCCR0_Dual|LCCR0_Act)) == LCCR0_Dual)
998			mask |= GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12;
999
1000	}
1001
1002	if (mask) {
1003		GPDR |= mask;
1004		GAFR |= mask;
1005	}
1006}
1007
1008static void sa1100fb_enable_controller(struct sa1100fb_info *fbi)
1009{
1010	DPRINTK("Enabling LCD controller\n");
1011
1012	/*
1013	 * Make sure the mode bits are present in the first palette entry
1014	 */
1015	fbi->palette_cpu[0] &= 0xcfff;
1016	fbi->palette_cpu[0] |= palette_pbs(&fbi->fb.var);
1017
1018	/* Sequence from 11.7.10 */
1019	LCCR3 = fbi->reg_lccr3;
1020	LCCR2 = fbi->reg_lccr2;
1021	LCCR1 = fbi->reg_lccr1;
1022	LCCR0 = fbi->reg_lccr0 & ~LCCR0_LEN;
1023	DBAR1 = fbi->dbar1;
1024	DBAR2 = fbi->dbar2;
1025	LCCR0 |= LCCR0_LEN;
1026
1027	if (machine_is_shannon()) {
1028		GPDR |= SHANNON_GPIO_DISP_EN;
1029		GPSR |= SHANNON_GPIO_DISP_EN;
1030	}
1031
1032	DPRINTK("DBAR1 = 0x%08x\n", DBAR1);
1033	DPRINTK("DBAR2 = 0x%08x\n", DBAR2);
1034	DPRINTK("LCCR0 = 0x%08x\n", LCCR0);
1035	DPRINTK("LCCR1 = 0x%08x\n", LCCR1);
1036	DPRINTK("LCCR2 = 0x%08x\n", LCCR2);
1037	DPRINTK("LCCR3 = 0x%08x\n", LCCR3);
1038}
1039
1040static void sa1100fb_disable_controller(struct sa1100fb_info *fbi)
1041{
1042	DECLARE_WAITQUEUE(wait, current);
1043
1044	DPRINTK("Disabling LCD controller\n");
1045
1046	if (machine_is_shannon()) {
1047		GPCR |= SHANNON_GPIO_DISP_EN;
1048	}
1049
1050	set_current_state(TASK_UNINTERRUPTIBLE);
1051	add_wait_queue(&fbi->ctrlr_wait, &wait);
1052
1053	LCSR = 0xffffffff;	/* Clear LCD Status Register */
1054	LCCR0 &= ~LCCR0_LDM;	/* Enable LCD Disable Done Interrupt */
1055	LCCR0 &= ~LCCR0_LEN;	/* Disable LCD Controller */
1056
1057	schedule_timeout(20 * HZ / 1000);
1058	remove_wait_queue(&fbi->ctrlr_wait, &wait);
1059}
1060
1061/*
1062 *  sa1100fb_handle_irq: Handle 'LCD DONE' interrupts.
1063 */
1064static irqreturn_t sa1100fb_handle_irq(int irq, void *dev_id)
1065{
1066	struct sa1100fb_info *fbi = dev_id;
1067	unsigned int lcsr = LCSR;
1068
1069	if (lcsr & LCSR_LDD) {
1070		LCCR0 |= LCCR0_LDM;
1071		wake_up(&fbi->ctrlr_wait);
1072	}
1073
1074	LCSR = lcsr;
1075	return IRQ_HANDLED;
1076}
1077
1078/*
1079 * This function must be called from task context only, since it will
1080 * sleep when disabling the LCD controller, or if we get two contending
1081 * processes trying to alter state.
1082 */
1083static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state)
1084{
1085	u_int old_state;
1086
1087	down(&fbi->ctrlr_sem);
1088
1089	old_state = fbi->state;
1090
1091	/*
1092	 * Hack around fbcon initialisation.
1093	 */
1094	if (old_state == C_STARTUP && state == C_REENABLE)
1095		state = C_ENABLE;
1096
1097	switch (state) {
1098	case C_DISABLE_CLKCHANGE:
1099		/*
1100		 * Disable controller for clock change.  If the
1101		 * controller is already disabled, then do nothing.
1102		 */
1103		if (old_state != C_DISABLE && old_state != C_DISABLE_PM) {
1104			fbi->state = state;
1105			sa1100fb_disable_controller(fbi);
1106		}
1107		break;
1108
1109	case C_DISABLE_PM:
1110	case C_DISABLE:
1111		/*
1112		 * Disable controller
1113		 */
1114		if (old_state != C_DISABLE) {
1115			fbi->state = state;
1116
1117			__sa1100fb_backlight_power(fbi, 0);
1118			if (old_state != C_DISABLE_CLKCHANGE)
1119				sa1100fb_disable_controller(fbi);
1120			__sa1100fb_lcd_power(fbi, 0);
1121		}
1122		break;
1123
1124	case C_ENABLE_CLKCHANGE:
1125		/*
1126		 * Enable the controller after clock change.  Only
1127		 * do this if we were disabled for the clock change.
1128		 */
1129		if (old_state == C_DISABLE_CLKCHANGE) {
1130			fbi->state = C_ENABLE;
1131			sa1100fb_enable_controller(fbi);
1132		}
1133		break;
1134
1135	case C_REENABLE:
1136		/*
1137		 * Re-enable the controller only if it was already
1138		 * enabled.  This is so we reprogram the control
1139		 * registers.
1140		 */
1141		if (old_state == C_ENABLE) {
1142			sa1100fb_disable_controller(fbi);
1143			sa1100fb_setup_gpio(fbi);
1144			sa1100fb_enable_controller(fbi);
1145		}
1146		break;
1147
1148	case C_ENABLE_PM:
1149		/*
1150		 * Re-enable the controller after PM.  This is not
1151		 * perfect - think about the case where we were doing
1152		 * a clock change, and we suspended half-way through.
1153		 */
1154		if (old_state != C_DISABLE_PM)
1155			break;
1156		/* fall through */
1157
1158	case C_ENABLE:
1159		/*
1160		 * Power up the LCD screen, enable controller, and
1161		 * turn on the backlight.
1162		 */
1163		if (old_state != C_ENABLE) {
1164			fbi->state = C_ENABLE;
1165			sa1100fb_setup_gpio(fbi);
1166			__sa1100fb_lcd_power(fbi, 1);
1167			sa1100fb_enable_controller(fbi);
1168			__sa1100fb_backlight_power(fbi, 1);
1169		}
1170		break;
1171	}
1172	up(&fbi->ctrlr_sem);
1173}
1174
1175/*
1176 * Our LCD controller task (which is called when we blank or unblank)
1177 * via keventd.
1178 */
1179static void sa1100fb_task(struct work_struct *w)
1180{
1181	struct sa1100fb_info *fbi = container_of(w, struct sa1100fb_info, task);
1182	u_int state = xchg(&fbi->task_state, -1);
1183
1184	set_ctrlr_state(fbi, state);
1185}
1186
1187#ifdef CONFIG_CPU_FREQ
1188/*
1189 * Calculate the minimum DMA period over all displays that we own.
1190 * This, together with the SDRAM bandwidth defines the slowest CPU
1191 * frequency that can be selected.
1192 */
1193static unsigned int sa1100fb_min_dma_period(struct sa1100fb_info *fbi)
1194{
1195	return sa1100fb_display_dma_period(&fbi->fb.var);
1196}
1197
1198/*
1199 * CPU clock speed change handler.  We need to adjust the LCD timing
1200 * parameters when the CPU clock is adjusted by the power management
1201 * subsystem.
1202 */
1203static int
1204sa1100fb_freq_transition(struct notifier_block *nb, unsigned long val,
1205			 void *data)
1206{
1207	struct sa1100fb_info *fbi = TO_INF(nb, freq_transition);
1208	struct cpufreq_freqs *f = data;
1209	u_int pcd;
1210
1211	switch (val) {
1212	case CPUFREQ_PRECHANGE:
1213		set_ctrlr_state(fbi, C_DISABLE_CLKCHANGE);
1214		break;
1215
1216	case CPUFREQ_POSTCHANGE:
1217		pcd = get_pcd(fbi->fb.var.pixclock, f->new);
1218		fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd);
1219		set_ctrlr_state(fbi, C_ENABLE_CLKCHANGE);
1220		break;
1221	}
1222	return 0;
1223}
1224
1225static int
1226sa1100fb_freq_policy(struct notifier_block *nb, unsigned long val,
1227		     void *data)
1228{
1229	struct sa1100fb_info *fbi = TO_INF(nb, freq_policy);
1230	struct cpufreq_policy *policy = data;
1231
1232	switch (val) {
1233	case CPUFREQ_ADJUST:
1234	case CPUFREQ_INCOMPATIBLE:
1235		printk(KERN_DEBUG "min dma period: %d ps, "
1236			"new clock %d kHz\n", sa1100fb_min_dma_period(fbi),
1237			policy->max);
1238		/* todo: fill in min/max values */
1239		break;
1240	case CPUFREQ_NOTIFY:
1241		do {} while(0);
1242		/* todo: panic if min/max values aren't fulfilled
1243		 * [can't really happen unless there's a bug in the
1244		 * CPU policy verififcation process *
1245		 */
1246		break;
1247	}
1248	return 0;
1249}
1250#endif
1251
1252#ifdef CONFIG_PM
1253/*
1254 * Power management hooks.  Note that we won't be called from IRQ context,
1255 * unlike the blank functions above, so we may sleep.
1256 */
1257static int sa1100fb_suspend(struct platform_device *dev, pm_message_t state)
1258{
1259	struct sa1100fb_info *fbi = platform_get_drvdata(dev);
1260
1261	set_ctrlr_state(fbi, C_DISABLE_PM);
1262	return 0;
1263}
1264
1265static int sa1100fb_resume(struct platform_device *dev)
1266{
1267	struct sa1100fb_info *fbi = platform_get_drvdata(dev);
1268
1269	set_ctrlr_state(fbi, C_ENABLE_PM);
1270	return 0;
1271}
1272#else
1273#define sa1100fb_suspend	NULL
1274#define sa1100fb_resume		NULL
1275#endif
1276
1277/*
1278 * sa1100fb_map_video_memory():
1279 *      Allocates the DRAM memory for the frame buffer.  This buffer is
1280 *	remapped into a non-cached, non-buffered, memory region to
1281 *      allow palette and pixel writes to occur without flushing the
1282 *      cache.  Once this area is remapped, all virtual memory
1283 *      access to the video memory should occur at the new region.
1284 */
1285static int __init sa1100fb_map_video_memory(struct sa1100fb_info *fbi)
1286{
1287	/*
1288	 * We reserve one page for the palette, plus the size
1289	 * of the framebuffer.
1290	 */
1291	fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + PAGE_SIZE);
1292	fbi->map_cpu = dma_alloc_writecombine(fbi->dev, fbi->map_size,
1293					      &fbi->map_dma, GFP_KERNEL);
1294
1295	if (fbi->map_cpu) {
1296		fbi->fb.screen_base = fbi->map_cpu + PAGE_SIZE;
1297		fbi->screen_dma = fbi->map_dma + PAGE_SIZE;
1298		fbi->fb.fix.smem_start = fbi->screen_dma;
1299	}
1300
1301	return fbi->map_cpu ? 0 : -ENOMEM;
1302}
1303
1304/* Fake monspecs to fill in fbinfo structure */
1305static struct fb_monspecs monspecs __initdata = {
1306	.hfmin	= 30000,
1307	.hfmax	= 70000,
1308	.vfmin	= 50,
1309	.vfmax	= 65,
1310};
1311
1312
1313static struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev)
1314{
1315	struct sa1100fb_mach_info *inf;
1316	struct sa1100fb_info *fbi;
1317
1318	fbi = kmalloc(sizeof(struct sa1100fb_info) + sizeof(u32) * 16,
1319		      GFP_KERNEL);
1320	if (!fbi)
1321		return NULL;
1322
1323	memset(fbi, 0, sizeof(struct sa1100fb_info));
1324	fbi->dev = dev;
1325
1326	strcpy(fbi->fb.fix.id, SA1100_NAME);
1327
1328	fbi->fb.fix.type	= FB_TYPE_PACKED_PIXELS;
1329	fbi->fb.fix.type_aux	= 0;
1330	fbi->fb.fix.xpanstep	= 0;
1331	fbi->fb.fix.ypanstep	= 0;
1332	fbi->fb.fix.ywrapstep	= 0;
1333	fbi->fb.fix.accel	= FB_ACCEL_NONE;
1334
1335	fbi->fb.var.nonstd	= 0;
1336	fbi->fb.var.activate	= FB_ACTIVATE_NOW;
1337	fbi->fb.var.height	= -1;
1338	fbi->fb.var.width	= -1;
1339	fbi->fb.var.accel_flags	= 0;
1340	fbi->fb.var.vmode	= FB_VMODE_NONINTERLACED;
1341
1342	fbi->fb.fbops		= &sa1100fb_ops;
1343	fbi->fb.flags		= FBINFO_DEFAULT;
1344	fbi->fb.monspecs	= monspecs;
1345	fbi->fb.pseudo_palette	= (fbi + 1);
1346
1347	fbi->rgb[RGB_8]		= &rgb_8;
1348	fbi->rgb[RGB_16]	= &def_rgb_16;
1349
1350	inf = sa1100fb_get_machine_info(fbi);
1351
1352	/*
1353	 * People just don't seem to get this.  We don't support
1354	 * anything but correct entries now, so panic if someone
1355	 * does something stupid.
1356	 */
1357	if (inf->lccr3 & (LCCR3_VrtSnchL|LCCR3_HorSnchL|0xff) ||
1358	    inf->pixclock == 0)
1359		panic("sa1100fb error: invalid LCCR3 fields set or zero "
1360			"pixclock.");
1361
1362	fbi->max_xres			= inf->xres;
1363	fbi->fb.var.xres		= inf->xres;
1364	fbi->fb.var.xres_virtual	= inf->xres;
1365	fbi->max_yres			= inf->yres;
1366	fbi->fb.var.yres		= inf->yres;
1367	fbi->fb.var.yres_virtual	= inf->yres;
1368	fbi->max_bpp			= inf->bpp;
1369	fbi->fb.var.bits_per_pixel	= inf->bpp;
1370	fbi->fb.var.pixclock		= inf->pixclock;
1371	fbi->fb.var.hsync_len		= inf->hsync_len;
1372	fbi->fb.var.left_margin		= inf->left_margin;
1373	fbi->fb.var.right_margin	= inf->right_margin;
1374	fbi->fb.var.vsync_len		= inf->vsync_len;
1375	fbi->fb.var.upper_margin	= inf->upper_margin;
1376	fbi->fb.var.lower_margin	= inf->lower_margin;
1377	fbi->fb.var.sync		= inf->sync;
1378	fbi->fb.var.grayscale		= inf->cmap_greyscale;
1379	fbi->cmap_inverse		= inf->cmap_inverse;
1380	fbi->cmap_static		= inf->cmap_static;
1381	fbi->lccr0			= inf->lccr0;
1382	fbi->lccr3			= inf->lccr3;
1383	fbi->state			= C_STARTUP;
1384	fbi->task_state			= (u_char)-1;
1385	fbi->fb.fix.smem_len		= fbi->max_xres * fbi->max_yres *
1386					  fbi->max_bpp / 8;
1387
1388	init_waitqueue_head(&fbi->ctrlr_wait);
1389	INIT_WORK(&fbi->task, sa1100fb_task);
1390	init_MUTEX(&fbi->ctrlr_sem);
1391
1392	return fbi;
1393}
1394
1395static int __init sa1100fb_probe(struct platform_device *pdev)
1396{
1397	struct sa1100fb_info *fbi;
1398	int ret, irq;
1399
1400	irq = platform_get_irq(pdev, 0);
1401	if (irq < 0)
1402		return -EINVAL;
1403
1404	if (!request_mem_region(0xb0100000, 0x10000, "LCD"))
1405		return -EBUSY;
1406
1407	fbi = sa1100fb_init_fbinfo(&pdev->dev);
1408	ret = -ENOMEM;
1409	if (!fbi)
1410		goto failed;
1411
1412	/* Initialize video memory */
1413	ret = sa1100fb_map_video_memory(fbi);
1414	if (ret)
1415		goto failed;
1416
1417	ret = request_irq(irq, sa1100fb_handle_irq, IRQF_DISABLED,
1418			  "LCD", fbi);
1419	if (ret) {
1420		printk(KERN_ERR "sa1100fb: request_irq failed: %d\n", ret);
1421		goto failed;
1422	}
1423
1424#ifdef ASSABET_PAL_VIDEO
1425	if (machine_is_assabet())
1426		ASSABET_BCR_clear(ASSABET_BCR_LCD_ON);
1427#endif
1428
1429	/*
1430	 * This makes sure that our colour bitfield
1431	 * descriptors are correctly initialised.
1432	 */
1433	sa1100fb_check_var(&fbi->fb.var, &fbi->fb);
1434
1435	platform_set_drvdata(pdev, fbi);
1436
1437	ret = register_framebuffer(&fbi->fb);
1438	if (ret < 0)
1439		goto err_free_irq;
1440
1441#ifdef CONFIG_CPU_FREQ
1442	fbi->freq_transition.notifier_call = sa1100fb_freq_transition;
1443	fbi->freq_policy.notifier_call = sa1100fb_freq_policy;
1444	cpufreq_register_notifier(&fbi->freq_transition, CPUFREQ_TRANSITION_NOTIFIER);
1445	cpufreq_register_notifier(&fbi->freq_policy, CPUFREQ_POLICY_NOTIFIER);
1446#endif
1447
1448	/* This driver cannot be unloaded at the moment */
1449	return 0;
1450
1451 err_free_irq:
1452	free_irq(irq, fbi);
1453 failed:
1454	platform_set_drvdata(pdev, NULL);
1455	kfree(fbi);
1456	release_mem_region(0xb0100000, 0x10000);
1457	return ret;
1458}
1459
1460static struct platform_driver sa1100fb_driver = {
1461	.probe		= sa1100fb_probe,
1462	.suspend	= sa1100fb_suspend,
1463	.resume		= sa1100fb_resume,
1464	.driver		= {
1465		.name	= "sa11x0-fb",
1466	},
1467};
1468
1469int __init sa1100fb_init(void)
1470{
1471	if (fb_get_options("sa1100fb", NULL))
1472		return -ENODEV;
1473
1474	return platform_driver_register(&sa1100fb_driver);
1475}
1476
1477int __init sa1100fb_setup(char *options)
1478{
1479	return 0;
1480}
1481
1482module_init(sa1100fb_init);
1483MODULE_DESCRIPTION("StrongARM-1100/1110 framebuffer driver");
1484MODULE_LICENSE("GPL");
1485