1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * linux/drivers/video/omap2/omapfb-main.c
4 *
5 * Copyright (C) 2008 Nokia Corporation
6 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
7 *
8 * Some code and ideas taken from drivers/video/omap/ driver
9 * by Imre Deak.
10 */
11
12#include <linux/module.h>
13#include <linux/delay.h>
14#include <linux/slab.h>
15#include <linux/fb.h>
16#include <linux/dma-mapping.h>
17#include <linux/vmalloc.h>
18#include <linux/device.h>
19#include <linux/platform_device.h>
20#include <linux/omapfb.h>
21
22#include <video/omapfb_dss.h>
23#include <video/omapvrfb.h>
24
25#include "omapfb.h"
26
27#define MODULE_NAME     "omapfb"
28
29#define OMAPFB_PLANE_XRES_MIN		8
30#define OMAPFB_PLANE_YRES_MIN		8
31
32static char *def_mode;
33static char *def_vram;
34static bool def_vrfb;
35static int def_rotate;
36static bool def_mirror;
37static bool auto_update;
38static unsigned int auto_update_freq;
39module_param(auto_update, bool, 0);
40module_param(auto_update_freq, uint, 0644);
41
42#ifdef DEBUG
43bool omapfb_debug;
44module_param_named(debug, omapfb_debug, bool, 0644);
45static bool omapfb_test_pattern;
46module_param_named(test, omapfb_test_pattern, bool, 0644);
47#endif
48
49static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi);
50static int omapfb_get_recommended_bpp(struct omapfb2_device *fbdev,
51		struct omap_dss_device *dssdev);
52
53#ifdef DEBUG
54static void draw_pixel(struct fb_info *fbi, int x, int y, unsigned color)
55{
56	struct fb_var_screeninfo *var = &fbi->var;
57	struct fb_fix_screeninfo *fix = &fbi->fix;
58	void __iomem *addr = fbi->screen_base;
59	const unsigned bytespp = var->bits_per_pixel >> 3;
60	const unsigned line_len = fix->line_length / bytespp;
61
62	int r = (color >> 16) & 0xff;
63	int g = (color >> 8) & 0xff;
64	int b = (color >> 0) & 0xff;
65
66	if (var->bits_per_pixel == 16) {
67		u16 __iomem *p = (u16 __iomem *)addr;
68		p += y * line_len + x;
69
70		r = r * 32 / 256;
71		g = g * 64 / 256;
72		b = b * 32 / 256;
73
74		__raw_writew((r << 11) | (g << 5) | (b << 0), p);
75	} else if (var->bits_per_pixel == 24) {
76		u8 __iomem *p = (u8 __iomem *)addr;
77		p += (y * line_len + x) * 3;
78
79		__raw_writeb(b, p + 0);
80		__raw_writeb(g, p + 1);
81		__raw_writeb(r, p + 2);
82	} else if (var->bits_per_pixel == 32) {
83		u32 __iomem *p = (u32 __iomem *)addr;
84		p += y * line_len + x;
85		__raw_writel(color, p);
86	}
87}
88
89static void fill_fb(struct fb_info *fbi)
90{
91	struct fb_var_screeninfo *var = &fbi->var;
92	const short w = var->xres_virtual;
93	const short h = var->yres_virtual;
94	void __iomem *addr = fbi->screen_base;
95	int y, x;
96
97	if (!addr)
98		return;
99
100	DBG("fill_fb %dx%d, line_len %d bytes\n", w, h, fbi->fix.line_length);
101
102	for (y = 0; y < h; y++) {
103		for (x = 0; x < w; x++) {
104			if (x < 20 && y < 20)
105				draw_pixel(fbi, x, y, 0xffffff);
106			else if (x < 20 && (y > 20 && y < h - 20))
107				draw_pixel(fbi, x, y, 0xff);
108			else if (y < 20 && (x > 20 && x < w - 20))
109				draw_pixel(fbi, x, y, 0xff00);
110			else if (x > w - 20 && (y > 20 && y < h - 20))
111				draw_pixel(fbi, x, y, 0xff0000);
112			else if (y > h - 20 && (x > 20 && x < w - 20))
113				draw_pixel(fbi, x, y, 0xffff00);
114			else if (x == 20 || x == w - 20 ||
115					y == 20 || y == h - 20)
116				draw_pixel(fbi, x, y, 0xffffff);
117			else if (x == y || w - x == h - y)
118				draw_pixel(fbi, x, y, 0xff00ff);
119			else if (w - x == y || x == h - y)
120				draw_pixel(fbi, x, y, 0x00ffff);
121			else if (x > 20 && y > 20 && x < w - 20 && y < h - 20) {
122				int t = x * 3 / w;
123				unsigned r = 0, g = 0, b = 0;
124				unsigned c;
125				if (var->bits_per_pixel == 16) {
126					if (t == 0)
127						b = (y % 32) * 256 / 32;
128					else if (t == 1)
129						g = (y % 64) * 256 / 64;
130					else if (t == 2)
131						r = (y % 32) * 256 / 32;
132				} else {
133					if (t == 0)
134						b = (y % 256);
135					else if (t == 1)
136						g = (y % 256);
137					else if (t == 2)
138						r = (y % 256);
139				}
140				c = (r << 16) | (g << 8) | (b << 0);
141				draw_pixel(fbi, x, y, c);
142			} else {
143				draw_pixel(fbi, x, y, 0);
144			}
145		}
146	}
147}
148#endif
149
150static unsigned omapfb_get_vrfb_offset(const struct omapfb_info *ofbi, int rot)
151{
152	const struct vrfb *vrfb = &ofbi->region->vrfb;
153	unsigned offset;
154
155	switch (rot) {
156	case FB_ROTATE_UR:
157		offset = 0;
158		break;
159	case FB_ROTATE_CW:
160		offset = vrfb->yoffset;
161		break;
162	case FB_ROTATE_UD:
163		offset = vrfb->yoffset * OMAP_VRFB_LINE_LEN + vrfb->xoffset;
164		break;
165	case FB_ROTATE_CCW:
166		offset = vrfb->xoffset * OMAP_VRFB_LINE_LEN;
167		break;
168	default:
169		BUG();
170		return 0;
171	}
172
173	offset *= vrfb->bytespp;
174
175	return offset;
176}
177
178static u32 omapfb_get_region_rot_paddr(const struct omapfb_info *ofbi, int rot)
179{
180	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
181		return ofbi->region->vrfb.paddr[rot]
182			+ omapfb_get_vrfb_offset(ofbi, rot);
183	} else {
184		return ofbi->region->paddr;
185	}
186}
187
188static u32 omapfb_get_region_paddr(const struct omapfb_info *ofbi)
189{
190	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
191		return ofbi->region->vrfb.paddr[0];
192	else
193		return ofbi->region->paddr;
194}
195
196static void __iomem *omapfb_get_region_vaddr(const struct omapfb_info *ofbi)
197{
198	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
199		return ofbi->region->vrfb.vaddr[0];
200	else
201		return ofbi->region->vaddr;
202}
203
204static struct omapfb_colormode omapfb_colormodes[] = {
205	{
206		.dssmode = OMAP_DSS_COLOR_UYVY,
207		.bits_per_pixel = 16,
208		.nonstd = OMAPFB_COLOR_YUV422,
209	}, {
210		.dssmode = OMAP_DSS_COLOR_YUV2,
211		.bits_per_pixel = 16,
212		.nonstd = OMAPFB_COLOR_YUY422,
213	}, {
214		.dssmode = OMAP_DSS_COLOR_ARGB16,
215		.bits_per_pixel = 16,
216		.red	= { .length = 4, .offset = 8, .msb_right = 0 },
217		.green	= { .length = 4, .offset = 4, .msb_right = 0 },
218		.blue	= { .length = 4, .offset = 0, .msb_right = 0 },
219		.transp	= { .length = 4, .offset = 12, .msb_right = 0 },
220	}, {
221		.dssmode = OMAP_DSS_COLOR_RGB16,
222		.bits_per_pixel = 16,
223		.red	= { .length = 5, .offset = 11, .msb_right = 0 },
224		.green	= { .length = 6, .offset = 5, .msb_right = 0 },
225		.blue	= { .length = 5, .offset = 0, .msb_right = 0 },
226		.transp	= { .length = 0, .offset = 0, .msb_right = 0 },
227	}, {
228		.dssmode = OMAP_DSS_COLOR_RGB24P,
229		.bits_per_pixel = 24,
230		.red	= { .length = 8, .offset = 16, .msb_right = 0 },
231		.green	= { .length = 8, .offset = 8, .msb_right = 0 },
232		.blue	= { .length = 8, .offset = 0, .msb_right = 0 },
233		.transp	= { .length = 0, .offset = 0, .msb_right = 0 },
234	}, {
235		.dssmode = OMAP_DSS_COLOR_RGB24U,
236		.bits_per_pixel = 32,
237		.red	= { .length = 8, .offset = 16, .msb_right = 0 },
238		.green	= { .length = 8, .offset = 8, .msb_right = 0 },
239		.blue	= { .length = 8, .offset = 0, .msb_right = 0 },
240		.transp	= { .length = 0, .offset = 0, .msb_right = 0 },
241	}, {
242		.dssmode = OMAP_DSS_COLOR_ARGB32,
243		.bits_per_pixel = 32,
244		.red	= { .length = 8, .offset = 16, .msb_right = 0 },
245		.green	= { .length = 8, .offset = 8, .msb_right = 0 },
246		.blue	= { .length = 8, .offset = 0, .msb_right = 0 },
247		.transp	= { .length = 8, .offset = 24, .msb_right = 0 },
248	}, {
249		.dssmode = OMAP_DSS_COLOR_RGBA32,
250		.bits_per_pixel = 32,
251		.red	= { .length = 8, .offset = 24, .msb_right = 0 },
252		.green	= { .length = 8, .offset = 16, .msb_right = 0 },
253		.blue	= { .length = 8, .offset = 8, .msb_right = 0 },
254		.transp	= { .length = 8, .offset = 0, .msb_right = 0 },
255	}, {
256		.dssmode = OMAP_DSS_COLOR_RGBX32,
257		.bits_per_pixel = 32,
258		.red	= { .length = 8, .offset = 24, .msb_right = 0 },
259		.green	= { .length = 8, .offset = 16, .msb_right = 0 },
260		.blue	= { .length = 8, .offset = 8, .msb_right = 0 },
261		.transp	= { .length = 0, .offset = 0, .msb_right = 0 },
262	},
263};
264
265static bool cmp_component(struct fb_bitfield *f1, struct fb_bitfield *f2)
266{
267	return f1->length == f2->length &&
268		f1->offset == f2->offset &&
269		f1->msb_right == f2->msb_right;
270}
271
272static bool cmp_var_to_colormode(struct fb_var_screeninfo *var,
273		struct omapfb_colormode *color)
274{
275	if (var->bits_per_pixel == 0 ||
276			var->red.length == 0 ||
277			var->blue.length == 0 ||
278			var->green.length == 0)
279		return false;
280
281	return var->bits_per_pixel == color->bits_per_pixel &&
282		cmp_component(&var->red, &color->red) &&
283		cmp_component(&var->green, &color->green) &&
284		cmp_component(&var->blue, &color->blue) &&
285		cmp_component(&var->transp, &color->transp);
286}
287
288static void assign_colormode_to_var(struct fb_var_screeninfo *var,
289		struct omapfb_colormode *color)
290{
291	var->bits_per_pixel = color->bits_per_pixel;
292	var->nonstd = color->nonstd;
293	var->red = color->red;
294	var->green = color->green;
295	var->blue = color->blue;
296	var->transp = color->transp;
297}
298
299static int fb_mode_to_dss_mode(struct fb_var_screeninfo *var,
300		enum omap_color_mode *mode)
301{
302	enum omap_color_mode dssmode;
303	int i;
304
305	/* first match with nonstd field */
306	if (var->nonstd) {
307		for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
308			struct omapfb_colormode *m = &omapfb_colormodes[i];
309			if (var->nonstd == m->nonstd) {
310				assign_colormode_to_var(var, m);
311				*mode = m->dssmode;
312				return 0;
313			}
314		}
315
316		return -EINVAL;
317	}
318
319	/* then try exact match of bpp and colors */
320	for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
321		struct omapfb_colormode *m = &omapfb_colormodes[i];
322		if (cmp_var_to_colormode(var, m)) {
323			assign_colormode_to_var(var, m);
324			*mode = m->dssmode;
325			return 0;
326		}
327	}
328
329	/* match with bpp if user has not filled color fields
330	 * properly */
331	switch (var->bits_per_pixel) {
332	case 1:
333		dssmode = OMAP_DSS_COLOR_CLUT1;
334		break;
335	case 2:
336		dssmode = OMAP_DSS_COLOR_CLUT2;
337		break;
338	case 4:
339		dssmode = OMAP_DSS_COLOR_CLUT4;
340		break;
341	case 8:
342		dssmode = OMAP_DSS_COLOR_CLUT8;
343		break;
344	case 12:
345		dssmode = OMAP_DSS_COLOR_RGB12U;
346		break;
347	case 16:
348		dssmode = OMAP_DSS_COLOR_RGB16;
349		break;
350	case 24:
351		dssmode = OMAP_DSS_COLOR_RGB24P;
352		break;
353	case 32:
354		dssmode = OMAP_DSS_COLOR_RGB24U;
355		break;
356	default:
357		return -EINVAL;
358	}
359
360	for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
361		struct omapfb_colormode *m = &omapfb_colormodes[i];
362		if (dssmode == m->dssmode) {
363			assign_colormode_to_var(var, m);
364			*mode = m->dssmode;
365			return 0;
366		}
367	}
368
369	return -EINVAL;
370}
371
372static int check_fb_res_bounds(struct fb_var_screeninfo *var)
373{
374	int xres_min = OMAPFB_PLANE_XRES_MIN;
375	int xres_max = 2048;
376	int yres_min = OMAPFB_PLANE_YRES_MIN;
377	int yres_max = 2048;
378
379	/* XXX: some applications seem to set virtual res to 0. */
380	if (var->xres_virtual == 0)
381		var->xres_virtual = var->xres;
382
383	if (var->yres_virtual == 0)
384		var->yres_virtual = var->yres;
385
386	if (var->xres_virtual < xres_min || var->yres_virtual < yres_min)
387		return -EINVAL;
388
389	if (var->xres < xres_min)
390		var->xres = xres_min;
391	if (var->yres < yres_min)
392		var->yres = yres_min;
393	if (var->xres > xres_max)
394		var->xres = xres_max;
395	if (var->yres > yres_max)
396		var->yres = yres_max;
397
398	if (var->xres > var->xres_virtual)
399		var->xres = var->xres_virtual;
400	if (var->yres > var->yres_virtual)
401		var->yres = var->yres_virtual;
402
403	return 0;
404}
405
406static void shrink_height(unsigned long max_frame_size,
407		struct fb_var_screeninfo *var)
408{
409	DBG("can't fit FB into memory, reducing y\n");
410	var->yres_virtual = max_frame_size /
411		(var->xres_virtual * var->bits_per_pixel >> 3);
412
413	if (var->yres_virtual < OMAPFB_PLANE_YRES_MIN)
414		var->yres_virtual = OMAPFB_PLANE_YRES_MIN;
415
416	if (var->yres > var->yres_virtual)
417		var->yres = var->yres_virtual;
418}
419
420static void shrink_width(unsigned long max_frame_size,
421		struct fb_var_screeninfo *var)
422{
423	DBG("can't fit FB into memory, reducing x\n");
424	var->xres_virtual = max_frame_size / var->yres_virtual /
425		(var->bits_per_pixel >> 3);
426
427	if (var->xres_virtual < OMAPFB_PLANE_XRES_MIN)
428		var->xres_virtual = OMAPFB_PLANE_XRES_MIN;
429
430	if (var->xres > var->xres_virtual)
431		var->xres = var->xres_virtual;
432}
433
434static int check_vrfb_fb_size(unsigned long region_size,
435		const struct fb_var_screeninfo *var)
436{
437	unsigned long min_phys_size = omap_vrfb_min_phys_size(var->xres_virtual,
438		var->yres_virtual, var->bits_per_pixel >> 3);
439
440	return min_phys_size > region_size ? -EINVAL : 0;
441}
442
443static int check_fb_size(const struct omapfb_info *ofbi,
444		struct fb_var_screeninfo *var)
445{
446	unsigned long max_frame_size = ofbi->region->size;
447	int bytespp = var->bits_per_pixel >> 3;
448	unsigned long line_size = var->xres_virtual * bytespp;
449
450	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
451		/* One needs to check for both VRFB and OMAPFB limitations. */
452		if (check_vrfb_fb_size(max_frame_size, var))
453			shrink_height(omap_vrfb_max_height(
454				max_frame_size, var->xres_virtual, bytespp) *
455				line_size, var);
456
457		if (check_vrfb_fb_size(max_frame_size, var)) {
458			DBG("cannot fit FB to memory\n");
459			return -EINVAL;
460		}
461
462		return 0;
463	}
464
465	DBG("max frame size %lu, line size %lu\n", max_frame_size, line_size);
466
467	if (line_size * var->yres_virtual > max_frame_size)
468		shrink_height(max_frame_size, var);
469
470	if (line_size * var->yres_virtual > max_frame_size) {
471		shrink_width(max_frame_size, var);
472		line_size = var->xres_virtual * bytespp;
473	}
474
475	if (line_size * var->yres_virtual > max_frame_size) {
476		DBG("cannot fit FB to memory\n");
477		return -EINVAL;
478	}
479
480	return 0;
481}
482
483/*
484 * Consider if VRFB assisted rotation is in use and if the virtual space for
485 * the zero degree view needs to be mapped. The need for mapping also acts as
486 * the trigger for setting up the hardware on the context in question. This
487 * ensures that one does not attempt to access the virtual view before the
488 * hardware is serving the address translations.
489 */
490static int setup_vrfb_rotation(struct fb_info *fbi)
491{
492	struct omapfb_info *ofbi = FB2OFB(fbi);
493	struct omapfb2_mem_region *rg = ofbi->region;
494	struct vrfb *vrfb = &rg->vrfb;
495	struct fb_var_screeninfo *var = &fbi->var;
496	struct fb_fix_screeninfo *fix = &fbi->fix;
497	unsigned bytespp;
498	bool yuv_mode;
499	enum omap_color_mode mode;
500	int r;
501	bool reconf;
502
503	if (!rg->size || ofbi->rotation_type != OMAP_DSS_ROT_VRFB)
504		return 0;
505
506	DBG("setup_vrfb_rotation\n");
507
508	r = fb_mode_to_dss_mode(var, &mode);
509	if (r)
510		return r;
511
512	bytespp = var->bits_per_pixel >> 3;
513
514	yuv_mode = mode == OMAP_DSS_COLOR_YUV2 || mode == OMAP_DSS_COLOR_UYVY;
515
516	/* We need to reconfigure VRFB if the resolution changes, if yuv mode
517	 * is enabled/disabled, or if bytes per pixel changes */
518
519	/* XXX we shouldn't allow this when framebuffer is mmapped */
520
521	reconf = false;
522
523	if (yuv_mode != vrfb->yuv_mode)
524		reconf = true;
525	else if (bytespp != vrfb->bytespp)
526		reconf = true;
527	else if (vrfb->xres != var->xres_virtual ||
528			vrfb->yres != var->yres_virtual)
529		reconf = true;
530
531	if (vrfb->vaddr[0] && reconf) {
532		fbi->screen_base = NULL;
533		fix->smem_start = 0;
534		fix->smem_len = 0;
535		iounmap(vrfb->vaddr[0]);
536		vrfb->vaddr[0] = NULL;
537		DBG("setup_vrfb_rotation: reset fb\n");
538	}
539
540	if (vrfb->vaddr[0])
541		return 0;
542
543	omap_vrfb_setup(&rg->vrfb, rg->paddr,
544			var->xres_virtual,
545			var->yres_virtual,
546			bytespp, yuv_mode);
547
548	/* Now one can ioremap the 0 angle view */
549	r = omap_vrfb_map_angle(vrfb, var->yres_virtual, 0);
550	if (r)
551		return r;
552
553	/* used by open/write in fbmem.c */
554	fbi->screen_base = ofbi->region->vrfb.vaddr[0];
555
556	fix->smem_start = ofbi->region->vrfb.paddr[0];
557
558	switch (var->nonstd) {
559	case OMAPFB_COLOR_YUV422:
560	case OMAPFB_COLOR_YUY422:
561		fix->line_length =
562			(OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 2;
563		break;
564	default:
565		fix->line_length =
566			(OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 3;
567		break;
568	}
569
570	fix->smem_len = var->yres_virtual * fix->line_length;
571
572	return 0;
573}
574
575int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
576			struct fb_var_screeninfo *var)
577{
578	int i;
579
580	for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
581		struct omapfb_colormode *mode = &omapfb_colormodes[i];
582		if (dssmode == mode->dssmode) {
583			assign_colormode_to_var(var, mode);
584			return 0;
585		}
586	}
587	return -ENOENT;
588}
589
590void set_fb_fix(struct fb_info *fbi)
591{
592	struct fb_fix_screeninfo *fix = &fbi->fix;
593	struct fb_var_screeninfo *var = &fbi->var;
594	struct omapfb_info *ofbi = FB2OFB(fbi);
595	struct omapfb2_mem_region *rg = ofbi->region;
596
597	DBG("set_fb_fix\n");
598
599	/* used by open/write in fbmem.c */
600	fbi->screen_base = (char __iomem *)omapfb_get_region_vaddr(ofbi);
601
602	/* used by mmap in fbmem.c */
603	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
604		switch (var->nonstd) {
605		case OMAPFB_COLOR_YUV422:
606		case OMAPFB_COLOR_YUY422:
607			fix->line_length =
608				(OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 2;
609			break;
610		default:
611			fix->line_length =
612				(OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 3;
613			break;
614		}
615
616		fix->smem_len = var->yres_virtual * fix->line_length;
617	} else {
618		fix->line_length =
619			(var->xres_virtual * var->bits_per_pixel) >> 3;
620		fix->smem_len = rg->size;
621	}
622
623	fix->smem_start = omapfb_get_region_paddr(ofbi);
624
625	fix->type = FB_TYPE_PACKED_PIXELS;
626
627	if (var->nonstd)
628		fix->visual = FB_VISUAL_PSEUDOCOLOR;
629	else {
630		switch (var->bits_per_pixel) {
631		case 32:
632		case 24:
633		case 16:
634		case 12:
635			fix->visual = FB_VISUAL_TRUECOLOR;
636			/* 12bpp is stored in 16 bits */
637			break;
638		case 1:
639		case 2:
640		case 4:
641		case 8:
642			fix->visual = FB_VISUAL_PSEUDOCOLOR;
643			break;
644		}
645	}
646
647	fix->accel = FB_ACCEL_NONE;
648
649	fix->xpanstep = 1;
650	fix->ypanstep = 1;
651}
652
653/* check new var and possibly modify it to be ok */
654int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
655{
656	struct omapfb_info *ofbi = FB2OFB(fbi);
657	struct omap_dss_device *display = fb2display(fbi);
658	enum omap_color_mode mode = 0;
659	int i;
660	int r;
661
662	DBG("check_fb_var %d\n", ofbi->id);
663
664	WARN_ON(!atomic_read(&ofbi->region->lock_count));
665
666	r = fb_mode_to_dss_mode(var, &mode);
667	if (r) {
668		DBG("cannot convert var to omap dss mode\n");
669		return r;
670	}
671
672	for (i = 0; i < ofbi->num_overlays; ++i) {
673		if ((ofbi->overlays[i]->supported_modes & mode) == 0) {
674			DBG("invalid mode\n");
675			return -EINVAL;
676		}
677	}
678
679	if (var->rotate > 3)
680		return -EINVAL;
681
682	if (check_fb_res_bounds(var))
683		return -EINVAL;
684
685	/* When no memory is allocated ignore the size check */
686	if (ofbi->region->size != 0 && check_fb_size(ofbi, var))
687		return -EINVAL;
688
689	if (var->xres + var->xoffset > var->xres_virtual)
690		var->xoffset = var->xres_virtual - var->xres;
691	if (var->yres + var->yoffset > var->yres_virtual)
692		var->yoffset = var->yres_virtual - var->yres;
693
694	DBG("xres = %d, yres = %d, vxres = %d, vyres = %d\n",
695			var->xres, var->yres,
696			var->xres_virtual, var->yres_virtual);
697
698	if (display && display->driver->get_dimensions) {
699		u32 w, h;
700		display->driver->get_dimensions(display, &w, &h);
701		var->width = DIV_ROUND_CLOSEST(w, 1000);
702		var->height = DIV_ROUND_CLOSEST(h, 1000);
703	} else {
704		var->height = -1;
705		var->width = -1;
706	}
707
708	var->grayscale          = 0;
709
710	if (display && display->driver->get_timings) {
711		struct omap_video_timings timings;
712		display->driver->get_timings(display, &timings);
713
714		/* pixclock in ps, the rest in pixclock */
715		var->pixclock = timings.pixelclock != 0 ?
716			KHZ2PICOS(timings.pixelclock / 1000) :
717			0;
718		var->left_margin = timings.hbp;
719		var->right_margin = timings.hfp;
720		var->upper_margin = timings.vbp;
721		var->lower_margin = timings.vfp;
722		var->hsync_len = timings.hsw;
723		var->vsync_len = timings.vsw;
724		var->sync |= timings.hsync_level == OMAPDSS_SIG_ACTIVE_HIGH ?
725				FB_SYNC_HOR_HIGH_ACT : 0;
726		var->sync |= timings.vsync_level == OMAPDSS_SIG_ACTIVE_HIGH ?
727				FB_SYNC_VERT_HIGH_ACT : 0;
728		var->vmode = timings.interlace ?
729				FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED;
730	} else {
731		var->pixclock = 0;
732		var->left_margin = 0;
733		var->right_margin = 0;
734		var->upper_margin = 0;
735		var->lower_margin = 0;
736		var->hsync_len = 0;
737		var->vsync_len = 0;
738		var->sync = 0;
739		var->vmode = FB_VMODE_NONINTERLACED;
740	}
741
742	return 0;
743}
744
745/*
746 * ---------------------------------------------------------------------------
747 * fbdev framework callbacks
748 * ---------------------------------------------------------------------------
749 */
750static int omapfb_open(struct fb_info *fbi, int user)
751{
752	return 0;
753}
754
755static int omapfb_release(struct fb_info *fbi, int user)
756{
757	return 0;
758}
759
760static unsigned calc_rotation_offset_dma(const struct fb_var_screeninfo *var,
761		const struct fb_fix_screeninfo *fix, int rotation)
762{
763	unsigned offset;
764
765	offset = var->yoffset * fix->line_length +
766		var->xoffset * (var->bits_per_pixel >> 3);
767
768	return offset;
769}
770
771static unsigned calc_rotation_offset_vrfb(const struct fb_var_screeninfo *var,
772		const struct fb_fix_screeninfo *fix, int rotation)
773{
774	unsigned offset;
775
776	if (rotation == FB_ROTATE_UD)
777		offset = (var->yres_virtual - var->yres) *
778			fix->line_length;
779	else if (rotation == FB_ROTATE_CW)
780		offset = (var->yres_virtual - var->yres) *
781			(var->bits_per_pixel >> 3);
782	else
783		offset = 0;
784
785	if (rotation == FB_ROTATE_UR)
786		offset += var->yoffset * fix->line_length +
787			var->xoffset * (var->bits_per_pixel >> 3);
788	else if (rotation == FB_ROTATE_UD)
789		offset -= var->yoffset * fix->line_length +
790			var->xoffset * (var->bits_per_pixel >> 3);
791	else if (rotation == FB_ROTATE_CW)
792		offset -= var->xoffset * fix->line_length +
793			var->yoffset * (var->bits_per_pixel >> 3);
794	else if (rotation == FB_ROTATE_CCW)
795		offset += var->xoffset * fix->line_length +
796			var->yoffset * (var->bits_per_pixel >> 3);
797
798	return offset;
799}
800
801static void omapfb_calc_addr(const struct omapfb_info *ofbi,
802			     const struct fb_var_screeninfo *var,
803			     const struct fb_fix_screeninfo *fix,
804			     int rotation, u32 *paddr)
805{
806	u32 data_start_p;
807	int offset;
808
809	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
810		data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation);
811	else
812		data_start_p = omapfb_get_region_paddr(ofbi);
813
814	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
815		offset = calc_rotation_offset_vrfb(var, fix, rotation);
816	else
817		offset = calc_rotation_offset_dma(var, fix, rotation);
818
819	data_start_p += offset;
820
821	if (offset)
822		DBG("offset %d, %d = %d\n",
823		    var->xoffset, var->yoffset, offset);
824
825	DBG("paddr %x\n", data_start_p);
826
827	*paddr = data_start_p;
828}
829
830/* setup overlay according to the fb */
831int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
832		u16 posx, u16 posy, u16 outw, u16 outh)
833{
834	int r = 0;
835	struct omapfb_info *ofbi = FB2OFB(fbi);
836	struct fb_var_screeninfo *var = &fbi->var;
837	struct fb_fix_screeninfo *fix = &fbi->fix;
838	enum omap_color_mode mode = 0;
839	u32 data_start_p = 0;
840	struct omap_overlay_info info;
841	int xres, yres;
842	int screen_width;
843	int mirror;
844	int rotation = var->rotate;
845	int i;
846
847	WARN_ON(!atomic_read(&ofbi->region->lock_count));
848
849	for (i = 0; i < ofbi->num_overlays; i++) {
850		if (ovl != ofbi->overlays[i])
851			continue;
852
853		rotation = (rotation + ofbi->rotation[i]) % 4;
854		break;
855	}
856
857	DBG("setup_overlay %d, posx %d, posy %d, outw %d, outh %d\n", ofbi->id,
858			posx, posy, outw, outh);
859
860	if (rotation == FB_ROTATE_CW || rotation == FB_ROTATE_CCW) {
861		xres = var->yres;
862		yres = var->xres;
863	} else {
864		xres = var->xres;
865		yres = var->yres;
866	}
867
868	if (ofbi->region->size)
869		omapfb_calc_addr(ofbi, var, fix, rotation, &data_start_p);
870
871	r = fb_mode_to_dss_mode(var, &mode);
872	if (r) {
873		DBG("fb_mode_to_dss_mode failed");
874		goto err;
875	}
876
877	switch (var->nonstd) {
878	case OMAPFB_COLOR_YUV422:
879	case OMAPFB_COLOR_YUY422:
880		if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
881			screen_width = fix->line_length
882				/ (var->bits_per_pixel >> 2);
883			break;
884		}
885		fallthrough;
886	default:
887		screen_width = fix->line_length / (var->bits_per_pixel >> 3);
888		break;
889	}
890
891	ovl->get_overlay_info(ovl, &info);
892
893	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
894		mirror = 0;
895	else
896		mirror = ofbi->mirror;
897
898	info.paddr = data_start_p;
899	info.screen_width = screen_width;
900	info.width = xres;
901	info.height = yres;
902	info.color_mode = mode;
903	info.rotation_type = ofbi->rotation_type;
904	info.rotation = rotation;
905	info.mirror = mirror;
906
907	info.pos_x = posx;
908	info.pos_y = posy;
909	info.out_width = outw;
910	info.out_height = outh;
911
912	r = ovl->set_overlay_info(ovl, &info);
913	if (r) {
914		DBG("ovl->setup_overlay_info failed\n");
915		goto err;
916	}
917
918	return 0;
919
920err:
921	DBG("setup_overlay failed\n");
922	return r;
923}
924
925/* apply var to the overlay */
926int omapfb_apply_changes(struct fb_info *fbi, int init)
927{
928	int r = 0;
929	struct omapfb_info *ofbi = FB2OFB(fbi);
930	struct fb_var_screeninfo *var = &fbi->var;
931	struct omap_overlay *ovl;
932	u16 posx, posy;
933	u16 outw, outh;
934	int i;
935
936#ifdef DEBUG
937	if (omapfb_test_pattern)
938		fill_fb(fbi);
939#endif
940
941	WARN_ON(!atomic_read(&ofbi->region->lock_count));
942
943	for (i = 0; i < ofbi->num_overlays; i++) {
944		ovl = ofbi->overlays[i];
945
946		DBG("apply_changes, fb %d, ovl %d\n", ofbi->id, ovl->id);
947
948		if (ofbi->region->size == 0) {
949			/* the fb is not available. disable the overlay */
950			omapfb_overlay_enable(ovl, 0);
951			if (!init && ovl->manager)
952				ovl->manager->apply(ovl->manager);
953			continue;
954		}
955
956		if (init || (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
957			int rotation = (var->rotate + ofbi->rotation[i]) % 4;
958			if (rotation == FB_ROTATE_CW ||
959					rotation == FB_ROTATE_CCW) {
960				outw = var->yres;
961				outh = var->xres;
962			} else {
963				outw = var->xres;
964				outh = var->yres;
965			}
966		} else {
967			struct omap_overlay_info info;
968			ovl->get_overlay_info(ovl, &info);
969			outw = info.out_width;
970			outh = info.out_height;
971		}
972
973		if (init) {
974			posx = 0;
975			posy = 0;
976		} else {
977			struct omap_overlay_info info;
978			ovl->get_overlay_info(ovl, &info);
979			posx = info.pos_x;
980			posy = info.pos_y;
981		}
982
983		r = omapfb_setup_overlay(fbi, ovl, posx, posy, outw, outh);
984		if (r)
985			goto err;
986
987		if (!init && ovl->manager)
988			ovl->manager->apply(ovl->manager);
989	}
990	return 0;
991err:
992	DBG("apply_changes failed\n");
993	return r;
994}
995
996/* checks var and eventually tweaks it to something supported,
997 * DO NOT MODIFY PAR */
998static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi)
999{
1000	struct omapfb_info *ofbi = FB2OFB(fbi);
1001	int r;
1002
1003	DBG("check_var(%d)\n", FB2OFB(fbi)->id);
1004
1005	omapfb_get_mem_region(ofbi->region);
1006
1007	r = check_fb_var(fbi, var);
1008
1009	omapfb_put_mem_region(ofbi->region);
1010
1011	return r;
1012}
1013
1014/* set the video mode according to info->var */
1015static int omapfb_set_par(struct fb_info *fbi)
1016{
1017	struct omapfb_info *ofbi = FB2OFB(fbi);
1018	int r;
1019
1020	DBG("set_par(%d)\n", FB2OFB(fbi)->id);
1021
1022	omapfb_get_mem_region(ofbi->region);
1023
1024	set_fb_fix(fbi);
1025
1026	r = setup_vrfb_rotation(fbi);
1027	if (r)
1028		goto out;
1029
1030	r = omapfb_apply_changes(fbi, 0);
1031
1032 out:
1033	omapfb_put_mem_region(ofbi->region);
1034
1035	return r;
1036}
1037
1038static int omapfb_pan_display(struct fb_var_screeninfo *var,
1039		struct fb_info *fbi)
1040{
1041	struct omapfb_info *ofbi = FB2OFB(fbi);
1042	struct fb_var_screeninfo new_var;
1043	int r;
1044
1045	DBG("pan_display(%d)\n", FB2OFB(fbi)->id);
1046
1047	if (var->xoffset == fbi->var.xoffset &&
1048	    var->yoffset == fbi->var.yoffset)
1049		return 0;
1050
1051	new_var = fbi->var;
1052	new_var.xoffset = var->xoffset;
1053	new_var.yoffset = var->yoffset;
1054
1055	fbi->var = new_var;
1056
1057	omapfb_get_mem_region(ofbi->region);
1058
1059	r = omapfb_apply_changes(fbi, 0);
1060
1061	omapfb_put_mem_region(ofbi->region);
1062
1063	return r;
1064}
1065
1066static void mmap_user_open(struct vm_area_struct *vma)
1067{
1068	struct omapfb2_mem_region *rg = vma->vm_private_data;
1069
1070	omapfb_get_mem_region(rg);
1071	atomic_inc(&rg->map_count);
1072	omapfb_put_mem_region(rg);
1073}
1074
1075static void mmap_user_close(struct vm_area_struct *vma)
1076{
1077	struct omapfb2_mem_region *rg = vma->vm_private_data;
1078
1079	omapfb_get_mem_region(rg);
1080	atomic_dec(&rg->map_count);
1081	omapfb_put_mem_region(rg);
1082}
1083
1084static const struct vm_operations_struct mmap_user_ops = {
1085	.open = mmap_user_open,
1086	.close = mmap_user_close,
1087};
1088
1089static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
1090{
1091	struct omapfb_info *ofbi = FB2OFB(fbi);
1092	struct fb_fix_screeninfo *fix = &fbi->fix;
1093	struct omapfb2_mem_region *rg;
1094	unsigned long start;
1095	u32 len;
1096	int r;
1097
1098	rg = omapfb_get_mem_region(ofbi->region);
1099
1100	start = omapfb_get_region_paddr(ofbi);
1101	len = fix->smem_len;
1102
1103	DBG("user mmap region start %lx, len %d, off %lx\n", start, len,
1104			vma->vm_pgoff << PAGE_SHIFT);
1105
1106	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
1107	vma->vm_ops = &mmap_user_ops;
1108	vma->vm_private_data = rg;
1109
1110	r = vm_iomap_memory(vma, start, len);
1111	if (r)
1112		goto error;
1113
1114	/* vm_ops.open won't be called for mmap itself. */
1115	atomic_inc(&rg->map_count);
1116
1117	omapfb_put_mem_region(rg);
1118
1119	return 0;
1120
1121error:
1122	omapfb_put_mem_region(ofbi->region);
1123
1124	return r;
1125}
1126
1127/* Store a single color palette entry into a pseudo palette or the hardware
1128 * palette if one is available. For now we support only 16bpp and thus store
1129 * the entry only to the pseudo palette.
1130 */
1131static int _setcolreg(struct fb_info *fbi, u_int regno, u_int red, u_int green,
1132		u_int blue, u_int transp, int update_hw_pal)
1133{
1134	/*struct omapfb_info *ofbi = FB2OFB(fbi);*/
1135	/*struct omapfb2_device *fbdev = ofbi->fbdev;*/
1136	struct fb_var_screeninfo *var = &fbi->var;
1137	int r = 0;
1138
1139	enum omapfb_color_format mode = OMAPFB_COLOR_RGB24U; /* XXX */
1140
1141	/*switch (plane->color_mode) {*/
1142	switch (mode) {
1143	case OMAPFB_COLOR_YUV422:
1144	case OMAPFB_COLOR_YUV420:
1145	case OMAPFB_COLOR_YUY422:
1146		r = -EINVAL;
1147		break;
1148	case OMAPFB_COLOR_CLUT_8BPP:
1149	case OMAPFB_COLOR_CLUT_4BPP:
1150	case OMAPFB_COLOR_CLUT_2BPP:
1151	case OMAPFB_COLOR_CLUT_1BPP:
1152		/*
1153		   if (fbdev->ctrl->setcolreg)
1154		   r = fbdev->ctrl->setcolreg(regno, red, green, blue,
1155		   transp, update_hw_pal);
1156		   */
1157		r = -EINVAL;
1158		break;
1159	case OMAPFB_COLOR_RGB565:
1160	case OMAPFB_COLOR_RGB444:
1161	case OMAPFB_COLOR_RGB24P:
1162	case OMAPFB_COLOR_RGB24U:
1163		if (regno < 16) {
1164			u32 pal;
1165			pal = ((red >> (16 - var->red.length)) <<
1166					var->red.offset) |
1167				((green >> (16 - var->green.length)) <<
1168				 var->green.offset) |
1169				(blue >> (16 - var->blue.length));
1170			((u32 *)(fbi->pseudo_palette))[regno] = pal;
1171		}
1172		break;
1173	default:
1174		BUG();
1175	}
1176	return r;
1177}
1178
1179static int omapfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
1180		u_int transp, struct fb_info *info)
1181{
1182	DBG("setcolreg\n");
1183
1184	return _setcolreg(info, regno, red, green, blue, transp, 1);
1185}
1186
1187static int omapfb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
1188{
1189	int count, index, r;
1190	u16 *red, *green, *blue, *transp;
1191	u16 trans = 0xffff;
1192
1193	DBG("setcmap\n");
1194
1195	red     = cmap->red;
1196	green   = cmap->green;
1197	blue    = cmap->blue;
1198	transp  = cmap->transp;
1199	index   = cmap->start;
1200
1201	for (count = 0; count < cmap->len; count++) {
1202		if (transp)
1203			trans = *transp++;
1204		r = _setcolreg(info, index++, *red++, *green++, *blue++, trans,
1205				count == cmap->len - 1);
1206		if (r != 0)
1207			return r;
1208	}
1209
1210	return 0;
1211}
1212
1213static int omapfb_blank(int blank, struct fb_info *fbi)
1214{
1215	struct omapfb_info *ofbi = FB2OFB(fbi);
1216	struct omapfb2_device *fbdev = ofbi->fbdev;
1217	struct omap_dss_device *display = fb2display(fbi);
1218	struct omapfb_display_data *d;
1219	int r = 0;
1220
1221	if (!display)
1222		return -EINVAL;
1223
1224	omapfb_lock(fbdev);
1225
1226	d = get_display_data(fbdev, display);
1227
1228	switch (blank) {
1229	case FB_BLANK_UNBLANK:
1230		if (display->state == OMAP_DSS_DISPLAY_ACTIVE)
1231			goto exit;
1232
1233		r = display->driver->enable(display);
1234
1235		if ((display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) &&
1236				d->update_mode == OMAPFB_AUTO_UPDATE &&
1237				!d->auto_update_work_enabled)
1238			omapfb_start_auto_update(fbdev, display);
1239
1240		break;
1241
1242	case FB_BLANK_NORMAL:
1243		/* FB_BLANK_NORMAL could be implemented.
1244		 * Needs DSS additions. */
1245	case FB_BLANK_VSYNC_SUSPEND:
1246	case FB_BLANK_HSYNC_SUSPEND:
1247	case FB_BLANK_POWERDOWN:
1248		if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
1249			goto exit;
1250
1251		if (d->auto_update_work_enabled)
1252			omapfb_stop_auto_update(fbdev, display);
1253
1254		display->driver->disable(display);
1255
1256		break;
1257
1258	default:
1259		r = -EINVAL;
1260	}
1261
1262exit:
1263	omapfb_unlock(fbdev);
1264
1265	return r;
1266}
1267
1268#if 0
1269/* XXX fb_read and fb_write are needed for VRFB */
1270ssize_t omapfb_write(struct fb_info *info, const char __user *buf,
1271		size_t count, loff_t *ppos)
1272{
1273	DBG("omapfb_write %d, %lu\n", count, (unsigned long)*ppos);
1274	/* XXX needed for VRFB */
1275	return count;
1276}
1277#endif
1278
1279static const struct fb_ops omapfb_ops = {
1280	.owner          = THIS_MODULE,
1281	.fb_open        = omapfb_open,
1282	.fb_release     = omapfb_release,
1283	.fb_fillrect    = cfb_fillrect,
1284	.fb_copyarea    = cfb_copyarea,
1285	.fb_imageblit   = cfb_imageblit,
1286	.fb_blank       = omapfb_blank,
1287	.fb_ioctl       = omapfb_ioctl,
1288	.fb_check_var   = omapfb_check_var,
1289	.fb_set_par     = omapfb_set_par,
1290	.fb_pan_display = omapfb_pan_display,
1291	.fb_mmap	= omapfb_mmap,
1292	.fb_setcolreg	= omapfb_setcolreg,
1293	.fb_setcmap	= omapfb_setcmap,
1294	/*.fb_write	= omapfb_write,*/
1295};
1296
1297static void omapfb_free_fbmem(struct fb_info *fbi)
1298{
1299	struct omapfb_info *ofbi = FB2OFB(fbi);
1300	struct omapfb2_device *fbdev = ofbi->fbdev;
1301	struct omapfb2_mem_region *rg;
1302
1303	rg = ofbi->region;
1304
1305	if (rg->token == NULL)
1306		return;
1307
1308	WARN_ON(atomic_read(&rg->map_count));
1309
1310	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
1311		/* unmap the 0 angle rotation */
1312		if (rg->vrfb.vaddr[0]) {
1313			iounmap(rg->vrfb.vaddr[0]);
1314			rg->vrfb.vaddr[0] = NULL;
1315		}
1316
1317		omap_vrfb_release_ctx(&rg->vrfb);
1318	}
1319
1320	dma_free_attrs(fbdev->dev, rg->size, rg->token, rg->dma_handle,
1321			rg->attrs);
1322
1323	rg->token = NULL;
1324	rg->vaddr = NULL;
1325	rg->paddr = 0;
1326	rg->alloc = 0;
1327	rg->size = 0;
1328}
1329
1330static void clear_fb_info(struct fb_info *fbi)
1331{
1332	memset(&fbi->var, 0, sizeof(fbi->var));
1333	memset(&fbi->fix, 0, sizeof(fbi->fix));
1334	strscpy(fbi->fix.id, MODULE_NAME, sizeof(fbi->fix.id));
1335}
1336
1337static int omapfb_free_all_fbmem(struct omapfb2_device *fbdev)
1338{
1339	int i;
1340
1341	DBG("free all fbmem\n");
1342
1343	for (i = 0; i < fbdev->num_fbs; i++) {
1344		struct fb_info *fbi = fbdev->fbs[i];
1345		omapfb_free_fbmem(fbi);
1346		clear_fb_info(fbi);
1347	}
1348
1349	return 0;
1350}
1351
1352static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
1353		unsigned long paddr)
1354{
1355	struct omapfb_info *ofbi = FB2OFB(fbi);
1356	struct omapfb2_device *fbdev = ofbi->fbdev;
1357	struct omapfb2_mem_region *rg;
1358	void *token;
1359	unsigned long attrs;
1360	dma_addr_t dma_handle;
1361	int r;
1362
1363	rg = ofbi->region;
1364
1365	rg->paddr = 0;
1366	rg->vaddr = NULL;
1367	memset(&rg->vrfb, 0, sizeof rg->vrfb);
1368	rg->size = 0;
1369	rg->type = 0;
1370	rg->alloc = false;
1371	rg->map = false;
1372
1373	size = PAGE_ALIGN(size);
1374
1375	attrs = DMA_ATTR_WRITE_COMBINE;
1376
1377	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
1378		attrs |= DMA_ATTR_NO_KERNEL_MAPPING;
1379
1380	DBG("allocating %lu bytes for fb %d\n", size, ofbi->id);
1381
1382	token = dma_alloc_attrs(fbdev->dev, size, &dma_handle,
1383			GFP_KERNEL, attrs);
1384
1385	if (token == NULL) {
1386		dev_err(fbdev->dev, "failed to allocate framebuffer\n");
1387		return -ENOMEM;
1388	}
1389
1390	DBG("allocated VRAM paddr %lx, vaddr %p\n",
1391			(unsigned long)dma_handle, token);
1392
1393	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
1394		r = omap_vrfb_request_ctx(&rg->vrfb);
1395		if (r) {
1396			dma_free_attrs(fbdev->dev, size, token, dma_handle,
1397					attrs);
1398			dev_err(fbdev->dev, "vrfb create ctx failed\n");
1399			return r;
1400		}
1401	}
1402
1403	rg->attrs = attrs;
1404	rg->token = token;
1405	rg->dma_handle = dma_handle;
1406
1407	rg->paddr = (unsigned long)dma_handle;
1408	rg->vaddr = (void __iomem *)token;
1409	rg->size = size;
1410	rg->alloc = 1;
1411
1412	return 0;
1413}
1414
1415/* allocate fbmem using display resolution as reference */
1416static int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size,
1417		unsigned long paddr)
1418{
1419	struct omapfb_info *ofbi = FB2OFB(fbi);
1420	struct omapfb2_device *fbdev = ofbi->fbdev;
1421	struct omap_dss_device *display;
1422	int bytespp;
1423
1424	display =  fb2display(fbi);
1425
1426	if (!display)
1427		return 0;
1428
1429	switch (omapfb_get_recommended_bpp(fbdev, display)) {
1430	case 16:
1431		bytespp = 2;
1432		break;
1433	case 24:
1434		bytespp = 4;
1435		break;
1436	default:
1437		bytespp = 4;
1438		break;
1439	}
1440
1441	if (!size) {
1442		u16 w, h;
1443
1444		display->driver->get_resolution(display, &w, &h);
1445
1446		if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
1447			size = max(omap_vrfb_min_phys_size(w, h, bytespp),
1448					omap_vrfb_min_phys_size(h, w, bytespp));
1449
1450			DBG("adjusting fb mem size for VRFB, %u -> %lu\n",
1451					w * h * bytespp, size);
1452		} else {
1453			size = w * h * bytespp;
1454		}
1455	}
1456
1457	if (!size)
1458		return 0;
1459
1460	return omapfb_alloc_fbmem(fbi, size, paddr);
1461}
1462
1463static int omapfb_parse_vram_param(const char *param, int max_entries,
1464		unsigned long *sizes, unsigned long *paddrs)
1465{
1466	unsigned int fbnum;
1467	unsigned long size;
1468	unsigned long paddr = 0;
1469	char *p, *start;
1470
1471	start = (char *)param;
1472
1473	while (1) {
1474		p = start;
1475
1476		fbnum = simple_strtoul(p, &p, 10);
1477
1478		if (p == start)
1479			return -EINVAL;
1480
1481		if (*p != ':')
1482			return -EINVAL;
1483
1484		if (fbnum >= max_entries)
1485			return -EINVAL;
1486
1487		size = memparse(p + 1, &p);
1488
1489		if (!size)
1490			return -EINVAL;
1491
1492		paddr = 0;
1493
1494		if (*p == '@') {
1495			paddr = simple_strtoul(p + 1, &p, 16);
1496
1497			if (!paddr)
1498				return -EINVAL;
1499
1500		}
1501
1502		WARN_ONCE(paddr,
1503			"reserving memory at predefined address not supported\n");
1504
1505		paddrs[fbnum] = paddr;
1506		sizes[fbnum] = size;
1507
1508		if (*p == 0)
1509			break;
1510
1511		if (*p != ',')
1512			return -EINVAL;
1513
1514		++p;
1515
1516		start = p;
1517	}
1518
1519	return 0;
1520}
1521
1522static int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev)
1523{
1524	int i, r;
1525	unsigned long vram_sizes[10];
1526	unsigned long vram_paddrs[10];
1527
1528	memset(&vram_sizes, 0, sizeof(vram_sizes));
1529	memset(&vram_paddrs, 0, sizeof(vram_paddrs));
1530
1531	if (def_vram &&	omapfb_parse_vram_param(def_vram, 10,
1532				vram_sizes, vram_paddrs)) {
1533		dev_err(fbdev->dev, "failed to parse vram parameter\n");
1534
1535		memset(&vram_sizes, 0, sizeof(vram_sizes));
1536		memset(&vram_paddrs, 0, sizeof(vram_paddrs));
1537	}
1538
1539	for (i = 0; i < fbdev->num_fbs; i++) {
1540		/* allocate memory automatically only for fb0, or if
1541		 * excplicitly defined with vram or plat data option */
1542		if (i == 0 || vram_sizes[i] != 0) {
1543			r = omapfb_alloc_fbmem_display(fbdev->fbs[i],
1544					vram_sizes[i], vram_paddrs[i]);
1545
1546			if (r)
1547				return r;
1548		}
1549	}
1550
1551	for (i = 0; i < fbdev->num_fbs; i++) {
1552		struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
1553		struct omapfb2_mem_region *rg;
1554		rg = ofbi->region;
1555
1556		DBG("region%d phys %08x virt %p size=%lu\n",
1557				i,
1558				rg->paddr,
1559				rg->vaddr,
1560				rg->size);
1561	}
1562
1563	return 0;
1564}
1565
1566static void omapfb_clear_fb(struct fb_info *fbi)
1567{
1568	const struct fb_fillrect rect = {
1569		.dx = 0,
1570		.dy = 0,
1571		.width = fbi->var.xres_virtual,
1572		.height = fbi->var.yres_virtual,
1573		.color = 0,
1574		.rop = ROP_COPY,
1575	};
1576
1577	cfb_fillrect(fbi, &rect);
1578}
1579
1580int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
1581{
1582	struct omapfb_info *ofbi = FB2OFB(fbi);
1583	struct omapfb2_device *fbdev = ofbi->fbdev;
1584	struct omapfb2_mem_region *rg = ofbi->region;
1585	unsigned long old_size = rg->size;
1586	unsigned long old_paddr = rg->paddr;
1587	int old_type = rg->type;
1588	int r;
1589
1590	if (type != OMAPFB_MEMTYPE_SDRAM)
1591		return -EINVAL;
1592
1593	size = PAGE_ALIGN(size);
1594
1595	if (old_size == size && old_type == type)
1596		return 0;
1597
1598	omapfb_free_fbmem(fbi);
1599
1600	if (size == 0) {
1601		clear_fb_info(fbi);
1602		return 0;
1603	}
1604
1605	r = omapfb_alloc_fbmem(fbi, size, 0);
1606
1607	if (r) {
1608		if (old_size)
1609			omapfb_alloc_fbmem(fbi, old_size, old_paddr);
1610
1611		if (rg->size == 0)
1612			clear_fb_info(fbi);
1613
1614		return r;
1615	}
1616
1617	if (old_size == size)
1618		return 0;
1619
1620	if (old_size == 0) {
1621		DBG("initializing fb %d\n", ofbi->id);
1622		r = omapfb_fb_init(fbdev, fbi);
1623		if (r) {
1624			DBG("omapfb_fb_init failed\n");
1625			goto err;
1626		}
1627		r = omapfb_apply_changes(fbi, 1);
1628		if (r) {
1629			DBG("omapfb_apply_changes failed\n");
1630			goto err;
1631		}
1632	} else {
1633		struct fb_var_screeninfo new_var;
1634		memcpy(&new_var, &fbi->var, sizeof(new_var));
1635		r = check_fb_var(fbi, &new_var);
1636		if (r)
1637			goto err;
1638		memcpy(&fbi->var, &new_var, sizeof(fbi->var));
1639		set_fb_fix(fbi);
1640		r = setup_vrfb_rotation(fbi);
1641		if (r)
1642			goto err;
1643	}
1644
1645	omapfb_clear_fb(fbi);
1646
1647	return 0;
1648err:
1649	omapfb_free_fbmem(fbi);
1650	clear_fb_info(fbi);
1651	return r;
1652}
1653
1654static void omapfb_auto_update_work(struct work_struct *work)
1655{
1656	struct omap_dss_device *dssdev;
1657	struct omap_dss_driver *dssdrv;
1658	struct omapfb_display_data *d;
1659	u16 w, h;
1660	unsigned int freq;
1661	struct omapfb2_device *fbdev;
1662
1663	d = container_of(work, struct omapfb_display_data,
1664			auto_update_work.work);
1665
1666	dssdev = d->dssdev;
1667	dssdrv = dssdev->driver;
1668	fbdev = d->fbdev;
1669
1670	if (!dssdrv || !dssdrv->update)
1671		return;
1672
1673	if (dssdrv->sync)
1674		dssdrv->sync(dssdev);
1675
1676	dssdrv->get_resolution(dssdev, &w, &h);
1677	dssdrv->update(dssdev, 0, 0, w, h);
1678
1679	freq = auto_update_freq;
1680	if (freq == 0)
1681		freq = 20;
1682	queue_delayed_work(fbdev->auto_update_wq,
1683			&d->auto_update_work, HZ / freq);
1684}
1685
1686void omapfb_start_auto_update(struct omapfb2_device *fbdev,
1687		struct omap_dss_device *display)
1688{
1689	struct omapfb_display_data *d;
1690
1691	if (fbdev->auto_update_wq == NULL) {
1692		struct workqueue_struct *wq;
1693
1694		wq = create_singlethread_workqueue("omapfb_auto_update");
1695
1696		if (wq == NULL) {
1697			dev_err(fbdev->dev, "Failed to create workqueue for "
1698					"auto-update\n");
1699			return;
1700		}
1701
1702		fbdev->auto_update_wq = wq;
1703	}
1704
1705	d = get_display_data(fbdev, display);
1706
1707	INIT_DELAYED_WORK(&d->auto_update_work, omapfb_auto_update_work);
1708
1709	d->auto_update_work_enabled = true;
1710
1711	omapfb_auto_update_work(&d->auto_update_work.work);
1712}
1713
1714void omapfb_stop_auto_update(struct omapfb2_device *fbdev,
1715		struct omap_dss_device *display)
1716{
1717	struct omapfb_display_data *d;
1718
1719	d = get_display_data(fbdev, display);
1720
1721	cancel_delayed_work_sync(&d->auto_update_work);
1722
1723	d->auto_update_work_enabled = false;
1724}
1725
1726/* initialize fb_info, var, fix to something sane based on the display */
1727static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
1728{
1729	struct fb_var_screeninfo *var = &fbi->var;
1730	struct omap_dss_device *display = fb2display(fbi);
1731	struct omapfb_info *ofbi = FB2OFB(fbi);
1732	int r = 0;
1733
1734	fbi->fbops = &omapfb_ops;
1735	fbi->pseudo_palette = fbdev->pseudo_palette;
1736
1737	if (ofbi->region->size == 0) {
1738		clear_fb_info(fbi);
1739		return 0;
1740	}
1741
1742	var->nonstd = 0;
1743	var->bits_per_pixel = 0;
1744
1745	var->rotate = def_rotate;
1746
1747	if (display) {
1748		u16 w, h;
1749		int rotation = (var->rotate + ofbi->rotation[0]) % 4;
1750
1751		display->driver->get_resolution(display, &w, &h);
1752
1753		if (rotation == FB_ROTATE_CW ||
1754				rotation == FB_ROTATE_CCW) {
1755			var->xres = h;
1756			var->yres = w;
1757		} else {
1758			var->xres = w;
1759			var->yres = h;
1760		}
1761
1762		var->xres_virtual = var->xres;
1763		var->yres_virtual = var->yres;
1764
1765		if (!var->bits_per_pixel) {
1766			switch (omapfb_get_recommended_bpp(fbdev, display)) {
1767			case 16:
1768				var->bits_per_pixel = 16;
1769				break;
1770			case 24:
1771				var->bits_per_pixel = 32;
1772				break;
1773			default:
1774				dev_err(fbdev->dev, "illegal display "
1775						"bpp\n");
1776				return -EINVAL;
1777			}
1778		}
1779	} else {
1780		/* if there's no display, let's just guess some basic values */
1781		var->xres = 320;
1782		var->yres = 240;
1783		var->xres_virtual = var->xres;
1784		var->yres_virtual = var->yres;
1785		if (!var->bits_per_pixel)
1786			var->bits_per_pixel = 16;
1787	}
1788
1789	r = check_fb_var(fbi, var);
1790	if (r)
1791		goto err;
1792
1793	set_fb_fix(fbi);
1794	r = setup_vrfb_rotation(fbi);
1795	if (r)
1796		goto err;
1797
1798	r = fb_alloc_cmap(&fbi->cmap, 256, 0);
1799	if (r)
1800		dev_err(fbdev->dev, "unable to allocate color map memory\n");
1801
1802err:
1803	return r;
1804}
1805
1806static void fbinfo_cleanup(struct omapfb2_device *fbdev, struct fb_info *fbi)
1807{
1808	fb_dealloc_cmap(&fbi->cmap);
1809}
1810
1811
1812static void omapfb_free_resources(struct omapfb2_device *fbdev)
1813{
1814	int i;
1815
1816	DBG("free_resources\n");
1817
1818	if (fbdev == NULL)
1819		return;
1820
1821	for (i = 0; i < fbdev->num_overlays; i++) {
1822		struct omap_overlay *ovl = fbdev->overlays[i];
1823
1824		ovl->disable(ovl);
1825
1826		if (ovl->manager)
1827			ovl->unset_manager(ovl);
1828	}
1829
1830	for (i = 0; i < fbdev->num_fbs; i++)
1831		unregister_framebuffer(fbdev->fbs[i]);
1832
1833	/* free the reserved fbmem */
1834	omapfb_free_all_fbmem(fbdev);
1835
1836	for (i = 0; i < fbdev->num_fbs; i++) {
1837		fbinfo_cleanup(fbdev, fbdev->fbs[i]);
1838		framebuffer_release(fbdev->fbs[i]);
1839	}
1840
1841	for (i = 0; i < fbdev->num_displays; i++) {
1842		struct omap_dss_device *dssdev = fbdev->displays[i].dssdev;
1843
1844		if (fbdev->displays[i].auto_update_work_enabled)
1845			omapfb_stop_auto_update(fbdev, dssdev);
1846
1847		if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)
1848			dssdev->driver->disable(dssdev);
1849
1850		dssdev->driver->disconnect(dssdev);
1851
1852		omap_dss_put_device(dssdev);
1853	}
1854
1855	if (fbdev->auto_update_wq != NULL) {
1856		destroy_workqueue(fbdev->auto_update_wq);
1857		fbdev->auto_update_wq = NULL;
1858	}
1859
1860	dev_set_drvdata(fbdev->dev, NULL);
1861}
1862
1863static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
1864{
1865	int r, i;
1866
1867	fbdev->num_fbs = 0;
1868
1869	DBG("create %d framebuffers\n",	CONFIG_FB_OMAP2_NUM_FBS);
1870
1871	/* allocate fb_infos */
1872	for (i = 0; i < CONFIG_FB_OMAP2_NUM_FBS; i++) {
1873		struct fb_info *fbi;
1874		struct omapfb_info *ofbi;
1875
1876		fbi = framebuffer_alloc(sizeof(struct omapfb_info),
1877				fbdev->dev);
1878		if (!fbi)
1879			return -ENOMEM;
1880
1881		clear_fb_info(fbi);
1882
1883		fbdev->fbs[i] = fbi;
1884
1885		ofbi = FB2OFB(fbi);
1886		ofbi->fbdev = fbdev;
1887		ofbi->id = i;
1888
1889		ofbi->region = &fbdev->regions[i];
1890		ofbi->region->id = i;
1891		init_rwsem(&ofbi->region->lock);
1892
1893		/* assign these early, so that fb alloc can use them */
1894		ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB :
1895			OMAP_DSS_ROT_DMA;
1896		ofbi->mirror = def_mirror;
1897
1898		fbdev->num_fbs++;
1899	}
1900
1901	DBG("fb_infos allocated\n");
1902
1903	/* assign overlays for the fbs */
1904	for (i = 0; i < min(fbdev->num_fbs, fbdev->num_overlays); i++) {
1905		struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
1906
1907		ofbi->overlays[0] = fbdev->overlays[i];
1908		ofbi->num_overlays = 1;
1909	}
1910
1911	/* allocate fb memories */
1912	r = omapfb_allocate_all_fbs(fbdev);
1913	if (r) {
1914		dev_err(fbdev->dev, "failed to allocate fbmem\n");
1915		return r;
1916	}
1917
1918	DBG("fbmems allocated\n");
1919
1920	/* setup fb_infos */
1921	for (i = 0; i < fbdev->num_fbs; i++) {
1922		struct fb_info *fbi = fbdev->fbs[i];
1923		struct omapfb_info *ofbi = FB2OFB(fbi);
1924
1925		omapfb_get_mem_region(ofbi->region);
1926		r = omapfb_fb_init(fbdev, fbi);
1927		omapfb_put_mem_region(ofbi->region);
1928
1929		if (r) {
1930			dev_err(fbdev->dev, "failed to setup fb_info\n");
1931			return r;
1932		}
1933	}
1934
1935	for (i = 0; i < fbdev->num_fbs; i++) {
1936		struct fb_info *fbi = fbdev->fbs[i];
1937		struct omapfb_info *ofbi = FB2OFB(fbi);
1938
1939		if (ofbi->region->size == 0)
1940			continue;
1941
1942		omapfb_clear_fb(fbi);
1943	}
1944
1945	DBG("fb_infos initialized\n");
1946
1947	for (i = 0; i < fbdev->num_fbs; i++) {
1948		r = register_framebuffer(fbdev->fbs[i]);
1949		if (r != 0) {
1950			dev_err(fbdev->dev,
1951				"registering framebuffer %d failed\n", i);
1952			return r;
1953		}
1954	}
1955
1956	DBG("framebuffers registered\n");
1957
1958	for (i = 0; i < fbdev->num_fbs; i++) {
1959		struct fb_info *fbi = fbdev->fbs[i];
1960		struct omapfb_info *ofbi = FB2OFB(fbi);
1961
1962		omapfb_get_mem_region(ofbi->region);
1963		r = omapfb_apply_changes(fbi, 1);
1964		omapfb_put_mem_region(ofbi->region);
1965
1966		if (r) {
1967			dev_err(fbdev->dev, "failed to change mode\n");
1968			return r;
1969		}
1970	}
1971
1972	/* Enable fb0 */
1973	if (fbdev->num_fbs > 0) {
1974		struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[0]);
1975
1976		if (ofbi->num_overlays > 0) {
1977			struct omap_overlay *ovl = ofbi->overlays[0];
1978
1979			ovl->manager->apply(ovl->manager);
1980
1981			r = omapfb_overlay_enable(ovl, 1);
1982
1983			if (r) {
1984				dev_err(fbdev->dev,
1985						"failed to enable overlay\n");
1986				return r;
1987			}
1988		}
1989	}
1990
1991	DBG("create_framebuffers done\n");
1992
1993	return 0;
1994}
1995
1996static int omapfb_mode_to_timings(const char *mode_str,
1997		struct omap_dss_device *display,
1998		struct omap_video_timings *timings, u8 *bpp)
1999{
2000	struct fb_info *fbi;
2001	struct fb_var_screeninfo *var;
2002	struct fb_ops *fbops;
2003	int r;
2004
2005#ifdef CONFIG_OMAP2_DSS_VENC
2006	if (strcmp(mode_str, "pal") == 0) {
2007		*timings = omap_dss_pal_timings;
2008		*bpp = 24;
2009		return 0;
2010	} else if (strcmp(mode_str, "ntsc") == 0) {
2011		*timings = omap_dss_ntsc_timings;
2012		*bpp = 24;
2013		return 0;
2014	}
2015#endif
2016
2017	/* this is quite a hack, but I wanted to use the modedb and for
2018	 * that we need fb_info and var, so we create dummy ones */
2019
2020	*bpp = 0;
2021	fbi = NULL;
2022	var = NULL;
2023	fbops = NULL;
2024
2025	fbi = kzalloc(sizeof(*fbi), GFP_KERNEL);
2026	if (fbi == NULL) {
2027		r = -ENOMEM;
2028		goto err;
2029	}
2030
2031	var = kzalloc(sizeof(*var), GFP_KERNEL);
2032	if (var == NULL) {
2033		r = -ENOMEM;
2034		goto err;
2035	}
2036
2037	fbops = kzalloc(sizeof(*fbops), GFP_KERNEL);
2038	if (fbops == NULL) {
2039		r = -ENOMEM;
2040		goto err;
2041	}
2042
2043	fbi->fbops = fbops;
2044
2045	r = fb_find_mode(var, fbi, mode_str, NULL, 0, NULL, 24);
2046	if (r == 0) {
2047		r = -EINVAL;
2048		goto err;
2049	}
2050
2051	if (display->driver->get_timings) {
2052		display->driver->get_timings(display, timings);
2053	} else {
2054		timings->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
2055		timings->de_level = OMAPDSS_SIG_ACTIVE_HIGH;
2056		timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE;
2057	}
2058
2059	timings->pixelclock = PICOS2KHZ(var->pixclock) * 1000;
2060	timings->hbp = var->left_margin;
2061	timings->hfp = var->right_margin;
2062	timings->vbp = var->upper_margin;
2063	timings->vfp = var->lower_margin;
2064	timings->hsw = var->hsync_len;
2065	timings->vsw = var->vsync_len;
2066	timings->x_res = var->xres;
2067	timings->y_res = var->yres;
2068	timings->hsync_level = var->sync & FB_SYNC_HOR_HIGH_ACT ?
2069				OMAPDSS_SIG_ACTIVE_HIGH :
2070				OMAPDSS_SIG_ACTIVE_LOW;
2071	timings->vsync_level = var->sync & FB_SYNC_VERT_HIGH_ACT ?
2072				OMAPDSS_SIG_ACTIVE_HIGH :
2073				OMAPDSS_SIG_ACTIVE_LOW;
2074	timings->interlace = var->vmode & FB_VMODE_INTERLACED;
2075
2076	switch (var->bits_per_pixel) {
2077	case 16:
2078		*bpp = 16;
2079		break;
2080	case 24:
2081	case 32:
2082	default:
2083		*bpp = 24;
2084		break;
2085	}
2086
2087	r = 0;
2088
2089err:
2090	kfree(fbi);
2091	kfree(var);
2092	kfree(fbops);
2093
2094	return r;
2095}
2096
2097static int omapfb_set_def_mode(struct omapfb2_device *fbdev,
2098		struct omap_dss_device *display, char *mode_str)
2099{
2100	int r;
2101	u8 bpp;
2102	struct omap_video_timings timings, temp_timings;
2103	struct omapfb_display_data *d;
2104
2105	r = omapfb_mode_to_timings(mode_str, display, &timings, &bpp);
2106	if (r)
2107		return r;
2108
2109	d = get_display_data(fbdev, display);
2110	d->bpp_override = bpp;
2111
2112	if (display->driver->check_timings) {
2113		r = display->driver->check_timings(display, &timings);
2114		if (r)
2115			return r;
2116	} else {
2117		/* If check_timings is not present compare xres and yres */
2118		if (display->driver->get_timings) {
2119			display->driver->get_timings(display, &temp_timings);
2120
2121			if (temp_timings.x_res != timings.x_res ||
2122				temp_timings.y_res != timings.y_res)
2123				return -EINVAL;
2124		}
2125	}
2126
2127	if (display->driver->set_timings)
2128			display->driver->set_timings(display, &timings);
2129
2130	return 0;
2131}
2132
2133static int omapfb_get_recommended_bpp(struct omapfb2_device *fbdev,
2134		struct omap_dss_device *dssdev)
2135{
2136	struct omapfb_display_data *d;
2137
2138	BUG_ON(dssdev->driver->get_recommended_bpp == NULL);
2139
2140	d = get_display_data(fbdev, dssdev);
2141
2142	if (d->bpp_override != 0)
2143		return d->bpp_override;
2144
2145	return dssdev->driver->get_recommended_bpp(dssdev);
2146}
2147
2148static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
2149{
2150	char *str, *options, *this_opt;
2151	int r = 0;
2152
2153	str = kstrdup(def_mode, GFP_KERNEL);
2154	if (!str)
2155		return -ENOMEM;
2156	options = str;
2157
2158	while (!r && (this_opt = strsep(&options, ",")) != NULL) {
2159		char *p, *display_str, *mode_str;
2160		struct omap_dss_device *display;
2161		int i;
2162
2163		p = strchr(this_opt, ':');
2164		if (!p) {
2165			r = -EINVAL;
2166			break;
2167		}
2168
2169		*p = 0;
2170		display_str = this_opt;
2171		mode_str = p + 1;
2172
2173		display = NULL;
2174		for (i = 0; i < fbdev->num_displays; ++i) {
2175			if (strcmp(fbdev->displays[i].dssdev->name,
2176						display_str) == 0) {
2177				display = fbdev->displays[i].dssdev;
2178				break;
2179			}
2180		}
2181
2182		if (!display) {
2183			r = -EINVAL;
2184			break;
2185		}
2186
2187		r = omapfb_set_def_mode(fbdev, display, mode_str);
2188		if (r)
2189			break;
2190	}
2191
2192	kfree(str);
2193
2194	return r;
2195}
2196
2197static void fb_videomode_to_omap_timings(struct fb_videomode *m,
2198		struct omap_dss_device *display,
2199		struct omap_video_timings *t)
2200{
2201	if (display->driver->get_timings) {
2202		display->driver->get_timings(display, t);
2203	} else {
2204		t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
2205		t->de_level = OMAPDSS_SIG_ACTIVE_HIGH;
2206		t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE;
2207	}
2208
2209	t->x_res = m->xres;
2210	t->y_res = m->yres;
2211	t->pixelclock = PICOS2KHZ(m->pixclock) * 1000;
2212	t->hsw = m->hsync_len;
2213	t->hfp = m->right_margin;
2214	t->hbp = m->left_margin;
2215	t->vsw = m->vsync_len;
2216	t->vfp = m->lower_margin;
2217	t->vbp = m->upper_margin;
2218	t->hsync_level = m->sync & FB_SYNC_HOR_HIGH_ACT ?
2219				OMAPDSS_SIG_ACTIVE_HIGH :
2220				OMAPDSS_SIG_ACTIVE_LOW;
2221	t->vsync_level = m->sync & FB_SYNC_VERT_HIGH_ACT ?
2222				OMAPDSS_SIG_ACTIVE_HIGH :
2223				OMAPDSS_SIG_ACTIVE_LOW;
2224	t->interlace = m->vmode & FB_VMODE_INTERLACED;
2225}
2226
2227static int omapfb_find_best_mode(struct omap_dss_device *display,
2228		struct omap_video_timings *timings)
2229{
2230	struct fb_monspecs *specs;
2231	u8 *edid;
2232	int r, i, best_idx, len;
2233
2234	if (!display->driver->read_edid)
2235		return -ENODEV;
2236
2237	len = 0x80 * 2;
2238	edid = kmalloc(len, GFP_KERNEL);
2239	if (edid == NULL)
2240		return -ENOMEM;
2241
2242	r = display->driver->read_edid(display, edid, len);
2243	if (r < 0)
2244		goto err1;
2245
2246	specs = kzalloc(sizeof(*specs), GFP_KERNEL);
2247	if (specs == NULL) {
2248		r = -ENOMEM;
2249		goto err1;
2250	}
2251
2252	fb_edid_to_monspecs(edid, specs);
2253
2254	best_idx = -1;
2255
2256	for (i = 0; i < specs->modedb_len; ++i) {
2257		struct fb_videomode *m;
2258		struct omap_video_timings t;
2259
2260		m = &specs->modedb[i];
2261
2262		if (m->pixclock == 0)
2263			continue;
2264
2265		/* skip repeated pixel modes */
2266		if (m->xres == 2880 || m->xres == 1440)
2267			continue;
2268
2269		if (m->vmode & FB_VMODE_INTERLACED ||
2270				m->vmode & FB_VMODE_DOUBLE)
2271			continue;
2272
2273		fb_videomode_to_omap_timings(m, display, &t);
2274
2275		r = display->driver->check_timings(display, &t);
2276		if (r == 0) {
2277			best_idx = i;
2278			break;
2279		}
2280	}
2281
2282	if (best_idx == -1) {
2283		r = -ENOENT;
2284		goto err2;
2285	}
2286
2287	fb_videomode_to_omap_timings(&specs->modedb[best_idx], display,
2288		timings);
2289
2290	r = 0;
2291
2292err2:
2293	fb_destroy_modedb(specs->modedb);
2294	kfree(specs);
2295err1:
2296	kfree(edid);
2297
2298	return r;
2299}
2300
2301static int omapfb_init_display(struct omapfb2_device *fbdev,
2302		struct omap_dss_device *dssdev)
2303{
2304	struct omap_dss_driver *dssdrv = dssdev->driver;
2305	struct omapfb_display_data *d;
2306	int r;
2307
2308	r = dssdrv->enable(dssdev);
2309	if (r) {
2310		dev_warn(fbdev->dev, "Failed to enable display '%s'\n",
2311				dssdev->name);
2312		return r;
2313	}
2314
2315	d = get_display_data(fbdev, dssdev);
2316
2317	d->fbdev = fbdev;
2318
2319	if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
2320		u16 w, h;
2321
2322		if (auto_update) {
2323			omapfb_start_auto_update(fbdev, dssdev);
2324			d->update_mode = OMAPFB_AUTO_UPDATE;
2325		} else {
2326			d->update_mode = OMAPFB_MANUAL_UPDATE;
2327		}
2328
2329		if (dssdrv->enable_te) {
2330			r = dssdrv->enable_te(dssdev, 1);
2331			if (r) {
2332				dev_err(fbdev->dev, "Failed to set TE\n");
2333				return r;
2334			}
2335		}
2336
2337		dssdrv->get_resolution(dssdev, &w, &h);
2338		r = dssdrv->update(dssdev, 0, 0, w, h);
2339		if (r) {
2340			dev_err(fbdev->dev,
2341					"Failed to update display\n");
2342			return r;
2343		}
2344	} else {
2345		d->update_mode = OMAPFB_AUTO_UPDATE;
2346	}
2347
2348	return 0;
2349}
2350
2351static int omapfb_init_connections(struct omapfb2_device *fbdev,
2352		struct omap_dss_device *def_dssdev)
2353{
2354	int i, r;
2355	struct omap_overlay_manager *mgr;
2356
2357	r = def_dssdev->driver->connect(def_dssdev);
2358	if (r) {
2359		dev_err(fbdev->dev, "failed to connect default display\n");
2360		return r;
2361	}
2362
2363	for (i = 0; i < fbdev->num_displays; ++i) {
2364		struct omap_dss_device *dssdev = fbdev->displays[i].dssdev;
2365
2366		if (dssdev == def_dssdev)
2367			continue;
2368
2369		/*
2370		 * We don't care if the connect succeeds or not. We just want to
2371		 * connect as many displays as possible.
2372		 */
2373		dssdev->driver->connect(dssdev);
2374	}
2375
2376	mgr = omapdss_find_mgr_from_display(def_dssdev);
2377
2378	if (!mgr) {
2379		dev_err(fbdev->dev, "no ovl manager for the default display\n");
2380		return -EINVAL;
2381	}
2382
2383	for (i = 0; i < fbdev->num_overlays; i++) {
2384		struct omap_overlay *ovl = fbdev->overlays[i];
2385
2386		if (ovl->manager)
2387			ovl->unset_manager(ovl);
2388
2389		r = ovl->set_manager(ovl, mgr);
2390		if (r)
2391			dev_warn(fbdev->dev,
2392					"failed to connect overlay %s to manager %s\n",
2393					ovl->name, mgr->name);
2394	}
2395
2396	return 0;
2397}
2398
2399static struct omap_dss_device *
2400omapfb_find_default_display(struct omapfb2_device *fbdev)
2401{
2402	const char *def_name;
2403	int i;
2404
2405	/*
2406	 * Search with the display name from the user or the board file,
2407	 * comparing to display names and aliases
2408	 */
2409
2410	def_name = omapdss_get_default_display_name();
2411
2412	if (def_name) {
2413		for (i = 0; i < fbdev->num_displays; ++i) {
2414			struct omap_dss_device *dssdev;
2415
2416			dssdev = fbdev->displays[i].dssdev;
2417
2418			if (dssdev->name && strcmp(def_name, dssdev->name) == 0)
2419				return dssdev;
2420
2421			if (strcmp(def_name, dssdev->alias) == 0)
2422				return dssdev;
2423		}
2424
2425		/* def_name given but not found */
2426		return NULL;
2427	}
2428
2429	/* then look for DT alias display0 */
2430	for (i = 0; i < fbdev->num_displays; ++i) {
2431		struct omap_dss_device *dssdev;
2432		int id;
2433
2434		dssdev = fbdev->displays[i].dssdev;
2435
2436		if (dssdev->dev->of_node == NULL)
2437			continue;
2438
2439		id = of_alias_get_id(dssdev->dev->of_node, "display");
2440		if (id == 0)
2441			return dssdev;
2442	}
2443
2444	/* return the first display we have in the list */
2445	return fbdev->displays[0].dssdev;
2446}
2447
2448static int omapfb_probe(struct platform_device *pdev)
2449{
2450	struct omapfb2_device *fbdev = NULL;
2451	int r = 0;
2452	int i;
2453	struct omap_dss_device *def_display;
2454	struct omap_dss_device *dssdev;
2455
2456	DBG("omapfb_probe\n");
2457
2458	if (omapdss_is_initialized() == false)
2459		return -EPROBE_DEFER;
2460
2461	if (pdev->num_resources != 0) {
2462		dev_err(&pdev->dev, "probed for an unknown device\n");
2463		r = -ENODEV;
2464		goto err0;
2465	}
2466
2467	fbdev = devm_kzalloc(&pdev->dev, sizeof(struct omapfb2_device),
2468			GFP_KERNEL);
2469	if (fbdev == NULL) {
2470		r = -ENOMEM;
2471		goto err0;
2472	}
2473
2474	if (def_vrfb && !omap_vrfb_supported()) {
2475		def_vrfb = 0;
2476		dev_warn(&pdev->dev, "VRFB is not supported on this hardware, "
2477				"ignoring the module parameter vrfb=y\n");
2478	}
2479
2480	r = omapdss_compat_init();
2481	if (r)
2482		goto err0;
2483
2484	mutex_init(&fbdev->mtx);
2485
2486	fbdev->dev = &pdev->dev;
2487	platform_set_drvdata(pdev, fbdev);
2488
2489	fbdev->num_displays = 0;
2490	dssdev = NULL;
2491	for_each_dss_dev(dssdev) {
2492		struct omapfb_display_data *d;
2493
2494		omap_dss_get_device(dssdev);
2495
2496		if (!dssdev->driver) {
2497			dev_warn(&pdev->dev, "no driver for display: %s\n",
2498				dssdev->name);
2499			omap_dss_put_device(dssdev);
2500			continue;
2501		}
2502
2503		d = &fbdev->displays[fbdev->num_displays++];
2504		d->dssdev = dssdev;
2505		if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE)
2506			d->update_mode = OMAPFB_MANUAL_UPDATE;
2507		else
2508			d->update_mode = OMAPFB_AUTO_UPDATE;
2509	}
2510
2511	if (fbdev->num_displays == 0) {
2512		dev_err(&pdev->dev, "no displays\n");
2513		r = -EPROBE_DEFER;
2514		goto cleanup;
2515	}
2516
2517	fbdev->num_overlays = omap_dss_get_num_overlays();
2518	for (i = 0; i < fbdev->num_overlays; i++)
2519		fbdev->overlays[i] = omap_dss_get_overlay(i);
2520
2521	fbdev->num_managers = omap_dss_get_num_overlay_managers();
2522	for (i = 0; i < fbdev->num_managers; i++)
2523		fbdev->managers[i] = omap_dss_get_overlay_manager(i);
2524
2525	def_display = omapfb_find_default_display(fbdev);
2526	if (def_display == NULL) {
2527		dev_err(fbdev->dev, "failed to find default display\n");
2528		r = -EPROBE_DEFER;
2529		goto cleanup;
2530	}
2531
2532	r = omapfb_init_connections(fbdev, def_display);
2533	if (r) {
2534		dev_err(fbdev->dev, "failed to init overlay connections\n");
2535		goto cleanup;
2536	}
2537
2538	if (def_mode && strlen(def_mode) > 0) {
2539		if (omapfb_parse_def_modes(fbdev))
2540			dev_warn(&pdev->dev, "cannot parse default modes\n");
2541	} else if (def_display && def_display->driver->set_timings &&
2542			def_display->driver->check_timings) {
2543		struct omap_video_timings t;
2544
2545		r = omapfb_find_best_mode(def_display, &t);
2546
2547		if (r == 0)
2548			def_display->driver->set_timings(def_display, &t);
2549	}
2550
2551	r = omapfb_create_framebuffers(fbdev);
2552	if (r)
2553		goto cleanup;
2554
2555	for (i = 0; i < fbdev->num_managers; i++) {
2556		struct omap_overlay_manager *mgr;
2557		mgr = fbdev->managers[i];
2558		r = mgr->apply(mgr);
2559		if (r)
2560			dev_warn(fbdev->dev, "failed to apply dispc config\n");
2561	}
2562
2563	DBG("mgr->apply'ed\n");
2564
2565	if (def_display) {
2566		r = omapfb_init_display(fbdev, def_display);
2567		if (r) {
2568			dev_err(fbdev->dev,
2569					"failed to initialize default "
2570					"display\n");
2571			goto cleanup;
2572		}
2573	}
2574
2575	DBG("create sysfs for fbs\n");
2576	r = omapfb_create_sysfs(fbdev);
2577	if (r) {
2578		dev_err(fbdev->dev, "failed to create sysfs entries\n");
2579		goto cleanup;
2580	}
2581
2582	if (def_display) {
2583		u16 w, h;
2584
2585		def_display->driver->get_resolution(def_display, &w, &h);
2586
2587		dev_info(fbdev->dev, "using display '%s' mode %dx%d\n",
2588			def_display->name, w, h);
2589	}
2590
2591	return 0;
2592
2593cleanup:
2594	omapfb_free_resources(fbdev);
2595	omapdss_compat_uninit();
2596err0:
2597	dev_err(&pdev->dev, "failed to setup omapfb\n");
2598	return r;
2599}
2600
2601static void omapfb_remove(struct platform_device *pdev)
2602{
2603	struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
2604
2605	/* FIXME: wait till completion of pending events */
2606
2607	omapfb_remove_sysfs(fbdev);
2608
2609	omapfb_free_resources(fbdev);
2610
2611	omapdss_compat_uninit();
2612}
2613
2614static struct platform_driver omapfb_driver = {
2615	.probe		= omapfb_probe,
2616	.remove_new     = omapfb_remove,
2617	.driver         = {
2618		.name   = "omapfb",
2619	},
2620};
2621
2622module_param_named(mode, def_mode, charp, 0);
2623module_param_named(vram, def_vram, charp, 0);
2624module_param_named(rotate, def_rotate, int, 0);
2625module_param_named(vrfb, def_vrfb, bool, 0);
2626module_param_named(mirror, def_mirror, bool, 0);
2627
2628module_platform_driver(omapfb_driver);
2629
2630MODULE_ALIAS("platform:omapfb");
2631MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
2632MODULE_DESCRIPTION("OMAP2/3 Framebuffer");
2633MODULE_LICENSE("GPL v2");
2634