1b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen/*
2b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen * linux/drivers/video/omap2/omapfb-main.c
3b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen *
4b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen * Copyright (C) 2008 Nokia Corporation
5b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen *
7b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen * Some code and ideas taken from drivers/video/omap/ driver
8b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen * by Imre Deak.
9b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen *
10b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen * This program is free software; you can redistribute it and/or modify it
11b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen * under the terms of the GNU General Public License version 2 as published by
12b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen * the Free Software Foundation.
13b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen *
14b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen * This program is distributed in the hope that it will be useful, but WITHOUT
15b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
17b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen * more details.
18b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen *
19b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen * You should have received a copy of the GNU General Public License along with
20b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen * this program.  If not, see <http://www.gnu.org/licenses/>.
21b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen */
22b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
23b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen#include <linux/module.h>
24b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen#include <linux/delay.h>
255a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
26b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen#include <linux/fb.h>
27b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen#include <linux/dma-mapping.h>
28b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen#include <linux/vmalloc.h>
29b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen#include <linux/device.h>
30b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen#include <linux/platform_device.h>
31b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen#include <linux/omapfb.h>
32b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
33a0b38cc4d35e095f14ab0f486135f8a619ebfc14Tomi Valkeinen#include <video/omapdss.h>
34b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen#include <plat/vram.h>
35b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen#include <plat/vrfb.h>
36b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
37b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen#include "omapfb.h"
38b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
39b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen#define MODULE_NAME     "omapfb"
40b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
41b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen#define OMAPFB_PLANE_XRES_MIN		8
42b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen#define OMAPFB_PLANE_YRES_MIN		8
43b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
44b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic char *def_mode;
45b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic char *def_vram;
4690ab5ee94171b3e28de6bb42ee30b527014e0be7Rusty Russellstatic bool def_vrfb;
47b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic int def_rotate;
4890ab5ee94171b3e28de6bb42ee30b527014e0be7Rusty Russellstatic bool def_mirror;
4927cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinenstatic bool auto_update;
5027cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinenstatic unsigned int auto_update_freq;
5127cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinenmodule_param(auto_update, bool, 0);
5227cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinenmodule_param(auto_update_freq, uint, 0644);
53b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
54b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen#ifdef DEBUG
5590ab5ee94171b3e28de6bb42ee30b527014e0be7Rusty Russellbool omapfb_debug;
56b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenmodule_param_named(debug, omapfb_debug, bool, 0644);
5790ab5ee94171b3e28de6bb42ee30b527014e0be7Rusty Russellstatic bool omapfb_test_pattern;
58b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenmodule_param_named(test, omapfb_test_pattern, bool, 0644);
59b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen#endif
60b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
61b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi);
62a269950405ab17ce3a604ddcd939709a4a7a747cTomi Valkeinenstatic int omapfb_get_recommended_bpp(struct omapfb2_device *fbdev,
63a269950405ab17ce3a604ddcd939709a4a7a747cTomi Valkeinen		struct omap_dss_device *dssdev);
64b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
65b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen#ifdef DEBUG
66b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic void draw_pixel(struct fb_info *fbi, int x, int y, unsigned color)
67b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
68b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct fb_var_screeninfo *var = &fbi->var;
69b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct fb_fix_screeninfo *fix = &fbi->fix;
70b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	void __iomem *addr = fbi->screen_base;
71b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	const unsigned bytespp = var->bits_per_pixel >> 3;
72b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	const unsigned line_len = fix->line_length / bytespp;
73b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
74b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int r = (color >> 16) & 0xff;
75b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int g = (color >> 8) & 0xff;
76b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int b = (color >> 0) & 0xff;
77b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
78b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (var->bits_per_pixel == 16) {
79b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		u16 __iomem *p = (u16 __iomem *)addr;
80b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		p += y * line_len + x;
81b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
82b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		r = r * 32 / 256;
83b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		g = g * 64 / 256;
84b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		b = b * 32 / 256;
85b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
86b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		__raw_writew((r << 11) | (g << 5) | (b << 0), p);
87b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	} else if (var->bits_per_pixel == 24) {
88b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		u8 __iomem *p = (u8 __iomem *)addr;
89b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		p += (y * line_len + x) * 3;
90b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
91b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		__raw_writeb(b, p + 0);
92b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		__raw_writeb(g, p + 1);
93b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		__raw_writeb(r, p + 2);
94b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	} else if (var->bits_per_pixel == 32) {
95b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		u32 __iomem *p = (u32 __iomem *)addr;
96b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		p += y * line_len + x;
97b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		__raw_writel(color, p);
98b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
99b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
100b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
101b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic void fill_fb(struct fb_info *fbi)
102b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
103b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct fb_var_screeninfo *var = &fbi->var;
104b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	const short w = var->xres_virtual;
105b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	const short h = var->yres_virtual;
106b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	void __iomem *addr = fbi->screen_base;
107b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int y, x;
108b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
109b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (!addr)
110b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		return;
111b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
112b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	DBG("fill_fb %dx%d, line_len %d bytes\n", w, h, fbi->fix.line_length);
113b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
114b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	for (y = 0; y < h; y++) {
115b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		for (x = 0; x < w; x++) {
116b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			if (x < 20 && y < 20)
117b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				draw_pixel(fbi, x, y, 0xffffff);
118b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			else if (x < 20 && (y > 20 && y < h - 20))
119b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				draw_pixel(fbi, x, y, 0xff);
120b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			else if (y < 20 && (x > 20 && x < w - 20))
121b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				draw_pixel(fbi, x, y, 0xff00);
122b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			else if (x > w - 20 && (y > 20 && y < h - 20))
123b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				draw_pixel(fbi, x, y, 0xff0000);
124b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			else if (y > h - 20 && (x > 20 && x < w - 20))
125b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				draw_pixel(fbi, x, y, 0xffff00);
126b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			else if (x == 20 || x == w - 20 ||
127b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen					y == 20 || y == h - 20)
128b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				draw_pixel(fbi, x, y, 0xffffff);
129b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			else if (x == y || w - x == h - y)
130b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				draw_pixel(fbi, x, y, 0xff00ff);
131b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			else if (w - x == y || x == h - y)
132b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				draw_pixel(fbi, x, y, 0x00ffff);
133b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			else if (x > 20 && y > 20 && x < w - 20 && y < h - 20) {
134b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				int t = x * 3 / w;
135b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				unsigned r = 0, g = 0, b = 0;
136b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				unsigned c;
137b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				if (var->bits_per_pixel == 16) {
138b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen					if (t == 0)
139b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen						b = (y % 32) * 256 / 32;
140b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen					else if (t == 1)
141b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen						g = (y % 64) * 256 / 64;
142b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen					else if (t == 2)
143b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen						r = (y % 32) * 256 / 32;
144b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				} else {
145b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen					if (t == 0)
146b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen						b = (y % 256);
147b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen					else if (t == 1)
148b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen						g = (y % 256);
149b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen					else if (t == 2)
150b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen						r = (y % 256);
151b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				}
152b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				c = (r << 16) | (g << 8) | (b << 0);
153b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				draw_pixel(fbi, x, y, c);
154b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			} else {
155b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				draw_pixel(fbi, x, y, 0);
156b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			}
157b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		}
158b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
159b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
160b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen#endif
161b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
162a4c1a148a0c4c690b95938e9577be9e461bc5e5aVille Syrjälästatic unsigned omapfb_get_vrfb_offset(const struct omapfb_info *ofbi, int rot)
163b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
164078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä	const struct vrfb *vrfb = &ofbi->region->vrfb;
165b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	unsigned offset;
166b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
167b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	switch (rot) {
168b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	case FB_ROTATE_UR:
169b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		offset = 0;
170b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		break;
171b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	case FB_ROTATE_CW:
172b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		offset = vrfb->yoffset;
173b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		break;
174b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	case FB_ROTATE_UD:
175b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		offset = vrfb->yoffset * OMAP_VRFB_LINE_LEN + vrfb->xoffset;
176b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		break;
177b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	case FB_ROTATE_CCW:
178b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		offset = vrfb->xoffset * OMAP_VRFB_LINE_LEN;
179b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		break;
180b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	default:
181b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		BUG();
182b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
183b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
184b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	offset *= vrfb->bytespp;
185b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
186b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return offset;
187b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
188b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
189a4c1a148a0c4c690b95938e9577be9e461bc5e5aVille Syrjälästatic u32 omapfb_get_region_rot_paddr(const struct omapfb_info *ofbi, int rot)
190b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
191b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
192078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä		return ofbi->region->vrfb.paddr[rot]
193b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			+ omapfb_get_vrfb_offset(ofbi, rot);
194b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	} else {
195078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä		return ofbi->region->paddr;
196b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
197b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
198b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
199a4c1a148a0c4c690b95938e9577be9e461bc5e5aVille Syrjälästatic u32 omapfb_get_region_paddr(const struct omapfb_info *ofbi)
200b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
201b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
202078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä		return ofbi->region->vrfb.paddr[0];
203b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	else
204078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä		return ofbi->region->paddr;
205b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
206b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
207a4c1a148a0c4c690b95938e9577be9e461bc5e5aVille Syrjälästatic void __iomem *omapfb_get_region_vaddr(const struct omapfb_info *ofbi)
208b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
209b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
210078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä		return ofbi->region->vrfb.vaddr[0];
211b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	else
212078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä		return ofbi->region->vaddr;
213b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
214b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
215b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic struct omapfb_colormode omapfb_colormodes[] = {
216b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	{
217b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.dssmode = OMAP_DSS_COLOR_UYVY,
218b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.bits_per_pixel = 16,
219b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.nonstd = OMAPFB_COLOR_YUV422,
220b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}, {
221b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.dssmode = OMAP_DSS_COLOR_YUV2,
222b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.bits_per_pixel = 16,
223b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.nonstd = OMAPFB_COLOR_YUY422,
224b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}, {
225b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.dssmode = OMAP_DSS_COLOR_ARGB16,
226b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.bits_per_pixel = 16,
227b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.red	= { .length = 4, .offset = 8, .msb_right = 0 },
228b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.green	= { .length = 4, .offset = 4, .msb_right = 0 },
229b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.blue	= { .length = 4, .offset = 0, .msb_right = 0 },
230b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.transp	= { .length = 4, .offset = 12, .msb_right = 0 },
231b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}, {
232b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.dssmode = OMAP_DSS_COLOR_RGB16,
233b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.bits_per_pixel = 16,
234b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.red	= { .length = 5, .offset = 11, .msb_right = 0 },
235b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.green	= { .length = 6, .offset = 5, .msb_right = 0 },
236b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.blue	= { .length = 5, .offset = 0, .msb_right = 0 },
237b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.transp	= { .length = 0, .offset = 0, .msb_right = 0 },
238b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}, {
239b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.dssmode = OMAP_DSS_COLOR_RGB24P,
240b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.bits_per_pixel = 24,
241b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.red	= { .length = 8, .offset = 16, .msb_right = 0 },
242b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.green	= { .length = 8, .offset = 8, .msb_right = 0 },
243b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.blue	= { .length = 8, .offset = 0, .msb_right = 0 },
244b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.transp	= { .length = 0, .offset = 0, .msb_right = 0 },
245b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}, {
246b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.dssmode = OMAP_DSS_COLOR_RGB24U,
247b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.bits_per_pixel = 32,
248b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.red	= { .length = 8, .offset = 16, .msb_right = 0 },
249b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.green	= { .length = 8, .offset = 8, .msb_right = 0 },
250b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.blue	= { .length = 8, .offset = 0, .msb_right = 0 },
251b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.transp	= { .length = 0, .offset = 0, .msb_right = 0 },
252b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}, {
253b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.dssmode = OMAP_DSS_COLOR_ARGB32,
254b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.bits_per_pixel = 32,
255b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.red	= { .length = 8, .offset = 16, .msb_right = 0 },
256b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.green	= { .length = 8, .offset = 8, .msb_right = 0 },
257b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.blue	= { .length = 8, .offset = 0, .msb_right = 0 },
258b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.transp	= { .length = 8, .offset = 24, .msb_right = 0 },
259b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}, {
260b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.dssmode = OMAP_DSS_COLOR_RGBA32,
261b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.bits_per_pixel = 32,
262b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.red	= { .length = 8, .offset = 24, .msb_right = 0 },
263b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.green	= { .length = 8, .offset = 16, .msb_right = 0 },
264b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.blue	= { .length = 8, .offset = 8, .msb_right = 0 },
265b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.transp	= { .length = 8, .offset = 0, .msb_right = 0 },
266b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}, {
267b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.dssmode = OMAP_DSS_COLOR_RGBX32,
268b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.bits_per_pixel = 32,
269b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.red	= { .length = 8, .offset = 24, .msb_right = 0 },
270b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.green	= { .length = 8, .offset = 16, .msb_right = 0 },
271b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.blue	= { .length = 8, .offset = 8, .msb_right = 0 },
272b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.transp	= { .length = 0, .offset = 0, .msb_right = 0 },
273b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	},
274b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen};
275b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
276b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic bool cmp_var_to_colormode(struct fb_var_screeninfo *var,
277b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		struct omapfb_colormode *color)
278b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
279b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	bool cmp_component(struct fb_bitfield *f1, struct fb_bitfield *f2)
280b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	{
281b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		return f1->length == f2->length &&
282b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			f1->offset == f2->offset &&
283b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			f1->msb_right == f2->msb_right;
284b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
285b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
286b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (var->bits_per_pixel == 0 ||
287b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			var->red.length == 0 ||
288b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			var->blue.length == 0 ||
289b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			var->green.length == 0)
290b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		return 0;
291b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
292b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return var->bits_per_pixel == color->bits_per_pixel &&
293b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		cmp_component(&var->red, &color->red) &&
294b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		cmp_component(&var->green, &color->green) &&
295b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		cmp_component(&var->blue, &color->blue) &&
296b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		cmp_component(&var->transp, &color->transp);
297b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
298b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
299b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic void assign_colormode_to_var(struct fb_var_screeninfo *var,
300b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		struct omapfb_colormode *color)
301b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
302b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	var->bits_per_pixel = color->bits_per_pixel;
303b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	var->nonstd = color->nonstd;
304b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	var->red = color->red;
305b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	var->green = color->green;
306b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	var->blue = color->blue;
307b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	var->transp = color->transp;
308b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
309b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
310b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic int fb_mode_to_dss_mode(struct fb_var_screeninfo *var,
311b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		enum omap_color_mode *mode)
312b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
313b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	enum omap_color_mode dssmode;
314b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int i;
315b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
316b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	/* first match with nonstd field */
317b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (var->nonstd) {
318b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
319b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			struct omapfb_colormode *m = &omapfb_colormodes[i];
320b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			if (var->nonstd == m->nonstd) {
321b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				assign_colormode_to_var(var, m);
322b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				*mode = m->dssmode;
323b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				return 0;
324b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			}
325b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		}
326b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
327b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		return -EINVAL;
328b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
329b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
330b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	/* then try exact match of bpp and colors */
331b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
332b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		struct omapfb_colormode *m = &omapfb_colormodes[i];
333b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (cmp_var_to_colormode(var, m)) {
334b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			assign_colormode_to_var(var, m);
335b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			*mode = m->dssmode;
336b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			return 0;
337b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		}
338b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
339b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
340b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	/* match with bpp if user has not filled color fields
341b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	 * properly */
342b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	switch (var->bits_per_pixel) {
343b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	case 1:
344b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		dssmode = OMAP_DSS_COLOR_CLUT1;
345b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		break;
346b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	case 2:
347b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		dssmode = OMAP_DSS_COLOR_CLUT2;
348b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		break;
349b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	case 4:
350b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		dssmode = OMAP_DSS_COLOR_CLUT4;
351b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		break;
352b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	case 8:
353b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		dssmode = OMAP_DSS_COLOR_CLUT8;
354b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		break;
355b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	case 12:
356b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		dssmode = OMAP_DSS_COLOR_RGB12U;
357b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		break;
358b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	case 16:
359b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		dssmode = OMAP_DSS_COLOR_RGB16;
360b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		break;
361b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	case 24:
362b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		dssmode = OMAP_DSS_COLOR_RGB24P;
363b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		break;
364b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	case 32:
365b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		dssmode = OMAP_DSS_COLOR_RGB24U;
366b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		break;
367b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	default:
368b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		return -EINVAL;
369b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
370b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
371b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
372b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		struct omapfb_colormode *m = &omapfb_colormodes[i];
373b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (dssmode == m->dssmode) {
374b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			assign_colormode_to_var(var, m);
375b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			*mode = m->dssmode;
376b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			return 0;
377b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		}
378b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
379b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
380b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return -EINVAL;
381b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
382b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
383b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic int check_fb_res_bounds(struct fb_var_screeninfo *var)
384b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
385b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int xres_min = OMAPFB_PLANE_XRES_MIN;
386b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int xres_max = 2048;
387b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int yres_min = OMAPFB_PLANE_YRES_MIN;
388b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int yres_max = 2048;
389b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
390b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	/* XXX: some applications seem to set virtual res to 0. */
391b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (var->xres_virtual == 0)
392b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		var->xres_virtual = var->xres;
393b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
394b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (var->yres_virtual == 0)
395b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		var->yres_virtual = var->yres;
396b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
397b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (var->xres_virtual < xres_min || var->yres_virtual < yres_min)
398b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		return -EINVAL;
399b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
400b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (var->xres < xres_min)
401b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		var->xres = xres_min;
402b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (var->yres < yres_min)
403b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		var->yres = yres_min;
404b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (var->xres > xres_max)
405b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		var->xres = xres_max;
406b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (var->yres > yres_max)
407b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		var->yres = yres_max;
408b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
409b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (var->xres > var->xres_virtual)
410b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		var->xres = var->xres_virtual;
411b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (var->yres > var->yres_virtual)
412b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		var->yres = var->yres_virtual;
413b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
414b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return 0;
415b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
416b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
417b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic void shrink_height(unsigned long max_frame_size,
418b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		struct fb_var_screeninfo *var)
419b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
420b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	DBG("can't fit FB into memory, reducing y\n");
421b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	var->yres_virtual = max_frame_size /
422b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		(var->xres_virtual * var->bits_per_pixel >> 3);
423b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
424b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (var->yres_virtual < OMAPFB_PLANE_YRES_MIN)
425b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		var->yres_virtual = OMAPFB_PLANE_YRES_MIN;
426b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
427b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (var->yres > var->yres_virtual)
428b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		var->yres = var->yres_virtual;
429b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
430b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
431b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic void shrink_width(unsigned long max_frame_size,
432b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		struct fb_var_screeninfo *var)
433b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
434b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	DBG("can't fit FB into memory, reducing x\n");
435b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	var->xres_virtual = max_frame_size / var->yres_virtual /
436b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		(var->bits_per_pixel >> 3);
437b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
438b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (var->xres_virtual < OMAPFB_PLANE_XRES_MIN)
439b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		var->xres_virtual = OMAPFB_PLANE_XRES_MIN;
440b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
441b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (var->xres > var->xres_virtual)
442b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		var->xres = var->xres_virtual;
443b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
444b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
445b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic int check_vrfb_fb_size(unsigned long region_size,
446b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		const struct fb_var_screeninfo *var)
447b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
448b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	unsigned long min_phys_size = omap_vrfb_min_phys_size(var->xres_virtual,
449b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		var->yres_virtual, var->bits_per_pixel >> 3);
450b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
451b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return min_phys_size > region_size ? -EINVAL : 0;
452b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
453b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
454b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic int check_fb_size(const struct omapfb_info *ofbi,
455b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		struct fb_var_screeninfo *var)
456b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
457078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä	unsigned long max_frame_size = ofbi->region->size;
458b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int bytespp = var->bits_per_pixel >> 3;
459b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	unsigned long line_size = var->xres_virtual * bytespp;
460b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
461b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
462b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		/* One needs to check for both VRFB and OMAPFB limitations. */
463b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (check_vrfb_fb_size(max_frame_size, var))
464b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			shrink_height(omap_vrfb_max_height(
465b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				max_frame_size, var->xres_virtual, bytespp) *
466b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				line_size, var);
467b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
468b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (check_vrfb_fb_size(max_frame_size, var)) {
469b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			DBG("cannot fit FB to memory\n");
470b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			return -EINVAL;
471b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		}
472b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
473b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		return 0;
474b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
475b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
476b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	DBG("max frame size %lu, line size %lu\n", max_frame_size, line_size);
477b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
478b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (line_size * var->yres_virtual > max_frame_size)
479b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		shrink_height(max_frame_size, var);
480b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
481b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (line_size * var->yres_virtual > max_frame_size) {
482b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		shrink_width(max_frame_size, var);
483b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		line_size = var->xres_virtual * bytespp;
484b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
485b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
486b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (line_size * var->yres_virtual > max_frame_size) {
487b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		DBG("cannot fit FB to memory\n");
488b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		return -EINVAL;
489b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
490b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
491b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return 0;
492b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
493b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
494b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen/*
495b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen * Consider if VRFB assisted rotation is in use and if the virtual space for
496b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen * the zero degree view needs to be mapped. The need for mapping also acts as
497b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen * the trigger for setting up the hardware on the context in question. This
498b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen * ensures that one does not attempt to access the virtual view before the
499b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen * hardware is serving the address translations.
500b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen */
501b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic int setup_vrfb_rotation(struct fb_info *fbi)
502b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
503b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct omapfb_info *ofbi = FB2OFB(fbi);
504078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä	struct omapfb2_mem_region *rg = ofbi->region;
505b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct vrfb *vrfb = &rg->vrfb;
506b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct fb_var_screeninfo *var = &fbi->var;
507b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct fb_fix_screeninfo *fix = &fbi->fix;
508b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	unsigned bytespp;
509b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	bool yuv_mode;
510b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	enum omap_color_mode mode;
511b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int r;
512b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	bool reconf;
513b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
514b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (!rg->size || ofbi->rotation_type != OMAP_DSS_ROT_VRFB)
515b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		return 0;
516b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
517b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	DBG("setup_vrfb_rotation\n");
518b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
519b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	r = fb_mode_to_dss_mode(var, &mode);
520b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (r)
521b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		return r;
522b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
523b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	bytespp = var->bits_per_pixel >> 3;
524b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
525b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	yuv_mode = mode == OMAP_DSS_COLOR_YUV2 || mode == OMAP_DSS_COLOR_UYVY;
526b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
527b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	/* We need to reconfigure VRFB if the resolution changes, if yuv mode
528b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	 * is enabled/disabled, or if bytes per pixel changes */
529b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
530b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	/* XXX we shouldn't allow this when framebuffer is mmapped */
531b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
532b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	reconf = false;
533b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
534b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (yuv_mode != vrfb->yuv_mode)
535b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		reconf = true;
536b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	else if (bytespp != vrfb->bytespp)
537b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		reconf = true;
538b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	else if (vrfb->xres != var->xres_virtual ||
539b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			vrfb->yres != var->yres_virtual)
540b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		reconf = true;
541b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
542b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (vrfb->vaddr[0] && reconf) {
543b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		fbi->screen_base = NULL;
544b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		fix->smem_start = 0;
545b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		fix->smem_len = 0;
546b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		iounmap(vrfb->vaddr[0]);
547b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		vrfb->vaddr[0] = NULL;
548b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		DBG("setup_vrfb_rotation: reset fb\n");
549b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
550b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
551b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (vrfb->vaddr[0])
552b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		return 0;
553b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
554b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	omap_vrfb_setup(&rg->vrfb, rg->paddr,
555b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			var->xres_virtual,
556b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			var->yres_virtual,
557b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			bytespp, yuv_mode);
558b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
559b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	/* Now one can ioremap the 0 angle view */
560b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	r = omap_vrfb_map_angle(vrfb, var->yres_virtual, 0);
561b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (r)
562b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		return r;
563b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
564b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	/* used by open/write in fbmem.c */
565078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä	fbi->screen_base = ofbi->region->vrfb.vaddr[0];
566b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
567078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä	fix->smem_start = ofbi->region->vrfb.paddr[0];
568b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
569b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	switch (var->nonstd) {
570b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	case OMAPFB_COLOR_YUV422:
571b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	case OMAPFB_COLOR_YUY422:
572b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		fix->line_length =
573b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			(OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 2;
574b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		break;
575b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	default:
576b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		fix->line_length =
577b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			(OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 3;
578b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		break;
579b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
580b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
581b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	fix->smem_len = var->yres_virtual * fix->line_length;
582b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
583b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return 0;
584b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
585b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
586b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenint dss_mode_to_fb_mode(enum omap_color_mode dssmode,
587b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			struct fb_var_screeninfo *var)
588b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
589b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int i;
590b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
591b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
592b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		struct omapfb_colormode *mode = &omapfb_colormodes[i];
593b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (dssmode == mode->dssmode) {
594b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			assign_colormode_to_var(var, mode);
595b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			return 0;
596b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		}
597b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
598b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return -ENOENT;
599b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
600b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
601b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenvoid set_fb_fix(struct fb_info *fbi)
602b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
603b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct fb_fix_screeninfo *fix = &fbi->fix;
604b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct fb_var_screeninfo *var = &fbi->var;
605b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct omapfb_info *ofbi = FB2OFB(fbi);
606078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä	struct omapfb2_mem_region *rg = ofbi->region;
607b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
608b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	DBG("set_fb_fix\n");
609b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
610b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	/* used by open/write in fbmem.c */
611b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	fbi->screen_base = (char __iomem *)omapfb_get_region_vaddr(ofbi);
612b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
613b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	/* used by mmap in fbmem.c */
614b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
615b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		switch (var->nonstd) {
616b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		case OMAPFB_COLOR_YUV422:
617b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		case OMAPFB_COLOR_YUY422:
618b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			fix->line_length =
619b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				(OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 2;
620b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			break;
621b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		default:
622b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			fix->line_length =
623b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				(OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 3;
624b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			break;
625b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		}
626b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
627b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		fix->smem_len = var->yres_virtual * fix->line_length;
628b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	} else {
629b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		fix->line_length =
630b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			(var->xres_virtual * var->bits_per_pixel) >> 3;
631b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		fix->smem_len = rg->size;
632b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
633b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
634b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	fix->smem_start = omapfb_get_region_paddr(ofbi);
635b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
636b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	fix->type = FB_TYPE_PACKED_PIXELS;
637b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
638b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (var->nonstd)
639b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		fix->visual = FB_VISUAL_PSEUDOCOLOR;
640b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	else {
641b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		switch (var->bits_per_pixel) {
642b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		case 32:
643b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		case 24:
644b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		case 16:
645b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		case 12:
646b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			fix->visual = FB_VISUAL_TRUECOLOR;
647b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			/* 12bpp is stored in 16 bits */
648b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			break;
649b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		case 1:
650b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		case 2:
651b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		case 4:
652b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		case 8:
653b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			fix->visual = FB_VISUAL_PSEUDOCOLOR;
654b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			break;
655b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		}
656b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
657b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
658b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	fix->accel = FB_ACCEL_NONE;
659b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
660b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	fix->xpanstep = 1;
661b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	fix->ypanstep = 1;
662b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
663b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
664b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen/* check new var and possibly modify it to be ok */
665b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenint check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
666b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
667b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct omapfb_info *ofbi = FB2OFB(fbi);
668b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct omap_dss_device *display = fb2display(fbi);
669b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	enum omap_color_mode mode = 0;
670b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int i;
671b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int r;
672b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
673b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	DBG("check_fb_var %d\n", ofbi->id);
674b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
6751ceafc00910439c8e5450fae189b69427725992cVille Syrjälä	WARN_ON(!atomic_read(&ofbi->region->lock_count));
6761ceafc00910439c8e5450fae189b69427725992cVille Syrjälä
677b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	r = fb_mode_to_dss_mode(var, &mode);
678b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (r) {
679b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		DBG("cannot convert var to omap dss mode\n");
680b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		return r;
681b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
682b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
683b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	for (i = 0; i < ofbi->num_overlays; ++i) {
684b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if ((ofbi->overlays[i]->supported_modes & mode) == 0) {
685b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			DBG("invalid mode\n");
686b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			return -EINVAL;
687b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		}
688b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
689b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
69086f2d7dd72e1ff4656107e42a12c999a7b9c26d4Jani Nikula	if (var->rotate > 3)
691b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		return -EINVAL;
692b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
693b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (check_fb_res_bounds(var))
694b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		return -EINVAL;
695b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
696276a1d4337c9c261f42d5a7f813d96ca18f67c2bVille Syrjälä	/* When no memory is allocated ignore the size check */
697078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä	if (ofbi->region->size != 0 && check_fb_size(ofbi, var))
698b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		return -EINVAL;
699b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
700b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (var->xres + var->xoffset > var->xres_virtual)
701b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		var->xoffset = var->xres_virtual - var->xres;
702b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (var->yres + var->yoffset > var->yres_virtual)
703b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		var->yoffset = var->yres_virtual - var->yres;
704b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
705b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	DBG("xres = %d, yres = %d, vxres = %d, vyres = %d\n",
706b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			var->xres, var->yres,
707b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			var->xres_virtual, var->yres_virtual);
708b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
7097a0987bf2cf2683901d0cd7f1504023da2584c5fJani Nikula	if (display && display->driver->get_dimensions) {
7107a0987bf2cf2683901d0cd7f1504023da2584c5fJani Nikula		u32 w, h;
7117a0987bf2cf2683901d0cd7f1504023da2584c5fJani Nikula		display->driver->get_dimensions(display, &w, &h);
7127a0987bf2cf2683901d0cd7f1504023da2584c5fJani Nikula		var->width = DIV_ROUND_CLOSEST(w, 1000);
7137a0987bf2cf2683901d0cd7f1504023da2584c5fJani Nikula		var->height = DIV_ROUND_CLOSEST(h, 1000);
7147a0987bf2cf2683901d0cd7f1504023da2584c5fJani Nikula	} else {
7157a0987bf2cf2683901d0cd7f1504023da2584c5fJani Nikula		var->height = -1;
7167a0987bf2cf2683901d0cd7f1504023da2584c5fJani Nikula		var->width = -1;
7177a0987bf2cf2683901d0cd7f1504023da2584c5fJani Nikula	}
7187a0987bf2cf2683901d0cd7f1504023da2584c5fJani Nikula
719b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	var->grayscale          = 0;
720b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
72169b2048f44ead2d278e25d12adf0494b469ffb1cTomi Valkeinen	if (display && display->driver->get_timings) {
722b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		struct omap_video_timings timings;
72369b2048f44ead2d278e25d12adf0494b469ffb1cTomi Valkeinen		display->driver->get_timings(display, &timings);
724b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
725b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		/* pixclock in ps, the rest in pixclock */
726b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		var->pixclock = timings.pixel_clock != 0 ?
727b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			KHZ2PICOS(timings.pixel_clock) :
728b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			0;
72987ba8288670c53f66ce41d8ce292c64674de821eTasslehoff Kjappfot		var->left_margin = timings.hbp;
73087ba8288670c53f66ce41d8ce292c64674de821eTasslehoff Kjappfot		var->right_margin = timings.hfp;
73187ba8288670c53f66ce41d8ce292c64674de821eTasslehoff Kjappfot		var->upper_margin = timings.vbp;
73287ba8288670c53f66ce41d8ce292c64674de821eTasslehoff Kjappfot		var->lower_margin = timings.vfp;
733b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		var->hsync_len = timings.hsw;
734b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		var->vsync_len = timings.vsw;
735b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	} else {
736b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		var->pixclock = 0;
737b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		var->left_margin = 0;
738b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		var->right_margin = 0;
739b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		var->upper_margin = 0;
740b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		var->lower_margin = 0;
741b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		var->hsync_len = 0;
742b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		var->vsync_len = 0;
743b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
744b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
745b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	/* TODO: get these from panel->config */
746b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	var->vmode              = FB_VMODE_NONINTERLACED;
747b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	var->sync               = 0;
748b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
749b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return 0;
750b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
751b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
752b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen/*
753b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen * ---------------------------------------------------------------------------
754b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen * fbdev framework callbacks
755b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen * ---------------------------------------------------------------------------
756b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen */
757b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic int omapfb_open(struct fb_info *fbi, int user)
758b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
759b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return 0;
760b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
761b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
762b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic int omapfb_release(struct fb_info *fbi, int user)
763b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
764b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return 0;
765b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
766b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
767a4c1a148a0c4c690b95938e9577be9e461bc5e5aVille Syrjälästatic unsigned calc_rotation_offset_dma(const struct fb_var_screeninfo *var,
768a4c1a148a0c4c690b95938e9577be9e461bc5e5aVille Syrjälä		const struct fb_fix_screeninfo *fix, int rotation)
769b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
770b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	unsigned offset;
771b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
772b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	offset = var->yoffset * fix->line_length +
773b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		var->xoffset * (var->bits_per_pixel >> 3);
774b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
775b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return offset;
776b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
777b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
778a4c1a148a0c4c690b95938e9577be9e461bc5e5aVille Syrjälästatic unsigned calc_rotation_offset_vrfb(const struct fb_var_screeninfo *var,
779a4c1a148a0c4c690b95938e9577be9e461bc5e5aVille Syrjälä		const struct fb_fix_screeninfo *fix, int rotation)
780b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
781b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	unsigned offset;
782b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
783b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (rotation == FB_ROTATE_UD)
784b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		offset = (var->yres_virtual - var->yres) *
785b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			fix->line_length;
786b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	else if (rotation == FB_ROTATE_CW)
787b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		offset = (var->yres_virtual - var->yres) *
788b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			(var->bits_per_pixel >> 3);
789b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	else
790b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		offset = 0;
791b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
792b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (rotation == FB_ROTATE_UR)
793b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		offset += var->yoffset * fix->line_length +
794b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			var->xoffset * (var->bits_per_pixel >> 3);
795b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	else if (rotation == FB_ROTATE_UD)
796b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		offset -= var->yoffset * fix->line_length +
797b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			var->xoffset * (var->bits_per_pixel >> 3);
798b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	else if (rotation == FB_ROTATE_CW)
799b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		offset -= var->xoffset * fix->line_length +
800b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			var->yoffset * (var->bits_per_pixel >> 3);
801b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	else if (rotation == FB_ROTATE_CCW)
802b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		offset += var->xoffset * fix->line_length +
803b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			var->yoffset * (var->bits_per_pixel >> 3);
804b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
805b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return offset;
806b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
807b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
80846d3524a1b9155dd9cd57ea28e00db08c7a95c1aVille Syrjälästatic void omapfb_calc_addr(const struct omapfb_info *ofbi,
80946d3524a1b9155dd9cd57ea28e00db08c7a95c1aVille Syrjälä			     const struct fb_var_screeninfo *var,
81046d3524a1b9155dd9cd57ea28e00db08c7a95c1aVille Syrjälä			     const struct fb_fix_screeninfo *fix,
811212b0d50e2eb7fc60f7bea1e90e5867b5fc0647dTomi Valkeinen			     int rotation, u32 *paddr)
81246d3524a1b9155dd9cd57ea28e00db08c7a95c1aVille Syrjälä{
81346d3524a1b9155dd9cd57ea28e00db08c7a95c1aVille Syrjälä	u32 data_start_p;
81446d3524a1b9155dd9cd57ea28e00db08c7a95c1aVille Syrjälä	int offset;
81546d3524a1b9155dd9cd57ea28e00db08c7a95c1aVille Syrjälä
816212b0d50e2eb7fc60f7bea1e90e5867b5fc0647dTomi Valkeinen	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
81746d3524a1b9155dd9cd57ea28e00db08c7a95c1aVille Syrjälä		data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation);
818212b0d50e2eb7fc60f7bea1e90e5867b5fc0647dTomi Valkeinen	else
81946d3524a1b9155dd9cd57ea28e00db08c7a95c1aVille Syrjälä		data_start_p = omapfb_get_region_paddr(ofbi);
82046d3524a1b9155dd9cd57ea28e00db08c7a95c1aVille Syrjälä
82146d3524a1b9155dd9cd57ea28e00db08c7a95c1aVille Syrjälä	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
82246d3524a1b9155dd9cd57ea28e00db08c7a95c1aVille Syrjälä		offset = calc_rotation_offset_vrfb(var, fix, rotation);
82346d3524a1b9155dd9cd57ea28e00db08c7a95c1aVille Syrjälä	else
82446d3524a1b9155dd9cd57ea28e00db08c7a95c1aVille Syrjälä		offset = calc_rotation_offset_dma(var, fix, rotation);
82546d3524a1b9155dd9cd57ea28e00db08c7a95c1aVille Syrjälä
82646d3524a1b9155dd9cd57ea28e00db08c7a95c1aVille Syrjälä	data_start_p += offset;
82746d3524a1b9155dd9cd57ea28e00db08c7a95c1aVille Syrjälä
82846d3524a1b9155dd9cd57ea28e00db08c7a95c1aVille Syrjälä	if (offset)
82946d3524a1b9155dd9cd57ea28e00db08c7a95c1aVille Syrjälä		DBG("offset %d, %d = %d\n",
83046d3524a1b9155dd9cd57ea28e00db08c7a95c1aVille Syrjälä		    var->xoffset, var->yoffset, offset);
83146d3524a1b9155dd9cd57ea28e00db08c7a95c1aVille Syrjälä
832212b0d50e2eb7fc60f7bea1e90e5867b5fc0647dTomi Valkeinen	DBG("paddr %x\n", data_start_p);
83346d3524a1b9155dd9cd57ea28e00db08c7a95c1aVille Syrjälä
83446d3524a1b9155dd9cd57ea28e00db08c7a95c1aVille Syrjälä	*paddr = data_start_p;
83546d3524a1b9155dd9cd57ea28e00db08c7a95c1aVille Syrjälä}
836b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
837b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen/* setup overlay according to the fb */
838078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjäläint omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
839b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		u16 posx, u16 posy, u16 outw, u16 outh)
840b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
841b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int r = 0;
842b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct omapfb_info *ofbi = FB2OFB(fbi);
843b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct fb_var_screeninfo *var = &fbi->var;
844b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct fb_fix_screeninfo *fix = &fbi->fix;
845b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	enum omap_color_mode mode = 0;
84646d3524a1b9155dd9cd57ea28e00db08c7a95c1aVille Syrjälä	u32 data_start_p = 0;
847b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct omap_overlay_info info;
848b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int xres, yres;
849b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int screen_width;
850b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int mirror;
851b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int rotation = var->rotate;
852b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int i;
853b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
8541ceafc00910439c8e5450fae189b69427725992cVille Syrjälä	WARN_ON(!atomic_read(&ofbi->region->lock_count));
8551ceafc00910439c8e5450fae189b69427725992cVille Syrjälä
856b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	for (i = 0; i < ofbi->num_overlays; i++) {
857b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (ovl != ofbi->overlays[i])
858b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			continue;
859b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
860b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		rotation = (rotation + ofbi->rotation[i]) % 4;
861b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		break;
862b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
863b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
864b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	DBG("setup_overlay %d, posx %d, posy %d, outw %d, outh %d\n", ofbi->id,
865b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			posx, posy, outw, outh);
866b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
867b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (rotation == FB_ROTATE_CW || rotation == FB_ROTATE_CCW) {
868b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		xres = var->yres;
869b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		yres = var->xres;
870b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	} else {
871b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		xres = var->xres;
872b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		yres = var->yres;
873b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
874b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
875078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä	if (ofbi->region->size)
876212b0d50e2eb7fc60f7bea1e90e5867b5fc0647dTomi Valkeinen		omapfb_calc_addr(ofbi, var, fix, rotation, &data_start_p);
877b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
878b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	r = fb_mode_to_dss_mode(var, &mode);
879b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (r) {
880b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		DBG("fb_mode_to_dss_mode failed");
881b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		goto err;
882b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
883b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
884b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	switch (var->nonstd) {
885b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	case OMAPFB_COLOR_YUV422:
886b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	case OMAPFB_COLOR_YUY422:
887b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
888b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			screen_width = fix->line_length
889b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				/ (var->bits_per_pixel >> 2);
890b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			break;
891b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		}
892b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	default:
893b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		screen_width = fix->line_length / (var->bits_per_pixel >> 3);
894b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		break;
895b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
896b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
897b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	ovl->get_overlay_info(ovl, &info);
898b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
899b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
900b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		mirror = 0;
901b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	else
902b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		mirror = ofbi->mirror;
903b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
904b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	info.paddr = data_start_p;
905b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	info.screen_width = screen_width;
906b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	info.width = xres;
907b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	info.height = yres;
908b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	info.color_mode = mode;
909b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	info.rotation_type = ofbi->rotation_type;
910b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	info.rotation = rotation;
911b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	info.mirror = mirror;
912b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
913b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	info.pos_x = posx;
914b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	info.pos_y = posy;
915b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	info.out_width = outw;
916b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	info.out_height = outh;
917b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
918b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	r = ovl->set_overlay_info(ovl, &info);
919b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (r) {
920b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		DBG("ovl->setup_overlay_info failed\n");
921b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		goto err;
922b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
923b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
924b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return 0;
925b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
926b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenerr:
927b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	DBG("setup_overlay failed\n");
928b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return r;
929b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
930b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
931b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen/* apply var to the overlay */
932b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenint omapfb_apply_changes(struct fb_info *fbi, int init)
933b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
934b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int r = 0;
935b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct omapfb_info *ofbi = FB2OFB(fbi);
936b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct fb_var_screeninfo *var = &fbi->var;
937b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct omap_overlay *ovl;
938b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	u16 posx, posy;
939b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	u16 outw, outh;
940b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int i;
941b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
942b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen#ifdef DEBUG
943b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (omapfb_test_pattern)
944b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		fill_fb(fbi);
945b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen#endif
946b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
9471ceafc00910439c8e5450fae189b69427725992cVille Syrjälä	WARN_ON(!atomic_read(&ofbi->region->lock_count));
9481ceafc00910439c8e5450fae189b69427725992cVille Syrjälä
949b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	for (i = 0; i < ofbi->num_overlays; i++) {
950b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		ovl = ofbi->overlays[i];
951b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
952b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		DBG("apply_changes, fb %d, ovl %d\n", ofbi->id, ovl->id);
953b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
954078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä		if (ofbi->region->size == 0) {
955b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			/* the fb is not available. disable the overlay */
956b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			omapfb_overlay_enable(ovl, 0);
957b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			if (!init && ovl->manager)
958b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				ovl->manager->apply(ovl->manager);
959b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			continue;
960b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		}
961b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
962b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (init || (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
963b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			int rotation = (var->rotate + ofbi->rotation[i]) % 4;
964b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			if (rotation == FB_ROTATE_CW ||
965b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen					rotation == FB_ROTATE_CCW) {
966b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				outw = var->yres;
967b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				outh = var->xres;
968b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			} else {
969b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				outw = var->xres;
970b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				outh = var->yres;
971b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			}
972b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		} else {
973c1a9febfafa2a9a9ac09b2de4c80aa96b41a03d1Tomi Valkeinen			struct omap_overlay_info info;
974c1a9febfafa2a9a9ac09b2de4c80aa96b41a03d1Tomi Valkeinen			ovl->get_overlay_info(ovl, &info);
975c1a9febfafa2a9a9ac09b2de4c80aa96b41a03d1Tomi Valkeinen			outw = info.out_width;
976c1a9febfafa2a9a9ac09b2de4c80aa96b41a03d1Tomi Valkeinen			outh = info.out_height;
977b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		}
978b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
979b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (init) {
980b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			posx = 0;
981b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			posy = 0;
982b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		} else {
983c1a9febfafa2a9a9ac09b2de4c80aa96b41a03d1Tomi Valkeinen			struct omap_overlay_info info;
984c1a9febfafa2a9a9ac09b2de4c80aa96b41a03d1Tomi Valkeinen			ovl->get_overlay_info(ovl, &info);
985c1a9febfafa2a9a9ac09b2de4c80aa96b41a03d1Tomi Valkeinen			posx = info.pos_x;
986c1a9febfafa2a9a9ac09b2de4c80aa96b41a03d1Tomi Valkeinen			posy = info.pos_y;
987b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		}
988b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
989b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		r = omapfb_setup_overlay(fbi, ovl, posx, posy, outw, outh);
990b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (r)
991b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			goto err;
992b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
993b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (!init && ovl->manager)
994b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			ovl->manager->apply(ovl->manager);
995b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
996b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return 0;
997b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenerr:
998b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	DBG("apply_changes failed\n");
999b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return r;
1000b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
1001b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1002b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen/* checks var and eventually tweaks it to something supported,
1003b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen * DO NOT MODIFY PAR */
1004b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi)
1005b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
1006430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä	struct omapfb_info *ofbi = FB2OFB(fbi);
1007b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int r;
1008b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1009b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	DBG("check_var(%d)\n", FB2OFB(fbi)->id);
1010b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1011430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä	omapfb_get_mem_region(ofbi->region);
1012430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä
1013b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	r = check_fb_var(fbi, var);
1014b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1015430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä	omapfb_put_mem_region(ofbi->region);
1016430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä
1017b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return r;
1018b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
1019b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1020b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen/* set the video mode according to info->var */
1021b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic int omapfb_set_par(struct fb_info *fbi)
1022b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
1023430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä	struct omapfb_info *ofbi = FB2OFB(fbi);
1024b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int r;
1025b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1026b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	DBG("set_par(%d)\n", FB2OFB(fbi)->id);
1027b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1028430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä	omapfb_get_mem_region(ofbi->region);
1029430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä
1030b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	set_fb_fix(fbi);
1031b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1032b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	r = setup_vrfb_rotation(fbi);
1033b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (r)
1034430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä		goto out;
1035b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1036b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	r = omapfb_apply_changes(fbi, 0);
1037b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1038430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä out:
1039430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä	omapfb_put_mem_region(ofbi->region);
1040430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä
1041b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return r;
1042b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
1043b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1044b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic int omapfb_pan_display(struct fb_var_screeninfo *var,
1045b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		struct fb_info *fbi)
1046b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
1047430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä	struct omapfb_info *ofbi = FB2OFB(fbi);
1048b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct fb_var_screeninfo new_var;
1049b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int r;
1050b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1051b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	DBG("pan_display(%d)\n", FB2OFB(fbi)->id);
1052b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1053b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (var->xoffset == fbi->var.xoffset &&
1054b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	    var->yoffset == fbi->var.yoffset)
1055b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		return 0;
1056b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1057b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	new_var = fbi->var;
1058b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	new_var.xoffset = var->xoffset;
1059b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	new_var.yoffset = var->yoffset;
1060b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1061b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	fbi->var = new_var;
1062b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1063430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä	omapfb_get_mem_region(ofbi->region);
1064430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä
1065b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	r = omapfb_apply_changes(fbi, 0);
1066b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1067430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä	omapfb_put_mem_region(ofbi->region);
1068430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä
1069b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return r;
1070b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
1071b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1072b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic void mmap_user_open(struct vm_area_struct *vma)
1073b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
1074078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä	struct omapfb2_mem_region *rg = vma->vm_private_data;
1075b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1076430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä	omapfb_get_mem_region(rg);
1077078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä	atomic_inc(&rg->map_count);
1078430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä	omapfb_put_mem_region(rg);
1079b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
1080b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1081b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic void mmap_user_close(struct vm_area_struct *vma)
1082b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
1083078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä	struct omapfb2_mem_region *rg = vma->vm_private_data;
1084b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1085430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä	omapfb_get_mem_region(rg);
1086078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä	atomic_dec(&rg->map_count);
1087430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä	omapfb_put_mem_region(rg);
1088b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
1089b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1090b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic struct vm_operations_struct mmap_user_ops = {
1091b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	.open = mmap_user_open,
1092b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	.close = mmap_user_close,
1093b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen};
1094b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1095b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
1096b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
1097b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct omapfb_info *ofbi = FB2OFB(fbi);
1098b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct fb_fix_screeninfo *fix = &fbi->fix;
1099078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä	struct omapfb2_mem_region *rg;
1100b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	unsigned long off;
1101b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	unsigned long start;
1102b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	u32 len;
1103430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä	int r = -EINVAL;
1104b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1105b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (vma->vm_end - vma->vm_start == 0)
1106b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		return 0;
1107b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
1108b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		return -EINVAL;
1109b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	off = vma->vm_pgoff << PAGE_SHIFT;
1110b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1111430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä	rg = omapfb_get_mem_region(ofbi->region);
1112078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä
1113b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	start = omapfb_get_region_paddr(ofbi);
1114b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	len = fix->smem_len;
1115b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (off >= len)
1116430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä		goto error;
1117b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if ((vma->vm_end - vma->vm_start + off) > len)
1118430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä		goto error;
1119b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1120b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	off += start;
1121b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1122b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	DBG("user mmap region start %lx, len %d, off %lx\n", start, len, off);
1123b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1124b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	vma->vm_pgoff = off >> PAGE_SHIFT;
1125b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	vma->vm_flags |= VM_IO | VM_RESERVED;
1126b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
1127b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	vma->vm_ops = &mmap_user_ops;
1128078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä	vma->vm_private_data = rg;
1129b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
1130430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä			       vma->vm_end - vma->vm_start,
1131430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä			       vma->vm_page_prot)) {
1132430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä		r = -EAGAIN;
1133430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä		goto error;
1134430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä	}
1135430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä
1136b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	/* vm_ops.open won't be called for mmap itself. */
1137078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä	atomic_inc(&rg->map_count);
1138430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä
1139430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä	omapfb_put_mem_region(rg);
1140430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä
1141b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return 0;
1142430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä
1143430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä error:
1144430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä	omapfb_put_mem_region(ofbi->region);
1145430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä
1146430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä	return r;
1147b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
1148b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1149b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen/* Store a single color palette entry into a pseudo palette or the hardware
1150b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen * palette if one is available. For now we support only 16bpp and thus store
1151b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen * the entry only to the pseudo palette.
1152b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen */
1153b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic int _setcolreg(struct fb_info *fbi, u_int regno, u_int red, u_int green,
1154b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		u_int blue, u_int transp, int update_hw_pal)
1155b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
1156b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	/*struct omapfb_info *ofbi = FB2OFB(fbi);*/
1157b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	/*struct omapfb2_device *fbdev = ofbi->fbdev;*/
1158b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct fb_var_screeninfo *var = &fbi->var;
1159b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int r = 0;
1160b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1161b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	enum omapfb_color_format mode = OMAPFB_COLOR_RGB24U; /* XXX */
1162b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1163b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	/*switch (plane->color_mode) {*/
1164b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	switch (mode) {
1165b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	case OMAPFB_COLOR_YUV422:
1166b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	case OMAPFB_COLOR_YUV420:
1167b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	case OMAPFB_COLOR_YUY422:
1168b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		r = -EINVAL;
1169b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		break;
1170b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	case OMAPFB_COLOR_CLUT_8BPP:
1171b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	case OMAPFB_COLOR_CLUT_4BPP:
1172b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	case OMAPFB_COLOR_CLUT_2BPP:
1173b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	case OMAPFB_COLOR_CLUT_1BPP:
1174b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		/*
1175b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		   if (fbdev->ctrl->setcolreg)
1176b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		   r = fbdev->ctrl->setcolreg(regno, red, green, blue,
1177b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		   transp, update_hw_pal);
1178b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		   */
1179b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		/* Fallthrough */
1180b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		r = -EINVAL;
1181b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		break;
1182b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	case OMAPFB_COLOR_RGB565:
1183b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	case OMAPFB_COLOR_RGB444:
1184b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	case OMAPFB_COLOR_RGB24P:
1185b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	case OMAPFB_COLOR_RGB24U:
1186b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (r != 0)
1187b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			break;
1188b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1189b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (regno < 16) {
1190b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			u16 pal;
1191b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			pal = ((red >> (16 - var->red.length)) <<
1192b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen					var->red.offset) |
1193b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				((green >> (16 - var->green.length)) <<
1194b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				 var->green.offset) |
1195b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				(blue >> (16 - var->blue.length));
1196b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			((u32 *)(fbi->pseudo_palette))[regno] = pal;
1197b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		}
1198b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		break;
1199b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	default:
1200b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		BUG();
1201b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
1202b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return r;
1203b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
1204b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1205b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic int omapfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
1206b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		u_int transp, struct fb_info *info)
1207b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
1208b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	DBG("setcolreg\n");
1209b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1210b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return _setcolreg(info, regno, red, green, blue, transp, 1);
1211b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
1212b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1213b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic int omapfb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
1214b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
1215b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int count, index, r;
1216b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	u16 *red, *green, *blue, *transp;
1217b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	u16 trans = 0xffff;
1218b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1219b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	DBG("setcmap\n");
1220b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1221b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	red     = cmap->red;
1222b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	green   = cmap->green;
1223b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	blue    = cmap->blue;
1224b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	transp  = cmap->transp;
1225b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	index   = cmap->start;
1226b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1227b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	for (count = 0; count < cmap->len; count++) {
1228b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (transp)
1229b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			trans = *transp++;
1230b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		r = _setcolreg(info, index++, *red++, *green++, *blue++, trans,
1231b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				count == cmap->len - 1);
1232b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (r != 0)
1233b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			return r;
1234b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
1235b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1236b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return 0;
1237b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
1238b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1239b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic int omapfb_blank(int blank, struct fb_info *fbi)
1240b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
1241b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct omapfb_info *ofbi = FB2OFB(fbi);
1242b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct omapfb2_device *fbdev = ofbi->fbdev;
1243b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct omap_dss_device *display = fb2display(fbi);
124427cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen	struct omapfb_display_data *d;
1245b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int r = 0;
1246b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
12479325588757aa7d08bf2ca9c63b669d0d7aa2fc40Jani Nikula	if (!display)
12489325588757aa7d08bf2ca9c63b669d0d7aa2fc40Jani Nikula		return -EINVAL;
12499325588757aa7d08bf2ca9c63b669d0d7aa2fc40Jani Nikula
1250b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	omapfb_lock(fbdev);
1251b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
125227cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen	d = get_display_data(fbdev, display);
125327cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen
1254b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	switch (blank) {
1255b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	case FB_BLANK_UNBLANK:
1256b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (display->state != OMAP_DSS_DISPLAY_SUSPENDED)
1257b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			goto exit;
1258b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
125937ac60e414052f1d9301368437db8f0cb9e323feTomi Valkeinen		if (display->driver->resume)
126037ac60e414052f1d9301368437db8f0cb9e323feTomi Valkeinen			r = display->driver->resume(display);
1261b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
126227cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen		if ((display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) &&
126327cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen				d->update_mode == OMAPFB_AUTO_UPDATE &&
126427cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen				!d->auto_update_work_enabled)
126527cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen			omapfb_start_auto_update(fbdev, display);
126627cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen
1267b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		break;
1268b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1269b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	case FB_BLANK_NORMAL:
1270b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		/* FB_BLANK_NORMAL could be implemented.
1271b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		 * Needs DSS additions. */
1272b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	case FB_BLANK_VSYNC_SUSPEND:
1273b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	case FB_BLANK_HSYNC_SUSPEND:
1274b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	case FB_BLANK_POWERDOWN:
1275b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
1276b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			goto exit;
1277b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
127827cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen		if (d->auto_update_work_enabled)
127927cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen			omapfb_stop_auto_update(fbdev, display);
128027cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen
128137ac60e414052f1d9301368437db8f0cb9e323feTomi Valkeinen		if (display->driver->suspend)
128237ac60e414052f1d9301368437db8f0cb9e323feTomi Valkeinen			r = display->driver->suspend(display);
1283b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1284b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		break;
1285b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1286b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	default:
1287b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		r = -EINVAL;
1288b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
1289b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1290b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenexit:
1291b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	omapfb_unlock(fbdev);
1292b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1293b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return r;
1294b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
1295b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1296b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen#if 0
1297b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen/* XXX fb_read and fb_write are needed for VRFB */
1298b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenssize_t omapfb_write(struct fb_info *info, const char __user *buf,
1299b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		size_t count, loff_t *ppos)
1300b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
1301b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	DBG("omapfb_write %d, %lu\n", count, (unsigned long)*ppos);
1302b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	/* XXX needed for VRFB */
1303b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return count;
1304b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
1305b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen#endif
1306b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1307b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic struct fb_ops omapfb_ops = {
1308b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	.owner          = THIS_MODULE,
1309b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	.fb_open        = omapfb_open,
1310b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	.fb_release     = omapfb_release,
1311b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	.fb_fillrect    = cfb_fillrect,
1312b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	.fb_copyarea    = cfb_copyarea,
1313b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	.fb_imageblit   = cfb_imageblit,
1314b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	.fb_blank       = omapfb_blank,
1315b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	.fb_ioctl       = omapfb_ioctl,
1316b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	.fb_check_var   = omapfb_check_var,
1317b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	.fb_set_par     = omapfb_set_par,
1318b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	.fb_pan_display = omapfb_pan_display,
1319b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	.fb_mmap	= omapfb_mmap,
1320b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	.fb_setcolreg	= omapfb_setcolreg,
1321b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	.fb_setcmap	= omapfb_setcmap,
1322b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	/*.fb_write	= omapfb_write,*/
1323b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen};
1324b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1325b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic void omapfb_free_fbmem(struct fb_info *fbi)
1326b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
1327b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct omapfb_info *ofbi = FB2OFB(fbi);
1328b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct omapfb2_device *fbdev = ofbi->fbdev;
1329b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct omapfb2_mem_region *rg;
1330b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1331078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä	rg = ofbi->region;
1332078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä
1333078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä	WARN_ON(atomic_read(&rg->map_count));
1334b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1335b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (rg->paddr)
1336b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (omap_vram_free(rg->paddr, rg->size))
1337b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			dev_err(fbdev->dev, "VRAM FREE failed\n");
1338b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1339b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (rg->vaddr)
1340b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		iounmap(rg->vaddr);
1341b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1342b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
1343b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		/* unmap the 0 angle rotation */
1344b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (rg->vrfb.vaddr[0]) {
1345b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			iounmap(rg->vrfb.vaddr[0]);
1346b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			omap_vrfb_release_ctx(&rg->vrfb);
1347f3a82d11d478a9eb5ff0cfa83796f0ba8149d841Tomi Valkeinen			rg->vrfb.vaddr[0] = NULL;
1348b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		}
1349b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
1350b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1351b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	rg->vaddr = NULL;
1352b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	rg->paddr = 0;
1353b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	rg->alloc = 0;
1354b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	rg->size = 0;
1355b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
1356b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1357b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic void clear_fb_info(struct fb_info *fbi)
1358b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
1359b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	memset(&fbi->var, 0, sizeof(fbi->var));
1360b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	memset(&fbi->fix, 0, sizeof(fbi->fix));
1361b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	strlcpy(fbi->fix.id, MODULE_NAME, sizeof(fbi->fix.id));
1362b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
1363b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1364b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic int omapfb_free_all_fbmem(struct omapfb2_device *fbdev)
1365b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
1366b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int i;
1367b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1368b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	DBG("free all fbmem\n");
1369b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1370b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	for (i = 0; i < fbdev->num_fbs; i++) {
1371b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		struct fb_info *fbi = fbdev->fbs[i];
1372b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		omapfb_free_fbmem(fbi);
1373b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		clear_fb_info(fbi);
1374b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
1375b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1376b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return 0;
1377b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
1378b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1379b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
1380b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		unsigned long paddr)
1381b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
1382b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct omapfb_info *ofbi = FB2OFB(fbi);
1383b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct omapfb2_device *fbdev = ofbi->fbdev;
1384b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct omapfb2_mem_region *rg;
1385b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	void __iomem *vaddr;
1386b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int r;
1387b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1388078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä	rg = ofbi->region;
1389078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä
1390078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä	rg->paddr = 0;
1391078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä	rg->vaddr = NULL;
1392078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä	memset(&rg->vrfb, 0, sizeof rg->vrfb);
1393078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä	rg->size = 0;
1394078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä	rg->type = 0;
1395078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä	rg->alloc = false;
1396078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä	rg->map = false;
1397b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1398b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	size = PAGE_ALIGN(size);
1399b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1400b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (!paddr) {
1401b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		DBG("allocating %lu bytes for fb %d\n", size, ofbi->id);
14022a803c887b654bad7d6699f1270eaac31361afc9Tomi Valkeinen		r = omap_vram_alloc(size, &paddr);
1403b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	} else {
1404b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		DBG("reserving %lu bytes at %lx for fb %d\n", size, paddr,
1405b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				ofbi->id);
1406b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		r = omap_vram_reserve(paddr, size);
1407b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
1408b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1409b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (r) {
1410b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		dev_err(fbdev->dev, "failed to allocate framebuffer\n");
1411b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		return -ENOMEM;
1412b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
1413b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1414b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (ofbi->rotation_type != OMAP_DSS_ROT_VRFB) {
1415b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		vaddr = ioremap_wc(paddr, size);
1416b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1417b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (!vaddr) {
1418b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			dev_err(fbdev->dev, "failed to ioremap framebuffer\n");
1419b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			omap_vram_free(paddr, size);
1420b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			return -ENOMEM;
1421b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		}
1422b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1423b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		DBG("allocated VRAM paddr %lx, vaddr %p\n", paddr, vaddr);
1424b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	} else {
1425b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		r = omap_vrfb_request_ctx(&rg->vrfb);
1426b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (r) {
1427b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			dev_err(fbdev->dev, "vrfb create ctx failed\n");
1428b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			return r;
1429b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		}
1430b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1431b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		vaddr = NULL;
1432b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
1433b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1434b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	rg->paddr = paddr;
1435b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	rg->vaddr = vaddr;
1436b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	rg->size = size;
1437b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	rg->alloc = 1;
1438b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1439b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return 0;
1440b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
1441b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1442b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen/* allocate fbmem using display resolution as reference */
1443b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size,
1444b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		unsigned long paddr)
1445b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
1446b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct omapfb_info *ofbi = FB2OFB(fbi);
1447a269950405ab17ce3a604ddcd939709a4a7a747cTomi Valkeinen	struct omapfb2_device *fbdev = ofbi->fbdev;
1448b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct omap_dss_device *display;
1449b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int bytespp;
1450b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1451b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	display =  fb2display(fbi);
1452b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1453b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (!display)
1454b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		return 0;
1455b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1456a269950405ab17ce3a604ddcd939709a4a7a747cTomi Valkeinen	switch (omapfb_get_recommended_bpp(fbdev, display)) {
1457b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	case 16:
1458b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		bytespp = 2;
1459b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		break;
1460b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	case 24:
1461b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		bytespp = 4;
1462b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		break;
1463b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	default:
1464b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		bytespp = 4;
1465b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		break;
1466b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
1467b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1468b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (!size) {
1469b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		u16 w, h;
1470b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
147196adceceedefff9b849d25ff582bc6f516903994Tomi Valkeinen		display->driver->get_resolution(display, &w, &h);
1472b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1473b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
1474b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			size = max(omap_vrfb_min_phys_size(w, h, bytespp),
1475b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen					omap_vrfb_min_phys_size(h, w, bytespp));
1476b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1477b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			DBG("adjusting fb mem size for VRFB, %u -> %lu\n",
1478b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen					w * h * bytespp, size);
1479b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		} else {
1480b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			size = w * h * bytespp;
1481b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		}
1482b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
1483b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1484b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (!size)
1485b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		return 0;
1486b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1487b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return omapfb_alloc_fbmem(fbi, size, paddr);
1488b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
1489b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1490b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic int omapfb_parse_vram_param(const char *param, int max_entries,
1491b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		unsigned long *sizes, unsigned long *paddrs)
1492b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
1493b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int fbnum;
1494b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	unsigned long size;
1495b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	unsigned long paddr = 0;
1496b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	char *p, *start;
1497b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1498b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	start = (char *)param;
1499b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1500b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	while (1) {
1501b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		p = start;
1502b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1503b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		fbnum = simple_strtoul(p, &p, 10);
1504b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1505b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (p == param)
1506b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			return -EINVAL;
1507b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1508b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (*p != ':')
1509b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			return -EINVAL;
1510b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1511b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (fbnum >= max_entries)
1512b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			return -EINVAL;
1513b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1514b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		size = memparse(p + 1, &p);
1515b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1516b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (!size)
1517b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			return -EINVAL;
1518b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1519b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		paddr = 0;
1520b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1521b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (*p == '@') {
1522b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			paddr = simple_strtoul(p + 1, &p, 16);
1523b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1524b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			if (!paddr)
1525b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				return -EINVAL;
1526b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1527b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		}
1528b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1529b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		paddrs[fbnum] = paddr;
1530b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		sizes[fbnum] = size;
1531b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1532b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (*p == 0)
1533b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			break;
1534b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1535b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (*p != ',')
1536b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			return -EINVAL;
1537b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1538b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		++p;
1539b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1540b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		start = p;
1541b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
1542b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1543b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return 0;
1544b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
1545b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1546b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev)
1547b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
1548b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int i, r;
1549b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	unsigned long vram_sizes[10];
1550b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	unsigned long vram_paddrs[10];
1551b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1552b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	memset(&vram_sizes, 0, sizeof(vram_sizes));
1553b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	memset(&vram_paddrs, 0, sizeof(vram_paddrs));
1554b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1555b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (def_vram &&	omapfb_parse_vram_param(def_vram, 10,
1556b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				vram_sizes, vram_paddrs)) {
1557b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		dev_err(fbdev->dev, "failed to parse vram parameter\n");
1558b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1559b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		memset(&vram_sizes, 0, sizeof(vram_sizes));
1560b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		memset(&vram_paddrs, 0, sizeof(vram_paddrs));
1561b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
1562b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1563b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	for (i = 0; i < fbdev->num_fbs; i++) {
1564b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		/* allocate memory automatically only for fb0, or if
1565b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		 * excplicitly defined with vram or plat data option */
1566b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (i == 0 || vram_sizes[i] != 0) {
1567b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			r = omapfb_alloc_fbmem_display(fbdev->fbs[i],
1568b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen					vram_sizes[i], vram_paddrs[i]);
1569b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1570b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			if (r)
1571b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				return r;
1572b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		}
1573b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
1574b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1575b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	for (i = 0; i < fbdev->num_fbs; i++) {
1576b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
1577b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		struct omapfb2_mem_region *rg;
1578078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä		rg = ofbi->region;
1579b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1580b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		DBG("region%d phys %08x virt %p size=%lu\n",
1581b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				i,
1582b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				rg->paddr,
1583b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				rg->vaddr,
1584b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				rg->size);
1585b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
1586b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1587b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return 0;
1588b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
1589b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1590b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenint omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
1591b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
1592b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct omapfb_info *ofbi = FB2OFB(fbi);
1593b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct omapfb2_device *fbdev = ofbi->fbdev;
1594b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct omap_dss_device *display = fb2display(fbi);
1595078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä	struct omapfb2_mem_region *rg = ofbi->region;
1596b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	unsigned long old_size = rg->size;
1597b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	unsigned long old_paddr = rg->paddr;
1598b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int old_type = rg->type;
1599b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int r;
1600b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
16012a803c887b654bad7d6699f1270eaac31361afc9Tomi Valkeinen	if (type != OMAPFB_MEMTYPE_SDRAM)
1602b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		return -EINVAL;
1603b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1604b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	size = PAGE_ALIGN(size);
1605b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1606b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (old_size == size && old_type == type)
1607b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		return 0;
1608b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
160918946f62c6cc8cf051bafca8b7fa72309e8a1067Tomi Valkeinen	if (display && display->driver->sync)
161018946f62c6cc8cf051bafca8b7fa72309e8a1067Tomi Valkeinen			display->driver->sync(display);
1611b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1612b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	omapfb_free_fbmem(fbi);
1613b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1614b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (size == 0) {
1615b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		clear_fb_info(fbi);
1616b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		return 0;
1617b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
1618b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1619b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	r = omapfb_alloc_fbmem(fbi, size, 0);
1620b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1621b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (r) {
1622b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (old_size)
1623b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			omapfb_alloc_fbmem(fbi, old_size, old_paddr);
1624b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1625b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (rg->size == 0)
1626b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			clear_fb_info(fbi);
1627b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1628b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		return r;
1629b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
1630b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1631b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (old_size == size)
1632b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		return 0;
1633b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1634b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (old_size == 0) {
1635b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		DBG("initializing fb %d\n", ofbi->id);
1636b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		r = omapfb_fb_init(fbdev, fbi);
1637b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (r) {
1638b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			DBG("omapfb_fb_init failed\n");
1639b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			goto err;
1640b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		}
1641b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		r = omapfb_apply_changes(fbi, 1);
1642b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (r) {
1643b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			DBG("omapfb_apply_changes failed\n");
1644b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			goto err;
1645b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		}
1646b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	} else {
1647b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		struct fb_var_screeninfo new_var;
1648b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		memcpy(&new_var, &fbi->var, sizeof(new_var));
1649b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		r = check_fb_var(fbi, &new_var);
1650b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (r)
1651b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			goto err;
1652b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		memcpy(&fbi->var, &new_var, sizeof(fbi->var));
1653b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		set_fb_fix(fbi);
1654b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		r = setup_vrfb_rotation(fbi);
1655b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (r)
1656b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			goto err;
1657b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
1658b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1659b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return 0;
1660b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenerr:
1661b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	omapfb_free_fbmem(fbi);
1662b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	clear_fb_info(fbi);
1663b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return r;
1664b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
1665b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
166627cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinenstatic void omapfb_auto_update_work(struct work_struct *work)
166727cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen{
166827cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen	struct omap_dss_device *dssdev;
166927cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen	struct omap_dss_driver *dssdrv;
167027cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen	struct omapfb_display_data *d;
167127cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen	u16 w, h;
167227cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen	unsigned int freq;
167327cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen	struct omapfb2_device *fbdev;
167427cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen
167527cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen	d = container_of(work, struct omapfb_display_data,
167627cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen			auto_update_work.work);
167727cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen
167827cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen	dssdev = d->dssdev;
167927cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen	dssdrv = dssdev->driver;
168027cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen	fbdev = d->fbdev;
168127cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen
168227cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen	if (!dssdrv || !dssdrv->update)
168327cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen		return;
168427cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen
168527cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen	if (dssdrv->sync)
168627cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen		dssdrv->sync(dssdev);
168727cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen
168827cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen	dssdrv->get_resolution(dssdev, &w, &h);
168927cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen	dssdrv->update(dssdev, 0, 0, w, h);
169027cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen
169127cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen	freq = auto_update_freq;
169227cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen	if (freq == 0)
169327cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen		freq = 20;
169427cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen	queue_delayed_work(fbdev->auto_update_wq,
169527cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen			&d->auto_update_work, HZ / freq);
169627cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen}
169727cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen
169827cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinenvoid omapfb_start_auto_update(struct omapfb2_device *fbdev,
169927cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen		struct omap_dss_device *display)
170027cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen{
170127cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen	struct omapfb_display_data *d;
170227cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen
170327cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen	if (fbdev->auto_update_wq == NULL) {
170427cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen		struct workqueue_struct *wq;
170527cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen
170627cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen		wq = create_singlethread_workqueue("omapfb_auto_update");
170727cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen
170827cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen		if (wq == NULL) {
170927cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen			dev_err(fbdev->dev, "Failed to create workqueue for "
171027cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen					"auto-update\n");
171127cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen			return;
171227cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen		}
171327cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen
171427cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen		fbdev->auto_update_wq = wq;
171527cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen	}
171627cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen
171727cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen	d = get_display_data(fbdev, display);
171827cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen
171927cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen	INIT_DELAYED_WORK(&d->auto_update_work, omapfb_auto_update_work);
172027cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen
172127cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen	d->auto_update_work_enabled = true;
172227cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen
172327cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen	omapfb_auto_update_work(&d->auto_update_work.work);
172427cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen}
172527cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen
172627cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinenvoid omapfb_stop_auto_update(struct omapfb2_device *fbdev,
172727cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen		struct omap_dss_device *display)
172827cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen{
172927cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen	struct omapfb_display_data *d;
173027cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen
173127cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen	d = get_display_data(fbdev, display);
173227cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen
173327cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen	cancel_delayed_work_sync(&d->auto_update_work);
173427cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen
173527cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen	d->auto_update_work_enabled = false;
173627cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen}
173727cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen
1738b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen/* initialize fb_info, var, fix to something sane based on the display */
1739b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
1740b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
1741b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct fb_var_screeninfo *var = &fbi->var;
1742b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct omap_dss_device *display = fb2display(fbi);
1743b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct omapfb_info *ofbi = FB2OFB(fbi);
1744b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int r = 0;
1745b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1746b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	fbi->fbops = &omapfb_ops;
1747b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	fbi->flags = FBINFO_FLAG_DEFAULT;
1748b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	fbi->pseudo_palette = fbdev->pseudo_palette;
1749b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1750078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä	if (ofbi->region->size == 0) {
1751b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		clear_fb_info(fbi);
1752b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		return 0;
1753b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
1754b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1755b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	var->nonstd = 0;
1756b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	var->bits_per_pixel = 0;
1757b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1758b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	var->rotate = def_rotate;
1759b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1760b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (display) {
1761b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		u16 w, h;
1762b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		int rotation = (var->rotate + ofbi->rotation[0]) % 4;
1763b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
176496adceceedefff9b849d25ff582bc6f516903994Tomi Valkeinen		display->driver->get_resolution(display, &w, &h);
1765b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1766b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (rotation == FB_ROTATE_CW ||
1767b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				rotation == FB_ROTATE_CCW) {
1768b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			var->xres = h;
1769b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			var->yres = w;
1770b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		} else {
1771b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			var->xres = w;
1772b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			var->yres = h;
1773b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		}
1774b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1775b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		var->xres_virtual = var->xres;
1776b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		var->yres_virtual = var->yres;
1777b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1778b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (!var->bits_per_pixel) {
1779a269950405ab17ce3a604ddcd939709a4a7a747cTomi Valkeinen			switch (omapfb_get_recommended_bpp(fbdev, display)) {
1780b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			case 16:
1781b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				var->bits_per_pixel = 16;
1782b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				break;
1783b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			case 24:
1784b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				var->bits_per_pixel = 32;
1785b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				break;
1786b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			default:
1787b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				dev_err(fbdev->dev, "illegal display "
1788b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen						"bpp\n");
1789b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				return -EINVAL;
1790b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			}
1791b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		}
1792b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	} else {
1793b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		/* if there's no display, let's just guess some basic values */
1794b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		var->xres = 320;
1795b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		var->yres = 240;
1796b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		var->xres_virtual = var->xres;
1797b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		var->yres_virtual = var->yres;
1798b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (!var->bits_per_pixel)
1799b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			var->bits_per_pixel = 16;
1800b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
1801b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1802b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	r = check_fb_var(fbi, var);
1803b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (r)
1804b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		goto err;
1805b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1806b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	set_fb_fix(fbi);
1807b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	r = setup_vrfb_rotation(fbi);
1808b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (r)
1809b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		goto err;
1810b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1811b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	r = fb_alloc_cmap(&fbi->cmap, 256, 0);
1812b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (r)
1813b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		dev_err(fbdev->dev, "unable to allocate color map memory\n");
1814b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1815b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenerr:
1816b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return r;
1817b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
1818b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1819b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic void fbinfo_cleanup(struct omapfb2_device *fbdev, struct fb_info *fbi)
1820b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
1821b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	fb_dealloc_cmap(&fbi->cmap);
1822b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
1823b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1824b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1825b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic void omapfb_free_resources(struct omapfb2_device *fbdev)
1826b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
1827b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int i;
1828b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1829b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	DBG("free_resources\n");
1830b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1831b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (fbdev == NULL)
1832b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		return;
1833b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1834b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	for (i = 0; i < fbdev->num_fbs; i++)
1835b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		unregister_framebuffer(fbdev->fbs[i]);
1836b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1837b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	/* free the reserved fbmem */
1838b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	omapfb_free_all_fbmem(fbdev);
1839b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1840b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	for (i = 0; i < fbdev->num_fbs; i++) {
1841b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		fbinfo_cleanup(fbdev, fbdev->fbs[i]);
1842b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		framebuffer_release(fbdev->fbs[i]);
1843b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
1844b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1845b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	for (i = 0; i < fbdev->num_displays; i++) {
1846065a40bd461d3709a2c36adf0ec383581cc692a7Tomi Valkeinen		struct omap_dss_device *dssdev = fbdev->displays[i].dssdev;
184727cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen
184827cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen		if (fbdev->displays[i].auto_update_work_enabled)
184927cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen			omapfb_stop_auto_update(fbdev, dssdev);
185027cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen
1851065a40bd461d3709a2c36adf0ec383581cc692a7Tomi Valkeinen		if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)
1852065a40bd461d3709a2c36adf0ec383581cc692a7Tomi Valkeinen			dssdev->driver->disable(dssdev);
1853b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1854065a40bd461d3709a2c36adf0ec383581cc692a7Tomi Valkeinen		omap_dss_put_device(dssdev);
1855b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
1856b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
185727cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen	if (fbdev->auto_update_wq != NULL) {
185827cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen		flush_workqueue(fbdev->auto_update_wq);
185927cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen		destroy_workqueue(fbdev->auto_update_wq);
186027cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen		fbdev->auto_update_wq = NULL;
186127cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen	}
186227cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen
1863b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	dev_set_drvdata(fbdev->dev, NULL);
1864b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	kfree(fbdev);
1865b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
1866b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1867b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
1868b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
1869b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int r, i;
1870b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1871b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	fbdev->num_fbs = 0;
1872b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1873b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	DBG("create %d framebuffers\n",	CONFIG_FB_OMAP2_NUM_FBS);
1874b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1875b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	/* allocate fb_infos */
1876b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	for (i = 0; i < CONFIG_FB_OMAP2_NUM_FBS; i++) {
1877b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		struct fb_info *fbi;
1878b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		struct omapfb_info *ofbi;
1879b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1880b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		fbi = framebuffer_alloc(sizeof(struct omapfb_info),
1881b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				fbdev->dev);
1882b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1883b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (fbi == NULL) {
1884b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			dev_err(fbdev->dev,
1885b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				"unable to allocate memory for plane info\n");
1886b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			return -ENOMEM;
1887b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		}
1888b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1889b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		clear_fb_info(fbi);
1890b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1891b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		fbdev->fbs[i] = fbi;
1892b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1893b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		ofbi = FB2OFB(fbi);
1894b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		ofbi->fbdev = fbdev;
1895b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		ofbi->id = i;
1896b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1897078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä		ofbi->region = &fbdev->regions[i];
1898078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä		ofbi->region->id = i;
18992f642a17503838e256b8b7e9f1153512e2efc38bVille Syrjälä		init_rwsem(&ofbi->region->lock);
1900078ff546a806b2c2ab74c25c8edd4c6d4680656aVille Syrjälä
1901b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		/* assign these early, so that fb alloc can use them */
1902b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB :
1903b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			OMAP_DSS_ROT_DMA;
1904b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		ofbi->mirror = def_mirror;
1905b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1906b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		fbdev->num_fbs++;
1907b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
1908b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1909b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	DBG("fb_infos allocated\n");
1910b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1911b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	/* assign overlays for the fbs */
1912b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	for (i = 0; i < min(fbdev->num_fbs, fbdev->num_overlays); i++) {
1913b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
1914b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1915b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		ofbi->overlays[0] = fbdev->overlays[i];
1916b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		ofbi->num_overlays = 1;
1917b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
1918b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1919b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	/* allocate fb memories */
1920b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	r = omapfb_allocate_all_fbs(fbdev);
1921b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (r) {
1922b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		dev_err(fbdev->dev, "failed to allocate fbmem\n");
1923b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		return r;
1924b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
1925b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1926b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	DBG("fbmems allocated\n");
1927b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1928b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	/* setup fb_infos */
1929b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	for (i = 0; i < fbdev->num_fbs; i++) {
1930430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä		struct fb_info *fbi = fbdev->fbs[i];
1931430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä		struct omapfb_info *ofbi = FB2OFB(fbi);
1932430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä
1933430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä		omapfb_get_mem_region(ofbi->region);
1934430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä		r = omapfb_fb_init(fbdev, fbi);
1935430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä		omapfb_put_mem_region(ofbi->region);
1936430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä
1937b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (r) {
1938b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			dev_err(fbdev->dev, "failed to setup fb_info\n");
1939b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			return r;
1940b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		}
1941b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
1942b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1943b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	DBG("fb_infos initialized\n");
1944b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1945b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	for (i = 0; i < fbdev->num_fbs; i++) {
1946b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		r = register_framebuffer(fbdev->fbs[i]);
1947b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (r != 0) {
1948b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			dev_err(fbdev->dev,
1949b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				"registering framebuffer %d failed\n", i);
1950b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			return r;
1951b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		}
1952b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
1953b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1954b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	DBG("framebuffers registered\n");
1955b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1956b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	for (i = 0; i < fbdev->num_fbs; i++) {
1957430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä		struct fb_info *fbi = fbdev->fbs[i];
1958430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä		struct omapfb_info *ofbi = FB2OFB(fbi);
1959430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä
1960430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä		omapfb_get_mem_region(ofbi->region);
1961430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä		r = omapfb_apply_changes(fbi, 1);
1962430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä		omapfb_put_mem_region(ofbi->region);
1963430571d59a0b51c6541c153ad8b08e72fef26098Ville Syrjälä
1964b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (r) {
1965b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			dev_err(fbdev->dev, "failed to change mode\n");
1966b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			return r;
1967b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		}
1968b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
1969b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1970b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	/* Enable fb0 */
1971b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (fbdev->num_fbs > 0) {
1972b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[0]);
1973b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1974b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (ofbi->num_overlays > 0) {
1975b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			struct omap_overlay *ovl = ofbi->overlays[0];
1976b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1977aaa874a985158383c4b394c687c716ef26288741Tomi Valkeinen			ovl->manager->apply(ovl->manager);
1978aaa874a985158383c4b394c687c716ef26288741Tomi Valkeinen
1979b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			r = omapfb_overlay_enable(ovl, 1);
1980b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1981b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			if (r) {
1982b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				dev_err(fbdev->dev,
1983b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen						"failed to enable overlay\n");
1984b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				return r;
1985b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			}
1986b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		}
1987b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
1988b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1989b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	DBG("create_framebuffers done\n");
1990b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1991b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return 0;
1992b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
1993b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
1994b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic int omapfb_mode_to_timings(const char *mode_str,
1995b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		struct omap_video_timings *timings, u8 *bpp)
1996b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
1997897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	struct fb_info *fbi;
1998897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	struct fb_var_screeninfo *var;
1999897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	struct fb_ops *fbops;
2000b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int r;
2001b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2002b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen#ifdef CONFIG_OMAP2_DSS_VENC
2003b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (strcmp(mode_str, "pal") == 0) {
2004b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		*timings = omap_dss_pal_timings;
2005e8c66dcf5aa8df2d1b1f249519c920d3a45dd613Maurus Cuelenaere		*bpp = 24;
2006b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		return 0;
2007b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	} else if (strcmp(mode_str, "ntsc") == 0) {
2008b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		*timings = omap_dss_ntsc_timings;
2009e8c66dcf5aa8df2d1b1f249519c920d3a45dd613Maurus Cuelenaere		*bpp = 24;
2010b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		return 0;
2011b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
2012b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen#endif
2013b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2014b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	/* this is quite a hack, but I wanted to use the modedb and for
2015b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	 * that we need fb_info and var, so we create dummy ones */
2016b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2017897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	*bpp = 0;
2018897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	fbi = NULL;
2019897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	var = NULL;
2020897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	fbops = NULL;
2021b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2022897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	fbi = kzalloc(sizeof(*fbi), GFP_KERNEL);
2023897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	if (fbi == NULL) {
2024897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen		r = -ENOMEM;
2025897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen		goto err;
2026897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	}
2027897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen
2028897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	var = kzalloc(sizeof(*var), GFP_KERNEL);
2029897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	if (var == NULL) {
2030897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen		r = -ENOMEM;
2031897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen		goto err;
2032897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	}
2033897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen
2034897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	fbops = kzalloc(sizeof(*fbops), GFP_KERNEL);
2035897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	if (fbops == NULL) {
2036897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen		r = -ENOMEM;
2037897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen		goto err;
2038897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	}
2039897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen
2040897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	fbi->fbops = fbops;
2041897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen
2042897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	r = fb_find_mode(var, fbi, mode_str, NULL, 0, NULL, 24);
2043897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	if (r == 0) {
2044897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen		r = -EINVAL;
2045897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen		goto err;
2046b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
2047897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen
2048897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	timings->pixel_clock = PICOS2KHZ(var->pixclock);
2049897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	timings->hbp = var->left_margin;
2050897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	timings->hfp = var->right_margin;
2051897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	timings->vbp = var->upper_margin;
2052897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	timings->vfp = var->lower_margin;
2053897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	timings->hsw = var->hsync_len;
2054897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	timings->vsw = var->vsync_len;
2055897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	timings->x_res = var->xres;
2056897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	timings->y_res = var->yres;
2057897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen
2058897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	switch (var->bits_per_pixel) {
2059897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	case 16:
2060897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen		*bpp = 16;
2061897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen		break;
2062897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	case 24:
2063897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	case 32:
2064897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	default:
2065897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen		*bpp = 24;
2066897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen		break;
2067897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	}
2068897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen
2069897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	r = 0;
2070897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen
2071897044e99e437e908eef566d910692830546c2d9Tomi Valkeinenerr:
2072897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	kfree(fbi);
2073897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	kfree(var);
2074897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	kfree(fbops);
2075897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen
2076897044e99e437e908eef566d910692830546c2d9Tomi Valkeinen	return r;
2077b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
2078b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2079a269950405ab17ce3a604ddcd939709a4a7a747cTomi Valkeinenstatic int omapfb_set_def_mode(struct omapfb2_device *fbdev,
2080a269950405ab17ce3a604ddcd939709a4a7a747cTomi Valkeinen		struct omap_dss_device *display, char *mode_str)
2081b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
2082b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int r;
2083b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	u8 bpp;
2084371e2081447ce2bc6a25c20b513b9ba33cf5769eMayuresh Janorkar	struct omap_video_timings timings, temp_timings;
2085065a40bd461d3709a2c36adf0ec383581cc692a7Tomi Valkeinen	struct omapfb_display_data *d;
2086b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2087b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	r = omapfb_mode_to_timings(mode_str, &timings, &bpp);
2088b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (r)
2089b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		return r;
2090b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2091065a40bd461d3709a2c36adf0ec383581cc692a7Tomi Valkeinen	d = get_display_data(fbdev, display);
2092065a40bd461d3709a2c36adf0ec383581cc692a7Tomi Valkeinen	d->bpp_override = bpp;
2093b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2094371e2081447ce2bc6a25c20b513b9ba33cf5769eMayuresh Janorkar	if (display->driver->check_timings) {
2095371e2081447ce2bc6a25c20b513b9ba33cf5769eMayuresh Janorkar		r = display->driver->check_timings(display, &timings);
2096371e2081447ce2bc6a25c20b513b9ba33cf5769eMayuresh Janorkar		if (r)
2097371e2081447ce2bc6a25c20b513b9ba33cf5769eMayuresh Janorkar			return r;
2098371e2081447ce2bc6a25c20b513b9ba33cf5769eMayuresh Janorkar	} else {
2099371e2081447ce2bc6a25c20b513b9ba33cf5769eMayuresh Janorkar		/* If check_timings is not present compare xres and yres */
2100371e2081447ce2bc6a25c20b513b9ba33cf5769eMayuresh Janorkar		if (display->driver->get_timings) {
2101371e2081447ce2bc6a25c20b513b9ba33cf5769eMayuresh Janorkar			display->driver->get_timings(display, &temp_timings);
2102b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2103371e2081447ce2bc6a25c20b513b9ba33cf5769eMayuresh Janorkar			if (temp_timings.x_res != timings.x_res ||
2104371e2081447ce2bc6a25c20b513b9ba33cf5769eMayuresh Janorkar				temp_timings.y_res != timings.y_res)
2105371e2081447ce2bc6a25c20b513b9ba33cf5769eMayuresh Janorkar				return -EINVAL;
2106371e2081447ce2bc6a25c20b513b9ba33cf5769eMayuresh Janorkar		}
2107371e2081447ce2bc6a25c20b513b9ba33cf5769eMayuresh Janorkar	}
2108b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2109371e2081447ce2bc6a25c20b513b9ba33cf5769eMayuresh Janorkar	if (display->driver->set_timings)
2110371e2081447ce2bc6a25c20b513b9ba33cf5769eMayuresh Janorkar			display->driver->set_timings(display, &timings);
2111b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2112b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return 0;
2113b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
2114b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2115a269950405ab17ce3a604ddcd939709a4a7a747cTomi Valkeinenstatic int omapfb_get_recommended_bpp(struct omapfb2_device *fbdev,
2116a269950405ab17ce3a604ddcd939709a4a7a747cTomi Valkeinen		struct omap_dss_device *dssdev)
2117a269950405ab17ce3a604ddcd939709a4a7a747cTomi Valkeinen{
2118065a40bd461d3709a2c36adf0ec383581cc692a7Tomi Valkeinen	struct omapfb_display_data *d;
2119a269950405ab17ce3a604ddcd939709a4a7a747cTomi Valkeinen
2120a269950405ab17ce3a604ddcd939709a4a7a747cTomi Valkeinen	BUG_ON(dssdev->driver->get_recommended_bpp == NULL);
2121a269950405ab17ce3a604ddcd939709a4a7a747cTomi Valkeinen
2122065a40bd461d3709a2c36adf0ec383581cc692a7Tomi Valkeinen	d = get_display_data(fbdev, dssdev);
2123065a40bd461d3709a2c36adf0ec383581cc692a7Tomi Valkeinen
2124065a40bd461d3709a2c36adf0ec383581cc692a7Tomi Valkeinen	if (d->bpp_override != 0)
2125065a40bd461d3709a2c36adf0ec383581cc692a7Tomi Valkeinen		return d->bpp_override;
2126a269950405ab17ce3a604ddcd939709a4a7a747cTomi Valkeinen
2127a269950405ab17ce3a604ddcd939709a4a7a747cTomi Valkeinen	return dssdev->driver->get_recommended_bpp(dssdev);
2128a269950405ab17ce3a604ddcd939709a4a7a747cTomi Valkeinen}
2129a269950405ab17ce3a604ddcd939709a4a7a747cTomi Valkeinen
2130b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
2131b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
2132b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	char *str, *options, *this_opt;
2133b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int r = 0;
2134b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
213536e8c27f3bee5e58f96b0a79d65922fa9e53b030Samreen	str = kstrdup(def_mode, GFP_KERNEL);
213636e8c27f3bee5e58f96b0a79d65922fa9e53b030Samreen	if (!str)
213736e8c27f3bee5e58f96b0a79d65922fa9e53b030Samreen		return -ENOMEM;
2138b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	options = str;
2139b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2140b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	while (!r && (this_opt = strsep(&options, ",")) != NULL) {
2141b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		char *p, *display_str, *mode_str;
2142b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		struct omap_dss_device *display;
2143b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		int i;
2144b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2145b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		p = strchr(this_opt, ':');
2146b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (!p) {
2147b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			r = -EINVAL;
2148b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			break;
2149b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		}
2150b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2151b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		*p = 0;
2152b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		display_str = this_opt;
2153b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		mode_str = p + 1;
2154b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2155b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		display = NULL;
2156b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		for (i = 0; i < fbdev->num_displays; ++i) {
2157065a40bd461d3709a2c36adf0ec383581cc692a7Tomi Valkeinen			if (strcmp(fbdev->displays[i].dssdev->name,
2158b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen						display_str) == 0) {
2159065a40bd461d3709a2c36adf0ec383581cc692a7Tomi Valkeinen				display = fbdev->displays[i].dssdev;
2160b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen				break;
2161b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			}
2162b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		}
2163b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2164b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (!display) {
2165b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			r = -EINVAL;
2166b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			break;
2167b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		}
2168b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2169a269950405ab17ce3a604ddcd939709a4a7a747cTomi Valkeinen		r = omapfb_set_def_mode(fbdev, display, mode_str);
2170b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (r)
2171b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			break;
2172b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
2173b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2174b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	kfree(str);
2175b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2176b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return r;
2177b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
2178b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2179dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinenstatic void fb_videomode_to_omap_timings(struct fb_videomode *m,
2180dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen		struct omap_video_timings *t)
2181dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen{
2182dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	t->x_res = m->xres;
2183dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	t->y_res = m->yres;
2184dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	t->pixel_clock = PICOS2KHZ(m->pixclock);
2185dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	t->hsw = m->hsync_len;
2186dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	t->hfp = m->right_margin;
2187dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	t->hbp = m->left_margin;
2188dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	t->vsw = m->vsync_len;
2189dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	t->vfp = m->lower_margin;
2190dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	t->vbp = m->upper_margin;
2191dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen}
2192dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen
2193dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinenstatic int omapfb_find_best_mode(struct omap_dss_device *display,
2194dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen		struct omap_video_timings *timings)
2195dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen{
2196dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	struct fb_monspecs *specs;
2197dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	u8 *edid;
2198dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	int r, i, best_xres, best_idx, len;
2199dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen
2200dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	if (!display->driver->read_edid)
2201dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen		return -ENODEV;
2202dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen
2203dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	len = 0x80 * 2;
2204dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	edid = kmalloc(len, GFP_KERNEL);
2205dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen
2206dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	r = display->driver->read_edid(display, edid, len);
2207dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	if (r < 0)
2208dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen		goto err1;
2209dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen
2210dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	specs = kzalloc(sizeof(*specs), GFP_KERNEL);
2211dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen
2212dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	fb_edid_to_monspecs(edid, specs);
2213dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen
2214dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	if (edid[126] > 0)
2215dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen		fb_edid_add_monspecs(edid + 0x80, specs);
2216dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen
2217dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	best_xres = 0;
2218dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	best_idx = -1;
2219dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen
2220dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	for (i = 0; i < specs->modedb_len; ++i) {
2221dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen		struct fb_videomode *m;
2222dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen		struct omap_video_timings t;
2223dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen
2224dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen		m = &specs->modedb[i];
2225dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen
2226dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen		if (m->pixclock == 0)
2227dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen			continue;
2228dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen
2229dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen		/* skip repeated pixel modes */
2230dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen		if (m->xres == 2880 || m->xres == 1440)
2231dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen			continue;
2232dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen
2233dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen		fb_videomode_to_omap_timings(m, &t);
2234dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen
2235dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen		r = display->driver->check_timings(display, &t);
2236dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen		if (r == 0 && best_xres < m->xres) {
2237dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen			best_xres = m->xres;
2238dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen			best_idx = i;
2239dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen		}
2240dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	}
2241dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen
2242dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	if (best_xres == 0) {
2243dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen		r = -ENOENT;
2244dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen		goto err2;
2245dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	}
2246dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen
2247dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	fb_videomode_to_omap_timings(&specs->modedb[best_idx], timings);
2248dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen
2249dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	r = 0;
2250dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen
2251dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinenerr2:
2252dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	fb_destroy_modedb(specs->modedb);
2253dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	kfree(specs);
2254dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinenerr1:
2255dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	kfree(edid);
2256dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen
2257dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	return r;
2258dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen}
2259dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen
226091ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinenstatic int omapfb_init_display(struct omapfb2_device *fbdev,
226191ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen		struct omap_dss_device *dssdev)
226291ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen{
226391ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen	struct omap_dss_driver *dssdrv = dssdev->driver;
226427cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen	struct omapfb_display_data *d;
226591ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen	int r;
226691ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen
226791ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen	r = dssdrv->enable(dssdev);
226891ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen	if (r) {
226991ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen		dev_warn(fbdev->dev, "Failed to enable display '%s'\n",
227091ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen				dssdev->name);
227191ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen		return r;
227291ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen	}
227391ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen
227427cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen	d = get_display_data(fbdev, dssdev);
227527cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen
227627cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen	d->fbdev = fbdev;
227727cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen
227891ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen	if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
227991ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen		u16 w, h;
228027cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen
228127cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen		if (auto_update) {
228227cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen			omapfb_start_auto_update(fbdev, dssdev);
228327cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen			d->update_mode = OMAPFB_AUTO_UPDATE;
228427cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen		} else {
228527cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen			d->update_mode = OMAPFB_MANUAL_UPDATE;
228627cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen		}
228727cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen
228891ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen		if (dssdrv->enable_te) {
228991ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen			r = dssdrv->enable_te(dssdev, 1);
229091ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen			if (r) {
229191ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen				dev_err(fbdev->dev, "Failed to set TE\n");
229291ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen				return r;
229391ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen			}
229491ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen		}
229591ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen
229691ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen		dssdrv->get_resolution(dssdev, &w, &h);
229791ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen		r = dssdrv->update(dssdev, 0, 0, w, h);
229891ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen		if (r) {
229991ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen			dev_err(fbdev->dev,
230091ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen					"Failed to update display\n");
230191ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen			return r;
230291ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen		}
230391ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen	} else {
230427cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen		d->update_mode = OMAPFB_AUTO_UPDATE;
230591ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen	}
230691ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen
230791ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen	return 0;
230891ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen}
230991ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen
2310b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic int omapfb_probe(struct platform_device *pdev)
2311b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
2312b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct omapfb2_device *fbdev = NULL;
2313b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int r = 0;
2314b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	int i;
2315b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct omap_overlay *ovl;
2316b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct omap_dss_device *def_display;
2317b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct omap_dss_device *dssdev;
2318b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2319b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	DBG("omapfb_probe\n");
2320b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2321b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (pdev->num_resources != 0) {
2322b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		dev_err(&pdev->dev, "probed for an unknown device\n");
2323b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		r = -ENODEV;
2324b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		goto err0;
2325b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
2326b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2327b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	fbdev = kzalloc(sizeof(struct omapfb2_device), GFP_KERNEL);
2328b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (fbdev == NULL) {
2329b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		r = -ENOMEM;
2330b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		goto err0;
2331b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
2332b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
233341814cfc01b059df33011d929837558c22f3c0e0Senthilvadivu Guruswamy	/* TODO : Replace cpu check with omap_has_vrfb once HAS_FEATURE
233441814cfc01b059df33011d929837558c22f3c0e0Senthilvadivu Guruswamy	*	 available for OMAP2 and OMAP3
233541814cfc01b059df33011d929837558c22f3c0e0Senthilvadivu Guruswamy	*/
233641814cfc01b059df33011d929837558c22f3c0e0Senthilvadivu Guruswamy	if (def_vrfb && !cpu_is_omap24xx() && !cpu_is_omap34xx()) {
233741814cfc01b059df33011d929837558c22f3c0e0Senthilvadivu Guruswamy		def_vrfb = 0;
233841814cfc01b059df33011d929837558c22f3c0e0Senthilvadivu Guruswamy		dev_warn(&pdev->dev, "VRFB is not supported on this hardware, "
233941814cfc01b059df33011d929837558c22f3c0e0Senthilvadivu Guruswamy				"ignoring the module parameter vrfb=y\n");
234041814cfc01b059df33011d929837558c22f3c0e0Senthilvadivu Guruswamy	}
234141814cfc01b059df33011d929837558c22f3c0e0Senthilvadivu Guruswamy
234241814cfc01b059df33011d929837558c22f3c0e0Senthilvadivu Guruswamy
2343b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	mutex_init(&fbdev->mtx);
2344b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2345b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	fbdev->dev = &pdev->dev;
2346b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	platform_set_drvdata(pdev, fbdev);
2347b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2348b3f91eb8d8d17ad3ca5da4fa9f20d2e46133fd99Tomi Valkeinen	r = 0;
2349b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	fbdev->num_displays = 0;
2350b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	dssdev = NULL;
2351b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	for_each_dss_dev(dssdev) {
235227cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen		struct omapfb_display_data *d;
235327cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen
2354b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		omap_dss_get_device(dssdev);
2355b3f91eb8d8d17ad3ca5da4fa9f20d2e46133fd99Tomi Valkeinen
2356807a7515aea421f2b340140482ed4c8811c523c6Tomi Valkeinen		if (!dssdev->driver) {
2357bab59b4417ea1380578358bedaeb714de6f1f6a7Tomi Valkeinen			dev_warn(&pdev->dev, "no driver for display: %s\n",
2358c5f18d7babcb5a0822377f24d478bdaed6241770Andy Doan				dssdev->name);
2359bab59b4417ea1380578358bedaeb714de6f1f6a7Tomi Valkeinen			omap_dss_put_device(dssdev);
2360bab59b4417ea1380578358bedaeb714de6f1f6a7Tomi Valkeinen			continue;
2361807a7515aea421f2b340140482ed4c8811c523c6Tomi Valkeinen		}
2362b3f91eb8d8d17ad3ca5da4fa9f20d2e46133fd99Tomi Valkeinen
236327cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen		d = &fbdev->displays[fbdev->num_displays++];
236427cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen		d->dssdev = dssdev;
236527cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen		if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE)
236627cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen			d->update_mode = OMAPFB_MANUAL_UPDATE;
236727cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen		else
236827cc213ea7dde929692df46a64c8d8ef74663e48Tomi Valkeinen			d->update_mode = OMAPFB_AUTO_UPDATE;
2369b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
2370b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2371b3f91eb8d8d17ad3ca5da4fa9f20d2e46133fd99Tomi Valkeinen	if (r)
2372b3f91eb8d8d17ad3ca5da4fa9f20d2e46133fd99Tomi Valkeinen		goto cleanup;
2373b3f91eb8d8d17ad3ca5da4fa9f20d2e46133fd99Tomi Valkeinen
2374b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (fbdev->num_displays == 0) {
2375b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		dev_err(&pdev->dev, "no displays\n");
2376b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		r = -EINVAL;
2377b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		goto cleanup;
2378b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
2379b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2380b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	fbdev->num_overlays = omap_dss_get_num_overlays();
2381b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	for (i = 0; i < fbdev->num_overlays; i++)
2382b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		fbdev->overlays[i] = omap_dss_get_overlay(i);
2383b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2384b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	fbdev->num_managers = omap_dss_get_num_overlay_managers();
2385b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	for (i = 0; i < fbdev->num_managers; i++)
2386b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		fbdev->managers[i] = omap_dss_get_overlay_manager(i);
2387b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2388dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	/* gfx overlay should be the default one. find a display
2389dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	 * connected to that, and use it as default display */
2390dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	ovl = omap_dss_get_overlay(0);
2391dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	if (ovl->manager && ovl->manager->device) {
2392dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen		def_display = ovl->manager->device;
2393dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	} else {
2394dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen		dev_warn(&pdev->dev, "cannot find default display\n");
2395dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen		def_display = NULL;
2396dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	}
2397dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen
2398b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (def_mode && strlen(def_mode) > 0) {
2399b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (omapfb_parse_def_modes(fbdev))
2400b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			dev_warn(&pdev->dev, "cannot parse default modes\n");
2401dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen	} else if (def_display && def_display->driver->set_timings &&
2402dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen			def_display->driver->check_timings) {
2403dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen		struct omap_video_timings t;
2404dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen
2405dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen		r = omapfb_find_best_mode(def_display, &t);
2406dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen
2407dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen		if (r == 0)
2408dc891fab115380d9dfddcd252df45a941ff9cb4eTomi Valkeinen			def_display->driver->set_timings(def_display, &t);
2409b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
2410b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2411b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	r = omapfb_create_framebuffers(fbdev);
2412b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (r)
2413b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		goto cleanup;
2414b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2415b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	for (i = 0; i < fbdev->num_managers; i++) {
2416b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		struct omap_overlay_manager *mgr;
2417b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		mgr = fbdev->managers[i];
2418b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		r = mgr->apply(mgr);
2419b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		if (r)
2420b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen			dev_warn(fbdev->dev, "failed to apply dispc config\n");
2421b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
2422b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2423b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	DBG("mgr->apply'ed\n");
2424b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2425b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (def_display) {
242691ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen		r = omapfb_init_display(fbdev, def_display);
24276d2e0bd60848e97756f40e49da207e862f4f3851Tomi Valkeinen		if (r) {
242891ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen			dev_err(fbdev->dev,
242991ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen					"failed to initialize default "
243091ac27a6879df3865e160adf979960a14f17d1aaTomi Valkeinen					"display\n");
24316d2e0bd60848e97756f40e49da207e862f4f3851Tomi Valkeinen			goto cleanup;
24326d2e0bd60848e97756f40e49da207e862f4f3851Tomi Valkeinen		}
2433b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
2434b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2435e26ed44c950ed9d1feb7719100f475e4e80f1419Afzal Mohammed	DBG("create sysfs for fbs\n");
2436e26ed44c950ed9d1feb7719100f475e4e80f1419Afzal Mohammed	r = omapfb_create_sysfs(fbdev);
2437e26ed44c950ed9d1feb7719100f475e4e80f1419Afzal Mohammed	if (r) {
2438e26ed44c950ed9d1feb7719100f475e4e80f1419Afzal Mohammed		dev_err(fbdev->dev, "failed to create sysfs entries\n");
2439e26ed44c950ed9d1feb7719100f475e4e80f1419Afzal Mohammed		goto cleanup;
2440e26ed44c950ed9d1feb7719100f475e4e80f1419Afzal Mohammed	}
2441e26ed44c950ed9d1feb7719100f475e4e80f1419Afzal Mohammed
2442b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return 0;
2443b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2444b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinencleanup:
2445b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	omapfb_free_resources(fbdev);
2446b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenerr0:
2447b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	dev_err(&pdev->dev, "failed to setup omapfb\n");
2448b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return r;
2449b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
2450b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2451b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic int omapfb_remove(struct platform_device *pdev)
2452b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
2453b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
2454b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2455b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	/* FIXME: wait till completion of pending events */
2456b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2457b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	omapfb_remove_sysfs(fbdev);
2458b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2459b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	omapfb_free_resources(fbdev);
2460b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2461b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return 0;
2462b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
2463b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2464b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic struct platform_driver omapfb_driver = {
2465b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	.probe          = omapfb_probe,
2466b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	.remove         = omapfb_remove,
2467b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	.driver         = {
2468b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.name   = "omapfb",
2469b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		.owner  = THIS_MODULE,
2470b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	},
2471b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen};
2472b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2473b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic int __init omapfb_init(void)
2474b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
2475b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	DBG("omapfb_init\n");
2476b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2477b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	if (platform_driver_register(&omapfb_driver)) {
2478b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		printk(KERN_ERR "failed to register omapfb driver\n");
2479b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen		return -ENODEV;
2480b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	}
2481b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2482b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	return 0;
2483b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
2484b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2485b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenstatic void __exit omapfb_exit(void)
2486b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen{
2487b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	DBG("omapfb_exit\n");
2488b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen	platform_driver_unregister(&omapfb_driver);
2489b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen}
2490b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2491b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenmodule_param_named(mode, def_mode, charp, 0);
2492b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenmodule_param_named(vram, def_vram, charp, 0);
2493b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenmodule_param_named(rotate, def_rotate, int, 0);
2494b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenmodule_param_named(vrfb, def_vrfb, bool, 0);
2495b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenmodule_param_named(mirror, def_mirror, bool, 0);
2496b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2497b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen/* late_initcall to let panel/ctrl drivers loaded first.
2498b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen * I guess better option would be a more dynamic approach,
2499b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen * so that omapfb reacts to new panels when they are loaded */
2500b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenlate_initcall(omapfb_init);
2501b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen/*module_init(omapfb_init);*/
2502b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinenmodule_exit(omapfb_exit);
2503b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi Valkeinen
2504b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi ValkeinenMODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
2505b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi ValkeinenMODULE_DESCRIPTION("OMAP2/3 Framebuffer");
2506b39a982ddecf1d95ed96f8457c39d3ea11df93f6Tomi ValkeinenMODULE_LICENSE("GPL v2");
2507