1/*
2 *  Driver for AT91/AT32 LCD Controller
3 *
4 *  Copyright (C) 2007 Atmel Corporation
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License.  See the file COPYING in the main directory of this archive for
8 * more details.
9 */
10
11#include <linux/kernel.h>
12#include <linux/platform_device.h>
13#include <linux/dma-mapping.h>
14#include <linux/interrupt.h>
15#include <linux/clk.h>
16#include <linux/fb.h>
17#include <linux/init.h>
18#include <linux/delay.h>
19
20#include <asm/arch/board.h>
21#include <asm/arch/cpu.h>
22#include <asm/arch/gpio.h>
23
24#include <video/atmel_lcdc.h>
25
26#define lcdc_readl(sinfo, reg)		__raw_readl((sinfo)->mmio+(reg))
27#define lcdc_writel(sinfo, reg, val)	__raw_writel((val), (sinfo)->mmio+(reg))
28
29/* configurable parameters */
30#define ATMEL_LCDC_CVAL_DEFAULT		0xc8
31#define ATMEL_LCDC_DMA_BURST_LEN	8
32
33#if defined(CONFIG_ARCH_AT91SAM9263)
34#define ATMEL_LCDC_FIFO_SIZE		2048
35#else
36#define ATMEL_LCDC_FIFO_SIZE		512
37#endif
38
39#if defined(CONFIG_ARCH_AT91)
40#define	ATMEL_LCDFB_FBINFO_DEFAULT	FBINFO_DEFAULT
41
42static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
43					struct fb_var_screeninfo *var)
44{
45
46}
47#elif defined(CONFIG_AVR32)
48#define	ATMEL_LCDFB_FBINFO_DEFAULT	(FBINFO_DEFAULT \
49					| FBINFO_PARTIAL_PAN_OK \
50					| FBINFO_HWACCEL_XPAN \
51					| FBINFO_HWACCEL_YPAN)
52
53static void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
54				     struct fb_var_screeninfo *var)
55{
56	u32 dma2dcfg;
57	u32 pixeloff;
58
59	pixeloff = (var->xoffset * var->bits_per_pixel) & 0x1f;
60
61	dma2dcfg = ((var->xres_virtual - var->xres) * var->bits_per_pixel) / 8;
62	dma2dcfg |= pixeloff << ATMEL_LCDC_PIXELOFF_OFFSET;
63	lcdc_writel(sinfo, ATMEL_LCDC_DMA2DCFG, dma2dcfg);
64
65	/* Update configuration */
66	lcdc_writel(sinfo, ATMEL_LCDC_DMACON,
67		    lcdc_readl(sinfo, ATMEL_LCDC_DMACON)
68		    | ATMEL_LCDC_DMAUPDT);
69}
70#endif
71
72
73static struct fb_fix_screeninfo atmel_lcdfb_fix __initdata = {
74	.type		= FB_TYPE_PACKED_PIXELS,
75	.visual		= FB_VISUAL_TRUECOLOR,
76	.xpanstep	= 0,
77	.ypanstep	= 0,
78	.ywrapstep	= 0,
79	.accel		= FB_ACCEL_NONE,
80};
81
82
83static void atmel_lcdfb_update_dma(struct fb_info *info,
84			       struct fb_var_screeninfo *var)
85{
86	struct atmel_lcdfb_info *sinfo = info->par;
87	struct fb_fix_screeninfo *fix = &info->fix;
88	unsigned long dma_addr;
89
90	dma_addr = (fix->smem_start + var->yoffset * fix->line_length
91		    + var->xoffset * var->bits_per_pixel / 8);
92
93	dma_addr &= ~3UL;
94
95	/* Set framebuffer DMA base address and pixel offset */
96	lcdc_writel(sinfo, ATMEL_LCDC_DMABADDR1, dma_addr);
97
98	atmel_lcdfb_update_dma2d(sinfo, var);
99}
100
101static inline void atmel_lcdfb_free_video_memory(struct atmel_lcdfb_info *sinfo)
102{
103	struct fb_info *info = sinfo->info;
104
105	dma_free_writecombine(info->device, info->fix.smem_len,
106				info->screen_base, info->fix.smem_start);
107}
108
109/**
110 *	atmel_lcdfb_alloc_video_memory - Allocate framebuffer memory
111 *	@sinfo: the frame buffer to allocate memory for
112 */
113static int atmel_lcdfb_alloc_video_memory(struct atmel_lcdfb_info *sinfo)
114{
115	struct fb_info *info = sinfo->info;
116	struct fb_var_screeninfo *var = &info->var;
117
118	info->fix.smem_len = (var->xres_virtual * var->yres_virtual
119			    * ((var->bits_per_pixel + 7) / 8));
120
121	info->screen_base = dma_alloc_writecombine(info->device, info->fix.smem_len,
122					(dma_addr_t *)&info->fix.smem_start, GFP_KERNEL);
123
124	if (!info->screen_base) {
125		return -ENOMEM;
126	}
127
128	return 0;
129}
130
131/**
132 *      atmel_lcdfb_check_var - Validates a var passed in.
133 *      @var: frame buffer variable screen structure
134 *      @info: frame buffer structure that represents a single frame buffer
135 *
136 *	Checks to see if the hardware supports the state requested by
137 *	var passed in. This function does not alter the hardware
138 *	state!!!  This means the data stored in struct fb_info and
139 *	struct atmel_lcdfb_info do not change. This includes the var
140 *	inside of struct fb_info.  Do NOT change these. This function
141 *	can be called on its own if we intent to only test a mode and
142 *	not actually set it. The stuff in modedb.c is a example of
143 *	this. If the var passed in is slightly off by what the
144 *	hardware can support then we alter the var PASSED in to what
145 *	we can do. If the hardware doesn't support mode change a
146 *	-EINVAL will be returned by the upper layers. You don't need
147 *	to implement this function then. If you hardware doesn't
148 *	support changing the resolution then this function is not
149 *	needed. In this case the driver would just provide a var that
150 *	represents the static state the screen is in.
151 *
152 *	Returns negative errno on error, or zero on success.
153 */
154static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
155			     struct fb_info *info)
156{
157	struct device *dev = info->device;
158	struct atmel_lcdfb_info *sinfo = info->par;
159	unsigned long clk_value_khz;
160
161	clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000;
162
163	dev_dbg(dev, "%s:\n", __func__);
164	dev_dbg(dev, "  resolution: %ux%u\n", var->xres, var->yres);
165	dev_dbg(dev, "  pixclk:     %lu KHz\n", PICOS2KHZ(var->pixclock));
166	dev_dbg(dev, "  bpp:        %u\n", var->bits_per_pixel);
167	dev_dbg(dev, "  clk:        %lu KHz\n", clk_value_khz);
168
169	if ((PICOS2KHZ(var->pixclock) * var->bits_per_pixel / 8) > clk_value_khz) {
170		dev_err(dev, "%lu KHz pixel clock is too fast\n", PICOS2KHZ(var->pixclock));
171		return -EINVAL;
172	}
173
174	/* Force same alignment for each line */
175	var->xres = (var->xres + 3) & ~3UL;
176	var->xres_virtual = (var->xres_virtual + 3) & ~3UL;
177
178	var->red.msb_right = var->green.msb_right = var->blue.msb_right = 0;
179	var->transp.msb_right = 0;
180	var->transp.offset = var->transp.length = 0;
181	var->xoffset = var->yoffset = 0;
182
183	switch (var->bits_per_pixel) {
184	case 2:
185	case 4:
186	case 8:
187		var->red.offset = var->green.offset = var->blue.offset = 0;
188		var->red.length = var->green.length = var->blue.length
189			= var->bits_per_pixel;
190		break;
191	case 15:
192	case 16:
193		var->red.offset = 0;
194		var->green.offset = 5;
195		var->blue.offset = 10;
196		var->red.length = var->green.length = var->blue.length = 5;
197		break;
198	case 24:
199	case 32:
200		var->red.offset = 0;
201		var->green.offset = 8;
202		var->blue.offset = 16;
203		var->red.length = var->green.length = var->blue.length = 8;
204		break;
205	default:
206		dev_err(dev, "color depth %d not supported\n",
207					var->bits_per_pixel);
208		return -EINVAL;
209	}
210
211	return 0;
212}
213
214/**
215 *      atmel_lcdfb_set_par - Alters the hardware state.
216 *      @info: frame buffer structure that represents a single frame buffer
217 *
218 *	Using the fb_var_screeninfo in fb_info we set the resolution
219 *	of the this particular framebuffer. This function alters the
220 *	par AND the fb_fix_screeninfo stored in fb_info. It doesn't
221 *	not alter var in fb_info since we are using that data. This
222 *	means we depend on the data in var inside fb_info to be
223 *	supported by the hardware.  atmel_lcdfb_check_var is always called
224 *	before atmel_lcdfb_set_par to ensure this.  Again if you can't
225 *	change the resolution you don't need this function.
226 *
227 */
228static int atmel_lcdfb_set_par(struct fb_info *info)
229{
230	struct atmel_lcdfb_info *sinfo = info->par;
231	unsigned long value;
232	unsigned long clk_value_khz;
233
234	dev_dbg(info->device, "%s:\n", __func__);
235	dev_dbg(info->device, "  * resolution: %ux%u (%ux%u virtual)\n",
236		 info->var.xres, info->var.yres,
237		 info->var.xres_virtual, info->var.yres_virtual);
238
239	/* Turn off the LCD controller and the DMA controller */
240	lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET);
241
242	lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0);
243
244	if (info->var.bits_per_pixel <= 8)
245		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
246	else
247		info->fix.visual = FB_VISUAL_TRUECOLOR;
248
249	info->fix.line_length = info->var.xres_virtual * (info->var.bits_per_pixel / 8);
250
251	/* Re-initialize the DMA engine... */
252	dev_dbg(info->device, "  * update DMA engine\n");
253	atmel_lcdfb_update_dma(info, &info->var);
254
255	/* ...set frame size and burst length = 8 words (?) */
256	value = (info->var.yres * info->var.xres * info->var.bits_per_pixel) / 32;
257	value |= ((ATMEL_LCDC_DMA_BURST_LEN - 1) << ATMEL_LCDC_BLENGTH_OFFSET);
258	lcdc_writel(sinfo, ATMEL_LCDC_DMAFRMCFG, value);
259
260	/* Now, the LCDC core... */
261
262	/* Set pixel clock */
263	clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000;
264
265	value = clk_value_khz / PICOS2KHZ(info->var.pixclock);
266
267	if (clk_value_khz % PICOS2KHZ(info->var.pixclock))
268		value++;
269
270	value = (value / 2) - 1;
271
272	if (value <= 0) {
273		dev_notice(info->device, "Bypassing pixel clock divider\n");
274		lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1, ATMEL_LCDC_BYPASS);
275	} else
276		lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1, value << ATMEL_LCDC_CLKVAL_OFFSET);
277
278	/* Initialize control register 2 */
279	value = sinfo->default_lcdcon2;
280
281	if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
282		value |= ATMEL_LCDC_INVLINE_INVERTED;
283	if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
284		value |= ATMEL_LCDC_INVFRAME_INVERTED;
285
286	switch (info->var.bits_per_pixel) {
287		case 1:	value |= ATMEL_LCDC_PIXELSIZE_1; break;
288		case 2: value |= ATMEL_LCDC_PIXELSIZE_2; break;
289		case 4: value |= ATMEL_LCDC_PIXELSIZE_4; break;
290		case 8: value |= ATMEL_LCDC_PIXELSIZE_8; break;
291		case 15: /* fall through */
292		case 16: value |= ATMEL_LCDC_PIXELSIZE_16; break;
293		case 24: value |= ATMEL_LCDC_PIXELSIZE_24; break;
294		case 32: value |= ATMEL_LCDC_PIXELSIZE_32; break;
295		default: BUG(); break;
296	}
297	dev_dbg(info->device, "  * LCDCON2 = %08lx\n", value);
298	lcdc_writel(sinfo, ATMEL_LCDC_LCDCON2, value);
299
300	/* Vertical timing */
301	value = (info->var.vsync_len - 1) << ATMEL_LCDC_VPW_OFFSET;
302	value |= info->var.upper_margin << ATMEL_LCDC_VBP_OFFSET;
303	value |= info->var.lower_margin;
304	dev_dbg(info->device, "  * LCDTIM1 = %08lx\n", value);
305	lcdc_writel(sinfo, ATMEL_LCDC_TIM1, value);
306
307	/* Horizontal timing */
308	value = (info->var.right_margin - 1) << ATMEL_LCDC_HFP_OFFSET;
309	value |= (info->var.hsync_len - 1) << ATMEL_LCDC_HPW_OFFSET;
310	value |= (info->var.left_margin - 1);
311	dev_dbg(info->device, "  * LCDTIM2 = %08lx\n", value);
312	lcdc_writel(sinfo, ATMEL_LCDC_TIM2, value);
313
314	/* Display size */
315	value = (info->var.xres - 1) << ATMEL_LCDC_HOZVAL_OFFSET;
316	value |= info->var.yres - 1;
317	lcdc_writel(sinfo, ATMEL_LCDC_LCDFRMCFG, value);
318
319	/* FIFO Threshold: Use formula from data sheet */
320	value = ATMEL_LCDC_FIFO_SIZE - (2 * ATMEL_LCDC_DMA_BURST_LEN + 3);
321	lcdc_writel(sinfo, ATMEL_LCDC_FIFO, value);
322
323	/* Toggle LCD_MODE every frame */
324	lcdc_writel(sinfo, ATMEL_LCDC_MVAL, 0);
325
326	/* Disable all interrupts */
327	lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL);
328
329	/* Set contrast */
330	value = ATMEL_LCDC_PS_DIV8 | ATMEL_LCDC_POL_POSITIVE | ATMEL_LCDC_ENA_PWMENABLE;
331	lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, value);
332	lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, ATMEL_LCDC_CVAL_DEFAULT);
333	/* ...wait for DMA engine to become idle... */
334	while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY)
335		msleep(10);
336
337	dev_dbg(info->device, "  * re-enable DMA engine\n");
338	/* ...and enable it with updated configuration */
339	lcdc_writel(sinfo, ATMEL_LCDC_DMACON, sinfo->default_dmacon);
340
341	dev_dbg(info->device, "  * re-enable LCDC core\n");
342	lcdc_writel(sinfo, ATMEL_LCDC_PWRCON,
343		(sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET) | ATMEL_LCDC_PWR);
344
345	dev_dbg(info->device, "  * DONE\n");
346
347	return 0;
348}
349
350static inline unsigned int chan_to_field(unsigned int chan, const struct fb_bitfield *bf)
351{
352	chan &= 0xffff;
353	chan >>= 16 - bf->length;
354	return chan << bf->offset;
355}
356
357/**
358 *  	atmel_lcdfb_setcolreg - Optional function. Sets a color register.
359 *      @regno: Which register in the CLUT we are programming
360 *      @red: The red value which can be up to 16 bits wide
361 *	@green: The green value which can be up to 16 bits wide
362 *	@blue:  The blue value which can be up to 16 bits wide.
363 *	@transp: If supported the alpha value which can be up to 16 bits wide.
364 *      @info: frame buffer info structure
365 *
366 *  	Set a single color register. The values supplied have a 16 bit
367 *  	magnitude which needs to be scaled in this function for the hardware.
368 *	Things to take into consideration are how many color registers, if
369 *	any, are supported with the current color visual. With truecolor mode
370 *	no color palettes are supported. Here a psuedo palette is created
371 *	which we store the value in pseudo_palette in struct fb_info. For
372 *	pseudocolor mode we have a limited color palette. To deal with this
373 *	we can program what color is displayed for a particular pixel value.
374 *	DirectColor is similar in that we can program each color field. If
375 *	we have a static colormap we don't need to implement this function.
376 *
377 *	Returns negative errno on error, or zero on success. In an
378 *	ideal world, this would have been the case, but as it turns
379 *	out, the other drivers return 1 on failure, so that's what
380 *	we're going to do.
381 */
382static int atmel_lcdfb_setcolreg(unsigned int regno, unsigned int red,
383			     unsigned int green, unsigned int blue,
384			     unsigned int transp, struct fb_info *info)
385{
386	struct atmel_lcdfb_info *sinfo = info->par;
387	unsigned int val;
388	u32 *pal;
389	int ret = 1;
390
391	if (info->var.grayscale)
392		red = green = blue = (19595 * red + 38470 * green
393				      + 7471 * blue) >> 16;
394
395	switch (info->fix.visual) {
396	case FB_VISUAL_TRUECOLOR:
397		if (regno < 16) {
398			pal = info->pseudo_palette;
399
400			val  = chan_to_field(red, &info->var.red);
401			val |= chan_to_field(green, &info->var.green);
402			val |= chan_to_field(blue, &info->var.blue);
403
404			pal[regno] = val;
405			ret = 0;
406		}
407		break;
408
409	case FB_VISUAL_PSEUDOCOLOR:
410		if (regno < 256) {
411			val  = ((red   >> 11) & 0x001f);
412			val |= ((green >>  6) & 0x03e0);
413			val |= ((blue  >>  1) & 0x7c00);
414
415			/*
416			 * TODO: intensity bit. Maybe something like
417			 *   ~(red[10] ^ green[10] ^ blue[10]) & 1
418			 */
419
420			lcdc_writel(sinfo, ATMEL_LCDC_LUT(regno), val);
421			ret = 0;
422		}
423		break;
424	}
425
426	return ret;
427}
428
429static int atmel_lcdfb_pan_display(struct fb_var_screeninfo *var,
430			       struct fb_info *info)
431{
432	dev_dbg(info->device, "%s\n", __func__);
433
434	atmel_lcdfb_update_dma(info, var);
435
436	return 0;
437}
438
439static struct fb_ops atmel_lcdfb_ops = {
440	.owner		= THIS_MODULE,
441	.fb_check_var	= atmel_lcdfb_check_var,
442	.fb_set_par	= atmel_lcdfb_set_par,
443	.fb_setcolreg	= atmel_lcdfb_setcolreg,
444	.fb_pan_display	= atmel_lcdfb_pan_display,
445	.fb_fillrect	= cfb_fillrect,
446	.fb_copyarea	= cfb_copyarea,
447	.fb_imageblit	= cfb_imageblit,
448};
449
450static irqreturn_t atmel_lcdfb_interrupt(int irq, void *dev_id)
451{
452	struct fb_info *info = dev_id;
453	struct atmel_lcdfb_info *sinfo = info->par;
454	u32 status;
455
456	status = lcdc_readl(sinfo, ATMEL_LCDC_ISR);
457	lcdc_writel(sinfo, ATMEL_LCDC_IDR, status);
458	return IRQ_HANDLED;
459}
460
461static int __init atmel_lcdfb_init_fbinfo(struct atmel_lcdfb_info *sinfo)
462{
463	struct fb_info *info = sinfo->info;
464	int ret = 0;
465
466	memset_io(info->screen_base, 0, info->fix.smem_len);
467	info->var.activate |= FB_ACTIVATE_FORCE | FB_ACTIVATE_NOW;
468
469	dev_info(info->device,
470	       "%luKiB frame buffer at %08lx (mapped at %p)\n",
471	       (unsigned long)info->fix.smem_len / 1024,
472	       (unsigned long)info->fix.smem_start,
473	       info->screen_base);
474
475	/* Allocate colormap */
476	ret = fb_alloc_cmap(&info->cmap, 256, 0);
477	if (ret < 0)
478		dev_err(info->device, "Alloc color map failed\n");
479
480	return ret;
481}
482
483static void atmel_lcdfb_start_clock(struct atmel_lcdfb_info *sinfo)
484{
485	if (sinfo->bus_clk)
486		clk_enable(sinfo->bus_clk);
487	clk_enable(sinfo->lcdc_clk);
488}
489
490static void atmel_lcdfb_stop_clock(struct atmel_lcdfb_info *sinfo)
491{
492	if (sinfo->bus_clk)
493		clk_disable(sinfo->bus_clk);
494	clk_disable(sinfo->lcdc_clk);
495}
496
497
498static int __init atmel_lcdfb_probe(struct platform_device *pdev)
499{
500	struct device *dev = &pdev->dev;
501	struct fb_info *info;
502	struct atmel_lcdfb_info *sinfo;
503	struct atmel_lcdfb_info *pdata_sinfo;
504	struct resource *regs = NULL;
505	struct resource *map = NULL;
506	int ret;
507
508	dev_dbg(dev, "%s BEGIN\n", __func__);
509
510	ret = -ENOMEM;
511	info = framebuffer_alloc(sizeof(struct atmel_lcdfb_info), dev);
512	if (!info) {
513		dev_err(dev, "cannot allocate memory\n");
514		goto out;
515	}
516
517	sinfo = info->par;
518
519	if (dev->platform_data) {
520		pdata_sinfo = (struct atmel_lcdfb_info *)dev->platform_data;
521		sinfo->default_bpp = pdata_sinfo->default_bpp;
522		sinfo->default_dmacon = pdata_sinfo->default_dmacon;
523		sinfo->default_lcdcon2 = pdata_sinfo->default_lcdcon2;
524		sinfo->default_monspecs = pdata_sinfo->default_monspecs;
525		sinfo->atmel_lcdfb_power_control = pdata_sinfo->atmel_lcdfb_power_control;
526		sinfo->guard_time = pdata_sinfo->guard_time;
527	} else {
528		dev_err(dev, "cannot get default configuration\n");
529		goto free_info;
530	}
531	sinfo->info = info;
532	sinfo->pdev = pdev;
533
534	strcpy(info->fix.id, sinfo->pdev->name);
535	info->flags = ATMEL_LCDFB_FBINFO_DEFAULT;
536	info->pseudo_palette = sinfo->pseudo_palette;
537	info->fbops = &atmel_lcdfb_ops;
538
539	memcpy(&info->monspecs, sinfo->default_monspecs, sizeof(info->monspecs));
540	info->fix = atmel_lcdfb_fix;
541
542	/* Enable LCDC Clocks */
543	if (cpu_is_at91sam9261() || cpu_is_at32ap7000()) {
544		sinfo->bus_clk = clk_get(dev, "hck1");
545		if (IS_ERR(sinfo->bus_clk)) {
546			ret = PTR_ERR(sinfo->bus_clk);
547			goto free_info;
548		}
549	}
550	sinfo->lcdc_clk = clk_get(dev, "lcdc_clk");
551	if (IS_ERR(sinfo->lcdc_clk)) {
552		ret = PTR_ERR(sinfo->lcdc_clk);
553		goto put_bus_clk;
554	}
555	atmel_lcdfb_start_clock(sinfo);
556
557	ret = fb_find_mode(&info->var, info, NULL, info->monspecs.modedb,
558			info->monspecs.modedb_len, info->monspecs.modedb,
559			sinfo->default_bpp);
560	if (!ret) {
561		dev_err(dev, "no suitable video mode found\n");
562		goto stop_clk;
563	}
564
565
566	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
567	if (!regs) {
568		dev_err(dev, "resources unusable\n");
569		ret = -ENXIO;
570		goto stop_clk;
571	}
572
573	sinfo->irq_base = platform_get_irq(pdev, 0);
574	if (sinfo->irq_base < 0) {
575		dev_err(dev, "unable to get irq\n");
576		ret = sinfo->irq_base;
577		goto stop_clk;
578	}
579
580	/* Initialize video memory */
581	map = platform_get_resource(pdev, IORESOURCE_MEM, 1);
582	if (map) {
583		/* use a pre-allocated memory buffer */
584		info->fix.smem_start = map->start;
585		info->fix.smem_len = map->end - map->start + 1;
586		if (!request_mem_region(info->fix.smem_start,
587					info->fix.smem_len, pdev->name)) {
588			ret = -EBUSY;
589			goto stop_clk;
590		}
591
592		info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
593		if (!info->screen_base)
594			goto release_intmem;
595	} else {
596		/* alocate memory buffer */
597		ret = atmel_lcdfb_alloc_video_memory(sinfo);
598		if (ret < 0) {
599			dev_err(dev, "cannot allocate framebuffer: %d\n", ret);
600			goto stop_clk;
601		}
602	}
603
604	/* LCDC registers */
605	info->fix.mmio_start = regs->start;
606	info->fix.mmio_len = regs->end - regs->start + 1;
607
608	if (!request_mem_region(info->fix.mmio_start,
609				info->fix.mmio_len, pdev->name)) {
610		ret = -EBUSY;
611		goto free_fb;
612	}
613
614	sinfo->mmio = ioremap(info->fix.mmio_start, info->fix.mmio_len);
615	if (!sinfo->mmio) {
616		dev_err(dev, "cannot map LCDC registers\n");
617		goto release_mem;
618	}
619
620	/* interrupt */
621	ret = request_irq(sinfo->irq_base, atmel_lcdfb_interrupt, 0, pdev->name, info);
622	if (ret) {
623		dev_err(dev, "request_irq failed: %d\n", ret);
624		goto unmap_mmio;
625	}
626
627	ret = atmel_lcdfb_init_fbinfo(sinfo);
628	if (ret < 0) {
629		dev_err(dev, "init fbinfo failed: %d\n", ret);
630		goto unregister_irqs;
631	}
632
633	/*
634	 * This makes sure that our colour bitfield
635	 * descriptors are correctly initialised.
636	 */
637	atmel_lcdfb_check_var(&info->var, info);
638
639	ret = fb_set_var(info, &info->var);
640	if (ret) {
641		dev_warn(dev, "unable to set display parameters\n");
642		goto free_cmap;
643	}
644
645	dev_set_drvdata(dev, info);
646
647	/*
648	 * Tell the world that we're ready to go
649	 */
650	ret = register_framebuffer(info);
651	if (ret < 0) {
652		dev_err(dev, "failed to register framebuffer device: %d\n", ret);
653		goto free_cmap;
654	}
655
656	/* Power up the LCDC screen */
657	if (sinfo->atmel_lcdfb_power_control)
658		sinfo->atmel_lcdfb_power_control(1);
659
660	dev_info(dev, "fb%d: Atmel LCDC at 0x%08lx (mapped at %p), irq %lu\n",
661		       info->node, info->fix.mmio_start, sinfo->mmio, sinfo->irq_base);
662
663	return 0;
664
665
666free_cmap:
667	fb_dealloc_cmap(&info->cmap);
668unregister_irqs:
669	free_irq(sinfo->irq_base, info);
670unmap_mmio:
671	iounmap(sinfo->mmio);
672release_mem:
673 	release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
674free_fb:
675	if (map)
676		iounmap(info->screen_base);
677	else
678		atmel_lcdfb_free_video_memory(sinfo);
679
680release_intmem:
681	if (map)
682		release_mem_region(info->fix.smem_start, info->fix.smem_len);
683stop_clk:
684	atmel_lcdfb_stop_clock(sinfo);
685	clk_put(sinfo->lcdc_clk);
686put_bus_clk:
687	if (sinfo->bus_clk)
688		clk_put(sinfo->bus_clk);
689free_info:
690	framebuffer_release(info);
691out:
692	dev_dbg(dev, "%s FAILED\n", __func__);
693	return ret;
694}
695
696static int __exit atmel_lcdfb_remove(struct platform_device *pdev)
697{
698	struct device *dev = &pdev->dev;
699	struct fb_info *info = dev_get_drvdata(dev);
700	struct atmel_lcdfb_info *sinfo = info->par;
701
702	if (!sinfo)
703		return 0;
704
705	if (sinfo->atmel_lcdfb_power_control)
706		sinfo->atmel_lcdfb_power_control(0);
707	unregister_framebuffer(info);
708	atmel_lcdfb_stop_clock(sinfo);
709	clk_put(sinfo->lcdc_clk);
710	if (sinfo->bus_clk)
711		clk_put(sinfo->bus_clk);
712	fb_dealloc_cmap(&info->cmap);
713	free_irq(sinfo->irq_base, info);
714	iounmap(sinfo->mmio);
715 	release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
716	if (platform_get_resource(pdev, IORESOURCE_MEM, 1)) {
717		iounmap(info->screen_base);
718		release_mem_region(info->fix.smem_start, info->fix.smem_len);
719	} else {
720		atmel_lcdfb_free_video_memory(sinfo);
721	}
722
723	dev_set_drvdata(dev, NULL);
724	framebuffer_release(info);
725
726	return 0;
727}
728
729static struct platform_driver atmel_lcdfb_driver = {
730	.remove		= __exit_p(atmel_lcdfb_remove),
731	.driver		= {
732		.name	= "atmel_lcdfb",
733		.owner	= THIS_MODULE,
734	},
735};
736
737static int __init atmel_lcdfb_init(void)
738{
739	return platform_driver_probe(&atmel_lcdfb_driver, atmel_lcdfb_probe);
740}
741
742static void __exit atmel_lcdfb_exit(void)
743{
744	platform_driver_unregister(&atmel_lcdfb_driver);
745}
746
747module_init(atmel_lcdfb_init);
748module_exit(atmel_lcdfb_exit);
749
750MODULE_DESCRIPTION("AT91/AT32 LCD Controller framebuffer driver");
751MODULE_AUTHOR("Nicolas Ferre <nicolas.ferre@rfo.atmel.com>");
752MODULE_LICENSE("GPL");
753