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