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	vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot);
1099
1100	rg = omapfb_get_mem_region(ofbi->region);
1101
1102	start = omapfb_get_region_paddr(ofbi);
1103	len = fix->smem_len;
1104
1105	DBG("user mmap region start %lx, len %d, off %lx\n", start, len,
1106			vma->vm_pgoff << PAGE_SHIFT);
1107
1108	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
1109	vma->vm_ops = &mmap_user_ops;
1110	vma->vm_private_data = rg;
1111
1112	r = vm_iomap_memory(vma, start, len);
1113	if (r)
1114		goto error;
1115
1116	/* vm_ops.open won't be called for mmap itself. */
1117	atomic_inc(&rg->map_count);
1118
1119	omapfb_put_mem_region(rg);
1120
1121	return 0;
1122
1123error:
1124	omapfb_put_mem_region(ofbi->region);
1125
1126	return r;
1127}
1128
1129/* Store a single color palette entry into a pseudo palette or the hardware
1130 * palette if one is available. For now we support only 16bpp and thus store
1131 * the entry only to the pseudo palette.
1132 */
1133static int _setcolreg(struct fb_info *fbi, u_int regno, u_int red, u_int green,
1134		u_int blue, u_int transp, int update_hw_pal)
1135{
1136	/*struct omapfb_info *ofbi = FB2OFB(fbi);*/
1137	/*struct omapfb2_device *fbdev = ofbi->fbdev;*/
1138	struct fb_var_screeninfo *var = &fbi->var;
1139	int r = 0;
1140
1141	enum omapfb_color_format mode = OMAPFB_COLOR_RGB24U; /* XXX */
1142
1143	/*switch (plane->color_mode) {*/
1144	switch (mode) {
1145	case OMAPFB_COLOR_YUV422:
1146	case OMAPFB_COLOR_YUV420:
1147	case OMAPFB_COLOR_YUY422:
1148		r = -EINVAL;
1149		break;
1150	case OMAPFB_COLOR_CLUT_8BPP:
1151	case OMAPFB_COLOR_CLUT_4BPP:
1152	case OMAPFB_COLOR_CLUT_2BPP:
1153	case OMAPFB_COLOR_CLUT_1BPP:
1154		/*
1155		   if (fbdev->ctrl->setcolreg)
1156		   r = fbdev->ctrl->setcolreg(regno, red, green, blue,
1157		   transp, update_hw_pal);
1158		   */
1159		r = -EINVAL;
1160		break;
1161	case OMAPFB_COLOR_RGB565:
1162	case OMAPFB_COLOR_RGB444:
1163	case OMAPFB_COLOR_RGB24P:
1164	case OMAPFB_COLOR_RGB24U:
1165		if (regno < 16) {
1166			u32 pal;
1167			pal = ((red >> (16 - var->red.length)) <<
1168					var->red.offset) |
1169				((green >> (16 - var->green.length)) <<
1170				 var->green.offset) |
1171				(blue >> (16 - var->blue.length));
1172			((u32 *)(fbi->pseudo_palette))[regno] = pal;
1173		}
1174		break;
1175	default:
1176		BUG();
1177	}
1178	return r;
1179}
1180
1181static int omapfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
1182		u_int transp, struct fb_info *info)
1183{
1184	DBG("setcolreg\n");
1185
1186	return _setcolreg(info, regno, red, green, blue, transp, 1);
1187}
1188
1189static int omapfb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
1190{
1191	int count, index, r;
1192	u16 *red, *green, *blue, *transp;
1193	u16 trans = 0xffff;
1194
1195	DBG("setcmap\n");
1196
1197	red     = cmap->red;
1198	green   = cmap->green;
1199	blue    = cmap->blue;
1200	transp  = cmap->transp;
1201	index   = cmap->start;
1202
1203	for (count = 0; count < cmap->len; count++) {
1204		if (transp)
1205			trans = *transp++;
1206		r = _setcolreg(info, index++, *red++, *green++, *blue++, trans,
1207				count == cmap->len - 1);
1208		if (r != 0)
1209			return r;
1210	}
1211
1212	return 0;
1213}
1214
1215static int omapfb_blank(int blank, struct fb_info *fbi)
1216{
1217	struct omapfb_info *ofbi = FB2OFB(fbi);
1218	struct omapfb2_device *fbdev = ofbi->fbdev;
1219	struct omap_dss_device *display = fb2display(fbi);
1220	struct omapfb_display_data *d;
1221	int r = 0;
1222
1223	if (!display)
1224		return -EINVAL;
1225
1226	omapfb_lock(fbdev);
1227
1228	d = get_display_data(fbdev, display);
1229
1230	switch (blank) {
1231	case FB_BLANK_UNBLANK:
1232		if (display->state == OMAP_DSS_DISPLAY_ACTIVE)
1233			goto exit;
1234
1235		r = display->driver->enable(display);
1236
1237		if ((display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) &&
1238				d->update_mode == OMAPFB_AUTO_UPDATE &&
1239				!d->auto_update_work_enabled)
1240			omapfb_start_auto_update(fbdev, display);
1241
1242		break;
1243
1244	case FB_BLANK_NORMAL:
1245		/* FB_BLANK_NORMAL could be implemented.
1246		 * Needs DSS additions. */
1247	case FB_BLANK_VSYNC_SUSPEND:
1248	case FB_BLANK_HSYNC_SUSPEND:
1249	case FB_BLANK_POWERDOWN:
1250		if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
1251			goto exit;
1252
1253		if (d->auto_update_work_enabled)
1254			omapfb_stop_auto_update(fbdev, display);
1255
1256		display->driver->disable(display);
1257
1258		break;
1259
1260	default:
1261		r = -EINVAL;
1262	}
1263
1264exit:
1265	omapfb_unlock(fbdev);
1266
1267	return r;
1268}
1269
1270#if 0
1271/* XXX fb_read and fb_write are needed for VRFB */
1272ssize_t omapfb_write(struct fb_info *info, const char __user *buf,
1273		size_t count, loff_t *ppos)
1274{
1275	DBG("omapfb_write %d, %lu\n", count, (unsigned long)*ppos);
1276	/* XXX needed for VRFB */
1277	return count;
1278}
1279#endif
1280
1281static const struct fb_ops omapfb_ops = {
1282	.owner          = THIS_MODULE,
1283	.fb_open        = omapfb_open,
1284	.fb_release     = omapfb_release,
1285	__FB_DEFAULT_IOMEM_OPS_RDWR,
1286	.fb_blank       = omapfb_blank,
1287	__FB_DEFAULT_IOMEM_OPS_DRAW,
1288	.fb_ioctl       = omapfb_ioctl,
1289	.fb_check_var   = omapfb_check_var,
1290	.fb_set_par     = omapfb_set_par,
1291	.fb_pan_display = omapfb_pan_display,
1292	.fb_mmap	= omapfb_mmap,
1293	.fb_setcolreg	= omapfb_setcolreg,
1294	.fb_setcmap	= omapfb_setcmap,
1295	/*.fb_write	= omapfb_write,*/
1296};
1297
1298static void omapfb_free_fbmem(struct fb_info *fbi)
1299{
1300	struct omapfb_info *ofbi = FB2OFB(fbi);
1301	struct omapfb2_device *fbdev = ofbi->fbdev;
1302	struct omapfb2_mem_region *rg;
1303
1304	rg = ofbi->region;
1305
1306	if (rg->token == NULL)
1307		return;
1308
1309	WARN_ON(atomic_read(&rg->map_count));
1310
1311	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
1312		/* unmap the 0 angle rotation */
1313		if (rg->vrfb.vaddr[0]) {
1314			iounmap(rg->vrfb.vaddr[0]);
1315			rg->vrfb.vaddr[0] = NULL;
1316		}
1317
1318		omap_vrfb_release_ctx(&rg->vrfb);
1319	}
1320
1321	dma_free_attrs(fbdev->dev, rg->size, rg->token, rg->dma_handle,
1322			rg->attrs);
1323
1324	rg->token = NULL;
1325	rg->vaddr = NULL;
1326	rg->paddr = 0;
1327	rg->alloc = 0;
1328	rg->size = 0;
1329}
1330
1331static void clear_fb_info(struct fb_info *fbi)
1332{
1333	memset(&fbi->var, 0, sizeof(fbi->var));
1334	memset(&fbi->fix, 0, sizeof(fbi->fix));
1335	strscpy(fbi->fix.id, MODULE_NAME, sizeof(fbi->fix.id));
1336}
1337
1338static int omapfb_free_all_fbmem(struct omapfb2_device *fbdev)
1339{
1340	int i;
1341
1342	DBG("free all fbmem\n");
1343
1344	for (i = 0; i < fbdev->num_fbs; i++) {
1345		struct fb_info *fbi = fbdev->fbs[i];
1346		omapfb_free_fbmem(fbi);
1347		clear_fb_info(fbi);
1348	}
1349
1350	return 0;
1351}
1352
1353static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
1354		unsigned long paddr)
1355{
1356	struct omapfb_info *ofbi = FB2OFB(fbi);
1357	struct omapfb2_device *fbdev = ofbi->fbdev;
1358	struct omapfb2_mem_region *rg;
1359	void *token;
1360	unsigned long attrs;
1361	dma_addr_t dma_handle;
1362	int r;
1363
1364	rg = ofbi->region;
1365
1366	rg->paddr = 0;
1367	rg->vaddr = NULL;
1368	memset(&rg->vrfb, 0, sizeof rg->vrfb);
1369	rg->size = 0;
1370	rg->type = 0;
1371	rg->alloc = false;
1372	rg->map = false;
1373
1374	size = PAGE_ALIGN(size);
1375
1376	attrs = DMA_ATTR_WRITE_COMBINE;
1377
1378	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
1379		attrs |= DMA_ATTR_NO_KERNEL_MAPPING;
1380
1381	DBG("allocating %lu bytes for fb %d\n", size, ofbi->id);
1382
1383	token = dma_alloc_attrs(fbdev->dev, size, &dma_handle,
1384			GFP_KERNEL, attrs);
1385
1386	if (token == NULL) {
1387		dev_err(fbdev->dev, "failed to allocate framebuffer\n");
1388		return -ENOMEM;
1389	}
1390
1391	DBG("allocated VRAM paddr %lx, vaddr %p\n",
1392			(unsigned long)dma_handle, token);
1393
1394	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
1395		r = omap_vrfb_request_ctx(&rg->vrfb);
1396		if (r) {
1397			dma_free_attrs(fbdev->dev, size, token, dma_handle,
1398					attrs);
1399			dev_err(fbdev->dev, "vrfb create ctx failed\n");
1400			return r;
1401		}
1402	}
1403
1404	rg->attrs = attrs;
1405	rg->token = token;
1406	rg->dma_handle = dma_handle;
1407
1408	rg->paddr = (unsigned long)dma_handle;
1409	rg->vaddr = (void __iomem *)token;
1410	rg->size = size;
1411	rg->alloc = 1;
1412
1413	return 0;
1414}
1415
1416/* allocate fbmem using display resolution as reference */
1417static int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size,
1418		unsigned long paddr)
1419{
1420	struct omapfb_info *ofbi = FB2OFB(fbi);
1421	struct omapfb2_device *fbdev = ofbi->fbdev;
1422	struct omap_dss_device *display;
1423	int bytespp;
1424
1425	display =  fb2display(fbi);
1426
1427	if (!display)
1428		return 0;
1429
1430	switch (omapfb_get_recommended_bpp(fbdev, display)) {
1431	case 16:
1432		bytespp = 2;
1433		break;
1434	case 24:
1435		bytespp = 4;
1436		break;
1437	default:
1438		bytespp = 4;
1439		break;
1440	}
1441
1442	if (!size) {
1443		u16 w, h;
1444
1445		display->driver->get_resolution(display, &w, &h);
1446
1447		if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
1448			size = max(omap_vrfb_min_phys_size(w, h, bytespp),
1449					omap_vrfb_min_phys_size(h, w, bytespp));
1450
1451			DBG("adjusting fb mem size for VRFB, %u -> %lu\n",
1452					w * h * bytespp, size);
1453		} else {
1454			size = w * h * bytespp;
1455		}
1456	}
1457
1458	if (!size)
1459		return 0;
1460
1461	return omapfb_alloc_fbmem(fbi, size, paddr);
1462}
1463
1464static int omapfb_parse_vram_param(const char *param, int max_entries,
1465		unsigned long *sizes, unsigned long *paddrs)
1466{
1467	unsigned int fbnum;
1468	unsigned long size;
1469	unsigned long paddr = 0;
1470	char *p, *start;
1471
1472	start = (char *)param;
1473
1474	while (1) {
1475		p = start;
1476
1477		fbnum = simple_strtoul(p, &p, 10);
1478
1479		if (p == start)
1480			return -EINVAL;
1481
1482		if (*p != ':')
1483			return -EINVAL;
1484
1485		if (fbnum >= max_entries)
1486			return -EINVAL;
1487
1488		size = memparse(p + 1, &p);
1489
1490		if (!size)
1491			return -EINVAL;
1492
1493		paddr = 0;
1494
1495		if (*p == '@') {
1496			paddr = simple_strtoul(p + 1, &p, 16);
1497
1498			if (!paddr)
1499				return -EINVAL;
1500
1501		}
1502
1503		WARN_ONCE(paddr,
1504			"reserving memory at predefined address not supported\n");
1505
1506		paddrs[fbnum] = paddr;
1507		sizes[fbnum] = size;
1508
1509		if (*p == 0)
1510			break;
1511
1512		if (*p != ',')
1513			return -EINVAL;
1514
1515		++p;
1516
1517		start = p;
1518	}
1519
1520	return 0;
1521}
1522
1523static int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev)
1524{
1525	int i, r;
1526	unsigned long vram_sizes[10];
1527	unsigned long vram_paddrs[10];
1528
1529	memset(&vram_sizes, 0, sizeof(vram_sizes));
1530	memset(&vram_paddrs, 0, sizeof(vram_paddrs));
1531
1532	if (def_vram &&	omapfb_parse_vram_param(def_vram, 10,
1533				vram_sizes, vram_paddrs)) {
1534		dev_err(fbdev->dev, "failed to parse vram parameter\n");
1535
1536		memset(&vram_sizes, 0, sizeof(vram_sizes));
1537		memset(&vram_paddrs, 0, sizeof(vram_paddrs));
1538	}
1539
1540	for (i = 0; i < fbdev->num_fbs; i++) {
1541		/* allocate memory automatically only for fb0, or if
1542		 * excplicitly defined with vram or plat data option */
1543		if (i == 0 || vram_sizes[i] != 0) {
1544			r = omapfb_alloc_fbmem_display(fbdev->fbs[i],
1545					vram_sizes[i], vram_paddrs[i]);
1546
1547			if (r)
1548				return r;
1549		}
1550	}
1551
1552	for (i = 0; i < fbdev->num_fbs; i++) {
1553		struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
1554		struct omapfb2_mem_region *rg;
1555		rg = ofbi->region;
1556
1557		DBG("region%d phys %08x virt %p size=%lu\n",
1558				i,
1559				rg->paddr,
1560				rg->vaddr,
1561				rg->size);
1562	}
1563
1564	return 0;
1565}
1566
1567static void omapfb_clear_fb(struct fb_info *fbi)
1568{
1569	const struct fb_fillrect rect = {
1570		.dx = 0,
1571		.dy = 0,
1572		.width = fbi->var.xres_virtual,
1573		.height = fbi->var.yres_virtual,
1574		.color = 0,
1575		.rop = ROP_COPY,
1576	};
1577
1578	cfb_fillrect(fbi, &rect);
1579}
1580
1581int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
1582{
1583	struct omapfb_info *ofbi = FB2OFB(fbi);
1584	struct omapfb2_device *fbdev = ofbi->fbdev;
1585	struct omapfb2_mem_region *rg = ofbi->region;
1586	unsigned long old_size = rg->size;
1587	unsigned long old_paddr = rg->paddr;
1588	int old_type = rg->type;
1589	int r;
1590
1591	if (type != OMAPFB_MEMTYPE_SDRAM)
1592		return -EINVAL;
1593
1594	size = PAGE_ALIGN(size);
1595
1596	if (old_size == size && old_type == type)
1597		return 0;
1598
1599	omapfb_free_fbmem(fbi);
1600
1601	if (size == 0) {
1602		clear_fb_info(fbi);
1603		return 0;
1604	}
1605
1606	r = omapfb_alloc_fbmem(fbi, size, 0);
1607
1608	if (r) {
1609		if (old_size)
1610			omapfb_alloc_fbmem(fbi, old_size, old_paddr);
1611
1612		if (rg->size == 0)
1613			clear_fb_info(fbi);
1614
1615		return r;
1616	}
1617
1618	if (old_size == size)
1619		return 0;
1620
1621	if (old_size == 0) {
1622		DBG("initializing fb %d\n", ofbi->id);
1623		r = omapfb_fb_init(fbdev, fbi);
1624		if (r) {
1625			DBG("omapfb_fb_init failed\n");
1626			goto err;
1627		}
1628		r = omapfb_apply_changes(fbi, 1);
1629		if (r) {
1630			DBG("omapfb_apply_changes failed\n");
1631			goto err;
1632		}
1633	} else {
1634		struct fb_var_screeninfo new_var;
1635		memcpy(&new_var, &fbi->var, sizeof(new_var));
1636		r = check_fb_var(fbi, &new_var);
1637		if (r)
1638			goto err;
1639		memcpy(&fbi->var, &new_var, sizeof(fbi->var));
1640		set_fb_fix(fbi);
1641		r = setup_vrfb_rotation(fbi);
1642		if (r)
1643			goto err;
1644	}
1645
1646	omapfb_clear_fb(fbi);
1647
1648	return 0;
1649err:
1650	omapfb_free_fbmem(fbi);
1651	clear_fb_info(fbi);
1652	return r;
1653}
1654
1655static void omapfb_auto_update_work(struct work_struct *work)
1656{
1657	struct omap_dss_device *dssdev;
1658	struct omap_dss_driver *dssdrv;
1659	struct omapfb_display_data *d;
1660	u16 w, h;
1661	unsigned int freq;
1662	struct omapfb2_device *fbdev;
1663
1664	d = container_of(work, struct omapfb_display_data,
1665			auto_update_work.work);
1666
1667	dssdev = d->dssdev;
1668	dssdrv = dssdev->driver;
1669	fbdev = d->fbdev;
1670
1671	if (!dssdrv || !dssdrv->update)
1672		return;
1673
1674	if (dssdrv->sync)
1675		dssdrv->sync(dssdev);
1676
1677	dssdrv->get_resolution(dssdev, &w, &h);
1678	dssdrv->update(dssdev, 0, 0, w, h);
1679
1680	freq = auto_update_freq;
1681	if (freq == 0)
1682		freq = 20;
1683	queue_delayed_work(fbdev->auto_update_wq,
1684			&d->auto_update_work, HZ / freq);
1685}
1686
1687void omapfb_start_auto_update(struct omapfb2_device *fbdev,
1688		struct omap_dss_device *display)
1689{
1690	struct omapfb_display_data *d;
1691
1692	if (fbdev->auto_update_wq == NULL) {
1693		struct workqueue_struct *wq;
1694
1695		wq = create_singlethread_workqueue("omapfb_auto_update");
1696
1697		if (wq == NULL) {
1698			dev_err(fbdev->dev, "Failed to create workqueue for "
1699					"auto-update\n");
1700			return;
1701		}
1702
1703		fbdev->auto_update_wq = wq;
1704	}
1705
1706	d = get_display_data(fbdev, display);
1707
1708	INIT_DELAYED_WORK(&d->auto_update_work, omapfb_auto_update_work);
1709
1710	d->auto_update_work_enabled = true;
1711
1712	omapfb_auto_update_work(&d->auto_update_work.work);
1713}
1714
1715void omapfb_stop_auto_update(struct omapfb2_device *fbdev,
1716		struct omap_dss_device *display)
1717{
1718	struct omapfb_display_data *d;
1719
1720	d = get_display_data(fbdev, display);
1721
1722	cancel_delayed_work_sync(&d->auto_update_work);
1723
1724	d->auto_update_work_enabled = false;
1725}
1726
1727/* initialize fb_info, var, fix to something sane based on the display */
1728static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
1729{
1730	struct fb_var_screeninfo *var = &fbi->var;
1731	struct omap_dss_device *display = fb2display(fbi);
1732	struct omapfb_info *ofbi = FB2OFB(fbi);
1733	int r = 0;
1734
1735	fbi->fbops = &omapfb_ops;
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		destroy_workqueue(fbdev->auto_update_wq);
1858		fbdev->auto_update_wq = NULL;
1859	}
1860
1861	dev_set_drvdata(fbdev->dev, NULL);
1862}
1863
1864static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
1865{
1866	int r, i;
1867
1868	fbdev->num_fbs = 0;
1869
1870	DBG("create %d framebuffers\n",	CONFIG_FB_OMAP2_NUM_FBS);
1871
1872	/* allocate fb_infos */
1873	for (i = 0; i < CONFIG_FB_OMAP2_NUM_FBS; i++) {
1874		struct fb_info *fbi;
1875		struct omapfb_info *ofbi;
1876
1877		fbi = framebuffer_alloc(sizeof(struct omapfb_info),
1878				fbdev->dev);
1879		if (!fbi)
1880			return -ENOMEM;
1881
1882		clear_fb_info(fbi);
1883
1884		fbdev->fbs[i] = fbi;
1885
1886		ofbi = FB2OFB(fbi);
1887		ofbi->fbdev = fbdev;
1888		ofbi->id = i;
1889
1890		ofbi->region = &fbdev->regions[i];
1891		ofbi->region->id = i;
1892		init_rwsem(&ofbi->region->lock);
1893
1894		/* assign these early, so that fb alloc can use them */
1895		ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB :
1896			OMAP_DSS_ROT_DMA;
1897		ofbi->mirror = def_mirror;
1898
1899		fbdev->num_fbs++;
1900	}
1901
1902	DBG("fb_infos allocated\n");
1903
1904	/* assign overlays for the fbs */
1905	for (i = 0; i < min(fbdev->num_fbs, fbdev->num_overlays); i++) {
1906		struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
1907
1908		ofbi->overlays[0] = fbdev->overlays[i];
1909		ofbi->num_overlays = 1;
1910	}
1911
1912	/* allocate fb memories */
1913	r = omapfb_allocate_all_fbs(fbdev);
1914	if (r) {
1915		dev_err(fbdev->dev, "failed to allocate fbmem\n");
1916		return r;
1917	}
1918
1919	DBG("fbmems allocated\n");
1920
1921	/* setup fb_infos */
1922	for (i = 0; i < fbdev->num_fbs; i++) {
1923		struct fb_info *fbi = fbdev->fbs[i];
1924		struct omapfb_info *ofbi = FB2OFB(fbi);
1925
1926		omapfb_get_mem_region(ofbi->region);
1927		r = omapfb_fb_init(fbdev, fbi);
1928		omapfb_put_mem_region(ofbi->region);
1929
1930		if (r) {
1931			dev_err(fbdev->dev, "failed to setup fb_info\n");
1932			return r;
1933		}
1934	}
1935
1936	for (i = 0; i < fbdev->num_fbs; i++) {
1937		struct fb_info *fbi = fbdev->fbs[i];
1938		struct omapfb_info *ofbi = FB2OFB(fbi);
1939
1940		if (ofbi->region->size == 0)
1941			continue;
1942
1943		omapfb_clear_fb(fbi);
1944	}
1945
1946	DBG("fb_infos initialized\n");
1947
1948	for (i = 0; i < fbdev->num_fbs; i++) {
1949		r = register_framebuffer(fbdev->fbs[i]);
1950		if (r != 0) {
1951			dev_err(fbdev->dev,
1952				"registering framebuffer %d failed\n", i);
1953			return r;
1954		}
1955	}
1956
1957	DBG("framebuffers registered\n");
1958
1959	for (i = 0; i < fbdev->num_fbs; i++) {
1960		struct fb_info *fbi = fbdev->fbs[i];
1961		struct omapfb_info *ofbi = FB2OFB(fbi);
1962
1963		omapfb_get_mem_region(ofbi->region);
1964		r = omapfb_apply_changes(fbi, 1);
1965		omapfb_put_mem_region(ofbi->region);
1966
1967		if (r) {
1968			dev_err(fbdev->dev, "failed to change mode\n");
1969			return r;
1970		}
1971	}
1972
1973	/* Enable fb0 */
1974	if (fbdev->num_fbs > 0) {
1975		struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[0]);
1976
1977		if (ofbi->num_overlays > 0) {
1978			struct omap_overlay *ovl = ofbi->overlays[0];
1979
1980			ovl->manager->apply(ovl->manager);
1981
1982			r = omapfb_overlay_enable(ovl, 1);
1983
1984			if (r) {
1985				dev_err(fbdev->dev,
1986						"failed to enable overlay\n");
1987				return r;
1988			}
1989		}
1990	}
1991
1992	DBG("create_framebuffers done\n");
1993
1994	return 0;
1995}
1996
1997static int omapfb_mode_to_timings(const char *mode_str,
1998		struct omap_dss_device *display,
1999		struct omap_video_timings *timings, u8 *bpp)
2000{
2001	struct fb_info *fbi;
2002	struct fb_var_screeninfo *var;
2003	struct fb_ops *fbops;
2004	int r;
2005
2006#ifdef CONFIG_OMAP2_DSS_VENC
2007	if (strcmp(mode_str, "pal") == 0) {
2008		*timings = omap_dss_pal_timings;
2009		*bpp = 24;
2010		return 0;
2011	} else if (strcmp(mode_str, "ntsc") == 0) {
2012		*timings = omap_dss_ntsc_timings;
2013		*bpp = 24;
2014		return 0;
2015	}
2016#endif
2017
2018	/* this is quite a hack, but I wanted to use the modedb and for
2019	 * that we need fb_info and var, so we create dummy ones */
2020
2021	*bpp = 0;
2022	fbi = NULL;
2023	var = NULL;
2024	fbops = NULL;
2025
2026	fbi = kzalloc(sizeof(*fbi), GFP_KERNEL);
2027	if (fbi == NULL) {
2028		r = -ENOMEM;
2029		goto err;
2030	}
2031
2032	var = kzalloc(sizeof(*var), GFP_KERNEL);
2033	if (var == NULL) {
2034		r = -ENOMEM;
2035		goto err;
2036	}
2037
2038	fbops = kzalloc(sizeof(*fbops), GFP_KERNEL);
2039	if (fbops == NULL) {
2040		r = -ENOMEM;
2041		goto err;
2042	}
2043
2044	fbi->fbops = fbops;
2045
2046	r = fb_find_mode(var, fbi, mode_str, NULL, 0, NULL, 24);
2047	if (r == 0) {
2048		r = -EINVAL;
2049		goto err;
2050	}
2051
2052	if (display->driver->get_timings) {
2053		display->driver->get_timings(display, timings);
2054	} else {
2055		timings->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
2056		timings->de_level = OMAPDSS_SIG_ACTIVE_HIGH;
2057		timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE;
2058	}
2059
2060	timings->pixelclock = PICOS2KHZ(var->pixclock) * 1000;
2061	timings->hbp = var->left_margin;
2062	timings->hfp = var->right_margin;
2063	timings->vbp = var->upper_margin;
2064	timings->vfp = var->lower_margin;
2065	timings->hsw = var->hsync_len;
2066	timings->vsw = var->vsync_len;
2067	timings->x_res = var->xres;
2068	timings->y_res = var->yres;
2069	timings->hsync_level = var->sync & FB_SYNC_HOR_HIGH_ACT ?
2070				OMAPDSS_SIG_ACTIVE_HIGH :
2071				OMAPDSS_SIG_ACTIVE_LOW;
2072	timings->vsync_level = var->sync & FB_SYNC_VERT_HIGH_ACT ?
2073				OMAPDSS_SIG_ACTIVE_HIGH :
2074				OMAPDSS_SIG_ACTIVE_LOW;
2075	timings->interlace = var->vmode & FB_VMODE_INTERLACED;
2076
2077	switch (var->bits_per_pixel) {
2078	case 16:
2079		*bpp = 16;
2080		break;
2081	case 24:
2082	case 32:
2083	default:
2084		*bpp = 24;
2085		break;
2086	}
2087
2088	r = 0;
2089
2090err:
2091	kfree(fbi);
2092	kfree(var);
2093	kfree(fbops);
2094
2095	return r;
2096}
2097
2098static int omapfb_set_def_mode(struct omapfb2_device *fbdev,
2099		struct omap_dss_device *display, char *mode_str)
2100{
2101	int r;
2102	u8 bpp;
2103	struct omap_video_timings timings, temp_timings;
2104	struct omapfb_display_data *d;
2105
2106	r = omapfb_mode_to_timings(mode_str, display, &timings, &bpp);
2107	if (r)
2108		return r;
2109
2110	d = get_display_data(fbdev, display);
2111	d->bpp_override = bpp;
2112
2113	if (display->driver->check_timings) {
2114		r = display->driver->check_timings(display, &timings);
2115		if (r)
2116			return r;
2117	} else {
2118		/* If check_timings is not present compare xres and yres */
2119		if (display->driver->get_timings) {
2120			display->driver->get_timings(display, &temp_timings);
2121
2122			if (temp_timings.x_res != timings.x_res ||
2123				temp_timings.y_res != timings.y_res)
2124				return -EINVAL;
2125		}
2126	}
2127
2128	if (display->driver->set_timings)
2129			display->driver->set_timings(display, &timings);
2130
2131	return 0;
2132}
2133
2134static int omapfb_get_recommended_bpp(struct omapfb2_device *fbdev,
2135		struct omap_dss_device *dssdev)
2136{
2137	struct omapfb_display_data *d;
2138
2139	BUG_ON(dssdev->driver->get_recommended_bpp == NULL);
2140
2141	d = get_display_data(fbdev, dssdev);
2142
2143	if (d->bpp_override != 0)
2144		return d->bpp_override;
2145
2146	return dssdev->driver->get_recommended_bpp(dssdev);
2147}
2148
2149static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
2150{
2151	char *str, *options, *this_opt;
2152	int r = 0;
2153
2154	str = kstrdup(def_mode, GFP_KERNEL);
2155	if (!str)
2156		return -ENOMEM;
2157	options = str;
2158
2159	while (!r && (this_opt = strsep(&options, ",")) != NULL) {
2160		char *p, *display_str, *mode_str;
2161		struct omap_dss_device *display;
2162		int i;
2163
2164		p = strchr(this_opt, ':');
2165		if (!p) {
2166			r = -EINVAL;
2167			break;
2168		}
2169
2170		*p = 0;
2171		display_str = this_opt;
2172		mode_str = p + 1;
2173
2174		display = NULL;
2175		for (i = 0; i < fbdev->num_displays; ++i) {
2176			if (strcmp(fbdev->displays[i].dssdev->name,
2177						display_str) == 0) {
2178				display = fbdev->displays[i].dssdev;
2179				break;
2180			}
2181		}
2182
2183		if (!display) {
2184			r = -EINVAL;
2185			break;
2186		}
2187
2188		r = omapfb_set_def_mode(fbdev, display, mode_str);
2189		if (r)
2190			break;
2191	}
2192
2193	kfree(str);
2194
2195	return r;
2196}
2197
2198static void fb_videomode_to_omap_timings(struct fb_videomode *m,
2199		struct omap_dss_device *display,
2200		struct omap_video_timings *t)
2201{
2202	if (display->driver->get_timings) {
2203		display->driver->get_timings(display, t);
2204	} else {
2205		t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
2206		t->de_level = OMAPDSS_SIG_ACTIVE_HIGH;
2207		t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE;
2208	}
2209
2210	t->x_res = m->xres;
2211	t->y_res = m->yres;
2212	t->pixelclock = PICOS2KHZ(m->pixclock) * 1000;
2213	t->hsw = m->hsync_len;
2214	t->hfp = m->right_margin;
2215	t->hbp = m->left_margin;
2216	t->vsw = m->vsync_len;
2217	t->vfp = m->lower_margin;
2218	t->vbp = m->upper_margin;
2219	t->hsync_level = m->sync & FB_SYNC_HOR_HIGH_ACT ?
2220				OMAPDSS_SIG_ACTIVE_HIGH :
2221				OMAPDSS_SIG_ACTIVE_LOW;
2222	t->vsync_level = m->sync & FB_SYNC_VERT_HIGH_ACT ?
2223				OMAPDSS_SIG_ACTIVE_HIGH :
2224				OMAPDSS_SIG_ACTIVE_LOW;
2225	t->interlace = m->vmode & FB_VMODE_INTERLACED;
2226}
2227
2228static int omapfb_find_best_mode(struct omap_dss_device *display,
2229		struct omap_video_timings *timings)
2230{
2231	struct fb_monspecs *specs;
2232	u8 *edid;
2233	int r, i, best_idx, len;
2234
2235	if (!display->driver->read_edid)
2236		return -ENODEV;
2237
2238	len = 0x80 * 2;
2239	edid = kmalloc(len, GFP_KERNEL);
2240	if (edid == NULL)
2241		return -ENOMEM;
2242
2243	r = display->driver->read_edid(display, edid, len);
2244	if (r < 0)
2245		goto err1;
2246
2247	specs = kzalloc(sizeof(*specs), GFP_KERNEL);
2248	if (specs == NULL) {
2249		r = -ENOMEM;
2250		goto err1;
2251	}
2252
2253	fb_edid_to_monspecs(edid, specs);
2254
2255	best_idx = -1;
2256
2257	for (i = 0; i < specs->modedb_len; ++i) {
2258		struct fb_videomode *m;
2259		struct omap_video_timings t;
2260
2261		m = &specs->modedb[i];
2262
2263		if (m->pixclock == 0)
2264			continue;
2265
2266		/* skip repeated pixel modes */
2267		if (m->xres == 2880 || m->xres == 1440)
2268			continue;
2269
2270		if (m->vmode & FB_VMODE_INTERLACED ||
2271				m->vmode & FB_VMODE_DOUBLE)
2272			continue;
2273
2274		fb_videomode_to_omap_timings(m, display, &t);
2275
2276		r = display->driver->check_timings(display, &t);
2277		if (r == 0) {
2278			best_idx = i;
2279			break;
2280		}
2281	}
2282
2283	if (best_idx == -1) {
2284		r = -ENOENT;
2285		goto err2;
2286	}
2287
2288	fb_videomode_to_omap_timings(&specs->modedb[best_idx], display,
2289		timings);
2290
2291	r = 0;
2292
2293err2:
2294	fb_destroy_modedb(specs->modedb);
2295	kfree(specs);
2296err1:
2297	kfree(edid);
2298
2299	return r;
2300}
2301
2302static int omapfb_init_display(struct omapfb2_device *fbdev,
2303		struct omap_dss_device *dssdev)
2304{
2305	struct omap_dss_driver *dssdrv = dssdev->driver;
2306	struct omapfb_display_data *d;
2307	int r;
2308
2309	r = dssdrv->enable(dssdev);
2310	if (r) {
2311		dev_warn(fbdev->dev, "Failed to enable display '%s'\n",
2312				dssdev->name);
2313		return r;
2314	}
2315
2316	d = get_display_data(fbdev, dssdev);
2317
2318	d->fbdev = fbdev;
2319
2320	if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
2321		u16 w, h;
2322
2323		if (auto_update) {
2324			omapfb_start_auto_update(fbdev, dssdev);
2325			d->update_mode = OMAPFB_AUTO_UPDATE;
2326		} else {
2327			d->update_mode = OMAPFB_MANUAL_UPDATE;
2328		}
2329
2330		if (dssdrv->enable_te) {
2331			r = dssdrv->enable_te(dssdev, 1);
2332			if (r) {
2333				dev_err(fbdev->dev, "Failed to set TE\n");
2334				return r;
2335			}
2336		}
2337
2338		dssdrv->get_resolution(dssdev, &w, &h);
2339		r = dssdrv->update(dssdev, 0, 0, w, h);
2340		if (r) {
2341			dev_err(fbdev->dev,
2342					"Failed to update display\n");
2343			return r;
2344		}
2345	} else {
2346		d->update_mode = OMAPFB_AUTO_UPDATE;
2347	}
2348
2349	return 0;
2350}
2351
2352static int omapfb_init_connections(struct omapfb2_device *fbdev,
2353		struct omap_dss_device *def_dssdev)
2354{
2355	int i, r;
2356	struct omap_overlay_manager *mgr;
2357
2358	r = def_dssdev->driver->connect(def_dssdev);
2359	if (r) {
2360		dev_err(fbdev->dev, "failed to connect default display\n");
2361		return r;
2362	}
2363
2364	for (i = 0; i < fbdev->num_displays; ++i) {
2365		struct omap_dss_device *dssdev = fbdev->displays[i].dssdev;
2366
2367		if (dssdev == def_dssdev)
2368			continue;
2369
2370		/*
2371		 * We don't care if the connect succeeds or not. We just want to
2372		 * connect as many displays as possible.
2373		 */
2374		dssdev->driver->connect(dssdev);
2375	}
2376
2377	mgr = omapdss_find_mgr_from_display(def_dssdev);
2378
2379	if (!mgr) {
2380		dev_err(fbdev->dev, "no ovl manager for the default display\n");
2381		return -EINVAL;
2382	}
2383
2384	for (i = 0; i < fbdev->num_overlays; i++) {
2385		struct omap_overlay *ovl = fbdev->overlays[i];
2386
2387		if (ovl->manager)
2388			ovl->unset_manager(ovl);
2389
2390		r = ovl->set_manager(ovl, mgr);
2391		if (r)
2392			dev_warn(fbdev->dev,
2393					"failed to connect overlay %s to manager %s\n",
2394					ovl->name, mgr->name);
2395	}
2396
2397	return 0;
2398}
2399
2400static struct omap_dss_device *
2401omapfb_find_default_display(struct omapfb2_device *fbdev)
2402{
2403	const char *def_name;
2404	int i;
2405
2406	/*
2407	 * Search with the display name from the user or the board file,
2408	 * comparing to display names and aliases
2409	 */
2410
2411	def_name = omapdss_get_default_display_name();
2412
2413	if (def_name) {
2414		for (i = 0; i < fbdev->num_displays; ++i) {
2415			struct omap_dss_device *dssdev;
2416
2417			dssdev = fbdev->displays[i].dssdev;
2418
2419			if (dssdev->name && strcmp(def_name, dssdev->name) == 0)
2420				return dssdev;
2421
2422			if (strcmp(def_name, dssdev->alias) == 0)
2423				return dssdev;
2424		}
2425
2426		/* def_name given but not found */
2427		return NULL;
2428	}
2429
2430	/* then look for DT alias display0 */
2431	for (i = 0; i < fbdev->num_displays; ++i) {
2432		struct omap_dss_device *dssdev;
2433		int id;
2434
2435		dssdev = fbdev->displays[i].dssdev;
2436
2437		if (dssdev->dev->of_node == NULL)
2438			continue;
2439
2440		id = of_alias_get_id(dssdev->dev->of_node, "display");
2441		if (id == 0)
2442			return dssdev;
2443	}
2444
2445	/* return the first display we have in the list */
2446	return fbdev->displays[0].dssdev;
2447}
2448
2449static int omapfb_probe(struct platform_device *pdev)
2450{
2451	struct omapfb2_device *fbdev = NULL;
2452	int r = 0;
2453	int i;
2454	struct omap_dss_device *def_display;
2455	struct omap_dss_device *dssdev;
2456
2457	DBG("omapfb_probe\n");
2458
2459	if (omapdss_is_initialized() == false)
2460		return -EPROBE_DEFER;
2461
2462	if (pdev->num_resources != 0) {
2463		dev_err(&pdev->dev, "probed for an unknown device\n");
2464		r = -ENODEV;
2465		goto err0;
2466	}
2467
2468	fbdev = devm_kzalloc(&pdev->dev, sizeof(struct omapfb2_device),
2469			GFP_KERNEL);
2470	if (fbdev == NULL) {
2471		r = -ENOMEM;
2472		goto err0;
2473	}
2474
2475	if (def_vrfb && !omap_vrfb_supported()) {
2476		def_vrfb = 0;
2477		dev_warn(&pdev->dev, "VRFB is not supported on this hardware, "
2478				"ignoring the module parameter vrfb=y\n");
2479	}
2480
2481	r = omapdss_compat_init();
2482	if (r)
2483		goto err0;
2484
2485	mutex_init(&fbdev->mtx);
2486
2487	fbdev->dev = &pdev->dev;
2488	platform_set_drvdata(pdev, fbdev);
2489
2490	fbdev->num_displays = 0;
2491	dssdev = NULL;
2492	for_each_dss_dev(dssdev) {
2493		struct omapfb_display_data *d;
2494
2495		omap_dss_get_device(dssdev);
2496
2497		if (!dssdev->driver) {
2498			dev_warn(&pdev->dev, "no driver for display: %s\n",
2499				dssdev->name);
2500			omap_dss_put_device(dssdev);
2501			continue;
2502		}
2503
2504		d = &fbdev->displays[fbdev->num_displays++];
2505		d->dssdev = dssdev;
2506		if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE)
2507			d->update_mode = OMAPFB_MANUAL_UPDATE;
2508		else
2509			d->update_mode = OMAPFB_AUTO_UPDATE;
2510	}
2511
2512	if (fbdev->num_displays == 0) {
2513		dev_err(&pdev->dev, "no displays\n");
2514		r = -EPROBE_DEFER;
2515		goto cleanup;
2516	}
2517
2518	fbdev->num_overlays = omap_dss_get_num_overlays();
2519	for (i = 0; i < fbdev->num_overlays; i++)
2520		fbdev->overlays[i] = omap_dss_get_overlay(i);
2521
2522	fbdev->num_managers = omap_dss_get_num_overlay_managers();
2523	for (i = 0; i < fbdev->num_managers; i++)
2524		fbdev->managers[i] = omap_dss_get_overlay_manager(i);
2525
2526	def_display = omapfb_find_default_display(fbdev);
2527	if (def_display == NULL) {
2528		dev_err(fbdev->dev, "failed to find default display\n");
2529		r = -EPROBE_DEFER;
2530		goto cleanup;
2531	}
2532
2533	r = omapfb_init_connections(fbdev, def_display);
2534	if (r) {
2535		dev_err(fbdev->dev, "failed to init overlay connections\n");
2536		goto cleanup;
2537	}
2538
2539	if (def_mode && strlen(def_mode) > 0) {
2540		if (omapfb_parse_def_modes(fbdev))
2541			dev_warn(&pdev->dev, "cannot parse default modes\n");
2542	} else if (def_display && def_display->driver->set_timings &&
2543			def_display->driver->check_timings) {
2544		struct omap_video_timings t;
2545
2546		r = omapfb_find_best_mode(def_display, &t);
2547
2548		if (r == 0)
2549			def_display->driver->set_timings(def_display, &t);
2550	}
2551
2552	r = omapfb_create_framebuffers(fbdev);
2553	if (r)
2554		goto cleanup;
2555
2556	for (i = 0; i < fbdev->num_managers; i++) {
2557		struct omap_overlay_manager *mgr;
2558		mgr = fbdev->managers[i];
2559		r = mgr->apply(mgr);
2560		if (r)
2561			dev_warn(fbdev->dev, "failed to apply dispc config\n");
2562	}
2563
2564	DBG("mgr->apply'ed\n");
2565
2566	if (def_display) {
2567		r = omapfb_init_display(fbdev, def_display);
2568		if (r) {
2569			dev_err(fbdev->dev,
2570					"failed to initialize default "
2571					"display\n");
2572			goto cleanup;
2573		}
2574	}
2575
2576	DBG("create sysfs for fbs\n");
2577	r = omapfb_create_sysfs(fbdev);
2578	if (r) {
2579		dev_err(fbdev->dev, "failed to create sysfs entries\n");
2580		goto cleanup;
2581	}
2582
2583	if (def_display) {
2584		u16 w, h;
2585
2586		def_display->driver->get_resolution(def_display, &w, &h);
2587
2588		dev_info(fbdev->dev, "using display '%s' mode %dx%d\n",
2589			def_display->name, w, h);
2590	}
2591
2592	return 0;
2593
2594cleanup:
2595	omapfb_free_resources(fbdev);
2596	omapdss_compat_uninit();
2597err0:
2598	dev_err(&pdev->dev, "failed to setup omapfb\n");
2599	return r;
2600}
2601
2602static void omapfb_remove(struct platform_device *pdev)
2603{
2604	struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
2605
2606	/* FIXME: wait till completion of pending events */
2607
2608	omapfb_remove_sysfs(fbdev);
2609
2610	omapfb_free_resources(fbdev);
2611
2612	omapdss_compat_uninit();
2613}
2614
2615static struct platform_driver omapfb_driver = {
2616	.probe		= omapfb_probe,
2617	.remove_new     = omapfb_remove,
2618	.driver         = {
2619		.name   = "omapfb",
2620	},
2621};
2622
2623module_param_named(mode, def_mode, charp, 0);
2624module_param_named(vram, def_vram, charp, 0);
2625module_param_named(rotate, def_rotate, int, 0);
2626module_param_named(vrfb, def_vrfb, bool, 0);
2627module_param_named(mirror, def_mirror, bool, 0);
2628
2629module_platform_driver(omapfb_driver);
2630
2631MODULE_ALIAS("platform:omapfb");
2632MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
2633MODULE_DESCRIPTION("OMAP2/3 Framebuffer");
2634MODULE_LICENSE("GPL v2");
2635