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	strlcpy(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->flags = FBINFO_FLAG_DEFAULT;
1736	fbi->pseudo_palette = fbdev->pseudo_palette;
1737
1738	if (ofbi->region->size == 0) {
1739		clear_fb_info(fbi);
1740		return 0;
1741	}
1742
1743	var->nonstd = 0;
1744	var->bits_per_pixel = 0;
1745
1746	var->rotate = def_rotate;
1747
1748	if (display) {
1749		u16 w, h;
1750		int rotation = (var->rotate + ofbi->rotation[0]) % 4;
1751
1752		display->driver->get_resolution(display, &w, &h);
1753
1754		if (rotation == FB_ROTATE_CW ||
1755				rotation == FB_ROTATE_CCW) {
1756			var->xres = h;
1757			var->yres = w;
1758		} else {
1759			var->xres = w;
1760			var->yres = h;
1761		}
1762
1763		var->xres_virtual = var->xres;
1764		var->yres_virtual = var->yres;
1765
1766		if (!var->bits_per_pixel) {
1767			switch (omapfb_get_recommended_bpp(fbdev, display)) {
1768			case 16:
1769				var->bits_per_pixel = 16;
1770				break;
1771			case 24:
1772				var->bits_per_pixel = 32;
1773				break;
1774			default:
1775				dev_err(fbdev->dev, "illegal display "
1776						"bpp\n");
1777				return -EINVAL;
1778			}
1779		}
1780	} else {
1781		/* if there's no display, let's just guess some basic values */
1782		var->xres = 320;
1783		var->yres = 240;
1784		var->xres_virtual = var->xres;
1785		var->yres_virtual = var->yres;
1786		if (!var->bits_per_pixel)
1787			var->bits_per_pixel = 16;
1788	}
1789
1790	r = check_fb_var(fbi, var);
1791	if (r)
1792		goto err;
1793
1794	set_fb_fix(fbi);
1795	r = setup_vrfb_rotation(fbi);
1796	if (r)
1797		goto err;
1798
1799	r = fb_alloc_cmap(&fbi->cmap, 256, 0);
1800	if (r)
1801		dev_err(fbdev->dev, "unable to allocate color map memory\n");
1802
1803err:
1804	return r;
1805}
1806
1807static void fbinfo_cleanup(struct omapfb2_device *fbdev, struct fb_info *fbi)
1808{
1809	fb_dealloc_cmap(&fbi->cmap);
1810}
1811
1812
1813static void omapfb_free_resources(struct omapfb2_device *fbdev)
1814{
1815	int i;
1816
1817	DBG("free_resources\n");
1818
1819	if (fbdev == NULL)
1820		return;
1821
1822	for (i = 0; i < fbdev->num_overlays; i++) {
1823		struct omap_overlay *ovl = fbdev->overlays[i];
1824
1825		ovl->disable(ovl);
1826
1827		if (ovl->manager)
1828			ovl->unset_manager(ovl);
1829	}
1830
1831	for (i = 0; i < fbdev->num_fbs; i++)
1832		unregister_framebuffer(fbdev->fbs[i]);
1833
1834	/* free the reserved fbmem */
1835	omapfb_free_all_fbmem(fbdev);
1836
1837	for (i = 0; i < fbdev->num_fbs; i++) {
1838		fbinfo_cleanup(fbdev, fbdev->fbs[i]);
1839		framebuffer_release(fbdev->fbs[i]);
1840	}
1841
1842	for (i = 0; i < fbdev->num_displays; i++) {
1843		struct omap_dss_device *dssdev = fbdev->displays[i].dssdev;
1844
1845		if (fbdev->displays[i].auto_update_work_enabled)
1846			omapfb_stop_auto_update(fbdev, dssdev);
1847
1848		if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)
1849			dssdev->driver->disable(dssdev);
1850
1851		dssdev->driver->disconnect(dssdev);
1852
1853		omap_dss_put_device(dssdev);
1854	}
1855
1856	if (fbdev->auto_update_wq != NULL) {
1857		flush_workqueue(fbdev->auto_update_wq);
1858		destroy_workqueue(fbdev->auto_update_wq);
1859		fbdev->auto_update_wq = NULL;
1860	}
1861
1862	dev_set_drvdata(fbdev->dev, NULL);
1863}
1864
1865static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
1866{
1867	int r, i;
1868
1869	fbdev->num_fbs = 0;
1870
1871	DBG("create %d framebuffers\n",	CONFIG_FB_OMAP2_NUM_FBS);
1872
1873	/* allocate fb_infos */
1874	for (i = 0; i < CONFIG_FB_OMAP2_NUM_FBS; i++) {
1875		struct fb_info *fbi;
1876		struct omapfb_info *ofbi;
1877
1878		fbi = framebuffer_alloc(sizeof(struct omapfb_info),
1879				fbdev->dev);
1880		if (!fbi)
1881			return -ENOMEM;
1882
1883		clear_fb_info(fbi);
1884
1885		fbdev->fbs[i] = fbi;
1886
1887		ofbi = FB2OFB(fbi);
1888		ofbi->fbdev = fbdev;
1889		ofbi->id = i;
1890
1891		ofbi->region = &fbdev->regions[i];
1892		ofbi->region->id = i;
1893		init_rwsem(&ofbi->region->lock);
1894
1895		/* assign these early, so that fb alloc can use them */
1896		ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB :
1897			OMAP_DSS_ROT_DMA;
1898		ofbi->mirror = def_mirror;
1899
1900		fbdev->num_fbs++;
1901	}
1902
1903	DBG("fb_infos allocated\n");
1904
1905	/* assign overlays for the fbs */
1906	for (i = 0; i < min(fbdev->num_fbs, fbdev->num_overlays); i++) {
1907		struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
1908
1909		ofbi->overlays[0] = fbdev->overlays[i];
1910		ofbi->num_overlays = 1;
1911	}
1912
1913	/* allocate fb memories */
1914	r = omapfb_allocate_all_fbs(fbdev);
1915	if (r) {
1916		dev_err(fbdev->dev, "failed to allocate fbmem\n");
1917		return r;
1918	}
1919
1920	DBG("fbmems allocated\n");
1921
1922	/* setup fb_infos */
1923	for (i = 0; i < fbdev->num_fbs; i++) {
1924		struct fb_info *fbi = fbdev->fbs[i];
1925		struct omapfb_info *ofbi = FB2OFB(fbi);
1926
1927		omapfb_get_mem_region(ofbi->region);
1928		r = omapfb_fb_init(fbdev, fbi);
1929		omapfb_put_mem_region(ofbi->region);
1930
1931		if (r) {
1932			dev_err(fbdev->dev, "failed to setup fb_info\n");
1933			return r;
1934		}
1935	}
1936
1937	for (i = 0; i < fbdev->num_fbs; i++) {
1938		struct fb_info *fbi = fbdev->fbs[i];
1939		struct omapfb_info *ofbi = FB2OFB(fbi);
1940
1941		if (ofbi->region->size == 0)
1942			continue;
1943
1944		omapfb_clear_fb(fbi);
1945	}
1946
1947	DBG("fb_infos initialized\n");
1948
1949	for (i = 0; i < fbdev->num_fbs; i++) {
1950		r = register_framebuffer(fbdev->fbs[i]);
1951		if (r != 0) {
1952			dev_err(fbdev->dev,
1953				"registering framebuffer %d failed\n", i);
1954			return r;
1955		}
1956	}
1957
1958	DBG("framebuffers registered\n");
1959
1960	for (i = 0; i < fbdev->num_fbs; i++) {
1961		struct fb_info *fbi = fbdev->fbs[i];
1962		struct omapfb_info *ofbi = FB2OFB(fbi);
1963
1964		omapfb_get_mem_region(ofbi->region);
1965		r = omapfb_apply_changes(fbi, 1);
1966		omapfb_put_mem_region(ofbi->region);
1967
1968		if (r) {
1969			dev_err(fbdev->dev, "failed to change mode\n");
1970			return r;
1971		}
1972	}
1973
1974	/* Enable fb0 */
1975	if (fbdev->num_fbs > 0) {
1976		struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[0]);
1977
1978		if (ofbi->num_overlays > 0) {
1979			struct omap_overlay *ovl = ofbi->overlays[0];
1980
1981			ovl->manager->apply(ovl->manager);
1982
1983			r = omapfb_overlay_enable(ovl, 1);
1984
1985			if (r) {
1986				dev_err(fbdev->dev,
1987						"failed to enable overlay\n");
1988				return r;
1989			}
1990		}
1991	}
1992
1993	DBG("create_framebuffers done\n");
1994
1995	return 0;
1996}
1997
1998static int omapfb_mode_to_timings(const char *mode_str,
1999		struct omap_dss_device *display,
2000		struct omap_video_timings *timings, u8 *bpp)
2001{
2002	struct fb_info *fbi;
2003	struct fb_var_screeninfo *var;
2004	struct fb_ops *fbops;
2005	int r;
2006
2007#ifdef CONFIG_OMAP2_DSS_VENC
2008	if (strcmp(mode_str, "pal") == 0) {
2009		*timings = omap_dss_pal_timings;
2010		*bpp = 24;
2011		return 0;
2012	} else if (strcmp(mode_str, "ntsc") == 0) {
2013		*timings = omap_dss_ntsc_timings;
2014		*bpp = 24;
2015		return 0;
2016	}
2017#endif
2018
2019	/* this is quite a hack, but I wanted to use the modedb and for
2020	 * that we need fb_info and var, so we create dummy ones */
2021
2022	*bpp = 0;
2023	fbi = NULL;
2024	var = NULL;
2025	fbops = NULL;
2026
2027	fbi = kzalloc(sizeof(*fbi), GFP_KERNEL);
2028	if (fbi == NULL) {
2029		r = -ENOMEM;
2030		goto err;
2031	}
2032
2033	var = kzalloc(sizeof(*var), GFP_KERNEL);
2034	if (var == NULL) {
2035		r = -ENOMEM;
2036		goto err;
2037	}
2038
2039	fbops = kzalloc(sizeof(*fbops), GFP_KERNEL);
2040	if (fbops == NULL) {
2041		r = -ENOMEM;
2042		goto err;
2043	}
2044
2045	fbi->fbops = fbops;
2046
2047	r = fb_find_mode(var, fbi, mode_str, NULL, 0, NULL, 24);
2048	if (r == 0) {
2049		r = -EINVAL;
2050		goto err;
2051	}
2052
2053	if (display->driver->get_timings) {
2054		display->driver->get_timings(display, timings);
2055	} else {
2056		timings->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
2057		timings->de_level = OMAPDSS_SIG_ACTIVE_HIGH;
2058		timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE;
2059	}
2060
2061	timings->pixelclock = PICOS2KHZ(var->pixclock) * 1000;
2062	timings->hbp = var->left_margin;
2063	timings->hfp = var->right_margin;
2064	timings->vbp = var->upper_margin;
2065	timings->vfp = var->lower_margin;
2066	timings->hsw = var->hsync_len;
2067	timings->vsw = var->vsync_len;
2068	timings->x_res = var->xres;
2069	timings->y_res = var->yres;
2070	timings->hsync_level = var->sync & FB_SYNC_HOR_HIGH_ACT ?
2071				OMAPDSS_SIG_ACTIVE_HIGH :
2072				OMAPDSS_SIG_ACTIVE_LOW;
2073	timings->vsync_level = var->sync & FB_SYNC_VERT_HIGH_ACT ?
2074				OMAPDSS_SIG_ACTIVE_HIGH :
2075				OMAPDSS_SIG_ACTIVE_LOW;
2076	timings->interlace = var->vmode & FB_VMODE_INTERLACED;
2077
2078	switch (var->bits_per_pixel) {
2079	case 16:
2080		*bpp = 16;
2081		break;
2082	case 24:
2083	case 32:
2084	default:
2085		*bpp = 24;
2086		break;
2087	}
2088
2089	r = 0;
2090
2091err:
2092	kfree(fbi);
2093	kfree(var);
2094	kfree(fbops);
2095
2096	return r;
2097}
2098
2099static int omapfb_set_def_mode(struct omapfb2_device *fbdev,
2100		struct omap_dss_device *display, char *mode_str)
2101{
2102	int r;
2103	u8 bpp;
2104	struct omap_video_timings timings, temp_timings;
2105	struct omapfb_display_data *d;
2106
2107	r = omapfb_mode_to_timings(mode_str, display, &timings, &bpp);
2108	if (r)
2109		return r;
2110
2111	d = get_display_data(fbdev, display);
2112	d->bpp_override = bpp;
2113
2114	if (display->driver->check_timings) {
2115		r = display->driver->check_timings(display, &timings);
2116		if (r)
2117			return r;
2118	} else {
2119		/* If check_timings is not present compare xres and yres */
2120		if (display->driver->get_timings) {
2121			display->driver->get_timings(display, &temp_timings);
2122
2123			if (temp_timings.x_res != timings.x_res ||
2124				temp_timings.y_res != timings.y_res)
2125				return -EINVAL;
2126		}
2127	}
2128
2129	if (display->driver->set_timings)
2130			display->driver->set_timings(display, &timings);
2131
2132	return 0;
2133}
2134
2135static int omapfb_get_recommended_bpp(struct omapfb2_device *fbdev,
2136		struct omap_dss_device *dssdev)
2137{
2138	struct omapfb_display_data *d;
2139
2140	BUG_ON(dssdev->driver->get_recommended_bpp == NULL);
2141
2142	d = get_display_data(fbdev, dssdev);
2143
2144	if (d->bpp_override != 0)
2145		return d->bpp_override;
2146
2147	return dssdev->driver->get_recommended_bpp(dssdev);
2148}
2149
2150static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
2151{
2152	char *str, *options, *this_opt;
2153	int r = 0;
2154
2155	str = kstrdup(def_mode, GFP_KERNEL);
2156	if (!str)
2157		return -ENOMEM;
2158	options = str;
2159
2160	while (!r && (this_opt = strsep(&options, ",")) != NULL) {
2161		char *p, *display_str, *mode_str;
2162		struct omap_dss_device *display;
2163		int i;
2164
2165		p = strchr(this_opt, ':');
2166		if (!p) {
2167			r = -EINVAL;
2168			break;
2169		}
2170
2171		*p = 0;
2172		display_str = this_opt;
2173		mode_str = p + 1;
2174
2175		display = NULL;
2176		for (i = 0; i < fbdev->num_displays; ++i) {
2177			if (strcmp(fbdev->displays[i].dssdev->name,
2178						display_str) == 0) {
2179				display = fbdev->displays[i].dssdev;
2180				break;
2181			}
2182		}
2183
2184		if (!display) {
2185			r = -EINVAL;
2186			break;
2187		}
2188
2189		r = omapfb_set_def_mode(fbdev, display, mode_str);
2190		if (r)
2191			break;
2192	}
2193
2194	kfree(str);
2195
2196	return r;
2197}
2198
2199static void fb_videomode_to_omap_timings(struct fb_videomode *m,
2200		struct omap_dss_device *display,
2201		struct omap_video_timings *t)
2202{
2203	if (display->driver->get_timings) {
2204		display->driver->get_timings(display, t);
2205	} else {
2206		t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
2207		t->de_level = OMAPDSS_SIG_ACTIVE_HIGH;
2208		t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE;
2209	}
2210
2211	t->x_res = m->xres;
2212	t->y_res = m->yres;
2213	t->pixelclock = PICOS2KHZ(m->pixclock) * 1000;
2214	t->hsw = m->hsync_len;
2215	t->hfp = m->right_margin;
2216	t->hbp = m->left_margin;
2217	t->vsw = m->vsync_len;
2218	t->vfp = m->lower_margin;
2219	t->vbp = m->upper_margin;
2220	t->hsync_level = m->sync & FB_SYNC_HOR_HIGH_ACT ?
2221				OMAPDSS_SIG_ACTIVE_HIGH :
2222				OMAPDSS_SIG_ACTIVE_LOW;
2223	t->vsync_level = m->sync & FB_SYNC_VERT_HIGH_ACT ?
2224				OMAPDSS_SIG_ACTIVE_HIGH :
2225				OMAPDSS_SIG_ACTIVE_LOW;
2226	t->interlace = m->vmode & FB_VMODE_INTERLACED;
2227}
2228
2229static int omapfb_find_best_mode(struct omap_dss_device *display,
2230		struct omap_video_timings *timings)
2231{
2232	struct fb_monspecs *specs;
2233	u8 *edid;
2234	int r, i, best_idx, len;
2235
2236	if (!display->driver->read_edid)
2237		return -ENODEV;
2238
2239	len = 0x80 * 2;
2240	edid = kmalloc(len, GFP_KERNEL);
2241	if (edid == NULL)
2242		return -ENOMEM;
2243
2244	r = display->driver->read_edid(display, edid, len);
2245	if (r < 0)
2246		goto err1;
2247
2248	specs = kzalloc(sizeof(*specs), GFP_KERNEL);
2249	if (specs == NULL) {
2250		r = -ENOMEM;
2251		goto err1;
2252	}
2253
2254	fb_edid_to_monspecs(edid, specs);
2255
2256	best_idx = -1;
2257
2258	for (i = 0; i < specs->modedb_len; ++i) {
2259		struct fb_videomode *m;
2260		struct omap_video_timings t;
2261
2262		m = &specs->modedb[i];
2263
2264		if (m->pixclock == 0)
2265			continue;
2266
2267		/* skip repeated pixel modes */
2268		if (m->xres == 2880 || m->xres == 1440)
2269			continue;
2270
2271		if (m->vmode & FB_VMODE_INTERLACED ||
2272				m->vmode & FB_VMODE_DOUBLE)
2273			continue;
2274
2275		fb_videomode_to_omap_timings(m, display, &t);
2276
2277		r = display->driver->check_timings(display, &t);
2278		if (r == 0) {
2279			best_idx = i;
2280			break;
2281		}
2282	}
2283
2284	if (best_idx == -1) {
2285		r = -ENOENT;
2286		goto err2;
2287	}
2288
2289	fb_videomode_to_omap_timings(&specs->modedb[best_idx], display,
2290		timings);
2291
2292	r = 0;
2293
2294err2:
2295	fb_destroy_modedb(specs->modedb);
2296	kfree(specs);
2297err1:
2298	kfree(edid);
2299
2300	return r;
2301}
2302
2303static int omapfb_init_display(struct omapfb2_device *fbdev,
2304		struct omap_dss_device *dssdev)
2305{
2306	struct omap_dss_driver *dssdrv = dssdev->driver;
2307	struct omapfb_display_data *d;
2308	int r;
2309
2310	r = dssdrv->enable(dssdev);
2311	if (r) {
2312		dev_warn(fbdev->dev, "Failed to enable display '%s'\n",
2313				dssdev->name);
2314		return r;
2315	}
2316
2317	d = get_display_data(fbdev, dssdev);
2318
2319	d->fbdev = fbdev;
2320
2321	if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
2322		u16 w, h;
2323
2324		if (auto_update) {
2325			omapfb_start_auto_update(fbdev, dssdev);
2326			d->update_mode = OMAPFB_AUTO_UPDATE;
2327		} else {
2328			d->update_mode = OMAPFB_MANUAL_UPDATE;
2329		}
2330
2331		if (dssdrv->enable_te) {
2332			r = dssdrv->enable_te(dssdev, 1);
2333			if (r) {
2334				dev_err(fbdev->dev, "Failed to set TE\n");
2335				return r;
2336			}
2337		}
2338
2339		dssdrv->get_resolution(dssdev, &w, &h);
2340		r = dssdrv->update(dssdev, 0, 0, w, h);
2341		if (r) {
2342			dev_err(fbdev->dev,
2343					"Failed to update display\n");
2344			return r;
2345		}
2346	} else {
2347		d->update_mode = OMAPFB_AUTO_UPDATE;
2348	}
2349
2350	return 0;
2351}
2352
2353static int omapfb_init_connections(struct omapfb2_device *fbdev,
2354		struct omap_dss_device *def_dssdev)
2355{
2356	int i, r;
2357	struct omap_overlay_manager *mgr;
2358
2359	r = def_dssdev->driver->connect(def_dssdev);
2360	if (r) {
2361		dev_err(fbdev->dev, "failed to connect default display\n");
2362		return r;
2363	}
2364
2365	for (i = 0; i < fbdev->num_displays; ++i) {
2366		struct omap_dss_device *dssdev = fbdev->displays[i].dssdev;
2367
2368		if (dssdev == def_dssdev)
2369			continue;
2370
2371		/*
2372		 * We don't care if the connect succeeds or not. We just want to
2373		 * connect as many displays as possible.
2374		 */
2375		dssdev->driver->connect(dssdev);
2376	}
2377
2378	mgr = omapdss_find_mgr_from_display(def_dssdev);
2379
2380	if (!mgr) {
2381		dev_err(fbdev->dev, "no ovl manager for the default display\n");
2382		return -EINVAL;
2383	}
2384
2385	for (i = 0; i < fbdev->num_overlays; i++) {
2386		struct omap_overlay *ovl = fbdev->overlays[i];
2387
2388		if (ovl->manager)
2389			ovl->unset_manager(ovl);
2390
2391		r = ovl->set_manager(ovl, mgr);
2392		if (r)
2393			dev_warn(fbdev->dev,
2394					"failed to connect overlay %s to manager %s\n",
2395					ovl->name, mgr->name);
2396	}
2397
2398	return 0;
2399}
2400
2401static struct omap_dss_device *
2402omapfb_find_default_display(struct omapfb2_device *fbdev)
2403{
2404	const char *def_name;
2405	int i;
2406
2407	/*
2408	 * Search with the display name from the user or the board file,
2409	 * comparing to display names and aliases
2410	 */
2411
2412	def_name = omapdss_get_default_display_name();
2413
2414	if (def_name) {
2415		for (i = 0; i < fbdev->num_displays; ++i) {
2416			struct omap_dss_device *dssdev;
2417
2418			dssdev = fbdev->displays[i].dssdev;
2419
2420			if (dssdev->name && strcmp(def_name, dssdev->name) == 0)
2421				return dssdev;
2422
2423			if (strcmp(def_name, dssdev->alias) == 0)
2424				return dssdev;
2425		}
2426
2427		/* def_name given but not found */
2428		return NULL;
2429	}
2430
2431	/* then look for DT alias display0 */
2432	for (i = 0; i < fbdev->num_displays; ++i) {
2433		struct omap_dss_device *dssdev;
2434		int id;
2435
2436		dssdev = fbdev->displays[i].dssdev;
2437
2438		if (dssdev->dev->of_node == NULL)
2439			continue;
2440
2441		id = of_alias_get_id(dssdev->dev->of_node, "display");
2442		if (id == 0)
2443			return dssdev;
2444	}
2445
2446	/* return the first display we have in the list */
2447	return fbdev->displays[0].dssdev;
2448}
2449
2450static int omapfb_probe(struct platform_device *pdev)
2451{
2452	struct omapfb2_device *fbdev = NULL;
2453	int r = 0;
2454	int i;
2455	struct omap_dss_device *def_display;
2456	struct omap_dss_device *dssdev;
2457
2458	DBG("omapfb_probe\n");
2459
2460	if (omapdss_is_initialized() == false)
2461		return -EPROBE_DEFER;
2462
2463	if (pdev->num_resources != 0) {
2464		dev_err(&pdev->dev, "probed for an unknown device\n");
2465		r = -ENODEV;
2466		goto err0;
2467	}
2468
2469	fbdev = devm_kzalloc(&pdev->dev, sizeof(struct omapfb2_device),
2470			GFP_KERNEL);
2471	if (fbdev == NULL) {
2472		r = -ENOMEM;
2473		goto err0;
2474	}
2475
2476	if (def_vrfb && !omap_vrfb_supported()) {
2477		def_vrfb = 0;
2478		dev_warn(&pdev->dev, "VRFB is not supported on this hardware, "
2479				"ignoring the module parameter vrfb=y\n");
2480	}
2481
2482	r = omapdss_compat_init();
2483	if (r)
2484		goto err0;
2485
2486	mutex_init(&fbdev->mtx);
2487
2488	fbdev->dev = &pdev->dev;
2489	platform_set_drvdata(pdev, fbdev);
2490
2491	fbdev->num_displays = 0;
2492	dssdev = NULL;
2493	for_each_dss_dev(dssdev) {
2494		struct omapfb_display_data *d;
2495
2496		omap_dss_get_device(dssdev);
2497
2498		if (!dssdev->driver) {
2499			dev_warn(&pdev->dev, "no driver for display: %s\n",
2500				dssdev->name);
2501			omap_dss_put_device(dssdev);
2502			continue;
2503		}
2504
2505		d = &fbdev->displays[fbdev->num_displays++];
2506		d->dssdev = dssdev;
2507		if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE)
2508			d->update_mode = OMAPFB_MANUAL_UPDATE;
2509		else
2510			d->update_mode = OMAPFB_AUTO_UPDATE;
2511	}
2512
2513	if (fbdev->num_displays == 0) {
2514		dev_err(&pdev->dev, "no displays\n");
2515		r = -EPROBE_DEFER;
2516		goto cleanup;
2517	}
2518
2519	fbdev->num_overlays = omap_dss_get_num_overlays();
2520	for (i = 0; i < fbdev->num_overlays; i++)
2521		fbdev->overlays[i] = omap_dss_get_overlay(i);
2522
2523	fbdev->num_managers = omap_dss_get_num_overlay_managers();
2524	for (i = 0; i < fbdev->num_managers; i++)
2525		fbdev->managers[i] = omap_dss_get_overlay_manager(i);
2526
2527	def_display = omapfb_find_default_display(fbdev);
2528	if (def_display == NULL) {
2529		dev_err(fbdev->dev, "failed to find default display\n");
2530		r = -EPROBE_DEFER;
2531		goto cleanup;
2532	}
2533
2534	r = omapfb_init_connections(fbdev, def_display);
2535	if (r) {
2536		dev_err(fbdev->dev, "failed to init overlay connections\n");
2537		goto cleanup;
2538	}
2539
2540	if (def_mode && strlen(def_mode) > 0) {
2541		if (omapfb_parse_def_modes(fbdev))
2542			dev_warn(&pdev->dev, "cannot parse default modes\n");
2543	} else if (def_display && def_display->driver->set_timings &&
2544			def_display->driver->check_timings) {
2545		struct omap_video_timings t;
2546
2547		r = omapfb_find_best_mode(def_display, &t);
2548
2549		if (r == 0)
2550			def_display->driver->set_timings(def_display, &t);
2551	}
2552
2553	r = omapfb_create_framebuffers(fbdev);
2554	if (r)
2555		goto cleanup;
2556
2557	for (i = 0; i < fbdev->num_managers; i++) {
2558		struct omap_overlay_manager *mgr;
2559		mgr = fbdev->managers[i];
2560		r = mgr->apply(mgr);
2561		if (r)
2562			dev_warn(fbdev->dev, "failed to apply dispc config\n");
2563	}
2564
2565	DBG("mgr->apply'ed\n");
2566
2567	if (def_display) {
2568		r = omapfb_init_display(fbdev, def_display);
2569		if (r) {
2570			dev_err(fbdev->dev,
2571					"failed to initialize default "
2572					"display\n");
2573			goto cleanup;
2574		}
2575	}
2576
2577	DBG("create sysfs for fbs\n");
2578	r = omapfb_create_sysfs(fbdev);
2579	if (r) {
2580		dev_err(fbdev->dev, "failed to create sysfs entries\n");
2581		goto cleanup;
2582	}
2583
2584	if (def_display) {
2585		u16 w, h;
2586
2587		def_display->driver->get_resolution(def_display, &w, &h);
2588
2589		dev_info(fbdev->dev, "using display '%s' mode %dx%d\n",
2590			def_display->name, w, h);
2591	}
2592
2593	return 0;
2594
2595cleanup:
2596	omapfb_free_resources(fbdev);
2597	omapdss_compat_uninit();
2598err0:
2599	dev_err(&pdev->dev, "failed to setup omapfb\n");
2600	return r;
2601}
2602
2603static int omapfb_remove(struct platform_device *pdev)
2604{
2605	struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
2606
2607	/* FIXME: wait till completion of pending events */
2608
2609	omapfb_remove_sysfs(fbdev);
2610
2611	omapfb_free_resources(fbdev);
2612
2613	omapdss_compat_uninit();
2614
2615	return 0;
2616}
2617
2618static struct platform_driver omapfb_driver = {
2619	.probe		= omapfb_probe,
2620	.remove         = omapfb_remove,
2621	.driver         = {
2622		.name   = "omapfb",
2623	},
2624};
2625
2626module_param_named(mode, def_mode, charp, 0);
2627module_param_named(vram, def_vram, charp, 0);
2628module_param_named(rotate, def_rotate, int, 0);
2629module_param_named(vrfb, def_vrfb, bool, 0);
2630module_param_named(mirror, def_mirror, bool, 0);
2631
2632module_platform_driver(omapfb_driver);
2633
2634MODULE_ALIAS("platform:omapfb");
2635MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
2636MODULE_DESCRIPTION("OMAP2/3 Framebuffer");
2637MODULE_LICENSE("GPL v2");
2638